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