Editing JSTemplates This edit will create a new revision. Your details (optional) Name Email (won’t be displayed; might be used for Gravatar) URL Test case details Title * Published (uncheck if you want to fiddle around before making the page public) Description (in case you feel further explanation is needed)(Markdown syntax is allowed) Are you a spammer? (just answer the question) Preparation code Preparation code HTML (this will be inserted in the <body> of a valid HTML5 document in standards mode) (useful when testing DOM operations or including libraries) <script src="https://github.com/olado/doT/raw/master/doT.js"></script> <script> ( function() { var _innerText = 'textContent'; // using cc to target execution only for IE /*@cc_on @if ( @_jscript ) _innerText = 'innerText'; @end @*/ function children( dom ) { var childs = dom.children || dom.childNodes, childs_out = []; for( var i=0, l=childs.length; i<l; i++ ) if( childs[i].nodeType === 1 ) childs_out.push(childs[i]); return childs_out; } var templateJS = function() { // templates cache var templates = []; return { getTemplate: function( id, kill ) { // template node var dom; // get node by #ID if( typeof id === 'string' ) dom = document.getElementById( id ); // get node by DOM-Element else if( id.nodeValue && id.nodeType ) dom = id; // break if no valid node given if( !dom ) return; // traverse template node // IMPORTANT - give a cloned node dom = dom.cloneNode(true); // create template var tmpl = { dom: dom }, children_stack = [ children( dom ) ], // Child STACK k = 0, // STACK counter // current STACK values childs = children_stack[k], i = [0], l = [childs.length], // curent STACK children counters j = i[k], n = l[k], has_children, current_dom, shortcuts = {}, // this shortcuts will be available shortcut_attr = "data-tmpl", shortcut_name, stack_switched = false; // indicates that STACK has been switched // check shortcut for root node shortcut_name = dom.getAttribute(shortcut_attr); if(shortcut_name) shortcuts[shortcut_name] = dom; // traverse all children of template for(; j < n;) { current_dom = childs[j]; // create shortcut shortcut_name = current_dom.getAttribute(shortcut_attr); if(shortcut_name) shortcuts[shortcut_name] = current_dom; has_children = children( current_dom ); // create new child object if( has_children.length ) { // increase STACKS children_stack.push( has_children ); i.push(0); l.push( has_children.length ); // save last STACK children counter i[k] = j+1; ++k; stack_switched = true; } else { j++; // if last children go up if( k > 0 && j === n ) { delete children_stack[k]; delete i[k]; delete l[k]; --k; stack_switched = true; } } // checkout switched stack data if( stack_switched ) { childs = children_stack[k]; j = i[k]; n = l[k]; stack_switched = false; } } // add childrens to template tmpl.shortcuts = shortcuts; // push template to cache templates.push( tmpl ); // delete template source after traversing if( kill ) dom.parentNode.removeChild( dom ); return templates.length - 1; }, // delete existing template killTemplate: function( id ) { if( templates[tmpl] ) delete templates[tmpl]; return this; }, // render existing template render: function( id, obj ) { if( !templates[id] ) return; var data = obj.data, keys = obj.keys, tmpl = templates[id], tmpl_shortcuts = tmpl.shortcuts, fragment = document.createDocumentFragment(), obj, shortcut_key, shortcut_dom, shortcut_obj, key; for( var i=0, l=data.length; i<l; i++ ) { obj = data[i]; for( var x=0, n=keys.length; x<n; x++ ) { shortcut_key = keys[x]; shortcut_dom = tmpl_shortcuts[ shortcut_key ]; shortcut_obj = obj[ shortcut_key ]; for( key in shortcut_obj ) { if( key == 'text' ) shortcut_dom[_innerText] = shortcut_obj[key]; else if( typeof shortcut_dom[key] !== 'undefined' ) shortcut_dom[key] = shortcut_obj[key]; else shortcut_dom.setAttribute( key, shortcut_obj[key] ); } } fragment.appendChild( tmpl.dom.cloneNode(true) ); } return fragment; } }; }(); window.templateJS = window.$t = templateJS; }()); </script> <li id="li-template" class="li" data-tmpl="li"> <a class="click" target="_self" href="" data-tmpl="link"> <img class="thumb" src="void:javascript(0)" data-tmpl="img"> <div class="info"> <h3 class="title" data-tmpl="title"></h3> <p class="desc" data-tmpl="desc"></p> <em class="misc" data-tmpl="misc"></em> </div> <em class="date" data-tmpl="date"></em> <em class="price" data-tmpl="price"></em> </a> </li> <ol id="li-box"> </ol> Include JavaScript libraries as follows: <script src="//cdn.ext/library.js"></script> Define setup for all tests (variables, functions, arrays or other objects that will be used in the tests) (runs before each clocked test loop, outside of the timed code region) (e.g. define local test variables, reset global variables, clear canvas, etc.) (see FAQ) var box = document.getElementById('li-box'), t = $t.getTemplate("li-template"); window.doTtemplate = doT.template('{{ for (var i = 0, l = it.data.length; i < l; i++) { }}<li class="item">{{= it.data[i] }}</li><li id="{{= it.data[i].li.id }}" class="li"><a class="click" target="_self" href="{{= it.data[i].link.href }}"><img class="thumb" src="{{= it.data[i].img.src }}"><div class="info"><h3 class="title">{{= it.data[i].title.text }}</h3><p class="desc">{{= it.data[i].desc.text }}</p><em class="misc">{{= it.data[i].misc.text }}</em></div><em class="date">{{= it.data[i].date.text }}</em><em class="price">{{= it.data[i].price.text }}</em></a></li>{{ } }}'); var shortcut_list = { keys:['li','link','img','title','desc','misc','date','price'], data: [ { li: { id:1 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 1" }, desc: { text:"Beschreibung 1" }, misc: { text:"Canton/Kategorie 1" }, date: { text:"Datum 1" }, price: { text:"Preis 1" } }, { li: { id:2 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 2" }, desc: { text:"Beschreibung 2" }, misc: { text:"Canton/Kategorie 2" }, date: { text:"Datum 2" }, price: { text:"Preis 2" } }, { li: { id:3 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 3" }, desc: { text:"Beschreibung 3" }, misc: { text:"Canton/Kategorie 3" }, date: { text:"Datum 3" }, price: { text:"Preis 3" } }, { li: { id:4 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 4" }, desc: { text:"Beschreibung 4" }, misc: { text:"Canton/Kategorie 4" }, date: { text:"Datum 4" }, price: { text:"Preis 4" } }, { li: { id:5 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 5" }, desc: { text:"Beschreibung 5" }, misc: { text:"Canton/Kategorie 5" }, date: { text:"Datum 5" }, price: { text:"Preis 5" } }, { li: { id:6 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 6" }, desc: { text:"Beschreibung 6" }, misc: { text:"Canton/Kategorie 6" }, date: { text:"Datum 6" }, price: { text:"Preis 6" } }, { li: { id:7 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 7" }, desc: { text:"Beschreibung 7" }, misc: { text:"Canton/Kategorie 7" }, date: { text:"Datum 7" }, price: { text:"Preis 7" } }, { li: { id:8 }, link: { href: "http://www.tutti.ch" }, img: { src: "http://lorempixel.com/200/100" }, title: { text:"Titel 8" }, desc: { text:"Beschreibung 8" }, misc: { text:"Canton/Kategorie 8" }, date: { text:"Datum 8" }, price: { text:"Preis 8" } } ] }; Define teardown for all tests (runs after each clocked test loop, outside of the timed code region) (see FAQ) Code snippets to compare Test 1 Title Async (check if this is an asynchronous test) Code frag = $t.render( t, shortcut_list ); box.appendChild(frag); box.innerHTML = ""; Test 2 Title Async (check if this is an asynchronous test) Code box.innerHTML = doTtemplate(shortcut_list); box.innerHTML = ""; Test 3 Title Async (check if this is an asynchronous test) Code var x = $t.getTemplate("li-template"); Test 4 Title Async (check if this is an asynchronous test) Code var y = doT.template('{{ for (var i = 0, l = it.data.length; i < l; i++) { }}<li class="item">{{= it.data[i] }}</li><li id="{{= it.data[i].li.id }}" class="li"><a class="click" target="_self" href="{{= it.data[i].link.href }}"><img class="thumb" src="{{= it.data[i].img.src }}"><div class="info"><h3 class="title">{{= it.data[i].title.text }}</h3><p class="desc">{{= it.data[i].desc.text }}</p><em class="misc">{{= it.data[i].misc.text }}</em></div><em class="date">{{= it.data[i].date.text }}</em><em class="price">{{= it.data[i].price.text }}</em></a></li>{{ } }}');