app/assets/javascripts/jquery.views.js in sprockets-jsrender-0.1.2 vs app/assets/javascripts/jquery.views.js in sprockets-jsrender-0.1.3

- old
+ new

@@ -5,11 +5,11 @@ * See JsRender at http://github.com/BorisMoore/jsrender * * Copyright 2012, Boris Moore * Released under the MIT License. */ -// informal pre beta commit counter: 2 +// informal pre beta commit counter: 3 this.jQuery && jQuery.link || (function( global, undefined ) { // global is the this object, which is window when running in the usual browser environment. //========================== Top-level vars ========================== @@ -417,116 +417,118 @@ currentView = parent, viewDepth = depth; context = context || {}; node = prevNode || node; - if ( !prevNode && node.nodeType === 1 ) { - if ( viewDepth++ === 0 ) { - // Add top-level element nodes to view.nodes - currentView.nodes.push( node ); - } - if ( linkMarkup = node.getAttribute( jsv.linkAttr ) ) { - linkIndex = currentView._lnk++; - // Compiled linkFn expressions are stored in the tmpl.links array of the template - links = currentView.links || currentView.tmpl.links; - if ( !(link = links[ linkIndex ] )) { - link = links [ linkIndex ] = {}; - if ( linkMarkup.charAt(linkMarkup.length-1) !== "}" ) { - // Simplified syntax is used: data-link="expression" - // Convert to data-link="{:expression}", or for inputs, data-link="{:expression:}" for (default) two-way binding - linkMarkup = delimOpen1 + ":" + linkMarkup + ($.nodeName( node, "input" ) ? ":" : "") + delimClose0; - } - while( tokens = rTag.exec( linkMarkup )) { // TODO require } to be followed by whitespace or $, and remove the \}(!\}) option. - // Iterate over the data-link expressions, for different target attrs, e.g. <input data-link="{:firstName:} title{:~description(firstName, lastName)}" - // tokens: [all, attr, tag, converter, colon, html, code, linkedParams] - attr = tokens[ 1 ]; - expression = tokens[ 2 ]; - if ( tokens[ 5 ]) { - // Only for {:} link" - if ( !attr && (convertBack = /^.*:([\w$]*)$/.exec( tokens[ 8 ] ))) { - // two-way binding - convertBack = convertBack[ 1 ]; - if ( cbLength = convertBack.length ) { - // There is a convertBack function - expression = tokens[ 2 ].slice( 0, -cbLength - 1 ) + delimClose0; // Remove the convertBack string from expression. + if ( node ) { + if ( !prevNode && node.nodeType === 1 ) { + if ( viewDepth++ === 0 ) { + // Add top-level element nodes to view.nodes + currentView.nodes.push( node ); + } + if ( linkMarkup = node.getAttribute( jsv.linkAttr ) ) { + linkIndex = currentView._lnk++; + // Compiled linkFn expressions are stored in the tmpl.links array of the template + links = currentView.links || currentView.tmpl.links; + if ( !(link = links[ linkIndex ] )) { + link = links [ linkIndex ] = {}; + if ( linkMarkup.charAt(linkMarkup.length-1) !== "}" ) { + // Simplified syntax is used: data-link="expression" + // Convert to data-link="{:expression}", or for inputs, data-link="{:expression:}" for (default) two-way binding + linkMarkup = delimOpen1 + ":" + linkMarkup + ($.nodeName( node, "input" ) ? ":" : "") + delimClose0; + } + while( tokens = rTag.exec( linkMarkup )) { // TODO require } to be followed by whitespace or $, and remove the \}(!\}) option. + // Iterate over the data-link expressions, for different target attrs, e.g. <input data-link="{:firstName:} title{:~description(firstName, lastName)}" + // tokens: [all, attr, tag, converter, colon, html, code, linkedParams] + attr = tokens[ 1 ]; + expression = tokens[ 2 ]; + if ( tokens[ 5 ]) { + // Only for {:} link" + if ( !attr && (convertBack = /^.*:([\w$]*)$/.exec( tokens[ 8 ] ))) { + // two-way binding + convertBack = convertBack[ 1 ]; + if ( cbLength = convertBack.length ) { + // There is a convertBack function + expression = tokens[ 2 ].slice( 0, -cbLength - 1 ) + delimClose0; // Remove the convertBack string from expression. + } } + if ( convertBack === null ) { + convertBack = undefined; + } } - if ( convertBack === null ) { - convertBack = undefined; + // Compile the linkFn expression which evaluates and binds a data-link expression + // TODO - optimize for the case of simple data path with no conversion, helpers, etc.: + // i.e. data-link="a.b.c". Avoid creating new instances of Function every time. Can use a default function for all of these... + link[ attr ] = jsv.tmplFn( delimOpen0 + expression + delimClose1, undefined, TRUE ); + if ( !attr && convertBack !== undefined ) { + link[ attr ].to = convertBack; } } - // Compile the linkFn expression which evaluates and binds a data-link expression - // TODO - optimize for the case of simple data path with no conversion, helpers, etc.: - // i.e. data-link="a.b.c". Avoid creating new instances of Function every time. Can use a default function for all of these... - link[ attr ] = jsv.tmplFn( delimOpen0 + expression + delimClose1, undefined, TRUE ); - if ( !attr && convertBack !== undefined ) { - link[ attr ].to = convertBack; - } } + for ( attr in link ) { + bindDataLinkTarget( + currentView.data || data, //source + node, //target + attr, //attr + link[ attr ], //compiled link markup expression + currentView //view + ); + } + // TODO - Add one-way-to-source support + // if ( linkMarkup.lastIndexOf( "toSrc{", 0 ) === 0 ) { + // linkMarkup = "{toSrc " + linkMarkup.slice(6); + // } } - for ( attr in link ) { - bindDataLinkTarget( - currentView.data|| data, //source - node, //target - attr, //attr - link[ attr ], //compiled link markup expression - currentView //view - ); - } -// TODO - Add one-way-to-source support -// if ( linkMarkup.lastIndexOf( "toSrc{", 0 ) === 0 ) { -// linkMarkup = "{toSrc " + linkMarkup.slice(6); -// } + node = node.firstChild; + } else { + node = node.nextSibling; } - node = node.firstChild; - } else { - node = node.nextSibling; - } - while ( node && node !== nextNode ) { - if ( node.nodeType === 1 ) { - linkViews( node, currentView, nextNode, viewDepth, data, context ); - } else if ( node.nodeType === 8 && (tokens = rTmplOrItemComment.exec( node.nodeValue ))) { - // tokens: [ all, slash, 'item', 'tmpl', path, index, tmplParam ] - parentNode = node.parentNode; - if ( tokens[ 1 ]) { - // <!--/item--> or <!--/tmpl--> - currentView.nextNode = node; - if ( currentView.ctx.onAfterCreate ) { - currentView.ctx.onAfterCreate.call( currentView, currentView ); - } - if ( tokens[ 2 ]) { - // An item close tag: <!--/item--> - currentView = parent; - } else { - // A tmpl close tag: <!--/tmpl--> - return node; - } - } else { - // <!--item--> or <!--tmpl--> - parentElViews = parentElViews || jsViewsData( parentNode, viewStr, TRUE ); - if ( tokens[ 2 ]) { - // An item open tag: <!--item--> - parentElViews.push( - currentView = linkedView( currentView.views[ index ] ) - ); - index++; - currentView.prevNode = node; + while ( node && node !== nextNode ) { + if ( node.nodeType === 1 ) { + linkViews( node, currentView, nextNode, viewDepth, data, context ); + } else if ( node.nodeType === 8 && (tokens = rTmplOrItemComment.exec( node.nodeValue ))) { + // tokens: [ all, slash, 'item', 'tmpl', path, index, tmplParam ] + parentNode = node.parentNode; + if ( tokens[ 1 ]) { + // <!--/item--> or <!--/tmpl--> + currentView.nextNode = node; + if ( currentView.ctx.onAfterCreate ) { + currentView.ctx.onAfterCreate.call( currentView, currentView ); + } + if ( tokens[ 2 ]) { + // An item close tag: <!--/item--> + currentView = parent; + } else { + // A tmpl close tag: <!--/tmpl--> + return node; + } } else { - // A tmpl open tag: <!--tmpl(path) name--> - parentElViews.push( - view = linkedView( currentView.views[ tokens[ 5 ]] ) - ); - view.prevNode = node; - // Jump to the nextNode of the tmpl view - node = linkViews( node, view, nextNode, 0, undefined, undefined, undefined, 0 ); + // <!--item--> or <!--tmpl--> + parentElViews = parentElViews || jsViewsData( parentNode, viewStr, TRUE ); + if ( tokens[ 2 ]) { + // An item open tag: <!--item--> + parentElViews.push( + currentView = linkedView( currentView.views[ index ] ) + ); + index++; + currentView.prevNode = node; + } else { + // A tmpl open tag: <!--tmpl(path) name--> + parentElViews.push( + view = linkedView( currentView.views[ tokens[ 5 ]] ) + ); + view.prevNode = node; + // Jump to the nextNode of the tmpl view + node = linkViews( node, view, nextNode, 0, undefined, undefined, undefined, 0 ); + } } + } else if ( viewDepth === 0 ) { + // Add top-level non-element nodes to view.nodes + currentView.nodes.push( node ); } - } else if ( viewDepth === 0 ) { - // Add top-level non-element nodes to view.nodes - currentView.nodes.push( node ); + node = node.nextSibling; } - node = node.nextSibling; } } function bindDataLinkTarget( source, target, attr, linkFn, view ) { //Add data link bindings for a link expression in data-link attribute markup