try and get ctrl-enter to add a clear all
[roojs1] / Roo / DomTemplate.js
index 4d04916..3ffe060 100644 (file)
 </code></pre>
  *  The tpl tag:
 <pre><code>
-        &lt;div roo-for="a_variable or condition.."&gt;&lt;/tpl&gt;
-        &lt;tpl roo-if="a_variable or condition"&gt;&lt;/tpl&gt;
-        &lt;tpl roo-exec="some javascript"&gt;&lt;/tpl&gt;
-        &lt;tpl roo-name="named_template"&gt;&lt;/tpl&gt; 
+        &lt;div roo-for="a_variable or condition.."&gt;&lt;/div&gt;
+        &lt;div roo-if="a_variable or condition"&gt;&lt;/div&gt;
+        &lt;div roo-exec="some javascript"&gt;&lt;/div&gt;
+        &lt;div roo-name="named_template"&gt;&lt;/div&gt; 
   
 </code></pre>
  *      
 Roo.DomTemplate = function()
 {
      Roo.DomTemplate.superclass.constructor.apply(this, arguments);
-    if (this.html) {
+     if (this.html) {
         this.compile();
-    }
+     }
 };
 
 
 Roo.extend(Roo.DomTemplate, Roo.Template, {
-
+    /**
+     * id counter for sub templates.
+     */
     id : 0,
+    /**
+     * flag to indicate if dom parser is inside a pre,
+     * it will strip whitespace if not.
+     */
+    inPre : false,
     
     /**
      * The various sub templates
      */
     tpls : false,
+    
+    
+    
     /**
      *
      * basic tag replacing syntax
@@ -61,15 +71,23 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
      *  x.t:(test,tesT) 
      * 
      */
-    re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
-
+    re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
+    //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
     
     iterChild : function (node, method) {
+        
+        var oldPre = this.inPre;
+        if (node.tagName == 'PRE') {
+            this.inPre = true;
+        }
         for( var i = 0; i < node.childNodes.length; i++) {
             method.call(this, node.childNodes[i]);
         }
+        this.inPre = oldPre;
     },
     
+    
+    
     /**
      * compile the template
      *
@@ -81,16 +99,47 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
         var s = this.html;
         
         // covert the html into DOM...
+        var doc = false;
+        var div =false;
+        try {
+            doc = document.implementation.createHTMLDocument("");
+            doc.documentElement.innerHTML =   this.html  ;
+            div = doc.documentElement;
+        } catch (e) {
+            // old IE... - nasty -- it causes all sorts of issues.. with
+            // images getting pulled from server..
+            div = document.createElement('div');
+            div.innerHTML = this.html;
+        }
+        //doc.documentElement.innerHTML = htmlBody
+         
         
-        var div = document.createElement('div');
-        div.innerHTML = '<div>' + this.html + '</div>';
         
         this.tpls = [];
         var _t = this;
         this.iterChild(div, function(n) {_t.compileNode(n, true); });
         
         var tpls = this.tpls;
-        Roo.log(div);
+        
+        // create a top level template from the snippet..
+        
+        //Roo.log(div.innerHTML);
+        
+        var tpl = {
+            uid : 'master',
+            id : this.id++,
+            attr : false,
+            value : false,
+            body : div.innerHTML,
+            
+            forCall : false,
+            execCall : false,
+            dom : div,
+            isTop : true
+            
+        };
+        tpls.unshift(tpl);
+        
         
         // compile them...
         this.tpls = [];
@@ -109,8 +158,14 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
         // test for
         //Roo.log(node);
         
+        
         // skip anything not a tag..
         if (node.nodeType != 1) {
+            if (node.nodeType == 3 && !this.inPre) {
+                // reduce white space..
+                node.nodeValue = node.nodeValue.replace(/\s+/g, ' '); 
+                
+            }
             return;
         }
         
@@ -128,35 +183,47 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
             
             
         };
+        
+        
         switch(true) {
             case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
             case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
-            case (node.hasAttribute('roo-if')): tpl.attr = 'name'; break;
+            case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
             case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
             // no default..
         }
+        
+        
         if (!tpl.attr) {
             // just itterate children..
-            this.iterChild(node,this.compileNode)
+            this.iterChild(node,this.compileNode);
             return;
         }
         tpl.uid = this.id++;
-        var value = node.getAttribute('roo-' +  tpl.attr);
+        tpl.value = node.getAttribute('roo-' +  tpl.attr);
         node.removeAttribute('roo-'+ tpl.attr);
         if (tpl.attr != 'name') {
             var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
             node.parentNode.replaceChild(placeholder,  node);
         } else {
-            node.parentNode.removeChild(node);
+            
+            var placeholder =  document.createElement('span');
+            placeholder.className = 'roo-tpl-' + tpl.value;
+            node.parentNode.replaceChild(placeholder,  node);
         }
         
         // parent now sees '{domtplXXXX}
-        this.iterChild(node,this.compileNode)
+        this.iterChild(node,this.compileNode);
         
         // we should now have node body...
         var div = document.createElement('div');
         div.appendChild(node);
         tpl.dom = node;
+        // this has the unfortunate side effect of converting tagged attributes
+        // eg. href="{...}" into %7C...%7D
+        // this has been fixed by searching for those combo's although it's a bit hacky..
+        
+        
         tpl.body = div.innerHTML;
         
         
@@ -180,7 +247,7 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
                 break;
             
             case 'name':
-                tpl.id  = value; // replace non characters???
+                tpl.id  = tpl.value; // replace non characters???
                 break;
             
         }
@@ -192,156 +259,47 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
         
     },
     
-    oldwrapper : function ()
-    { 
-        s = ['<tpl>', s, '</tpl>'].join('');
     
-        var re     = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
-            nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
-            ifRe   = /^<tpl\b[^>]*?if="(.*?)"/,
-            execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
-            namedRe = /^<tpl\b[^>]*?name="(\w+)"/,  // named templates..
-            m,
-            id     = 0,
-            tpls   = [];
     
-        while(true == !!(m = s.match(re))){
-            var forMatch   = m[0].match(nameRe),
-                ifMatch   = m[0].match(ifRe),
-                execMatch   = m[0].match(execRe),
-                namedMatch   = m[0].match(namedRe),
-                
-                exp  = null, 
-                fn   = null,
-                exec = null,
-                name = forMatch && forMatch[1] ? forMatch[1] : '';
-                
-            if (ifMatch) {
-                // if - puts fn into test..
-                exp = ifMatch && ifMatch[1] ? ifMatch[1] : null;
-                if(exp){
-                   fn = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(exp))+'; }');
-                }
-            }
-            
-            if (execMatch) {
-                // exec - calls a function... returns empty if true is  returned.
-                exp = execMatch && execMatch[1] ? execMatch[1] : null;
-                if(exp){
-                   exec = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(exp))+'; }');
-                }
-            }
-            
-            
-            if (name) {
-                // for = 
-                switch(name){
-                    case '.':  name = new Function('values', 'parent', 'with(values){ return values; }'); break;
-                    case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break;
-                    default:   name = new Function('values', 'parent', 'with(values){ return '+name+'; }');
-                }
-            }
-            var uid = namedMatch ? namedMatch[1] : id;
-            
-            
-            tpls.push({
-                id:     namedMatch ? namedMatch[1] : id,
-                target: name,
-                exec:   exec,
-                test:   fn,
-                body:   m[1] || ''
-            });
-            if (namedMatch) {
-                s = s.replace(m[0], '');
-            } else { 
-                s = s.replace(m[0], '{xtpl'+ id + '}');
-            }
-            ++id;
-        }
-        
-    },
+    
     /**
-     * same as applyTemplate, except it's done to one of the subTemplates
-     * when using named templates, you can do:
-     *
-     * var str = pl.applySubTemplate('your-name', values);
+     * Compile a segment of the template into a 'sub-template'
      *
      * 
-     * @param {Number} id of the template
-     * @param {Object} values to apply to template
-     * @param {Object} parent (normaly the instance of this object)
+     * 
+     *
      */
-    applySubTemplate : function(id, values, parent)
-    {
-        
-        
-        var t = this.tpls[id];
-        
-        
-        try { 
-            if(t.ifCall && !t.ifCall.call(this, values, parent)){
-                return '';
-            }
-        } catch(e) {
-            Roo.log("Xtemplate.applySubTemplate 'test': Exception thrown");
-            Roo.log(e.toString());
-            Roo.log(t.ifCall);
-            return ''
-        }
-        try { 
-            
-            if(t.execCall && t.execCall.call(this, values, parent)){
-                return '';
-            }
-        } catch(e) {
-            Roo.log("Xtemplate.applySubTemplate 'exec': Exception thrown");
-            Roo.log(e.toString());
-            Roo.log(t.execCall);
-            return ''
-        }
-        try {
-            var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
-            parent = t.target ? values : parent;
-            if(t.forCall && vs instanceof Array){
-                var buf = [];
-                for(var i = 0, len = vs.length; i < len; i++){
-                    buf[buf.length] = t.compiled.call(this, vs[i], parent);
-                }
-                return buf.join('');
-            }
-            return t.compiled.call(this, vs, parent);
-        } catch (e) {
-            Roo.log("Xtemplate.applySubTemplate : Exception thrown");
-            Roo.log(e.toString());
-            Roo.log(t.compiled);
-            return '';
-        }
-    },
-
     compileTpl : function(tpl)
     {
         var fm = Roo.util.Format;
         var useF = this.disableFormats !== true;
+        
         var sep = Roo.isGecko ? "+\n" : ",\n";
+        
         var undef = function(str) {
-            Roo.log("Property not found :"  + str);
+            Roo.debug && Roo.log("Property not found :"  + str);
             return '';
         };
+          
+        //Roo.log(tpl.body);
         
-        var fn = function(m, name, format, args)
+        
+        
+        var fn = function(m, lbrace, name, format, args)
         {
+            //Roo.log("ARGS");
             //Roo.log(arguments);
             args = args ? args.replace(/\\'/g,"'") : args;
             //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
             if (typeof(format) == 'undefined') {
-                format= 'htmlEncode';
+                format =  'htmlEncode'; 
             }
             if (format == 'raw' ) {
                 format = false;
             }
             
             if(name.substr(0, 6) == 'domtpl'){
-                return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent)'+sep+"'";
+                return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
             }
             
             // build an array of options to determine if value is undefined..
@@ -375,7 +333,7 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
                 return "'"+ sep +   udef_st   +    format + name + args + "))"+sep+"'";
             }
              
-            if (args.length) {
+            if (args && args.length) {
                 // called with xxyx.yuu:(test,test)
                 // change to ()
                 return "'"+ sep + udef_st  + name + '(' +  args + "))"+sep+"'";
@@ -405,6 +363,81 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
         
         return this;
     },
+     
+    /**
+     * same as applyTemplate, except it's done to one of the subTemplates
+     * when using named templates, you can do:
+     *
+     * var str = pl.applySubTemplate('your-name', values);
+     *
+     * 
+     * @param {Number} id of the template
+     * @param {Object} values to apply to template
+     * @param {Object} parent (normaly the instance of this object)
+     */
+    applySubTemplate : function(id, values, parent)
+    {
+        
+        
+        var t = this.tpls[id];
+        
+        
+        try { 
+            if(t.ifCall && !t.ifCall.call(this, values, parent)){
+                Roo.debug && Roo.log('if call on ' + t.value + ' return false');
+                return '';
+            }
+        } catch(e) {
+            Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
+            Roo.log(values);
+          
+            return '';
+        }
+        try { 
+            
+            if(t.execCall && t.execCall.call(this, values, parent)){
+                return '';
+            }
+        } catch(e) {
+            Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
+            Roo.log(values);
+            return '';
+        }
+        
+        try {
+            var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
+            parent = t.target ? values : parent;
+            if(t.forCall && vs instanceof Array){
+                var buf = [];
+                for(var i = 0, len = vs.length; i < len; i++){
+                    try {
+                        buf[buf.length] = t.compiled.call(this, vs[i], parent);
+                    } catch (e) {
+                        Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
+                        Roo.log(e.body);
+                        //Roo.log(t.compiled);
+                        Roo.log(vs[i]);
+                    }   
+                }
+                return buf.join('');
+            }
+        } catch (e) {
+            Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
+            Roo.log(values);
+            return '';
+        }
+        try {
+            return t.compiled.call(this, vs, parent);
+        } catch (e) {
+            Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
+            Roo.log(e.body);
+            //Roo.log(t.compiled);
+            Roo.log(values);
+            return '';
+        }
+    },
+
+   
 
     applyTemplate : function(values){
         return this.master.compiled.call(this, values, {});
@@ -417,7 +450,7 @@ Roo.extend(Roo.DomTemplate, Roo.Template, {
 
  });
 
-Roo.XTemplate.from = function(el){
+Roo.DomTemplate.from = function(el){
     el = Roo.getDom(el);
-    return new Roo.XTemplate(el.value || el.innerHTML);
+    return new Roo.Domtemplate(el.value || el.innerHTML);
 };
\ No newline at end of file