Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / src / core / Template-more.js
1 /*!
2  * Ext JS Library 3.2.0
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.Template
9  */
10 Ext.apply(Ext.Template.prototype, {
11     /**
12      * @cfg {Boolean} disableFormats Specify <tt>true</tt> to disable format
13      * functions in the template. If the template does not contain
14      * {@link Ext.util.Format format functions}, setting <code>disableFormats</code>
15      * to true will reduce <code>{@link #apply}</code> time. Defaults to <tt>false</tt>.
16      * <pre><code>
17 var t = new Ext.Template(
18     '&lt;div name="{id}"&gt;',
19         '&lt;span class="{cls}"&gt;{name} {value}&lt;/span&gt;',
20     '&lt;/div&gt;',
21     {
22         compiled: true,      // {@link #compile} immediately
23         disableFormats: true // reduce <code>{@link #apply}</code> time since no formatting
24     }    
25 );
26      * </code></pre>
27      * For a list of available format functions, see {@link Ext.util.Format}.
28      */
29     disableFormats : false,                             
30     /**
31      * See <code>{@link #disableFormats}</code>.
32      * @type Boolean
33      * @property disableFormats
34      */
35
36     /**
37      * The regular expression used to match template variables
38      * @type RegExp
39      * @property
40      * @hide repeat doc
41      */
42     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
43
44     /**
45      * Returns an HTML fragment of this template with the specified values applied.
46      * @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'})
47      * @return {String} The HTML fragment
48      * @hide repeat doc
49      */
50     applyTemplate : function(values){
51                 var me = this,
52                         useF = me.disableFormats !== true,
53                 fm = Ext.util.Format, 
54                 tpl = me;           
55             
56         if(me.compiled){
57             return me.compiled(values);
58         }
59         function fn(m, name, format, args){
60             if (format && useF) {
61                 if (format.substr(0, 5) == "this.") {
62                     return tpl.call(format.substr(5), values[name], values);
63                 } else {
64                     if (args) {
65                         // quoted values are required for strings in compiled templates,
66                         // but for non compiled we need to strip them
67                         // quoted reversed for jsmin
68                         var re = /^\s*['"](.*)["']\s*$/;
69                         args = args.split(',');
70                         for(var i = 0, len = args.length; i < len; i++){
71                             args[i] = args[i].replace(re, "$1");
72                         }
73                         args = [values[name]].concat(args);
74                     } else {
75                         args = [values[name]];
76                     }
77                     return fm[format].apply(fm, args);
78                 }
79             } else {
80                 return values[name] !== undefined ? values[name] : "";
81             }
82         }
83         return me.html.replace(me.re, fn);
84     },
85                 
86     /**
87      * Compiles the template into an internal function, eliminating the RegEx overhead.
88      * @return {Ext.Template} this
89      * @hide repeat doc
90      */
91     compile : function(){
92         var me = this,
93                 fm = Ext.util.Format,
94                 useF = me.disableFormats !== true,
95                 sep = Ext.isGecko ? "+" : ",",
96                 body;
97         
98         function fn(m, name, format, args){
99             if(format && useF){
100                 args = args ? ',' + args : "";
101                 if(format.substr(0, 5) != "this."){
102                     format = "fm." + format + '(';
103                 }else{
104                     format = 'this.call("'+ format.substr(5) + '", ';
105                     args = ", values";
106                 }
107             }else{
108                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
109             }
110             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
111         }
112         
113         // branched to use + in gecko and [].join() in others
114         if(Ext.isGecko){
115             body = "this.compiled = function(values){ return '" +
116                    me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
117                     "';};";
118         }else{
119             body = ["this.compiled = function(values){ return ['"];
120             body.push(me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
121             body.push("'].join('');};");
122             body = body.join('');
123         }
124         eval(body);
125         return me;
126     },
127     
128     // private function used to call members
129     call : function(fnName, value, allValues){
130         return this[fnName](value, allValues);
131     }
132 });
133 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;