1/* 2 * jQuery Templating Plugin 3 * NOTE: Created for demonstration purposes. 4 * Copyright 2010, John Resig 5 * Dual licensed under the MIT or GPL Version 2 licenses. 6 */ 7(function(jQuery){ 8 // Override the DOM manipulation function 9 var oldManip = jQuery.fn.domManip, 10 htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$/; 11 12 jQuery.fn.extend({ 13 render: function( data, options ) { 14 return this.map(function(i, tmpl){ 15 return jQuery.render( tmpl, data, options ); 16 }); 17 }, 18 19 // This will allow us to do: .append( "template", dataObject ) 20 domManip: function( args ) { 21 // This appears to be a bug in the appendTo, etc. implementation 22 // it should be doing .call() instead of .apply(). See #6227 23 if ( args.length > 1 && args[0].nodeType ) { 24 arguments[0] = [ jQuery.makeArray(args) ]; 25 } 26 27 if ( args.length >= 2 && typeof args[0] === "string" && typeof args[1] !== "string" ) { 28 arguments[0] = [ jQuery.render( args[0], args[1], args[2] ) ]; 29 } 30 31 return oldManip.apply( this, arguments ); 32 } 33 }); 34 35 jQuery.extend({ 36 render: function( tmpl, data, options ) { 37 var fn, node; 38 39 if ( typeof tmpl === "string" ) { 40 // Use a pre-defined template, if available 41 fn = jQuery.templates[ tmpl ]; 42 if ( !fn && !htmlExpr.test( tmpl ) ) { 43 // it is a selector 44 node = jQuery( tmpl ).get( 0 ); 45 } 46 else { 47 fn = jQuery.tmpl( tmpl ); 48 } 49 } else if ( tmpl instanceof jQuery ) { 50 node = tmpl.get( 0 ); 51 } else if ( tmpl.nodeType ) { 52 node = tmpl; 53 } 54 55 if ( !fn && node ) { 56 var elemData = jQuery.data( node ); 57 fn = elemData.tmpl || (elemData.tmpl = jQuery.tmpl( node.innerHTML )); 58 } 59 60 // We assume that if the template string is being passed directly 61 // in the user doesn't want it cached. They can stick it in 62 // jQuery.templates to cache it. 63 64 var context = { 65 data: data, 66 index: 0, 67 dataItem: data, 68 options: options || {} 69 }; 70 71 if ( jQuery.isArray( data ) ) { 72 return jQuery.map( data, function( data, i ) { 73 context.index = i; 74 context.dataItem = data; 75 return fn.call( data, jQuery, context ); 76 }); 77 78 } else { 79 return fn.call( data, jQuery, context ); 80 } 81 }, 82 83 // You can stick pre-built template functions here 84 templates: {}, 85 86 /* 87 * For example, someone could do: 88 * jQuery.templates.foo = jQuery.tmpl("some long templating string"); 89 * $("#test").append("foo", data); 90 */ 91 92 tmplcmd: { 93 "each": { 94 _default: [ null, "$i" ], 95 prefix: "jQuery.each($1,function($2){with(this){", 96 suffix: "}});" 97 }, 98 "if": { 99 prefix: "if($1){", 100 suffix: "}" 101 }, 102 "else": { 103 prefix: "}else{" 104 }, 105 "html": { 106 prefix: "_.push(typeof ($1)==='function'?($1).call(this):$1);" 107 }, 108 "=": { 109 _default: [ "this" ], 110 prefix: "_.push($.encode(typeof ($1)==='function'?($1).call(this):$1));" 111 } 112 }, 113 114 encode: function( text ) { 115 return text != null ? document.createTextNode( text.toString() ).nodeValue : ""; 116 }, 117 118 tmpl: function(str, data, i, options) { 119 // Generate a reusable function that will serve as a template 120 // generator (and which will be cached). 121 122 var fn = new Function("jQuery","$context", 123 "var $=jQuery,$data=$context.dataItem,$i=$context.index,_=[];_.data=$data;_.index=$i;" + 124 125 // Introduce the data as local variables using with(){} 126 "with($data){_.push('" + 127 128 // Convert the template into pure JavaScript 129 str 130 .replace(/[\r\t\n]/g, " ") 131 .replace(/\${([^}]*)}/g, "{{= $1}}") 132 .replace(/{{(\/?)(\w+|.)(?:\((.*?)\))?(?: (.*?))?}}/g, function(all, slash, type, fnargs, args) { 133 var tmpl = jQuery.tmplcmd[ type ]; 134 135 if ( !tmpl ) { 136 throw "Template not found: " + type; 137 } 138 139 var def = tmpl._default; 140 141 return "');" + tmpl[slash ? "suffix" : "prefix"] 142 .split("$1").join(args || (def ? def[0] : "")) 143 .split("$2").join(fnargs || (def ? def[1] : "")) + "_.push('"; 144 }) 145 + "');};return $(_.join('')).get();"); 146 147 // Provide some basic currying to the user 148 // TODO: When currying, the fact that only the dataItem and index are passed 149 // in means we cannot know the value of 'data' although we know 'dataItem' and 'index' 150 // If this api took the array and index, we could know all 3 values. 151 // e.g. instead of this: 152 // tmpl(tmpl, foo[i], i) // foo[i] passed in is the dataItem 153 // this: 154 // tmpl(tmpl, foo, i) // foo[i] used internally to get dataItem 155 // If you intend data to be as is, 156 // tmpl(tmpl, foo) or tmpl(tmpl, foo, null, options) 157 return data ? fn.call( this, jQuery, { data: null, dataItem: data, index: i, options: options } ) : fn; 158 } 159 }); 160})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.