PDA

View Full Version : Template improvement/fix



JanVenekamp
19 Nov 2010, 6:19 AM
This falls between an improvement and a fix.

When using format functions in a template you can call them with argument from your template, but when using your custom functions this doesn't work.



'<div>{val:this.customformat("doesntwork")}</div>';
This simple code change will allow it:



Ext.override(Ext.Template, {
/**
* Returns an HTML fragment of this template with the specified values applied.
* @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
* @return {String} The HTML fragment
* @hide repeat doc
*/
applyTemplate : function(values){
var me = this,
useF = me.disableFormats !== true,
fm = Ext.util.Format,
tpl = me;

if(me.compiled){
return me.compiled(values);
}
function fn(m, name, format, args){
if (format && useF) {
// #[
// --
// if (format.substr(0, 5) == "this.") {
// return tpl.call(format.substr(5), values[name], values);
// } else {
// if (args) {
// // quoted values are required for strings in compiled templates,
// // but for non compiled we need to strip them
// // quoted reversed for jsmin
// var re = me.argsRe;
// args = args.split(',');
// for(var i = 0, len = args.length; i < len; i++){
// args[i] = args[i].replace(re, "$1");
// }
// args = [values[name]].concat(args);
// } else {
// args = [values[name]];
// }
// return fm[format].apply(fm, args);
// }
// ++
if (args) {
// quoted values are required for strings in compiled templates,
// but for non compiled we need to strip them
// quoted reversed for jsmin
var re = me.argsRe;
args = args.split(',');
for(var i = 0, len = args.length; i < len; i++){
args[i] = args[i].replace(re, "$1");
}
} else {
args = [];
}

if (format.substr(0, 5) == "this.") {
return tpl[format.substr(5)].apply(tpl, [values[name], values].concat(args));
} else {
return fm[format].apply(fm, [values[name]].concat(args));
}
// ]#
} else {
return values[name] !== undefined ? values[name] : "";
}
}
return me.html.replace(me.re, fn);
},
});

Ext.override(Ext.XTemplate, {
// private
compileTpl : function(tpl){
var fm = Ext.util.Format,
useF = this.disableFormats !== true,
sep = Ext.isGecko ? "+" : ",",
body;

function fn(m, name, format, args, math){
if(name.substr(0, 4) == 'xtpl'){
return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
}
var v;
if(name === '.'){
v = 'values';
}else if(name === '#'){
v = 'xindex';
}else if(name.indexOf('.') != -1){
v = name;
}else{
v = "values['" + name + "']";
}
if(math){
v = '(' + v + math + ')';
}
if (format && useF) {
args = args ? ',' + args : "";
if(format.substr(0, 5) != "this."){
format = "fm." + format + '(';
}else{
// #[
// --
// format = 'this.call("'+ format.substr(5) + '", ';
// args = ", values";
// ++
format += '(';
args = ", values" + args;
// ]#
}
} else {
args= ''; format = "("+v+" === undefined ? '' : ";
}
return "'"+ sep + format + v + args + ")"+sep+"'";
}

function codeFn(m, code){
// Single quotes get escaped when the template is compiled, however we want to undo this when running code.
return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
}

// branched to use + in gecko and [].join() in others
if(Ext.isGecko){
body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
"';};";
}else{
body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
body.push("'].join('');};");
body = body.join('');
}
eval(body);
return this;
}
});
Here I'm overriding compileTpl in XTemplate, but the same code is in Template.
This also makes the private member call unnecessary (can someone explain me why it's there)?

This change will not break any existing code.
Hope this will make it to the ExtJS source code, as a fix.