Roo.js
[roojs1] / Roo.js
diff --git a/Roo.js b/Roo.js
index 7545ed9..8722e80 100644 (file)
--- a/Roo.js
+++ b/Roo.js
@@ -68,7 +68,7 @@ Roo.apply = function(o, c, defaults){
             document.execCommand("BackgroundImageCache", false, true);
         }catch(e){}
     }
-
+    
     Roo.apply(Roo, {
         /**
          * True if the browser is in strict mode
@@ -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
@@ -336,16 +456,16 @@ Roo.factory(conf, Roo.data);
             }
             var buf = [];
             for(var key in o){
-                var ov = o[key], k = encodeURIComponent(key);
+                var ov = o[key], k = Roo.encodeURIComponent(key);
                 var type = typeof ov;
                 if(type == 'undefined'){
                     buf.push(k, "=&");
                 }else if(type != "function" && type != "object"){
-                    buf.push(k, "=", encodeURIComponent(ov), "&");
+                    buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
                 }else if(ov instanceof Array){
                     if (ov.length) {
                            for(var i = 0, len = ov.length; i < len; i++) {
-                               buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
+                               buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
                            }
                        } else {
                            buf.push(k, "=&");
@@ -357,14 +477,14 @@ Roo.factory(conf, Roo.data);
         },
          /**
          * Safe version of encodeURIComponent
-         * @param {String} str
+         * @param {String} data 
          * @return {String} 
          */
         
-        encodeURIComponent : function (str)
+        encodeURIComponent : function (data)
         {
             try {
-                return encodeURIComponent(str);
+                return encodeURIComponent(data);
             } catch(e) {} // should be an uri encode error.
             
             if (data == '' || data == null){
@@ -382,30 +502,31 @@ Roo.factory(conf, Roo.data);
                 var bs = new Array();
                 if (c > 0x10000){
                         // 4 bytes
-                        bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
-                        bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
-                        bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
+                    bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
+                    bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
+                    bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
                     bs[3] = 0x80 | (c & 0x3F);
                 }else if (c > 0x800){
                          // 3 bytes
-                         bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
-                         bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
-                        bs[2] = 0x80 | (c & 0x3F);
+                    bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
+                    bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
+                    bs[2] = 0x80 | (c & 0x3F);
                 }else if (c > 0x80){
                        // 2 bytes
-                        bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
-                       bs[1] = 0x80 | (c & 0x3F);
+                    bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
+                    bs[1] = 0x80 | (c & 0x3F);
                 }else{
                         // 1 byte
-                     bs[0] = c;
+                    bs[0] = c;
                 }
                 for(var j=0; j<bs.length; j++){
-                       var b = bs[j];
-                        var hex = nibble_to_hex((b & 0xF0) >>> 4) 
-                       + nibble_to_hex(b &0x0F);buffer += '%'+hex;
+                    var b = bs[j];
+                    var hex = nibble_to_hex((b & 0xF0) >>> 4) 
+                            + nibble_to_hex(b &0x0F);
+                    buffer += '%'+hex;
                }
             }
-            return encodeURIComponent(buffer);    
+            return buffer;    
              
         },