X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/docs/source/Object2.html diff --git a/docs/source/Object2.html b/docs/source/Object2.html new file mode 100644 index 00000000..2724b8a9 --- /dev/null +++ b/docs/source/Object2.html @@ -0,0 +1,542 @@ + + +
+ +/** + * @author Jacky Nguyen <jacky@sencha.com> + * @docauthor Jacky Nguyen <jacky@sencha.com> + * @class Ext.Object + * + * A collection of useful static methods to deal with objects. + * + * @singleton + */ + +(function() { + +var ExtObject = Ext.Object = { + + /** + * 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 < 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; + }, + + /** + * Takes an object and converts it to an encoded query string. + * + * Non-recursive: + * + * Ext.Object.toQueryString({foo: 1, bar: 2}); // returns "foo=1&bar=2" + * Ext.Object.toQueryString({foo: null, bar: 2}); // returns "foo=&bar=2" + * Ext.Object.toQueryString({'some price': '$300'}); // returns "some%20price=%24300" + * Ext.Object.toQueryString({date: new Date(2011, 0, 1)}); // returns "date=%222011-01-01T00%3A00%3A00%22" + * Ext.Object.toQueryString({colors: ['red', 'green', 'blue']}); // returns "colors=red&colors=green&colors=blue" + * + * 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 + * // &dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911 + * // &hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&hobbies[3][0]=nested&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 < 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('&'); + }, + + /** + * Converts a query string back into an object. + * + * Non-recursive: + * + * Ext.Object.fromQueryString(foo=1&bar=2); // returns {foo: 1, bar: 2} + * Ext.Object.fromQueryString(foo=&bar=2); // returns {foo: null, bar: 2} + * Ext.Object.fromQueryString(some%20price=%24300); // returns {'some price': '$300'} + * Ext.Object.fromQueryString(colors=red&colors=green&colors=blue); // returns {colors: ['red', 'green', 'blue']} + * + * Recursive: + * + * Ext.Object.fromQueryString("username=Jacky&dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911&hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&hobbies[3][0]=nested&hobbies[3][1]=stuff", 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('&'), + object = {}, + temp, components, name, value, i, ln, + part, j, subLn, matchedKeys, matchedName, + keys, key, nextKey; + + for (i = 0, ln = parts.length; i < ln; i++) { + part = parts[i]; + + if (part.length > 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(/^([^\[]+)/); + + //<debug error> + if (!matchedName) { + Ext.Error.raise({ + sourceClass: "Ext.Object", + sourceMethod: "fromQueryString", + queryString: queryString, + recursive: recursive, + msg: 'Malformed query string given, failed parsing name from "' + part + '"' + }); + } + //</debug> + + name = matchedName[0]; + keys = []; + + if (matchedKeys === null) { + object[name] = value; + continue; + } + + for (j = 0, subLn = matchedKeys.length; j < 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 < subLn; j++) { + key = keys[j]; + + if (j === subLn - 1) { + if (Ext.isArray(temp) && 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; + }, + + /** + * 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 + ":" + 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; + } + } + } + }, + + /** + * 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 && value.constructor === Object) { + if (source[key] && 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 < ln; i++) { + object = arguments[i]; + + for (property in object) { + if (object.hasOwnProperty(property)) { + ExtObject.merge(source, property, object[property]); + } + } + } + + return source; + }, + + /** + * 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) && object[property] === value) { + return property; + } + } + + return null; + }, + + /** + * 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; + }, + + /** + * 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; + }, + + /** + * 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; + } +}; + + +/** + * A convenient alias method for {@link Ext.Object#merge}. + * + * @member Ext + * @method merge + * @alias Ext.Object#merge + */ +Ext.merge = Ext.Object.merge; + +/** + * 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] + '&'; + args[1] = false; + } + + return prefix + Ext.Object.toQueryString.apply(Ext.Object, args); +}; + +/** + * 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); +}; + +})(); ++ +