Object2.html 20 KB

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