Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Object2.html
diff --git a/docs/source/Object2.html b/docs/source/Object2.html
new file mode 100644 (file)
index 0000000..2724b8a
--- /dev/null
@@ -0,0 +1,542 @@
+<!DOCTYPE html>
+<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>
+  <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(); highlight();">
+  <pre class="prettyprint lang-js"><span id='Ext-Object'>/**
+</span> * @author Jacky Nguyen &lt;jacky@sencha.com&gt;
+ * @docauthor Jacky Nguyen &lt;jacky@sencha.com&gt;
+ * @class Ext.Object
+ *
+ * A collection of useful static methods to deal with objects.
+ *
+ * @singleton
+ */
+
+(function() {
+
+var ExtObject = Ext.Object = {
+
+<span id='Ext-Object-method-toQueryObjects'>    /**
+</span>     * Converts a `name` - `value` pair to an array of objects with support for nested structures. Useful to construct
+     * query strings. For example:
+     *
+     *     var objects = Ext.Object.toQueryObjects('hobbies', ['reading', 'cooking', 'swimming']);
+     *
+     *     // objects then equals:
+     *     [
+     *         { name: 'hobbies', value: 'reading' },
+     *         { name: 'hobbies', value: 'cooking' },
+     *         { name: 'hobbies', value: 'swimming' },
+     *     ];
+     *
+     *     var objects = Ext.Object.toQueryObjects('dateOfBirth', {
+     *         day: 3,
+     *         month: 8,
+     *         year: 1987,
+     *         extra: {
+     *             hour: 4
+     *             minute: 30
+     *         }
+     *     }, true); // Recursive
+     *
+     *     // objects then equals:
+     *     [
+     *         { name: 'dateOfBirth[day]', value: 3 },
+     *         { name: 'dateOfBirth[month]', value: 8 },
+     *         { name: 'dateOfBirth[year]', value: 1987 },
+     *         { name: 'dateOfBirth[extra][hour]', value: 4 },
+     *         { name: 'dateOfBirth[extra][minute]', value: 30 },
+     *     ];
+     *
+     * @param {String} name
+     * @param {Object/Array} value
+     * @param {Boolean} [recursive=false] True to traverse object recursively
+     * @return {Array}
+     */
+    toQueryObjects: function(name, value, recursive) {
+        var self = ExtObject.toQueryObjects,
+            objects = [],
+            i, ln;
+
+        if (Ext.isArray(value)) {
+            for (i = 0, ln = value.length; i &lt; ln; i++) {
+                if (recursive) {
+                    objects = objects.concat(self(name + '[' + i + ']', value[i], true));
+                }
+                else {
+                    objects.push({
+                        name: name,
+                        value: value[i]
+                    });
+                }
+            }
+        }
+        else if (Ext.isObject(value)) {
+            for (i in value) {
+                if (value.hasOwnProperty(i)) {
+                    if (recursive) {
+                        objects = objects.concat(self(name + '[' + i + ']', value[i], true));
+                    }
+                    else {
+                        objects.push({
+                            name: name,
+                            value: value[i]
+                        });
+                    }
+                }
+            }
+        }
+        else {
+            objects.push({
+                name: name,
+                value: value
+            });
+        }
+
+        return objects;
+    },
+
+<span id='Ext-Object-method-toQueryString'>    /**
+</span>     * Takes an object and converts it to an encoded query string.
+     *
+     * Non-recursive:
+     *
+     *     Ext.Object.toQueryString({foo: 1, bar: 2}); // returns &quot;foo=1&amp;bar=2&quot;
+     *     Ext.Object.toQueryString({foo: null, bar: 2}); // returns &quot;foo=&amp;bar=2&quot;
+     *     Ext.Object.toQueryString({'some price': '$300'}); // returns &quot;some%20price=%24300&quot;
+     *     Ext.Object.toQueryString({date: new Date(2011, 0, 1)}); // returns &quot;date=%222011-01-01T00%3A00%3A00%22&quot;
+     *     Ext.Object.toQueryString({colors: ['red', 'green', 'blue']}); // returns &quot;colors=red&amp;colors=green&amp;colors=blue&quot;
+     *
+     * Recursive:
+     *
+     *     Ext.Object.toQueryString({
+     *         username: 'Jacky',
+     *         dateOfBirth: {
+     *             day: 1,
+     *             month: 2,
+     *             year: 1911
+     *         },
+     *         hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
+     *     }, true); // returns the following string (broken down and url-decoded for ease of reading purpose):
+     *     // username=Jacky
+     *     //    &amp;dateOfBirth[day]=1&amp;dateOfBirth[month]=2&amp;dateOfBirth[year]=1911
+     *     //    &amp;hobbies[0]=coding&amp;hobbies[1]=eating&amp;hobbies[2]=sleeping&amp;hobbies[3][0]=nested&amp;hobbies[3][1]=stuff
+     *
+     * @param {Object} object The object to encode
+     * @param {Boolean} [recursive=false] Whether or not to interpret the object in recursive format.
+     * (PHP / Ruby on Rails servers and similar).
+     * @return {String} queryString
+     */
+    toQueryString: function(object, recursive) {
+        var paramObjects = [],
+            params = [],
+            i, j, ln, paramObject, value;
+
+        for (i in object) {
+            if (object.hasOwnProperty(i)) {
+                paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
+            }
+        }
+
+        for (j = 0, ln = paramObjects.length; j &lt; ln; j++) {
+            paramObject = paramObjects[j];
+            value = paramObject.value;
+
+            if (Ext.isEmpty(value)) {
+                value = '';
+            }
+            else if (Ext.isDate(value)) {
+                value = Ext.Date.toString(value);
+            }
+
+            params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
+        }
+
+        return params.join('&amp;');
+    },
+
+<span id='Ext-Object-method-fromQueryString'>    /**
+</span>     * Converts a query string back into an object.
+     *
+     * Non-recursive:
+     *
+     *     Ext.Object.fromQueryString(foo=1&amp;bar=2); // returns {foo: 1, bar: 2}
+     *     Ext.Object.fromQueryString(foo=&amp;bar=2); // returns {foo: null, bar: 2}
+     *     Ext.Object.fromQueryString(some%20price=%24300); // returns {'some price': '$300'}
+     *     Ext.Object.fromQueryString(colors=red&amp;colors=green&amp;colors=blue); // returns {colors: ['red', 'green', 'blue']}
+     *
+     * Recursive:
+     *
+     *       Ext.Object.fromQueryString(&quot;username=Jacky&amp;dateOfBirth[day]=1&amp;dateOfBirth[month]=2&amp;dateOfBirth[year]=1911&amp;hobbies[0]=coding&amp;hobbies[1]=eating&amp;hobbies[2]=sleeping&amp;hobbies[3][0]=nested&amp;hobbies[3][1]=stuff&quot;, true);
+     *     // returns
+     *     {
+     *         username: 'Jacky',
+     *         dateOfBirth: {
+     *             day: '1',
+     *             month: '2',
+     *             year: '1911'
+     *         },
+     *         hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
+     *     }
+     *
+     * @param {String} queryString The query string to decode
+     * @param {Boolean} [recursive=false] Whether or not to recursively decode the string. This format is supported by
+     * PHP / Ruby on Rails servers and similar.
+     * @return {Object}
+     */
+    fromQueryString: function(queryString, recursive) {
+        var parts = queryString.replace(/^\?/, '').split('&amp;'),
+            object = {},
+            temp, components, name, value, i, ln,
+            part, j, subLn, matchedKeys, matchedName,
+            keys, key, nextKey;
+
+        for (i = 0, ln = parts.length; i &lt; ln; i++) {
+            part = parts[i];
+
+            if (part.length &gt; 0) {
+                components = part.split('=');
+                name = decodeURIComponent(components[0]);
+                value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
+
+                if (!recursive) {
+                    if (object.hasOwnProperty(name)) {
+                        if (!Ext.isArray(object[name])) {
+                            object[name] = [object[name]];
+                        }
+
+                        object[name].push(value);
+                    }
+                    else {
+                        object[name] = value;
+                    }
+                }
+                else {
+                    matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
+                    matchedName = name.match(/^([^\[]+)/);
+
+                    //&lt;debug error&gt;
+                    if (!matchedName) {
+                        Ext.Error.raise({
+                            sourceClass: &quot;Ext.Object&quot;,
+                            sourceMethod: &quot;fromQueryString&quot;,
+                            queryString: queryString,
+                            recursive: recursive,
+                            msg: 'Malformed query string given, failed parsing name from &quot;' + part + '&quot;'
+                        });
+                    }
+                    //&lt;/debug&gt;
+
+                    name = matchedName[0];
+                    keys = [];
+
+                    if (matchedKeys === null) {
+                        object[name] = value;
+                        continue;
+                    }
+
+                    for (j = 0, subLn = matchedKeys.length; j &lt; subLn; j++) {
+                        key = matchedKeys[j];
+                        key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
+                        keys.push(key);
+                    }
+
+                    keys.unshift(name);
+
+                    temp = object;
+
+                    for (j = 0, subLn = keys.length; j &lt; subLn; j++) {
+                        key = keys[j];
+
+                        if (j === subLn - 1) {
+                            if (Ext.isArray(temp) &amp;&amp; key === '') {
+                                temp.push(value);
+                            }
+                            else {
+                                temp[key] = value;
+                            }
+                        }
+                        else {
+                            if (temp[key] === undefined || typeof temp[key] === 'string') {
+                                nextKey = keys[j+1];
+
+                                temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
+                            }
+
+                            temp = temp[key];
+                        }
+                    }
+                }
+            }
+        }
+
+        return object;
+    },
+
+<span id='Ext-Object-method-each'>    /**
+</span>     * Iterates through an object and invokes the given callback function for each iteration.
+     * The iteration can be stopped by returning `false` in the callback function. For example:
+     *
+     *     var person = {
+     *         name: 'Jacky'
+     *         hairColor: 'black'
+     *         loves: ['food', 'sleeping', 'wife']
+     *     };
+     *
+     *     Ext.Object.each(person, function(key, value, myself) {
+     *         console.log(key + &quot;:&quot; + value);
+     *
+     *         if (key === 'hairColor') {
+     *             return false; // stop the iteration
+     *         }
+     *     });
+     *
+     * @param {Object} object The object to iterate
+     * @param {Function} fn The callback function.
+     * @param {String} fn.key
+     * @param {Object} fn.value
+     * @param {Object} fn.object The object itself
+     * @param {Object} [scope] The execution scope (`this`) of the callback function
+     */
+    each: function(object, fn, scope) {
+        for (var property in object) {
+            if (object.hasOwnProperty(property)) {
+                if (fn.call(scope || object, property, object[property], object) === false) {
+                    return;
+                }
+            }
+        }
+    },
+
+<span id='Ext-Object-method-merge'>    /**
+</span>     * Merges any number of objects recursively without referencing them or their children.
+     *
+     *     var extjs = {
+     *         companyName: 'Ext JS',
+     *         products: ['Ext JS', 'Ext GWT', 'Ext Designer'],
+     *         isSuperCool: true
+     *         office: {
+     *             size: 2000,
+     *             location: 'Palo Alto',
+     *             isFun: true
+     *         }
+     *     };
+     *
+     *     var newStuff = {
+     *         companyName: 'Sencha Inc.',
+     *         products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
+     *         office: {
+     *             size: 40000,
+     *             location: 'Redwood City'
+     *         }
+     *     };
+     *
+     *     var sencha = Ext.Object.merge(extjs, newStuff);
+     *
+     *     // extjs and sencha then equals to
+     *     {
+     *         companyName: 'Sencha Inc.',
+     *         products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
+     *         isSuperCool: true
+     *         office: {
+     *             size: 30000,
+     *             location: 'Redwood City'
+     *             isFun: true
+     *         }
+     *     }
+     *
+     * @param {Object...} object Any number of objects to merge.
+     * @return {Object} merged The object that is created as a result of merging all the objects passed in.
+     */
+    merge: function(source, key, value) {
+        if (typeof key === 'string') {
+            if (value &amp;&amp; value.constructor === Object) {
+                if (source[key] &amp;&amp; source[key].constructor === Object) {
+                    ExtObject.merge(source[key], value);
+                }
+                else {
+                    source[key] = Ext.clone(value);
+                }
+            }
+            else {
+                source[key] = value;
+            }
+
+            return source;
+        }
+
+        var i = 1,
+            ln = arguments.length,
+            object, property;
+
+        for (; i &lt; ln; i++) {
+            object = arguments[i];
+
+            for (property in object) {
+                if (object.hasOwnProperty(property)) {
+                    ExtObject.merge(source, property, object[property]);
+                }
+            }
+        }
+
+        return source;
+    },
+
+<span id='Ext-Object-method-getKey'>    /**
+</span>     * Returns the first matching key corresponding to the given value.
+     * If no matching value is found, null is returned.
+     *
+     *     var person = {
+     *         name: 'Jacky',
+     *         loves: 'food'
+     *     };
+     *
+     *     alert(Ext.Object.getKey(person, 'food')); // alerts 'loves'
+     *
+     * @param {Object} object
+     * @param {Object} value The value to find
+     */
+    getKey: function(object, value) {
+        for (var property in object) {
+            if (object.hasOwnProperty(property) &amp;&amp; object[property] === value) {
+                return property;
+            }
+        }
+
+        return null;
+    },
+
+<span id='Ext-Object-method-getValues'>    /**
+</span>     * Gets all values of the given object as an array.
+     *
+     *     var values = Ext.Object.getValues({
+     *         name: 'Jacky',
+     *         loves: 'food'
+     *     }); // ['Jacky', 'food']
+     *
+     * @param {Object} object
+     * @return {Array} An array of values from the object
+     */
+    getValues: function(object) {
+        var values = [],
+            property;
+
+        for (property in object) {
+            if (object.hasOwnProperty(property)) {
+                values.push(object[property]);
+            }
+        }
+
+        return values;
+    },
+
+<span id='Ext-Object-method-getKeys'>    /**
+</span>     * Gets all keys of the given object as an array.
+     *
+     *     var values = Ext.Object.getKeys({
+     *         name: 'Jacky',
+     *         loves: 'food'
+     *     }); // ['name', 'loves']
+     *
+     * @param {Object} object
+     * @return {String[]} An array of keys from the object
+     * @method
+     */
+    getKeys: ('keys' in Object.prototype) ? Object.keys : function(object) {
+        var keys = [],
+            property;
+
+        for (property in object) {
+            if (object.hasOwnProperty(property)) {
+                keys.push(property);
+            }
+        }
+
+        return keys;
+    },
+
+<span id='Ext-Object-method-getSize'>    /**
+</span>     * Gets the total number of this object's own properties
+     *
+     *     var size = Ext.Object.getSize({
+     *         name: 'Jacky',
+     *         loves: 'food'
+     *     }); // size equals 2
+     *
+     * @param {Object} object
+     * @return {Number} size
+     */
+    getSize: function(object) {
+        var size = 0,
+            property;
+
+        for (property in object) {
+            if (object.hasOwnProperty(property)) {
+                size++;
+            }
+        }
+
+        return size;
+    }
+};
+
+
+<span id='Ext-method-merge'>/**
+</span> * A convenient alias method for {@link Ext.Object#merge}.
+ *
+ * @member Ext
+ * @method merge
+ * @alias Ext.Object#merge
+ */
+Ext.merge = Ext.Object.merge;
+
+<span id='Ext-method-urlEncode'>/**
+</span> * Alias for {@link Ext.Object#toQueryString}.
+ *
+ * @member Ext
+ * @method urlEncode
+ * @alias Ext.Object#toQueryString
+ * @deprecated 4.0.0 Use {@link Ext.Object#toQueryString} instead
+ */
+Ext.urlEncode = function() {
+    var args = Ext.Array.from(arguments),
+        prefix = '';
+
+    // Support for the old `pre` argument
+    if ((typeof args[1] === 'string')) {
+        prefix = args[1] + '&amp;';
+        args[1] = false;
+    }
+
+    return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
+};
+
+<span id='Ext-method-urlDecode'>/**
+</span> * Alias for {@link Ext.Object#fromQueryString}.
+ *
+ * @member Ext
+ * @method urlDecode
+ * @alias Ext.Object#fromQueryString
+ * @deprecated 4.0.0 Use {@link Ext.Object#fromQueryString} instead
+ */
+Ext.urlDecode = function() {
+    return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
+};
+
+})();
+</pre>
+</body>
+</html>