Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / XTemplate.html
index a8c0df8..b054702 100644 (file)
+<!DOCTYPE html>
 <html>
 <head>
-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>The source code</title>
-    <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
-    <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+  <style type="text/css">
+    .highlight { display: block; background-color: #ddd; }
+  </style>
+  <script type="text/javascript">
+    function highlight() {
+      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+    }
+  </script>
 </head>
-<body  onload="prettyPrint();">
-    <pre class="prettyprint lang-js">/*!
- * Ext JS Library 3.3.0
- * Copyright(c) 2006-2010 Ext JS, Inc.
- * licensing@extjs.com
- * http://www.extjs.com/license
- */
-<div id="cls-Ext.XTemplate"></div>/**
- * @class Ext.XTemplate
- * @extends Ext.Template
- * <p>A template class that supports advanced functionality like:<div class="mdetail-params"><ul>
- * <li>Autofilling arrays using templates and sub-templates</li>
- * <li>Conditional processing with basic comparison operators</li>
- * <li>Basic math function support</li>
- * <li>Execute arbitrary inline code with special built-in template variables</li>
- * <li>Custom member functions</li>
- * <li>Many special tags and built-in operators that aren't defined as part of
- * the API, but are supported in the templates that can be created</li>
- * </ul></div></p>
- * <p>XTemplate provides the templating mechanism built into:<div class="mdetail-params"><ul>
- * <li>{@link Ext.DataView}</li>
- * <li>{@link Ext.ListView}</li>
- * <li>{@link Ext.form.ComboBox}</li>
- * <li>{@link Ext.grid.TemplateColumn}</li>
- * <li>{@link Ext.grid.GroupingView}</li>
- * <li>{@link Ext.menu.Item}</li>
- * <li>{@link Ext.layout.MenuLayout}</li>
- * <li>{@link Ext.ColorPalette}</li>
- * </ul></div></p>
- *
- * <p>For example usage {@link #XTemplate see the constructor}.</p>
- *
- * @constructor
- * The {@link Ext.Template#Template Ext.Template constructor} describes
- * the acceptable parameters to pass to the constructor. The following
- * examples demonstrate all of the supported features.</p>
- *
- * <div class="mdetail-params"><ul>
- *
- * <li><b><u>Sample Data</u></b>
- * <div class="sub-desc">
- * <p>This is the data object used for reference in each code example:</p>
- * <pre><code>
-var data = {
-    name: 'Jack Slocum',
-    title: 'Lead Developer',
-    company: 'Ext JS, LLC',
-    email: 'jack@extjs.com',
-    address: '4 Red Bulls Drive',
-    city: 'Cleveland',
-    state: 'Ohio',
-    zip: '44102',
-    drinks: ['Red Bull', 'Coffee', 'Water'],
-    kids: [{
-        name: 'Sara Grace',
-        age:3
-    },{
-        name: 'Zachary',
-        age:2
-    },{
-        name: 'John James',
-        age:0
-    }]
-};
- * </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Auto filling of arrays</u></b>
- * <div class="sub-desc">
- * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>for</tt></b> operator are used
- * to process the provided data object:
- * <ul>
- * <li>If the value specified in <tt>for</tt> is an array, it will auto-fill,
- * repeating the template block inside the <tt>tpl</tt> tag for each item in the
- * array.</li>
- * <li>If <tt>for="."</tt> is specified, the data object provided is examined.</li>
- * <li>While processing an array, the special variable <tt>{#}</tt>
- * will provide the current array index + 1 (starts at 1, not 0).</li>
- * </ul>
- * </p>
- * <pre><code>
-&lt;tpl <b>for</b>=".">...&lt;/tpl>       // loop through array at root node
-&lt;tpl <b>for</b>="foo">...&lt;/tpl>     // loop through array at foo node
-&lt;tpl <b>for</b>="foo.bar">...&lt;/tpl> // loop through array at foo.bar node
- * </code></pre>
+<body onload="prettyPrint(); highlight();">
+  <pre class="prettyprint lang-js"><span id='Ext-XTemplate'>/**
+</span> * A template class that supports advanced functionality like:
+ *
+ * - Autofilling arrays using templates and sub-templates
+ * - Conditional processing with basic comparison operators
+ * - Basic math function support
+ * - Execute arbitrary inline code with special built-in template variables
+ * - Custom member functions
+ * - Many special tags and built-in operators that aren't defined as part of the API, but are supported in the templates that can be created
+ *
+ * XTemplate provides the templating mechanism built into:
+ *
+ * - {@link Ext.view.View}
+ *
+ * The {@link Ext.Template} describes the acceptable parameters to pass to the constructor. The following examples
+ * demonstrate all of the supported features.
+ *
+ * # Sample Data
+ *
+ * This is the data object used for reference in each code example:
+ *
+ *     var data = {
+ *         name: 'Tommy Maintz',
+ *         title: 'Lead Developer',
+ *         company: 'Sencha Inc.',
+ *         email: 'tommy@sencha.com',
+ *         address: '5 Cups Drive',
+ *         city: 'Palo Alto',
+ *         state: 'CA',
+ *         zip: '44102',
+ *         drinks: ['Coffee', 'Soda', 'Water'],
+ *         kids: [
+ *             {
+ *                 name: 'Joshua',
+ *                 age:3
+ *             },
+ *             {
+ *                 name: 'Matthew',
+ *                 age:2
+ *             },
+ *             {
+ *                 name: 'Solomon',
+ *                 age:0
+ *             }
+ *         ]
+ *     };
+ *
+ * # Auto filling of arrays
+ *
+ * The **tpl** tag and the **for** operator are used to process the provided data object:
+ *
+ * - If the value specified in for is an array, it will auto-fill, repeating the template block inside the tpl
+ *   tag for each item in the array.
+ * - If for=&quot;.&quot; is specified, the data object provided is examined.
+ * - While processing an array, the special variable {#} will provide the current array index + 1 (starts at 1, not 0).
+ *
+ * Examples:
+ *
+ *     &lt;tpl for=&quot;.&quot;&gt;...&lt;/tpl&gt;       // loop through array at root node
+ *     &lt;tpl for=&quot;foo&quot;&gt;...&lt;/tpl&gt;     // loop through array at foo node
+ *     &lt;tpl for=&quot;foo.bar&quot;&gt;...&lt;/tpl&gt; // loop through array at foo.bar node
+ *
  * Using the sample data above:
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Kids: ',
-    '&lt;tpl <b>for</b>=".">',       // process the data.kids node
-        '&lt;p>{#}. {name}&lt;/p>',  // use current array index to autonumber
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
- * </code></pre>
- * <p>An example illustrating how the <b><tt>for</tt></b> property can be leveraged
- * to access specified members of the provided data object to populate the template:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Title: {title}&lt;/p>',
-    '&lt;p>Company: {company}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl <b>for="kids"</b>>',     // interrogate the kids property within the data
-        '&lt;p>{name}&lt;/p>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);  // pass the root node of the data object
- * </code></pre>
- * <p>Flat arrays that contain values (and not objects) can be auto-rendered
- * using the special <b><tt>{.}</tt></b> variable inside a loop.  This variable
- * will represent the value of the array at the current index:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>{name}\&#39;s favorite beverages:&lt;/p>',
-    '&lt;tpl for="drinks">',
-       '&lt;div> - {.}&lt;/div>',
-    '&lt;/tpl>'
-);
-tpl.overwrite(panel.body, data);
- * </code></pre>
- * <p>When processing a sub-template, for example while looping through a child array,
- * you can access the parent object's members via the <b><tt>parent</tt></b> object:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="age > 1">',
-            '&lt;p>{name}&lt;/p>',
-            '&lt;p>Dad: {<b>parent</b>.name}&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
- * </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Conditional processing with basic comparison operators</u></b>
- * <div class="sub-desc">
- * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>if</tt></b> operator are used
- * to provide conditional checks for deciding whether or not to render specific
- * parts of the template. Notes:<div class="sub-desc"><ul>
- * <li>Double quotes must be encoded if used within the conditional</li>
- * <li>There is no <tt>else</tt> operator &mdash; if needed, two opposite
- * <tt>if</tt> statements should be used.</li>
- * </ul></div>
- * <pre><code>
-&lt;tpl if="age &gt; 1 &amp;&amp; age &lt; 10">Child&lt;/tpl>
-&lt;tpl if="age >= 10 && age < 18">Teenager&lt;/tpl>
-&lt;tpl <b>if</b>="this.isGirl(name)">...&lt;/tpl>
-&lt;tpl <b>if</b>="id==\'download\'">...&lt;/tpl>
-&lt;tpl <b>if</b>="needsIcon">&lt;img src="{icon}" class="{iconCls}"/>&lt;/tpl>
-// no good:
-&lt;tpl if="name == "Jack"">Hello&lt;/tpl>
-// encode &#34; if it is part of the condition, e.g.
-&lt;tpl if="name == &#38;quot;Jack&#38;quot;">Hello&lt;/tpl>
- * </code></pre>
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;.&quot;&gt;',       // process the data.kids node
+ *             '&lt;p&gt;{#}. {name}&lt;/p&gt;',  // use current array index to autonumber
+ *         '&lt;/tpl&gt;&lt;/p&gt;'
+ *     );
+ *     tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
+ *
+ * An example illustrating how the **for** property can be leveraged to access specified members of the provided data
+ * object to populate the template:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Name: {name}&lt;/p&gt;',
+ *         '&lt;p&gt;Title: {title}&lt;/p&gt;',
+ *         '&lt;p&gt;Company: {company}&lt;/p&gt;',
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;kids&quot;&gt;',     // interrogate the kids property within the data
+ *             '&lt;p&gt;{name}&lt;/p&gt;',
+ *         '&lt;/tpl&gt;&lt;/p&gt;'
+ *     );
+ *     tpl.overwrite(panel.body, data);  // pass the root node of the data object
+ *
+ * Flat arrays that contain values (and not objects) can be auto-rendered using the special **`{.}`** variable inside a
+ * loop. This variable will represent the value of the array at the current index:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;{name}\'s favorite beverages:&lt;/p&gt;',
+ *         '&lt;tpl for=&quot;drinks&quot;&gt;',
+ *             '&lt;div&gt; - {.}&lt;/div&gt;',
+ *         '&lt;/tpl&gt;'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * When processing a sub-template, for example while looping through a child array, you can access the parent object's
+ * members via the **parent** object:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Name: {name}&lt;/p&gt;',
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;kids&quot;&gt;',
+ *             '&lt;tpl if=&quot;age &amp;gt; 1&quot;&gt;',
+ *                 '&lt;p&gt;{name}&lt;/p&gt;',
+ *                 '&lt;p&gt;Dad: {parent.name}&lt;/p&gt;',
+ *             '&lt;/tpl&gt;',
+ *         '&lt;/tpl&gt;&lt;/p&gt;'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Conditional processing with basic comparison operators
+ *
+ * The **tpl** tag and the **if** operator are used to provide conditional checks for deciding whether or not to render
+ * specific parts of the template. Notes:
+ *
+ * - Double quotes must be encoded if used within the conditional
+ * - There is no else operator -- if needed, two opposite if statements should be used.
+ *
+ * Examples:
+ *
+ *     &lt;tpl if=&quot;age &gt; 1 &amp;&amp; age &lt; 10&quot;&gt;Child&lt;/tpl&gt;
+ *     &lt;tpl if=&quot;age &gt;= 10 &amp;&amp; age &lt; 18&quot;&gt;Teenager&lt;/tpl&gt;
+ *     &lt;tpl if=&quot;this.isGirl(name)&quot;&gt;...&lt;/tpl&gt;
+ *     &lt;tpl if=&quot;id==\'download\'&quot;&gt;...&lt;/tpl&gt;
+ *     &lt;tpl if=&quot;needsIcon&quot;&gt;&lt;img src=&quot;{icon}&quot; class=&quot;{iconCls}&quot;/&gt;&lt;/tpl&gt;
+ *     // no good:
+ *     &lt;tpl if=&quot;name == &quot;Tommy&quot;&quot;&gt;Hello&lt;/tpl&gt;
+ *     // encode &quot; if it is part of the condition, e.g.
+ *     &lt;tpl if=&quot;name == &amp;quot;Tommy&amp;quot;&quot;&gt;Hello&lt;/tpl&gt;
+ *
  * Using the sample data above:
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="age > 1">',
-            '&lt;p>{name}&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
- * </code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Basic math support</u></b>
- * <div class="sub-desc">
- * <p>The following basic math operators may be applied directly on numeric
- * data values:</p><pre>
- * + - * /
- * </pre>
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Name: {name}&lt;/p&gt;',
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;kids&quot;&gt;',
+ *             '&lt;tpl if=&quot;age &amp;gt; 1&quot;&gt;',
+ *                 '&lt;p&gt;{name}&lt;/p&gt;',
+ *             '&lt;/tpl&gt;',
+ *         '&lt;/tpl&gt;&lt;/p&gt;'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Basic math support
+ *
+ * The following basic math operators may be applied directly on numeric data values:
+ *
+ *     + - * /
+ *
  * For example:
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="age &amp;gt; 1">',  // <-- Note that the &gt; is encoded
-            '&lt;p>{#}: {name}&lt;/p>',  // <-- Auto-number each item
-            '&lt;p>In 5 Years: {age+5}&lt;/p>',  // <-- Basic math
-            '&lt;p>Dad: {parent.name}&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
-</code></pre>
- * </div>
- * </li>
- *
- *
- * <li><b><u>Execute arbitrary inline code with special built-in template variables</u></b>
- * <div class="sub-desc">
- * <p>Anything between <code>{[ ... ]}</code> is considered code to be executed
- * in the scope of the template. There are some special variables available in that code:
- * <ul>
- * <li><b><tt>values</tt></b>: The values in the current scope. If you are using
- * scope changing sub-templates, you can change what <tt>values</tt> is.</li>
- * <li><b><tt>parent</tt></b>: The scope (values) of the ancestor template.</li>
- * <li><b><tt>xindex</tt></b>: If you are in a looping template, the index of the
- * loop you are in (1-based).</li>
- * <li><b><tt>xcount</tt></b>: If you are in a looping template, the total length
- * of the array you are looping.</li>
- * <li><b><tt>fm</tt></b>: An alias for <tt>Ext.util.Format</tt>.</li>
- * </ul>
- * This example demonstrates basic row striping using an inline code block and the
- * <tt>xindex</tt> variable:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Company: {[values.company.toUpperCase() + ", " + values.title]}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-       '&lt;div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
-        '{name}',
-        '&lt;/div>',
-    '&lt;/tpl>&lt;/p>'
-);
-tpl.overwrite(panel.body, data);
- * </code></pre>
- * </div>
- * </li>
- *
- * <li><b><u>Template member functions</u></b>
- * <div class="sub-desc">
- * <p>One or more member functions can be specified in a configuration
- * object passed into the XTemplate constructor for more complex processing:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
-    '&lt;p>Name: {name}&lt;/p>',
-    '&lt;p>Kids: ',
-    '&lt;tpl for="kids">',
-        '&lt;tpl if="this.isGirl(name)">',
-            '&lt;p>Girl: {name} - {age}&lt;/p>',
-        '&lt;/tpl>',
-        // use opposite if statement to simulate 'else' processing:
-        '&lt;tpl if="this.isGirl(name) == false">',
-            '&lt;p>Boy: {name} - {age}&lt;/p>',
-        '&lt;/tpl>',
-        '&lt;tpl if="this.isBaby(age)">',
-            '&lt;p>{name} is a baby!&lt;/p>',
-        '&lt;/tpl>',
-    '&lt;/tpl>&lt;/p>',
-    {
-        // XTemplate configuration:
-        compiled: true,
-        disableFormats: true,
-        // member functions:
-        isGirl: function(name){
-            return name == 'Sara Grace';
-        },
-        isBaby: function(age){
-            return age < 1;
-        }
-    }
-);
-tpl.overwrite(panel.body, data);
- * </code></pre>
- * </div>
- * </li>
  *
- * </ul></div>
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Name: {name}&lt;/p&gt;',
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;kids&quot;&gt;',
+ *             '&lt;tpl if=&quot;age &amp;gt; 1&quot;&gt;',  // &lt;-- Note that the &gt; is encoded
+ *                 '&lt;p&gt;{#}: {name}&lt;/p&gt;',  // &lt;-- Auto-number each item
+ *                 '&lt;p&gt;In 5 Years: {age+5}&lt;/p&gt;',  // &lt;-- Basic math
+ *                 '&lt;p&gt;Dad: {parent.name}&lt;/p&gt;',
+ *             '&lt;/tpl&gt;',
+ *         '&lt;/tpl&gt;&lt;/p&gt;'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Execute arbitrary inline code with special built-in template variables
+ *
+ * Anything between `{[ ... ]}` is considered code to be executed in the scope of the template. There are some special
+ * variables available in that code:
  *
- * @param {Mixed} config
+ * - **values**: The values in the current scope. If you are using scope changing sub-templates,
+ *   you can change what values is.
+ * - **parent**: The scope (values) of the ancestor template.
+ * - **xindex**: If you are in a looping template, the index of the loop you are in (1-based).
+ * - **xcount**: If you are in a looping template, the total length of the array you are looping.
+ *
+ * This example demonstrates basic row striping using an inline code block and the xindex variable:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Name: {name}&lt;/p&gt;',
+ *         '&lt;p&gt;Company: {[values.company.toUpperCase() + &quot;, &quot; + values.title]}&lt;/p&gt;',
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;kids&quot;&gt;',
+ *             '&lt;div class=&quot;{[xindex % 2 === 0 ? &quot;even&quot; : &quot;odd&quot;]}&quot;&gt;',
+ *             '{name}',
+ *             '&lt;/div&gt;',
+ *         '&lt;/tpl&gt;&lt;/p&gt;'
+ *      );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Template member functions
+ *
+ * One or more member functions can be specified in a configuration object passed into the XTemplate constructor for
+ * more complex processing:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '&lt;p&gt;Name: {name}&lt;/p&gt;',
+ *         '&lt;p&gt;Kids: ',
+ *         '&lt;tpl for=&quot;kids&quot;&gt;',
+ *             '&lt;tpl if=&quot;this.isGirl(name)&quot;&gt;',
+ *                 '&lt;p&gt;Girl: {name} - {age}&lt;/p&gt;',
+ *             '&lt;/tpl&gt;',
+ *              // use opposite if statement to simulate 'else' processing:
+ *             '&lt;tpl if=&quot;this.isGirl(name) == false&quot;&gt;',
+ *                 '&lt;p&gt;Boy: {name} - {age}&lt;/p&gt;',
+ *             '&lt;/tpl&gt;',
+ *             '&lt;tpl if=&quot;this.isBaby(age)&quot;&gt;',
+ *                 '&lt;p&gt;{name} is a baby!&lt;/p&gt;',
+ *             '&lt;/tpl&gt;',
+ *         '&lt;/tpl&gt;&lt;/p&gt;',
+ *         {
+ *             // XTemplate configuration:
+ *             disableFormats: true,
+ *             // member functions:
+ *             isGirl: function(name){
+ *                return name == 'Sara Grace';
+ *             },
+ *             isBaby: function(age){
+ *                return age &lt; 1;
+ *             }
+ *         }
+ *     );
+ *     tpl.overwrite(panel.body, data);
  */
-Ext.XTemplate = function(){
-    Ext.XTemplate.superclass.constructor.apply(this, arguments);
+Ext.define('Ext.XTemplate', {
 
-    var me = this,
-        s = me.html,
-        re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
-        nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
-        ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
-        execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
-        m,
-        id = 0,
-        tpls = [],
-        VALUES = 'values',
-        PARENT = 'parent',
-        XINDEX = 'xindex',
-        XCOUNT = 'xcount',
-        RETURN = 'return ',
-        WITHVALUES = 'with(values){ ';
+    /* Begin Definitions */
 
-    s = ['<tpl>', s, '</tpl>'].join('');
+    extend: 'Ext.Template',
 
-    while((m = s.match(re))){
-        var m2 = m[0].match(nameRe),
-            m3 = m[0].match(ifRe),
-            m4 = m[0].match(execRe),
-            exp = null,
-            fn = null,
-            exec = null,
-            name = m2 && m2[1] ? m2[1] : '';
+    /* End Definitions */
 
-       if (m3) {
-           exp = m3 && m3[1] ? m3[1] : null;
-           if(exp){
-               fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
-           }
-       }
-       if (m4) {
-           exp = m4 && m4[1] ? m4[1] : null;
-           if(exp){
-               exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
-           }
-       }
-       if(name){
-           switch(name){
-               case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
-               case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
-               default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
-           }
-       }
-       tpls.push({
-            id: id,
-            target: name,
-            exec: exec,
-            test: fn,
-            body: m[1]||''
-        });
-       s = s.replace(m[0], '{xtpl'+ id + '}');
-       ++id;
-    }
-    for(var i = tpls.length-1; i >= 0; --i){
-        me.compileTpl(tpls[i]);
-    }
-    me.master = tpls[tpls.length-1];
-    me.tpls = tpls;
-};
-Ext.extend(Ext.XTemplate, Ext.Template, {
-    // private
-    re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
-    // private
-    codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
+    argsRe: /&lt;tpl\b[^&gt;]*&gt;((?:(?=([^&lt;]+))\2|&lt;(?!tpl\b[^&gt;]*&gt;))*?)&lt;\/tpl&gt;/,
+    nameRe: /^&lt;tpl\b[^&gt;]*?for=&quot;(.*?)&quot;/,
+    ifRe: /^&lt;tpl\b[^&gt;]*?if=&quot;(.*?)&quot;/,
+    execRe: /^&lt;tpl\b[^&gt;]*?exec=&quot;(.*?)&quot;/,
+    constructor: function() {
+        this.callParent(arguments);
 
-    // private
-    applySubTemplate : function(id, values, parent, xindex, xcount){
         var me = this,
-            len,
-            t = me.tpls[id],
-            vs,
-            buf = [];
-        if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
-            (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
-            return '';
-        }
-        vs = t.target ? t.target.call(me, values, parent) : values;
-        len = vs.length;
-        parent = t.target ? values : parent;
-        if(t.target && Ext.isArray(vs)){
-            for(var i = 0, len = vs.length; i < len; i++){
-                buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
+            html = me.html,
+            argsRe = me.argsRe,
+            nameRe = me.nameRe,
+            ifRe = me.ifRe,
+            execRe = me.execRe,
+            id = 0,
+            tpls = [],
+            VALUES = 'values',
+            PARENT = 'parent',
+            XINDEX = 'xindex',
+            XCOUNT = 'xcount',
+            RETURN = 'return ',
+            WITHVALUES = 'with(values){ ',
+            m, matchName, matchIf, matchExec, exp, fn, exec, name, i;
+
+        html = ['&lt;tpl&gt;', html, '&lt;/tpl&gt;'].join('');
+
+        while ((m = html.match(argsRe))) {
+            exp = null;
+            fn = null;
+            exec = null;
+            matchName = m[0].match(nameRe);
+            matchIf = m[0].match(ifRe);
+            matchExec = m[0].match(execRe);
+
+            exp = matchIf ? matchIf[1] : null;
+            if (exp) {
+                fn = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + Ext.String.htmlDecode(exp) + ';}catch(e){return;}}');
             }
-            return buf.join('');
+
+            exp = matchExec ? matchExec[1] : null;
+            if (exp) {
+                exec = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.String.htmlDecode(exp) + ';}');
+            }
+
+            name = matchName ? matchName[1] : null;
+            if (name) {
+                if (name === '.') {
+                    name = VALUES;
+                } else if (name === '..') {
+                    name = PARENT;
+                }
+                name = Ext.functionFactory(VALUES, PARENT, 'try{' + WITHVALUES + RETURN + name + ';}}catch(e){return;}');
+            }
+
+            tpls.push({
+                id: id,
+                target: name,
+                exec: exec,
+                test: fn,
+                body: m[1] || ''
+            });
+
+            html = html.replace(m[0], '{xtpl' + id + '}');
+            id = id + 1;
         }
-        return t.compiled.call(me, vs, parent, xindex, xcount);
+
+        for (i = tpls.length - 1; i &gt;= 0; --i) {
+            me.compileTpl(tpls[i]);
+        }
+        me.master = tpls[tpls.length - 1];
+        me.tpls = tpls;
+    },
+
+    // @private
+    applySubTemplate: function(id, values, parent, xindex, xcount) {
+        var me = this, t = me.tpls[id];
+        return t.compiled.call(me, values, parent, xindex, xcount);
     },
 
-    // private
-    compileTpl : function(tpl){
+<span id='Ext-XTemplate-cfg-codeRe'>    /**
+</span>     * @cfg {RegExp} codeRe
+     * The regular expression used to match code variables. Default: matches {[expression]}.
+     */
+    codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
+
+<span id='Ext-XTemplate-cfg-compiled'>    /**
+</span>     * @cfg {Boolean} compiled
+     * Only applies to {@link Ext.Template}, XTemplates are compiled automatically.
+     */
+
+    re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
+
+    // @private
+    compileTpl: function(tpl) {
         var fm = Ext.util.Format,
-            useF = this.disableFormats !== true,
-            sep = Ext.isGecko ? "+" : ",",
-            body;
+            me = this,
+            useFormat = me.disableFormats !== true,
+            body, bodyReturn, evaluatedFn;
 
-        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+"'";
-            }
+        function fn(m, name, format, args, math) {
             var v;
-            if(name === '.'){
-                v = 'values';
-            }else if(name === '#'){
+            // name is what is inside the {}
+            // Name begins with xtpl, use a Sub Template
+            if (name.substr(0, 4) == 'xtpl') {
+                return &quot;',this.applySubTemplate(&quot; + name.substr(4) + &quot;, values, parent, xindex, xcount),'&quot;;
+            }
+            // name = &quot;.&quot; - Just use the values object.
+            if (name == '.') {
+                // filter to not include arrays/objects/nulls
+                v = 'Ext.Array.indexOf([&quot;string&quot;, &quot;number&quot;, &quot;boolean&quot;], typeof values) &gt; -1 || Ext.isDate(values) ? values : &quot;&quot;';
+            }
+
+            // name = &quot;#&quot; - Use the xindex
+            else if (name == '#') {
                 v = 'xindex';
-            }else if(name.indexOf('.') != -1){
+            }
+            else if (name.substr(0, 7) == &quot;parent.&quot;) {
                 v = name;
-            }else{
-                v = "values['" + name + "']";
             }
-            if(math){
+            // name has a . in it - Use object literal notation, starting from values
+            else if (name.indexOf('.') != -1) {
+                v = &quot;values.&quot; + name;
+            }
+
+            // name is a property of values
+            else {
+                v = &quot;values['&quot; + name + &quot;']&quot;;
+            }
+            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";
+            if (format &amp;&amp; useFormat) {
+                args = args ? ',' + args : &quot;&quot;;
+                if (format.substr(0, 5) != &quot;this.&quot;) {
+                    format = &quot;fm.&quot; + format + '(';
+                }
+                else {
+                    format = 'this.' + format.substr(5) + '(';
                 }
-            } else {
-                args= ''; format = "("+v+" === undefined ? '' : ";
             }
-            return "'"+ sep + format + v + args + ")"+sep+"'";
+            else {
+                args = '';
+                format = &quot;(&quot; + v + &quot; === undefined ? '' : &quot;;
+            }
+            return &quot;',&quot; + format + v + args + &quot;),'&quot;;
         }
 
-        function codeFn(m, code){
+        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 + "'";
+            return &quot;',(&quot; + code.replace(me.compileARe, &quot;'&quot;) + &quot;),'&quot;;
         }
 
-        // 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('');
-        }
+        bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, &quot;\\'&quot;).replace(me.re, fn).replace(me.codeRe, codeFn);
+        body = &quot;evaluatedFn = function(values, parent, xindex, xcount){return ['&quot; + bodyReturn + &quot;'].join('');};&quot;;
         eval(body);
+
+        tpl.compiled = function(values, parent, xindex, xcount) {
+            var vs,
+                length,
+                buffer,
+                i;
+
+            if (tpl.test &amp;&amp; !tpl.test.call(me, values, parent, xindex, xcount)) {
+                return '';
+            }
+
+            vs = tpl.target ? tpl.target.call(me, values, parent) : values;
+            if (!vs) {
+               return '';
+            }
+
+            parent = tpl.target ? values : parent;
+            if (tpl.target &amp;&amp; Ext.isArray(vs)) {
+                buffer = [];
+                length = vs.length;
+                if (tpl.exec) {
+                    for (i = 0; i &lt; length; i++) {
+                        buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
+                        tpl.exec.call(me, vs[i], parent, i + 1, length);
+                    }
+                } else {
+                    for (i = 0; i &lt; length; i++) {
+                        buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
+                    }
+                }
+                return buffer.join('');
+            }
+
+            if (tpl.exec) {
+                tpl.exec.call(me, vs, parent, xindex, xcount);
+            }
+            return evaluatedFn.call(me, vs, parent, xindex, xcount);
+        };
+
         return this;
     },
 
-    <div id="method-Ext.XTemplate-applyTemplate"></div>/**
-     * Returns an HTML fragment of this template with the specified values applied.
-     * @param {Object} 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
-     */
-    applyTemplate : function(values){
+    // inherit docs from Ext.Template
+    applyTemplate: function(values) {
         return this.master.compiled.call(this, values, {}, 1, 1);
     },
 
-    <div id="method-Ext.XTemplate-compile"></div>/**
-     * Compile the template to a function for optimized performance.  Recommended if the template will be used frequently.
-     * @return {Function} The compiled function
-     */
-    compile : function(){return this;}
-
-    <div id="prop-Ext.XTemplate-re"></div>/**
-     * @property re
-     * @hide
-     */
-    <div id="prop-Ext.XTemplate-disableFormats"></div>/**
-     * @property disableFormats
-     * @hide
-     */
-    <div id="method-Ext.XTemplate-set"></div>/**
-     * @method set
-     * @hide
+<span id='Ext-XTemplate-method-compile'>    /**
+</span>     * Does nothing. XTemplates are compiled automatically, so this function simply returns this.
+     * @return {Ext.XTemplate} this
      */
-
+    compile: function() {
+        return this;
+    }
+}, function() {
+    // re-create the alias, inheriting it from Ext.Template doesn't work as intended.
+    this.createAlias('apply', 'applyTemplate');
 });
-<div id="method-Ext.XTemplate-apply"></div>/**
- * Alias for {@link #applyTemplate}
- * 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
- * @member Ext.XTemplate
- * @method apply
- */
-Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
-
-<div id="method-Ext.XTemplate-XTemplate.from"></div>/**
- * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
- * @param {String/HTMLElement} el A DOM element or its id
- * @return {Ext.Template} The created template
- * @static
- */
-Ext.XTemplate.from = function(el){
-    el = Ext.getDom(el);
-    return new Ext.XTemplate(el.value || el.innerHTML);
-};
-</pre>    
+</pre>
 </body>
-</html>
\ No newline at end of file
+</html>