roojs-core.js
[roojs1] / roojs-core-debug.js
index 63723c3..2103cba 100644 (file)
@@ -120,7 +120,127 @@ Roo.apply = function(o, c, defaults){
         BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
 
         emptyFn : function(){},
+        /**
+         *   Deep object/array copy. Function clones are actually wrappers around the
+         *   original function. Array-like objects are treated as arrays. Primitives are
+         *   returned untouched. Optionally, a function can be provided to handle other data
+         *   types, filter keys, validate values, etc.
+         *
+         *   **Note:** Cloning a non-trivial object is a reasonably heavy operation, due to
+         *   the need to recursively iterate down non-primitive properties. Clone should be
+         *   used only when a deep clone down to leaf level properties is explicitly
+         *   required. This method will also
+         *
+            In many cases (for example, when trying to isolate objects used as hashes for
+            configuration properties), a shallow copy, using `Y.merge()` is normally
+            sufficient. If more than one level of isolation is required, `Y.merge()` can be
+            used selectively at each level which needs to be isolated from the original
+            without going all the way to leaf properties.
+
+            @method clone
+            @param {object} o what to clone.
+            @param {boolean} safe if true, objects will not have prototype items from the
+                source. If false, they will. In this case, the original is initially
+                protected, but the clone is not completely immune from changes to the source
+                object prototype. Also, cloned prototype items that are deleted from the
+                clone will result in the value of the source prototype being exposed. If
+                operating on a non-safe clone, items should be nulled out rather than
+                deleted.
+            @param {function} f optional function to apply to each item in a collection; it
+                will be executed prior to applying the value to the new object.
+                Return false to prevent the copy.
+            @param {object} c optional execution context for f.
+            @param {object} owner Owner object passed when clone is iterating an object.
+                Used to set up context for cloned functions.
+            @param {object} cloned hash of previously cloned objects to avoid multiple
+                clones.
+            @return {Array|Object} the cloned object.
+          **/
+        clone : function(o, safe, f, c, owner, cloned) {
+            var o2, marked, stamp;
+
+            // Does not attempt to clone:
+            //
+            // * Non-typeof-object values, "primitive" values don't need cloning.
+            //
+            // * YUI instances, cloning complex object like YUI instances is not
+            //   advised, this is like cloning the world.
+            //
+            // * DOM nodes (#2528250), common host objects like DOM nodes cannot be
+            //   "subclassed" in Firefox and old versions of IE. Trying to use
+            //   `Object.create()` or `Y.extend()` on a DOM node will throw an error in
+            //   these browsers.
+            //
+            // Instad, the passed-in `o` will be return as-is when it matches one of the
+            // above criteria.
+//            if (!L.isObject(o) ||
+//                    Y.instanceOf(o, YUI) ||
+//                    (o.addEventListener || o.attachEvent)) {
+//
+//                return o;
+//            }
+
+            marked = cloned || {};
+
+            switch (this.type(o)) {
+                case 'date':
+                    return new Date(o);
+                case 'regexp':
+                    // if we do this we need to set the flags too
+                    // return new RegExp(o.source);
+                    return o;
+                case 'function':
+                    // o2 = Y.bind(o, owner);
+                    // break;
+                    return o;
+                case 'array':
+                    o2 = [];
+                    break;
+                default:
+                    
+                    // #2528250 only one clone of a given object should be created.
+                    if (o['_~roo~_']) {
+                        return marked[o['_~roo~_']];
+                    }
+
+                    stamp = Roo.id();
+
+                    o2 = (safe) ? {} : Roo.Object(o);
+
+                    o['_~roo~_'] = stamp;
+                    marked[stamp] = o;
+            }
+
+            Roo.each(o, function(v, k) {
+                if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
+                    if (k !== '_~roo~_') {
+                        if (k == 'prototype') {
+                            // skip the prototype
+                        // } else if (o[k] === o) {
+                        //     this[k] = this;
+                        } else {
+                            this[k] =
+                                Roo.clone(v, safe, f, c, owner || o, marked);
+                        }
+                    }
+                }
+            }, o2);
 
+            if (!cloned) {
+                Roo.Object.each(marked, function(v, k) {
+                    if (v['_~roo~_']) {
+                        try {
+                            delete v['_~roo~_'];
+                        } catch (e) {
+                            v['_~roo~_'] = null;
+                        }
+                    }
+                }, this);
+                marked = null;
+            }
+
+            return o2;
+        },
         /**
          * Copies all the properties of config to obj if they don't already exist.
          * @param {Object} obj The receiver of the properties
@@ -1774,11 +1894,28 @@ Date.prototype.add = function(interval, value){
  * <script type="text/javascript">
  */
 
