Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / docs / source / XTemplate.html
index ba21355..41d600a 100644 (file)
@@ -1,19 +1,52 @@
-<html>\r
-<head>\r
-  <title>The source code</title>\r
-    <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
-    <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
-</head>\r
-<body  onload="prettyPrint();">\r
-    <pre class="prettyprint lang-js"><div id="cls-Ext.XTemplate"></div>/**
+<html>
+<head>
+  <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>
+</head>
+<body  onload="prettyPrint();">
+    <pre class="prettyprint lang-js">/*!
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.com/license
+ */
+<div id="cls-Ext.XTemplate"></div>/**
  * @class Ext.XTemplate
  * @extends Ext.Template
  * @class Ext.XTemplate
  * @extends Ext.Template
- * <p>A template class that supports advanced functionality like autofilling arrays, conditional processing with
- * basic comparison operators, sub-templates, basic math function support, special built-in template variables,
- * inline code execution and more.  XTemplate also provides the templating mechanism built into {@link Ext.DataView}.</p>
- * <p>XTemplate supports 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.  The following examples demonstrate all of the supported features.
- * This is the data object used for reference in each code example:</p>
+ * <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',
  * <pre><code>
 var data = {
     name: 'Jack Slocum',
@@ -37,104 +70,161 @@ var data = {
     }]
 };
  * </code></pre>
     }]
 };
  * </code></pre>
- * <p><b>Auto filling of arrays</b><br/>The <tt>tpl</tt> tag and the <tt>for</tt> operator are used
- * to process the provided data object. If <tt>for="."</tt> is specified, the data object provided
- * is examined. If the variable 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:</p>
+ * </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>
+ * Using the sample data above:
  * <pre><code>
 var tpl = new Ext.XTemplate(
     '&lt;p>Kids: ',
  * <pre><code>
 var tpl = new Ext.XTemplate(
     '&lt;p>Kids: ',
-    '&lt;tpl for=".">',
-        '&lt;p>{name}&lt;/p>',
+    '&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>
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
  * </code></pre>
- * <p><b>Scope switching</b><br/>The <tt>for</tt> property can be leveraged to access specified members
- * of the provided data object to populate the template:</p>
+ * <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: ',
  * <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;tpl <b>for="kids"</b>>',     // interrogate the kids property within the data
         '&lt;p>{name}&lt;/p>',
     '&lt;/tpl>&lt;/p>'
 );
         '&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>
 tpl.overwrite(panel.body, data);
  * </code></pre>
- * <p><b>Access to parent object from within sub-template scope</b><br/>When processing a sub-template, for example while
- * looping through a child array, you can access the parent object's members via the <tt>parent</tt> object:</p>
+ * <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">',
  * <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;tpl if="age > 1">',
             '&lt;p>{name}&lt;/p>',
             '&lt;p>{name}&lt;/p>',
-            '&lt;p>Dad: {parent.name}&lt;/p>',
+            '&lt;p>Dad: {<b>parent</b>.name}&lt;/p>',
         '&lt;/tpl>',
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
         '&lt;/tpl>',
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Array item index and basic math support</b> <br/>While processing an array, the special variable <tt>{#}</tt>
- * will provide the current array index + 1 (starts at 1, not 0). Templates also support the basic math operators
- * + - * and / that can be applied directly on numeric data values:</p>
+ * </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>
+ * 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">',
  * <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 if="age > 1">',
+            '&lt;p>{name}&lt;/p>',
         '&lt;/tpl>',
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
         '&lt;/tpl>',
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Auto-rendering of flat arrays</b> <br/>Flat arrays that contain values (and not objects) can be auto-rendered
- * using the special <tt>{.}</tt> 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}\'s favorite beverages:&lt;/p>',
-    '&lt;tpl for="drinks">',
-       '&lt;div> - {.}&lt;/div>',
-    '&lt;/tpl>'
-);
-tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Basic conditional logic</b> <br/>Using the <tt>tpl</tt> tag and the <tt>if</tt>
- * operator you can provide conditional checks for deciding whether or not to render specific parts of the template.
- * Note that there is no <tt>else</tt> operator &mdash; if needed, you should use two opposite <tt>if</tt> statements.
- * Properly-encoded attributes are required as seen in the following example:</p>
+ * </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>
+ * 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
  * <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>',
+            '&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>
         '&lt;/tpl>',
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
 </code></pre>
- * <p><b>Ability to execute arbitrary inline code</b> <br/>In an XTemplate, anything between {[ ... ]}  is considered
- * code to be executed in the scope of the template. There are some special variables available in that code:
+ * </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>
  * <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>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>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>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>
  * <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>
+ * 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>',
  * <pre><code>
 var tpl = new Ext.XTemplate(
     '&lt;p>Name: {name}&lt;/p>',
@@ -147,8 +237,13 @@ var tpl = new Ext.XTemplate(
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
     '&lt;/tpl>&lt;/p>'
 );
 tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Template member functions</b> <br/>One or more member functions can be defined directly on the config
+ * </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(
  * object passed into the XTemplate constructor for more complex processing:</p>
  * <pre><code>
 var tpl = new Ext.XTemplate(
@@ -158,55 +253,65 @@ var tpl = new Ext.XTemplate(
         '&lt;tpl if="this.isGirl(name)">',
             '&lt;p>Girl: {name} - {age}&lt;/p>',
         '&lt;/tpl>',
         '&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 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>', {
-     isGirl: function(name){
-         return name == 'Sara Grace';
-     },
-     isBaby: function(age){
-        return age < 1;
-     }
-});
+    '&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);
 tpl.overwrite(panel.body, data);
-</code></pre>
- * @constructor
- * @param {String/Array/Object} parts The HTML fragment or an array of fragments to join(""), or multiple arguments
- * to join("") that can also include a config object
+ * </code></pre>
+ * </div>
+ * </li>
+ *
+ * </ul></div>
+ *
+ * @param {Mixed} config
  */
 Ext.XTemplate = function(){
     Ext.XTemplate.superclass.constructor.apply(this, arguments);
 
     var me = this,
  */
 Ext.XTemplate = function(){
     Ext.XTemplate.superclass.constructor.apply(this, arguments);
 
     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){ ';
+        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){ ';
 
     s = ['<tpl>', s, '</tpl>'].join('');
 
     while((m = s.match(re))){
 
     s = ['<tpl>', s, '</tpl>'].join('');
 
     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] : '';
+        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] : '';
 
        if (m3) {
            exp = m3 && m3[1] ? m3[1] : null;
 
        if (m3) {
            exp = m3 && m3[1] ? m3[1] : null;
@@ -237,9 +342,9 @@ Ext.XTemplate = function(){
        s = s.replace(m[0], '{xtpl'+ id + '}');
        ++id;
     }
        s = s.replace(m[0], '{xtpl'+ id + '}');
        ++id;
     }
-       Ext.each(tpls, function(t) {
-        me.compileTpl(t);
-    });
+    for(var i = tpls.length-1; i >= 0; --i){
+        me.compileTpl(tpls[i]);
+    }
     me.master = tpls[tpls.length-1];
     me.tpls = tpls;
 };
     me.master = tpls[tpls.length-1];
     me.tpls = tpls;
 };
