Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Object.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-Object'>/**
2 </span> * @author Jacky Nguyen &lt;jacky@sencha.com&gt;
3  * @docauthor Jacky Nguyen &lt;jacky@sencha.com&gt;
4  * @class Ext.Object
5  *
6  * A collection of useful static methods to deal with objects
7  *
8  * @singleton
9  */
10
11 (function() {
12
13 var ExtObject = Ext.Object = {
14
15 <span id='Ext-Object-method-toQueryObjects'>    /**
16 </span>     * Convert a `name` - `value` pair to an array of objects with support for nested structures; useful to construct
17      * query strings. For example:
18
19     var objects = Ext.Object.toQueryObjects('hobbies', ['reading', 'cooking', 'swimming']);
20
21     // objects then equals:
22     [
23         { name: 'hobbies', value: 'reading' },
24         { name: 'hobbies', value: 'cooking' },
25         { name: 'hobbies', value: 'swimming' },
26     ];
27
28     var objects = Ext.Object.toQueryObjects('dateOfBirth', {
29         day: 3,
30         month: 8,
31         year: 1987,
32         extra: {
33             hour: 4
34             minute: 30
35         }
36     }, true); // Recursive
37
38     // objects then equals:
39     [
40         { name: 'dateOfBirth[day]', value: 3 },
41         { name: 'dateOfBirth[month]', value: 8 },
42         { name: 'dateOfBirth[year]', value: 1987 },
43         { name: 'dateOfBirth[extra][hour]', value: 4 },
44         { name: 'dateOfBirth[extra][minute]', value: 30 },
45     ];
46
47      * @param {String} name
48      * @param {Mixed} value
49      * @param {Boolean} recursive
50      * @markdown
51      */
52     toQueryObjects: function(name, value, recursive) {
53         var self = ExtObject.toQueryObjects,
54             objects = [],
55             i, ln;
56
57         if (Ext.isArray(value)) {
58             for (i = 0, ln = value.length; i &lt; ln; i++) {
59                 if (recursive) {
60                     objects = objects.concat(self(name + '[' + i + ']', value[i], true));
61                 }
62                 else {
63                     objects.push({
64                         name: name,
65                         value: value[i]
66                     });
67                 }
68             }
69         }
70         else if (Ext.isObject(value)) {
71             for (i in value) {
72                 if (value.hasOwnProperty(i)) {
73                     if (recursive) {
74                         objects = objects.concat(self(name + '[' + i + ']', value[i], true));
75                     }
76                     else {
77                         objects.push({
78                             name: name,
79                             value: value[i]
80                         });
81                     }
82                 }
83             }
84         }
85         else {
86             objects.push({
87                 name: name,
88                 value: value
89             });
90         }
91
92         return objects;
93     },
94
95 <span id='Ext-Object-method-toQueryString'>    /**
96 </span>     * Takes an object and converts it to an encoded query string
97
98 - Non-recursive:
99
100     Ext.Object.toQueryString({foo: 1, bar: 2}); // returns &quot;foo=1&amp;bar=2&quot;
101     Ext.Object.toQueryString({foo: null, bar: 2}); // returns &quot;foo=&amp;bar=2&quot;
102     Ext.Object.toQueryString({'some price': '$300'}); // returns &quot;some%20price=%24300&quot;
103     Ext.Object.toQueryString({date: new Date(2011, 0, 1)}); // returns &quot;date=%222011-01-01T00%3A00%3A00%22&quot;
104     Ext.Object.toQueryString({colors: ['red', 'green', 'blue']}); // returns &quot;colors=red&amp;colors=green&amp;colors=blue&quot;
105
106 - Recursive:
107
108     Ext.Object.toQueryString({
109         username: 'Jacky',
110         dateOfBirth: {
111             day: 1,
112             month: 2,
113             year: 1911
114         },
115         hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
116     }, true); // returns the following string (broken down and url-decoded for ease of reading purpose):
117               // username=Jacky
118               //    &amp;dateOfBirth[day]=1&amp;dateOfBirth[month]=2&amp;dateOfBirth[year]=1911
119               //    &amp;hobbies[0]=coding&amp;hobbies[1]=eating&amp;hobbies[2]=sleeping&amp;hobbies[3][0]=nested&amp;hobbies[3][1]=stuff
120
121      *
122      * @param {Object} object The object to encode
123      * @param {Boolean} recursive (optional) Whether or not to interpret the object in recursive format.
124      * (PHP / Ruby on Rails servers and similar). Defaults to false
125      * @return {String} queryString
126      * @markdown
127      */
128     toQueryString: function(object, recursive) {
129         var paramObjects = [],
130             params = [],
131             i, j, ln, paramObject, value;
132
133         for (i in object) {
134             if (object.hasOwnProperty(i)) {
135                 paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
136             }
137         }
138
139         for (j = 0, ln = paramObjects.length; j &lt; ln; j++) {
140             paramObject = paramObjects[j];
141             value = paramObject.value;
142
143             if (Ext.isEmpty(value)) {
144                 value = '';
145             }
146             else if (Ext.isDate(value)) {
147                 value = Ext.Date.toString(value);
148             }
149
150             params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
151         }
152
153         return params.join('&amp;');
154     },
155
156 <span id='Ext-Object-method-fromQueryString'>    /**
157 </span>     * Converts a query string back into an object.
158      *
159 - Non-recursive:
160
161     Ext.Object.fromQueryString(foo=1&amp;bar=2); // returns {foo: 1, bar: 2}
162     Ext.Object.fromQueryString(foo=&amp;bar=2); // returns {foo: null, bar: 2}
163     Ext.Object.fromQueryString(some%20price=%24300); // returns {'some price': '$300'}
164     Ext.Object.fromQueryString(colors=red&amp;colors=green&amp;colors=blue); // returns {colors: ['red', 'green', 'blue']}
165
166 - Recursive:
167
168     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);
169
170     // returns
171     {
172         username: 'Jacky',
173         dateOfBirth: {
174             day: '1',
175             month: '2',
176             year: '1911'
177         },
178         hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
179     }
180
181      * @param {String} queryString The query string to decode
182      * @param {Boolean} recursive (Optional) Whether or not to recursively decode the string. This format is supported by
183      * PHP / Ruby on Rails servers and similar. Defaults to false
184      * @return {Object}
185      */
186     fromQueryString: function(queryString, recursive) {
187         var parts = queryString.replace(/^\?/, '').split('&amp;'),
188             object = {},
189             temp, components, name, value, i, ln,
190             part, j, subLn, matchedKeys, matchedName,
191             keys, key, nextKey;
192
193         for (i = 0, ln = parts.length; i &lt; ln; i++) {
194             part = parts[i];
195
196             if (part.length &gt; 0) {
197                 components = part.split('=');
198                 name = decodeURIComponent(components[0]);
199                 value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
200
201                 if (!recursive) {
202                     if (object.hasOwnProperty(name)) {
203                         if (!Ext.isArray(object[name])) {
204                             object[name] = [object[name]];
205                         }
206
207                         object[name].push(value);
208                     }
209                     else {
210                         object[name] = value;
211                     }
212                 }
213                 else {
214                     matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
215                     matchedName = name.match(/^([^\[]+)/);
216
217                     //&lt;debug error&gt;
218                     if (!matchedName) {
219                         Ext.Error.raise({
220                             sourceClass: &quot;Ext.Object&quot;,
221                             sourceMethod: &quot;fromQueryString&quot;,
222                             queryString: queryString,
223                             recursive: recursive,
224                             msg: 'Malformed query string given, failed parsing name from &quot;' + part + '&quot;'
225                         });
226                     }
227                     //&lt;/debug&gt;
228
229                     name = matchedName[0];
230                     keys = [];
231
232                     if (matchedKeys === null) {
233                         object[name] = value;
234                         continue;
235                     }
236
237                     for (j = 0, subLn = matchedKeys.length; j &lt; subLn; j++) {
238                         key = matchedKeys[j];
239                         key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
240                         keys.push(key);
241                     }
242
243                     keys.unshift(name);
244
245                     temp = object;
246
247                     for (j = 0, subLn = keys.length; j &lt; subLn; j++) {
248                         key = keys[j];
249
250                         if (j === subLn - 1) {
251                             if (Ext.isArray(temp) &amp;&amp; key === '') {
252                                 temp.push(value);
253                             }
254                             else {
255                                 temp[key] = value;
256                             }
257                         }
258                         else {
259                             if (temp[key] === undefined || typeof temp[key] === 'string') {
260                                 nextKey = keys[j+1];
261
262                                 temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
263                             }
264
265                             temp = temp[key];
266                         }
267                     }
268                 }
269             }
270         }
271
272         return object;
273     },
274
275 <span id='Ext-Object-method-each'>    /**
276 </span>     * Iterate through an object and invoke the given callback function for each iteration. The iteration can be stop
277      * by returning `false` in the callback function. For example:
278
279     var person = {
280         name: 'Jacky'
281         hairColor: 'black'
282         loves: ['food', 'sleeping', 'wife']
283     };
284
285     Ext.Object.each(person, function(key, value, myself) {
286         console.log(key + &quot;:&quot; + value);
287
288         if (key === 'hairColor') {
289             return false; // stop the iteration
290         }
291     });
292
293      * @param {Object} object The object to iterate
294      * @param {Function} fn The callback function. Passed arguments for each iteration are:
295
296 - {String} `key`
297 - {Mixed} `value`
298 - {Object} `object` The object itself
299
300      * @param {Object} scope (Optional) The execution scope (`this`) of the callback function
301      * @markdown
302      */
303     each: function(object, fn, scope) {
304         for (var property in object) {
305             if (object.hasOwnProperty(property)) {
306                 if (fn.call(scope || object, property, object[property], object) === false) {
307                     return;
308                 }
309             }
310         }
311     },
312
313 <span id='Ext-Object-method-merge'>    /**
314 </span>     * Merges any number of objects recursively without referencing them or their children.
315
316     var extjs = {
317         companyName: 'Ext JS',
318         products: ['Ext JS', 'Ext GWT', 'Ext Designer'],
319         isSuperCool: true
320         office: {
321             size: 2000,
322             location: 'Palo Alto',
323             isFun: true
324         }
325     };
326
327     var newStuff = {
328         companyName: 'Sencha Inc.',
329         products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
330         office: {
331             size: 40000,
332             location: 'Redwood City'
333         }
334     };
335
336     var sencha = Ext.Object.merge(extjs, newStuff);
337
338     // extjs and sencha then equals to
339     {
340         companyName: 'Sencha Inc.',
341         products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
342         isSuperCool: true
343         office: {
344             size: 30000,
345             location: 'Redwood City'
346             isFun: true
347         }
348     }
349
350      * @param {Object} object,...
351      * @return {Object} merged The object that is created as a result of merging all the objects passed in.
352      * @markdown
353      */
354     merge: function(source, key, value) {
355         if (typeof key === 'string') {
356             if (value &amp;&amp; value.constructor === Object) {
357                 if (source[key] &amp;&amp; source[key].constructor === Object) {
358                     ExtObject.merge(source[key], value);
359                 }
360                 else {
361                     source[key] = Ext.clone(value);
362                 }
363             }
364             else {
365                 source[key] = value;
366             }
367
368             return source;
369         }
370
371         var i = 1,
372             ln = arguments.length,
373             object, property;
374
375         for (; i &lt; ln; i++) {
376             object = arguments[i];
377
378             for (property in object) {
379                 if (object.hasOwnProperty(property)) {
380                     ExtObject.merge(source, property, object[property]);
381                 }
382             }
383         }
384
385         return source;
386     },
387
388 <span id='Ext-Object-method-getKey'>    /**
389 </span>     * Returns the first matching key corresponding to the given value.
390      * If no matching value is found, null is returned.
391
392     var person = {
393         name: 'Jacky',
394         loves: 'food'
395     };
396
397     alert(Ext.Object.getKey(sencha, 'loves')); // alerts 'food'
398
399      * @param {Object} object
400      * @param {Object} value The value to find
401      * @markdown
402      */
403     getKey: function(object, value) {
404         for (var property in object) {
405             if (object.hasOwnProperty(property) &amp;&amp; object[property] === value) {
406                 return property;
407             }
408         }
409
410         return null;
411     },
412
413 <span id='Ext-Object-method-getValues'>    /**
414 </span>     * Gets all values of the given object as an array.
415
416     var values = Ext.Object.getValues({
417         name: 'Jacky',
418         loves: 'food'
419     }); // ['Jacky', 'food']
420
421      * @param {Object} object
422      * @return {Array} An array of values from the object
423      * @markdown
424      */
425     getValues: function(object) {
426         var values = [],
427             property;
428
429         for (property in object) {
430             if (object.hasOwnProperty(property)) {
431                 values.push(object[property]);
432             }
433         }
434
435         return values;
436     },
437
438 <span id='Ext-Object-property-getKeys'>    /**
439 </span>     * Gets all keys of the given object as an array.
440
441     var values = Ext.Object.getKeys({
442         name: 'Jacky',
443         loves: 'food'
444     }); // ['name', 'loves']
445
446      * @param {Object} object
447      * @return {Array} An array of keys from the object
448      */
449     getKeys: ('keys' in Object.prototype) ? Object.keys : function(object) {
450         var keys = [],
451             property;
452
453         for (property in object) {
454             if (object.hasOwnProperty(property)) {
455                 keys.push(property);
456             }
457         }
458
459         return keys;
460     },
461
462 <span id='Ext-Object-method-getSize'>    /**
463 </span>     * Gets the total number of this object's own properties
464
465     var size = Ext.Object.getSize({
466         name: 'Jacky',
467         loves: 'food'
468     }); // size equals 2
469
470      * @param {Object} object
471      * @return {Number} size
472      * @markdown
473      */
474     getSize: function(object) {
475         var size = 0,
476             property;
477
478         for (property in object) {
479             if (object.hasOwnProperty(property)) {
480                 size++;
481             }
482         }
483
484         return size;
485     }
486 };
487
488
489 <span id='Ext-method-merge'>/**
490 </span> * A convenient alias method for {@link Ext.Object#merge}
491  *
492  * @member Ext
493  * @method merge
494  */
495 Ext.merge = Ext.Object.merge;
496
497 <span id='Ext-method-urlEncode'>/**
498 </span> * A convenient alias method for {@link Ext.Object#toQueryString}
499  *
500  * @member Ext
501  * @method urlEncode
502  * @deprecated 4.0.0 Use {@link Ext.Object#toQueryString Ext.Object.toQueryString} instead
503  */
504 Ext.urlEncode = function() {
505     var args = Ext.Array.from(arguments),
506         prefix = '';
507
508     // Support for the old `pre` argument
509     if ((typeof args[1] === 'string')) {
510         prefix = args[1] + '&amp;';
511         args[1] = false;
512     }
513
514     return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
515 };
516
517 <span id='Ext-method-urlDecode'>/**
518 </span> * A convenient alias method for {@link Ext.Object#fromQueryString}
519  *
520  * @member Ext
521  * @method urlDecode
522  * @deprecated 4.0.0 Use {@link Ext.Object#fromQueryString Ext.Object.fromQueryString} instead
523  */
524 Ext.urlDecode = function() {
525     return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
526 };
527
528 })();
529 </pre></pre></body></html>