+/**
+ * @class Roo.lib.Dom
+ * @static
+ * 
+ * Dom utils (from YIU afaik)
+ * 
+ **/
 Roo.lib.Dom = {
+    /**
+     * Get the view width
+     * @param {Boolean} full True will get the full document, otherwise it's the view width
+     * @return {Number} The width
+     */
+     
     getViewWidth : function(full) {
         return full ? this.getDocumentWidth() : this.getViewportWidth();
     },
-
+    /**
+     * Get the view height
+     * @param {Boolean} full True will get the full document, otherwise it's the view height
+     * @return {Number} The height
+     */
     getViewHeight : function(full) {
         return full ? this.getDocumentHeight() : this.getViewportHeight();
     },
@@ -2693,6 +2830,7 @@ Roo.lib.Event = function() {
             var oConn = this;
 
             if (callback && callback.timeout) {
+                
                 this.timeout[o.tId] = window.setTimeout(function() {
                     oConn.abort(o, callback, true);
                 }, callback.timeout);
@@ -4080,7 +4218,7 @@ Roo.lib.Easing = {
 /**
  * @class Roo.DomHelper
  * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
- * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
+ * For more information see <a href="http://web.archive.org/web/20071221063734/http://www.jackslocum.com/blog/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
  * @singleton
  */
 Roo.DomHelper = function(){
@@ -4530,7 +4668,9 @@ var t = new Roo.Template({
 });
 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
 </code></pre>
-* For more information see this blog post with examples: <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">DomHelper - Create Elements using DOM, HTML fragments and Templates</a>. 
+* For more information see this blog post with examples:
+*  <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
+     - Create Elements using DOM, HTML fragments and Templates</a>. 
 * @constructor
 * @param {Object} cfg - Configuration object.
 */
@@ -4549,11 +4689,18 @@ Roo.Template = function(cfg){
         // bc
         this.html = cfg;
     }
-    
+    if (this.url) {
+        this.load();
+    }
     
 };
 Roo.Template.prototype = {
     
+    /**
+     * @cfg {String} url  The Url to load the template from. beware if you are loading from a url, the data may not be ready if you use it instantly..
+     *                    it should be fixed so that template is observable...
+     */
+    url : false,
     /**
      * @cfg {String} html  The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
      */
@@ -4565,7 +4712,7 @@ Roo.Template.prototype = {
      */
     applyTemplate : function(values){
         try {
-            
+           
             if(this.compiled){
                 return this.compiled(values);
             }
@@ -4603,6 +4750,36 @@ Roo.Template.prototype = {
          
     },
     
+    loading : false,
+      
+    load : function ()
+    {
+         
+        if (this.loading) {
+            return;
+        }
+        var _t = this;
+        
+        this.loading = true;
+        this.compiled = false;
+        
+        var cx = new Roo.data.Connection();
+        cx.request({
+            url : this.url,
+            method : 'GET',
+            success : function (response) {
+                _t.loading = false;
+                _t.html = response.responseText;
+                _t.url = false;
+                _t.compile();
+             },
+            failure : function(response) {
+                Roo.log("Template failed to load from " + _t.url);
+                _t.loading = false;
+            }
+        });
+    },
+
     /**
      * Sets the HTML used as the template and optionally compiles it.
      * @param {String} html
@@ -9497,7 +9674,28 @@ if(opt.anim.isAnimated()){
         } : function(ns, name){
             var d = this.dom;
             return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
+        },
+        
+        
+        /**
+         * Sets or Returns the value the dom attribute value
+         * @param {String} name The attribute name
+         * @param {String} value (optional) The value to set the attribute to
+         * @return {String} The attribute value
+         */
+        attr : function(name){
+            if (arguments.length > 1) {
+                this.dom.setAttribute(name, arguments[1]);
+                return arguments[1];
+            }
+            if (!this.dom.hasAttribute(name)) {
+                return undefined;
+            }
+            return this.dom.getAttribute(name);
         }
+        
+        
+        
     };
 
     var ep = El.prototype;
@@ -11326,7 +11524,7 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
                 failure: this.handleFailure,
                 scope: this,
                 argument: {options: o},
-                timeout : this.timeout
+                timeout : o.timeout || this.timeout
             };
 
             var method = o.method||this.method||(p ? "POST" : "GET");
@@ -11485,87 +11683,7 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
         }
     }
 });
-
-/**
- * @class Roo.Ajax
- * @extends Roo.data.Connection
- * Global Ajax request class.
- *
- * @singleton
- */
-Roo.Ajax = new Roo.data.Connection({
-    // fix up the docs
-   /**
-     * @cfg {String} url @hide
-     */
-    /**
-     * @cfg {Object} extraParams @hide
-     */
-    /**
-     * @cfg {Object} defaultHeaders @hide
-     */
-    /**
-     * @cfg {String} method (Optional) @hide
-     */
-    /**
-     * @cfg {Number} timeout (Optional) @hide
-     */
-    /**
-     * @cfg {Boolean} autoAbort (Optional) @hide
-     */
-
-    /**
-     * @cfg {Boolean} disableCaching (Optional) @hide
-     */
-
-    /**
-     * @property  disableCaching
-     * True to add a unique cache-buster param to GET requests. (defaults to true)
-     * @type Boolean
-     */
-    /**
-     * @property  url
-     * The default URL to be used for requests to the server. (defaults to undefined)
-     * @type String
-     */
-    /**
-     * @property  extraParams
-     * An object containing properties which are used as
-     * extra parameters to each request made by this object. (defaults to undefined)
-     * @type Object
-     */
-    /**
-     * @property  defaultHeaders
-     * An object containing request headers which are added to each request made by this object. (defaults to undefined)
-     * @type Object
-     */
-    /**
-     * @property  method
-     * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
-     * @type String
-     */
-    /**
-     * @property  timeout
-     * The timeout in milliseconds to be used for requests. (defaults to 30000)
-     * @type Number
-     */
-
-    /**
-     * @property  autoAbort
-     * Whether a new request should abort any pending requests. (defaults to false)
-     * @type Boolean
-     */
-    autoAbort : false,
-
-    /**
-     * Serialize the passed form into a url encoded string
-     * @param {String/HTMLElement} form
-     * @return {String}
-     */
-    serializeForm : function(form){
-        return Roo.lib.Ajax.serializeForm(form);
-    }
-});/*
+/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -11799,7 +11917,8 @@ um.update({<br/>
      */
     update : function(url, params, callback, discardUrl){
         if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
-            var method = this.method, cfg;
+            var method = this.method,
+                cfg;
             if(typeof url == "object"){ // must be config object
                 cfg = url;
                 url = cfg.url;
@@ -11837,7 +11956,7 @@ um.update({<br/>
                 timeout: (this.timeout*1000),
                 argument: {"url": url, "form": null, "callback": callback, "params": params}
             });
-
+            Roo.log("updated manager called with timeout of " + o.timeout);
             this.transaction = Roo.Ajax.request(o);
         }
     },
@@ -12093,6 +12212,461 @@ Roo.UpdateManager.BasicRenderer.prototype = {
     }
 };
 /*
+ * Based on:
+ * Roo JS
+ * (c)) Alan Knowles
+ * Licence : LGPL
+ */
+
+
+/**
+ * @class Roo.DomTemplate
+ * @extends Roo.Template
+ * An effort at a dom based template engine..
+ *
+ * Similar to XTemplate, except it uses dom parsing to create the template..
+ *
+ * Supported features:
+ *
+ *  Tags:
+
+<pre><code>
+      {a_variable} - output encoded.
+      {a_variable.format:("Y-m-d")} - call a method on the variable
+      {a_variable:raw} - unencoded output
+      {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
+      {a_variable:this.method_on_template(...)} - call a method on the template object.
+</code></pre>
+ *  The tpl tag:
+<pre><code>
+        &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) {
+        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
+     * WORD:WORD()
+     *
+     * // you can fake an object call by doing this
+     *  x.t:(test,tesT) 
+     * 
+     */
+    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
+     *
+     * This is not recursive, so I'm not sure how nested templates are really going to be handled..
+     *
+     */
+    compile: function()
+    {
+        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
+         
+        
+        
+        this.tpls = [];
+        var _t = this;
+        this.iterChild(div, function(n) {_t.compileNode(n, true); });
+        
+        var tpls = this.tpls;
+        
+        // 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 = [];
+        Roo.each(tpls, function(tp){
+            this.compileTpl(tp);
+            this.tpls[tp.id] = tp;
+        }, this);
+        
+        this.master = tpls[0];
+        return this;
+        
+        
+    },
+    
+    compileNode : function(node, istop) {
+        // 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;
+        }
+        
+        var tpl = {
+            uid : false,
+            id : false,
+            attr : false,
+            value : false,
+            body : '',
+            
+            forCall : false,
+            execCall : false,
+            dom : false,
+            isTop : istop
+            
+            
+        };
+        
+        
+        switch(true) {
+            case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
+            case (node.hasAttribute('roo-if')): tpl.attr = 'if'; 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);
+            return;
+        }
+        tpl.uid = this.id++;
+        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 {
+            
+            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);
+        
+        // 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;
+        
+        
+         
+        tpl.id = tpl.uid;
+        switch(tpl.attr) {
+            case 'for' :
+                switch (tpl.value) {
+                    case '.':  tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
+                    case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
+                    default:   tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
+                }
+                break;
+            
+            case 'exec':
+                tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
+                break;
+            
+            case 'if':     
+                tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
+                break;
+            
+            case 'name':
+                tpl.id  = tpl.value; // replace non characters???
+                break;
+            
+        }
+        
+        
+        this.tpls.push(tpl);
+        
+        
+        
+    },
+    
+    
+    
+    
+    /**
+     * Compile a segment of the template into a 'sub-template'
+     *
+     * 
+     * 
+     *
+     */
+    compileTpl : function(tpl)
+    {
+        var fm = Roo.util.Format;
+        var useF = this.disableFormats !== true;
+        
+        var sep = Roo.isGecko ? "+\n" : ",\n";
+        
+        var undef = function(str) {
+            Roo.debug && Roo.log("Property not found :"  + str);
+            return '';
+        };
+          
+        //Roo.log(tpl.body);
+        
+        
+        
+        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'; 
+            }
+            if (format == 'raw' ) {
+                format = false;
+            }
+            
+            if(name.substr(0, 6) == 'domtpl'){
+                return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
+            }
+            
+            // build an array of options to determine if value is undefined..
+            
+            // basically get 'xxxx.yyyy' then do
+            // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
+            //    (function () { Roo.log("Property not found"); return ''; })() :
+            //    ......
+            
+            var udef_ar = [];
+            var lookfor = '';
+            Roo.each(name.split('.'), function(st) {
+                lookfor += (lookfor.length ? '.': '') + st;
+                udef_ar.push(  "(typeof(" + lookfor + ") == 'undefined')"  );
+            });
+            
+            var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
+            
+            
+            if(format && useF){
+                
+                args = args ? ',' + args : "";
+                 
+                if(format.substr(0, 5) != "this."){
+                    format = "fm." + format + '(';
+                }else{
+                    format = 'this.call("'+ format.substr(5) + '", ';
+                    args = ", values";
+                }
+                
+                return "'"+ sep +   udef_st   +    format + name + args + "))"+sep+"'";
+            }
+             
+            if (args && args.length) {
+                // called with xxyx.yuu:(test,test)
+                // change to ()
+                return "'"+ sep + udef_st  + name + '(' +  args + "))"+sep+"'";
+            }
+            // raw.. - :raw modifier..
+            return "'"+ sep + udef_st  + name + ")"+sep+"'";
+            
+        };
+        var body;
+        // branched to use + in gecko and [].join() in others
+        if(Roo.isGecko){
+            body = "tpl.compiled = function(values, parent){  with(values) { return '" +
+                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
+                    "';};};";
+        }else{
+            body = ["tpl.compiled = function(values, parent){  with (values) { return ['"];
+            body.push(tpl.body.replace(/(\r\n|\n)/g,
+                            '\\n').replace(/'/g, "\\'").replace(this.re, fn));
+            body.push("'].join('');};};");
+            body = body.join('');
+        }
+        
+        Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
+       
+        /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef  */
+        eval(body);
+        
+        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, {});
+        //var s = this.subs;
+    },
+
+    apply : function(){
+        return this.applyTemplate.apply(this, arguments);
+    }
+
+ });
+
+Roo.DomTemplate.from = function(el){
+    el = Roo.getDom(el);
+    return new Roo.Domtemplate(el.value || el.innerHTML);
+};/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -13086,17 +13660,47 @@ Roo.util.Format = function(){
          * @return {String} The formatted currency string
          */
         usMoney : function(v){
-            v = (Math.round((v-0)*100))/100;
-            v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
+            return '$' + Roo.util.Format.number(v);
+        },
+        
+        /**
+         * Format a number
+         * eventually this should probably emulate php's number_format
+         * @param {Number/String} value The numeric value to format
+         * @param {Number} decimals number of decimal places
+         * @return {String} The formatted currency string
+         */
+        number : function(v,decimals)
+        {
+            // multiply and round.
+            decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
+            var mul = Math.pow(10, decimals);
+            var zero = String(mul).substring(1);
+            v = (Math.round((v-0)*mul))/mul;
+            
+            // if it's '0' number.. then
+            
+            //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
             v = String(v);
             var ps = v.split('.');
             var whole = ps[0];
-            var sub = ps[1] ? '.'+ ps[1] : '.00';
+            
+            
             var r = /(\d+)(\d{3})/;
+            // add comma's
             while (r.test(whole)) {
                 whole = whole.replace(r, '$1' + ',' + '$2');
             }
-            return "$" + whole + sub ;
+            
+            
+            var sub = ps[1] ?
+                    // has decimals..
+                    (decimals ?  ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
+                    // does not have decimals
+                    (decimals ? ('.' + zero) : '');
+            
+            
+            return whole + sub ;
         },
         
         /**