@@ -252,10 +357,10 @@ Ext.extend(Ext.XTemplate, Ext.Template, {
     // private
     applySubTemplate : function(id, values, parent, xindex, xcount){
         var me = this,
     // private
     applySubTemplate : function(id, values, parent, xindex, xcount){
         var me = this,
-               len,
-               t = me.tpls[id],
-               vs,
-               buf = [];
+            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 '';
         if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
             (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
             return '';
@@ -264,9 +369,9 @@ Ext.extend(Ext.XTemplate, Ext.Template, {
         len = vs.length;
         parent = t.target ? values : parent;
         if(t.target && Ext.isArray(vs)){
         len = vs.length;
         parent = t.target ? values : parent;
         if(t.target && Ext.isArray(vs)){
-               Ext.each(vs, function(v, i) {
-                buf[buf.length] = t.compiled.call(me, v, parent, i+1, len);
-            });
+            for(var i = 0, len = vs.length; i < len; i++){
+                buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
+            }
             return buf.join('');
         }
         return t.compiled.call(me, vs, parent, xindex, xcount);
             return buf.join('');
         }
         return t.compiled.call(me, vs, parent, xindex, xcount);
@@ -275,7 +380,7 @@ Ext.extend(Ext.XTemplate, Ext.Template, {
     // private
     compileTpl : function(tpl){
         var fm = Ext.util.Format,
     // private
     compileTpl : function(tpl){
         var fm = Ext.util.Format,
-                       useF = this.disableFormats !== true,
+            useF = this.disableFormats !== true,
             sep = Ext.isGecko ? "+" : ",",
             body;
 
             sep = Ext.isGecko ? "+" : ",",
             body;
 
@@ -311,7 +416,8 @@ Ext.extend(Ext.XTemplate, Ext.Template, {
         }
 
         function codeFn(m, code){
         }
 
         function codeFn(m, code){
-            return "'"+ sep +'('+code+')'+sep+"'";
+            // 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
         }
 
         // branched to use + in gecko and [].join() in others
@@ -377,6 +483,7 @@ Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
 Ext.XTemplate.from = function(el){
     el = Ext.getDom(el);
     return new Ext.XTemplate(el.value || el.innerHTML);
 Ext.XTemplate.from = function(el){
     el = Ext.getDom(el);
     return new Ext.XTemplate(el.value || el.innerHTML);
-};</pre>    \r
-</body>\r
+};
+</pre>    
+</body>
 </html>
\ No newline at end of file
 </html>
\ No newline at end of file