X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=Roo%2FDomTemplate.js;h=3ffe06071494d9b7b4b7d78fc4e2adccc61c2b14;hb=refs%2Fheads%2Fwip_leon_T7094_logo_image_upload_in_boilerplate;hp=5ca600d89e2168cfd3024b7bb77110dddc9888ef;hpb=a6584841270482276f9940be7d5246b8287515a4;p=roojs1 diff --git a/Roo/DomTemplate.js b/Roo/DomTemplate.js index 5ca600d89e..3ffe060714 100644 --- a/Roo/DomTemplate.js +++ b/Roo/DomTemplate.js @@ -27,10 +27,10 @@ * The tpl tag:

-        <div roo-for="a_variable or condition.."></tpl>
-        <tpl roo-if="a_variable or condition"></tpl>
-        <tpl roo-exec="some javascript"></tpl>
-        <tpl roo-name="named_template"></tpl> 
+        <div roo-for="a_variable or condition.."></div>
+        <div roo-if="a_variable or condition"></div>
+        <div roo-exec="some javascript"></div>
+        <div roo-name="named_template"></div> 
   
 
* @@ -38,20 +38,30 @@ Roo.DomTemplate = function() { Roo.DomTemplate.superclass.constructor.apply(this, arguments); - if (this.html) { + if (this.html) { this.compile(); - } + } }; Roo.extend(Roo.DomTemplate, Roo.Template, { - + /** + * id counter for sub templates. + */ id : 0, + /** + * flag to indicate if dom parser is inside a pre, + * it will strip whitespace if not. + */ + inPre : false, /** * The various sub templates */ tpls : false, + + + /** * * basic tag replacing syntax @@ -61,15 +71,23 @@ Roo.extend(Roo.DomTemplate, Roo.Template, { * x.t:(test,tesT) * */ - re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g, - + re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g, + //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g, iterChild : function (node, method) { + + var oldPre = this.inPre; + if (node.tagName == 'PRE') { + this.inPre = true; + } for( var i = 0; i < node.childNodes.length; i++) { method.call(this, node.childNodes[i]); } + this.inPre = oldPre; }, + + /** * compile the template * @@ -81,21 +99,73 @@ Roo.extend(Roo.DomTemplate, Roo.Template, { var s = this.html; // covert the html into DOM... + var doc = false; + var div =false; + try { + doc = document.implementation.createHTMLDocument(""); + doc.documentElement.innerHTML = this.html ; + div = doc.documentElement; + } catch (e) { + // old IE... - nasty -- it causes all sorts of issues.. with + // images getting pulled from server.. + div = document.createElement('div'); + div.innerHTML = this.html; + } + //doc.documentElement.innerHTML = htmlBody + - var div = document.createElement('div'); - div.innerHTML = this.html; - this.iterChild(div, this.compileNode) + this.tpls = []; + var _t = this; + this.iterChild(div, function(n) {_t.compileNode(n, true); }); + + var tpls = this.tpls; + + // create a top level template from the snippet.. + + //Roo.log(div.innerHTML); + + var tpl = { + uid : 'master', + id : this.id++, + attr : false, + value : false, + body : div.innerHTML, + + forCall : false, + execCall : false, + dom : div, + isTop : true + + }; + tpls.unshift(tpl); + + + // compile them... + this.tpls = []; + Roo.each(tpls, function(tp){ + this.compileTpl(tp); + this.tpls[tp.id] = tp; + }, this); + + this.master = tpls[0]; + return this; }, - compileNode : function(node) { + compileNode : function(node, istop) { // test for //Roo.log(node); + // skip anything not a tag.. if (node.nodeType != 1) { + if (node.nodeType == 3 && !this.inPre) { + // reduce white space.. + node.nodeValue = node.nodeValue.replace(/\s+/g, ' '); + + } return; } @@ -108,238 +178,128 @@ Roo.extend(Roo.DomTemplate, Roo.Template, { forCall : false, execCall : false, - + dom : false, + isTop : istop }; + + switch(true) { case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break; case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break; - case (node.hasAttribute('roo-if')): tpl.attr = 'name'; break; + case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break; case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break; // no default.. } + + if (!tpl.attr) { // just itterate children.. - this.iterChild(node,this.compileNode) + this.iterChild(node,this.compileNode); return; } tpl.uid = this.id++; - var value = node.getAttribute('roo-' + tpl.attr); + tpl.value = node.getAttribute('roo-' + tpl.attr); node.removeAttribute('roo-'+ tpl.attr); if (tpl.attr != 'name') { var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}'); node.parentNode.replaceChild(placeholder, node); } else { - node.parentNode.removeChild(node); + + var placeholder = document.createElement('span'); + placeholder.className = 'roo-tpl-' + tpl.value; + node.parentNode.replaceChild(placeholder, node); } // parent now sees '{domtplXXXX} - this.iterChild(node,this.compileNode) + this.iterChild(node,this.compileNode); // we should now have node body... var div = document.createElement('div'); div.appendChild(node); - tpl.body = div.innerHTML; + tpl.dom = node; + // this has the unfortunate side effect of converting tagged attributes + // eg. href="{...}" into %7C...%7D + // this has been fixed by searching for those combo's although it's a bit hacky.. - Roo.log("TEMPLATE : " + tpl.uid); - Roo.log(html); + tpl.body = div.innerHTML; + + tpl.id = tpl.uid; switch(tpl.attr) { case 'for' : - switch (attr.value) { - case '.': attr.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break; - case '..': attr.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break; - default: attr.forCall= new Function('values', 'parent', 'with(values){ return '+attr.value+'; }'); + switch (tpl.value) { + case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break; + case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break; + default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }'); } break; case 'exec': - tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(attr.value))+'; }'); + tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }'); break; case 'if': - tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(attr.value))+'; }'); + tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }'); break; case 'name': - tpl.id = value; // replace non characters??? + tpl.id = tpl.value; // replace non characters??? break; } - - tpls.push({ - id: attr == 'name' ? value : id, - target: name, - exec: exec, - test: fn, - body: m[1] || '' - }); + this.tpls.push(tpl); }, - oldwrapper : function () - { - s = ['', s, ''].join(''); - var re = /]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/, - nameRe = /^]*?for="(.*?)"/, - ifRe = /^]*?if="(.*?)"/, - execRe = /^]*?exec="(.*?)"/, - namedRe = /^]*?name="(\w+)"/, // named templates.. - m, - id = 0, - tpls = []; - while(true == !!(m = s.match(re))){ - var forMatch = m[0].match(nameRe), - ifMatch = m[0].match(ifRe), - execMatch = m[0].match(execRe), - namedMatch = m[0].match(namedRe), - - exp = null, - fn = null, - exec = null, - name = forMatch && forMatch[1] ? forMatch[1] : ''; - - if (ifMatch) { - // if - puts fn into test.. - exp = ifMatch && ifMatch[1] ? ifMatch[1] : null; - if(exp){ - fn = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(exp))+'; }'); - } - } - - if (execMatch) { - // exec - calls a function... returns empty if true is returned. - exp = execMatch && execMatch[1] ? execMatch[1] : null; - if(exp){ - exec = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(exp))+'; }'); - } - } - - - if (name) { - // for = - switch(name){ - case '.': name = new Function('values', 'parent', 'with(values){ return values; }'); break; - case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break; - default: name = new Function('values', 'parent', 'with(values){ return '+name+'; }'); - } - } - var uid = namedMatch ? namedMatch[1] : id; - - - tpls.push({ - id: namedMatch ? namedMatch[1] : id, - target: name, - exec: exec, - test: fn, - body: m[1] || '' - }); - if (namedMatch) { - s = s.replace(m[0], ''); - } else { - s = s.replace(m[0], '{xtpl'+ id + '}'); - } - ++id; - } - this.tpls = []; - for(var i = tpls.length-1; i >= 0; --i){ - this.compileTpl(tpls[i]); - this.tpls[tpls[i].id] = tpls[i]; - } - this.master = tpls[tpls.length-1]; - return this; - }, + /** - * same as applyTemplate, except it's done to one of the subTemplates - * when using named templates, you can do: - * - * var str = pl.applySubTemplate('your-name', values); + * Compile a segment of the template into a 'sub-template' * * - * @param {Number} id of the template - * @param {Object} values to apply to template - * @param {Object} parent (normaly the instance of this object) + * + * */ - applySubTemplate : function(id, values, parent) - { - - - var t = this.tpls[id]; - - - try { - if(t.test && !t.test.call(this, values, parent)){ - return ''; - } - } catch(e) { - Roo.log("Xtemplate.applySubTemplate 'test': Exception thrown"); - Roo.log(e.toString()); - Roo.log(t.test); - return '' - } - try { - - if(t.exec && t.exec.call(this, values, parent)){ - return ''; - } - } catch(e) { - Roo.log("Xtemplate.applySubTemplate 'exec': Exception thrown"); - Roo.log(e.toString()); - Roo.log(t.exec); - return '' - } - try { - var vs = t.target ? t.target.call(this, values, parent) : values; - parent = t.target ? values : parent; - if(t.target && vs instanceof Array){ - var buf = []; - for(var i = 0, len = vs.length; i < len; i++){ - buf[buf.length] = t.compiled.call(this, vs[i], parent); - } - return buf.join(''); - } - return t.compiled.call(this, vs, parent); - } catch (e) { - Roo.log("Xtemplate.applySubTemplate : Exception thrown"); - Roo.log(e.toString()); - Roo.log(t.compiled); - return ''; - } - }, - compileTpl : function(tpl) { var fm = Roo.util.Format; var useF = this.disableFormats !== true; - var sep = Roo.isGecko ? "+" : ","; + + var sep = Roo.isGecko ? "+\n" : ",\n"; + var undef = function(str) { - Roo.log("Property not found :" + str); + Roo.debug && Roo.log("Property not found :" + str); return ''; }; + + //Roo.log(tpl.body); - var fn = function(m, name, format, args) + + + var fn = function(m, lbrace, name, format, args) { + //Roo.log("ARGS"); //Roo.log(arguments); args = args ? args.replace(/\\'/g,"'") : args; //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"] if (typeof(format) == 'undefined') { - format= 'htmlEncode'; + format = 'htmlEncode'; } if (format == 'raw' ) { format = false; } - if(name.substr(0, 4) == 'xtpl'){ - return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent)'+sep+"'"; + if(name.substr(0, 6) == 'domtpl'){ + return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'"; } // build an array of options to determine if value is undefined.. @@ -373,7 +333,7 @@ Roo.extend(Roo.DomTemplate, Roo.Template, { return "'"+ sep + udef_st + format + name + args + "))"+sep+"'"; } - if (args.length) { + if (args && args.length) { // called with xxyx.yuu:(test,test) // change to () return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'"; @@ -403,6 +363,81 @@ Roo.extend(Roo.DomTemplate, Roo.Template, { return this; }, + + /** + * same as applyTemplate, except it's done to one of the subTemplates + * when using named templates, you can do: + * + * var str = pl.applySubTemplate('your-name', values); + * + * + * @param {Number} id of the template + * @param {Object} values to apply to template + * @param {Object} parent (normaly the instance of this object) + */ + applySubTemplate : function(id, values, parent) + { + + + var t = this.tpls[id]; + + + try { + if(t.ifCall && !t.ifCall.call(this, values, parent)){ + Roo.debug && Roo.log('if call on ' + t.value + ' return false'); + return ''; + } + } catch(e) { + Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString()); + Roo.log(values); + + return ''; + } + try { + + if(t.execCall && t.execCall.call(this, values, parent)){ + return ''; + } + } catch(e) { + Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString()); + Roo.log(values); + return ''; + } + + try { + var vs = t.forCall ? t.forCall.call(this, values, parent) : values; + parent = t.target ? values : parent; + if(t.forCall && vs instanceof Array){ + var buf = []; + for(var i = 0, len = vs.length; i < len; i++){ + try { + buf[buf.length] = t.compiled.call(this, vs[i], parent); + } catch (e) { + Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString()); + Roo.log(e.body); + //Roo.log(t.compiled); + Roo.log(vs[i]); + } + } + return buf.join(''); + } + } catch (e) { + Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString()); + Roo.log(values); + return ''; + } + try { + return t.compiled.call(this, vs, parent); + } catch (e) { + Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString()); + Roo.log(e.body); + //Roo.log(t.compiled); + Roo.log(values); + return ''; + } + }, + + applyTemplate : function(values){ return this.master.compiled.call(this, values, {}); @@ -415,7 +450,7 @@ Roo.extend(Roo.DomTemplate, Roo.Template, { }); -Roo.XTemplate.from = function(el){ +Roo.DomTemplate.from = function(el){ el = Roo.getDom(el); - return new Roo.XTemplate(el.value || el.innerHTML); + return new Roo.Domtemplate(el.value || el.innerHTML); }; \ No newline at end of file