3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
18 * @author Jacky Nguyen <jacky@sencha.com>
19 * @docauthor Jacky Nguyen <jacky@sencha.com>
21 * A set of useful static methods to deal with arrays; provide missing methods for older browsers.
25 var arrayPrototype = Array.prototype,
26 slice = arrayPrototype.slice,
27 supportsSplice = function () {
36 // This detects a bug in IE8 splice method:
37 // see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/
43 array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
45 lengthBefore = array.length; //41
46 array.splice(13, 0, "XXX"); // add one element
48 if (lengthBefore+1 != array.length) {
55 supportsForEach = 'forEach' in arrayPrototype,
56 supportsMap = 'map' in arrayPrototype,
57 supportsIndexOf = 'indexOf' in arrayPrototype,
58 supportsEvery = 'every' in arrayPrototype,
59 supportsSome = 'some' in arrayPrototype,
60 supportsFilter = 'filter' in arrayPrototype,
61 supportsSort = function() {
62 var a = [1,2,3,4,5].sort(function(){ return 0; });
63 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
65 supportsSliceOnNodeList = true,
69 // IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList
70 if (typeof document !== 'undefined') {
71 slice.call(document.getElementsByTagName('body'));
74 supportsSliceOnNodeList = false;
77 function fixArrayIndex (array, index) {
78 return (index < 0) ? Math.max(0, array.length + index)
79 : Math.min(array.length, index);
83 Does the same work as splice, but with a slightly more convenient signature. The splice
84 method has bugs in IE8, so this is the implementation we use on that platform.
86 The rippling of items in the array can be tricky. Consider two use cases:
91 +---+---+---+---+---+---+---+---+
92 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
93 +---+---+---+---+---+---+---+---+
96 / / \/ \/ \ +--------------------------+
97 / / /\ /\ +--------------------------+ \
98 / / / \/ +--------------------------+ \ \
99 / / / /+--------------------------+ \ \ \
102 +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
103 | 0 | 1 | 4 | 5 | 6 | 7 | | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
104 +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
108 In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
109 that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
110 must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].
112 function replaceSim (array, index, removeCount, insert) {
113 var add = insert ? insert.length : 0,
114 length = array.length,
115 pos = fixArrayIndex(array, index);
117 // we try to use Array.push when we can for efficiency...
118 if (pos === length) {
120 array.push.apply(array, insert);
123 var remove = Math.min(removeCount, length - pos),
124 tailOldPos = pos + remove,
125 tailNewPos = tailOldPos + add - remove,
126 tailCount = length - tailOldPos,
127 lengthAfterRemove = length - remove,
130 if (tailNewPos < tailOldPos) { // case A
131 for (i = 0; i < tailCount; ++i) {
132 array[tailNewPos+i] = array[tailOldPos+i];
134 } else if (tailNewPos > tailOldPos) { // case B
135 for (i = tailCount; i--; ) {
136 array[tailNewPos+i] = array[tailOldPos+i];
138 } // else, add == remove (nothing to do)
140 if (add && pos === lengthAfterRemove) {
141 array.length = lengthAfterRemove; // truncate array
142 array.push.apply(array, insert);
144 array.length = lengthAfterRemove + add; // reserves space
145 for (i = 0; i < add; ++i) {
146 array[pos+i] = insert[i];
154 function replaceNative (array, index, removeCount, insert) {
155 if (insert && insert.length) {
156 if (index < array.length) {
157 array.splice.apply(array, [index, removeCount].concat(insert));
159 array.push.apply(array, insert);
162 array.splice(index, removeCount);
167 function eraseSim (array, index, removeCount) {
168 return replaceSim(array, index, removeCount);
171 function eraseNative (array, index, removeCount) {
172 array.splice(index, removeCount);
176 function spliceSim (array, index, removeCount) {
177 var pos = fixArrayIndex(array, index),
178 removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
180 if (arguments.length < 4) {
181 replaceSim(array, pos, removeCount);
183 replaceSim(array, pos, removeCount, slice.call(arguments, 3));
189 function spliceNative (array) {
190 return array.splice.apply(array, slice.call(arguments, 1));
193 var erase = supportsSplice ? eraseNative : eraseSim,
194 replace = supportsSplice ? replaceNative : replaceSim,
195 splice = supportsSplice ? spliceNative : spliceSim;
197 // NOTE: from here on, use erase, replace or splice (not native methods)...
199 ExtArray = Ext.Array = {
201 * Iterates an array or an iterable value and invoke the given callback function for each item.
203 * var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
205 * Ext.Array.each(countries, function(name, index, countriesItSelf) {
209 * var sum = function() {
212 * Ext.Array.each(arguments, function(value) {
219 * sum(1, 2, 3); // returns 6
221 * The iteration can be stopped by returning false in the function callback.
223 * Ext.Array.each(countries, function(name, index, countriesItSelf) {
224 * if (name === 'Singapore') {
225 * return false; // break here
229 * {@link Ext#each Ext.each} is alias for {@link Ext.Array#each Ext.Array.each}
231 * @param {Array/NodeList/Object} iterable The value to be iterated. If this
232 * argument is not iterable, the callback function is called once.
233 * @param {Function} fn The callback function. If it returns false, the iteration stops and this method returns
234 * the current `index`.
235 * @param {Object} fn.item The item at the current `index` in the passed `array`
236 * @param {Number} fn.index The current `index` within the `array`
237 * @param {Array} fn.allItems The `array` itself which was passed as the first argument
238 * @param {Boolean} fn.return Return false to stop iteration.
239 * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
240 * @param {Boolean} reverse (Optional) Reverse the iteration order (loop from the end to the beginning)
242 * @return {Boolean} See description for the `fn` parameter.
244 each: function(array, fn, scope, reverse) {
245 array = ExtArray.from(array);
250 if (reverse !== true) {
251 for (i = 0; i < ln; i++) {
252 if (fn.call(scope || array[i], array[i], i, array) === false) {
258 for (i = ln - 1; i > -1; i--) {
259 if (fn.call(scope || array[i], array[i], i, array) === false) {
269 * Iterates an array and invoke the given callback function for each item. Note that this will simply
270 * delegate to the native Array.prototype.forEach method if supported. It doesn't support stopping the
271 * iteration by returning false in the callback function like {@link Ext.Array#each}. However, performance
272 * could be much better in modern browsers comparing with {@link Ext.Array#each}
274 * @param {Array} array The array to iterate
275 * @param {Function} fn The callback function.
276 * @param {Object} fn.item The item at the current `index` in the passed `array`
277 * @param {Number} fn.index The current `index` within the `array`
278 * @param {Array} fn.allItems The `array` itself which was passed as the first argument
279 * @param {Object} scope (Optional) The execution scope (`this`) in which the specified function is executed.
281 forEach: function(array, fn, scope) {
282 if (supportsForEach) {
283 return array.forEach(fn, scope);
289 for (; i < ln; i++) {
290 fn.call(scope, array[i], i, array);
295 * Get the index of the provided `item` in the given `array`, a supplement for the
296 * missing arrayPrototype.indexOf in Internet Explorer.
298 * @param {Array} array The array to check
299 * @param {Object} item The item to look for
300 * @param {Number} from (Optional) The index at which to begin the search
301 * @return {Number} The index of item in the array (or -1 if it is not found)
303 indexOf: function(array, item, from) {
304 if (supportsIndexOf) {
305 return array.indexOf(item, from);
308 var i, length = array.length;
310 for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
311 if (array[i] === item) {
320 * Checks whether or not the given `array` contains the specified `item`
322 * @param {Array} array The array to check
323 * @param {Object} item The item to look for
324 * @return {Boolean} True if the array contains the item, false otherwise
326 contains: function(array, item) {
327 if (supportsIndexOf) {
328 return array.indexOf(item) !== -1;
333 for (i = 0, ln = array.length; i < ln; i++) {
334 if (array[i] === item) {
343 * Converts any iterable (numeric indices and a length property) into a true array.
346 * var args = Ext.Array.toArray(arguments),
347 * fromSecondToLastArgs = Ext.Array.toArray(arguments, 1);
349 * alert(args.join(' '));
350 * alert(fromSecondToLastArgs.join(' '));
353 * test('just', 'testing', 'here'); // alerts 'just testing here';
354 * // alerts 'testing here';
356 * Ext.Array.toArray(document.getElementsByTagName('div')); // will convert the NodeList into an array
357 * Ext.Array.toArray('splitted'); // returns ['s', 'p', 'l', 'i', 't', 't', 'e', 'd']
358 * Ext.Array.toArray('splitted', 0, 3); // returns ['s', 'p', 'l', 'i']
360 * {@link Ext#toArray Ext.toArray} is alias for {@link Ext.Array#toArray Ext.Array.toArray}
362 * @param {Object} iterable the iterable object to be turned into a true Array.
363 * @param {Number} start (Optional) a zero-based index that specifies the start of extraction. Defaults to 0
364 * @param {Number} end (Optional) a zero-based index that specifies the end of extraction. Defaults to the last
365 * index of the iterable value
366 * @return {Array} array
368 toArray: function(iterable, start, end){
369 if (!iterable || !iterable.length) {
373 if (typeof iterable === 'string') {
374 iterable = iterable.split('');
377 if (supportsSliceOnNodeList) {
378 return slice.call(iterable, start || 0, end || iterable.length);
385 end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
387 for (i = start; i < end; i++) {
388 array.push(iterable[i]);
395 * Plucks the value of a property from each item in the Array. Example:
397 * Ext.Array.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
399 * @param {Array/NodeList} array The Array of items to pluck the value from.
400 * @param {String} propertyName The property name to pluck from each element.
401 * @return {Array} The value from each item in the Array.
403 pluck: function(array, propertyName) {
407 for (i = 0, ln = array.length; i < ln; i++) {
410 ret.push(item[propertyName]);
417 * Creates a new array with the results of calling a provided function on every element in this array.
419 * @param {Array} array
420 * @param {Function} fn Callback function for each item
421 * @param {Object} scope Callback function scope
422 * @return {Array} results
424 map: function(array, fn, scope) {
426 return array.map(fn, scope);
433 for (; i < len; i++) {
434 results[i] = fn.call(scope, array[i], i, array);
441 * Executes the specified function for each array element until the function returns a falsy value.
442 * If such an item is found, the function will return false immediately.
443 * Otherwise, it will return true.
445 * @param {Array} array
446 * @param {Function} fn Callback function for each item
447 * @param {Object} scope Callback function scope
448 * @return {Boolean} True if no false value is returned by the callback function.
450 every: function(array, fn, scope) {
453 Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
457 return array.every(fn, scope);
463 for (; i < ln; ++i) {
464 if (!fn.call(scope, array[i], i, array)) {
473 * Executes the specified function for each array element until the function returns a truthy value.
474 * If such an item is found, the function will return true immediately. Otherwise, it will return false.
476 * @param {Array} array
477 * @param {Function} fn Callback function for each item
478 * @param {Object} scope Callback function scope
479 * @return {Boolean} True if the callback function returns a truthy value.
481 some: function(array, fn, scope) {
484 Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
488 return array.some(fn, scope);
494 for (; i < ln; ++i) {
495 if (fn.call(scope, array[i], i, array)) {
504 * Filter through an array and remove empty item as defined in {@link Ext#isEmpty Ext.isEmpty}
506 * See {@link Ext.Array#filter}
508 * @param {Array} array
509 * @return {Array} results
511 clean: function(array) {
517 for (; i < ln; i++) {
520 if (!Ext.isEmpty(item)) {
529 * Returns a new array with unique items
531 * @param {Array} array
532 * @return {Array} results
534 unique: function(array) {
540 for (; i < ln; i++) {
543 if (ExtArray.indexOf(clone, item) === -1) {
552 * Creates a new array with all of the elements of this array for which
553 * the provided filtering function returns true.
555 * @param {Array} array
556 * @param {Function} fn Callback function for each item
557 * @param {Object} scope Callback function scope
558 * @return {Array} results
560 filter: function(array, fn, scope) {
561 if (supportsFilter) {
562 return array.filter(fn, scope);
569 for (; i < ln; i++) {
570 if (fn.call(scope, array[i], i, array)) {
571 results.push(array[i]);
579 * Converts a value to an array if it's not already an array; returns:
581 * - An empty array if given value is `undefined` or `null`
582 * - Itself if given value is already an array
583 * - An array copy if given value is {@link Ext#isIterable iterable} (arguments, NodeList and alike)
584 * - An array with one item which is the given value, otherwise
586 * @param {Object} value The value to convert to an array if it's not already is an array
587 * @param {Boolean} newReference (Optional) True to clone the given array and return a new reference if necessary,
589 * @return {Array} array
591 from: function(value, newReference) {
592 if (value === undefined || value === null) {
596 if (Ext.isArray(value)) {
597 return (newReference) ? slice.call(value) : value;
600 if (value && value.length !== undefined && typeof value !== 'string') {
601 return Ext.toArray(value);
608 * Removes the specified item from the array if it exists
610 * @param {Array} array The array
611 * @param {Object} item The item to remove
612 * @return {Array} The passed array itself
614 remove: function(array, item) {
615 var index = ExtArray.indexOf(array, item);
618 erase(array, index, 1);
625 * Push an item into the array only if the array doesn't contain it yet
627 * @param {Array} array The array
628 * @param {Object} item The item to include
630 include: function(array, item) {
631 if (!ExtArray.contains(array, item)) {
637 * Clone a flat array without referencing the previous one. Note that this is different
638 * from Ext.clone since it doesn't handle recursive cloning. It's simply a convenient, easy-to-remember method
639 * for Array.prototype.slice.call(array)
641 * @param {Array} array The array
642 * @return {Array} The clone array
644 clone: function(array) {
645 return slice.call(array);
649 * Merge multiple arrays into one with unique items.
651 * {@link Ext.Array#union} is alias for {@link Ext.Array#merge}
653 * @param {Array} array1
654 * @param {Array} array2
656 * @return {Array} merged
659 var args = slice.call(arguments),
663 for (i = 0, ln = args.length; i < ln; i++) {
664 array = array.concat(args[i]);
667 return ExtArray.unique(array);
671 * Merge multiple arrays into one with unique items that exist in all of the arrays.
673 * @param {Array} array1
674 * @param {Array} array2
676 * @return {Array} intersect
678 intersect: function() {
680 arrays = slice.call(arguments),
681 i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
683 if (!arrays.length) {
687 // Find the smallest array
688 for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
689 if (!minArray || array.length < minArray.length) {
695 minArray = ExtArray.unique(minArray);
698 // Use the smallest unique'd array as the anchor loop. If the other array(s) do contain
699 // an item in the small array, we're likely to find it before reaching the end
700 // of the inner loop and can terminate the search early.
701 for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
704 for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
705 for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
713 if (count === arraysLn) {
722 * Perform a set difference A-B by subtracting all items in array B from array A.
724 * @param {Array} arrayA
725 * @param {Array} arrayB
726 * @return {Array} difference
728 difference: function(arrayA, arrayB) {
729 var clone = slice.call(arrayA),
733 for (i = 0,lnB = arrayB.length; i < lnB; i++) {
734 for (j = 0; j < ln; j++) {
735 if (clone[j] === arrayB[i]) {
747 * Returns a shallow copy of a part of an array. This is equivalent to the native
748 * call "Array.prototype.slice.call(array, begin, end)". This is often used when "array"
749 * is "arguments" since the arguments object does not supply a slice method but can
750 * be the context object to Array.prototype.slice.
752 * @param {Array} array The array (or arguments object).
753 * @param {Number} begin The index at which to begin. Negative values are offsets from
754 * the end of the array.
755 * @param {Number} end The index at which to end. The copied items do not include
756 * end. Negative values are offsets from the end of the array. If end is omitted,
757 * all items up to the end of the array are copied.
758 * @return {Array} The copied piece of the array.
760 // Note: IE6 will return [] on slice.call(x, undefined).
761 slice: ([1,2].slice(1, undefined).length ?
762 function (array, begin, end) {
763 return slice.call(array, begin, end);
765 // at least IE6 uses arguments.length for variadic signature
766 function (array, begin, end) {
767 // After tested for IE 6, the one below is of the best performance
768 // see http://jsperf.com/slice-fix
769 if (typeof begin === 'undefined') {
770 return slice.call(array);
772 if (typeof end === 'undefined') {
773 return slice.call(array, begin);
775 return slice.call(array, begin, end);
780 * Sorts the elements of an Array.
781 * By default, this method sorts the elements alphabetically and ascending.
783 * @param {Array} array The array to sort.
784 * @param {Function} sortFn (optional) The comparison function.
785 * @return {Array} The sorted array.
787 sort: function(array, sortFn) {
790 return array.sort(sortFn);
796 var length = array.length,
801 for (; i < length; i++) {
803 for (j = i + 1; j < length; j++) {
805 comparison = sortFn(array[j], array[min]);
806 if (comparison < 0) {
809 } else if (array[j] < array[min]) {
815 array[i] = array[min];
824 * Recursively flattens into 1-d Array. Injects Arrays inline.
826 * @param {Array} array The array to flatten
827 * @return {Array} The 1-d array.
829 flatten: function(array) {
832 function rFlatten(a) {
835 for (i = 0, ln = a.length; i < ln; i++) {
838 if (Ext.isArray(v)) {
848 return rFlatten(array);
852 * Returns the minimum value in the Array.
854 * @param {Array/NodeList} array The Array from which to select the minimum value.
855 * @param {Function} comparisonFn (optional) a function to perform the comparision which determines minimization.
856 * If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
857 * @return {Object} minValue The minimum value
859 min: function(array, comparisonFn) {
863 for (i = 0, ln = array.length; i < ln; i++) {
867 if (comparisonFn(min, item) === 1) {
882 * Returns the maximum value in the Array.
884 * @param {Array/NodeList} array The Array from which to select the maximum value.
885 * @param {Function} comparisonFn (optional) a function to perform the comparision which determines maximization.
886 * If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
887 * @return {Object} maxValue The maximum value
889 max: function(array, comparisonFn) {
893 for (i = 0, ln = array.length; i < ln; i++) {
897 if (comparisonFn(max, item) === -1) {
912 * Calculates the mean of all items in the array.
914 * @param {Array} array The Array to calculate the mean value of.
915 * @return {Number} The mean.
917 mean: function(array) {
918 return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
922 * Calculates the sum of all items in the given array.
924 * @param {Array} array The Array to calculate the sum value of.
925 * @return {Number} The sum.
927 sum: function(array) {
931 for (i = 0,ln = array.length; i < ln; i++) {
941 _replaceSim: replaceSim, // for unit testing
942 _spliceSim: spliceSim,
946 * Removes items from an array. This is functionally equivalent to the splice method
947 * of Array, but works around bugs in IE8's splice method and does not copy the
948 * removed elements in order to return them (because very often they are ignored).
950 * @param {Array} array The Array on which to replace.
951 * @param {Number} index The index in the array at which to operate.
952 * @param {Number} removeCount The number of items to remove at index.
953 * @return {Array} The array passed.
959 * Inserts items in to an array.
961 * @param {Array} array The Array on which to replace.
962 * @param {Number} index The index in the array at which to operate.
963 * @param {Array} items The array of items to insert at index.
964 * @return {Array} The array passed.
966 insert: function (array, index, items) {
967 return replace(array, index, 0, items);
971 * Replaces items in an array. This is functionally equivalent to the splice method
972 * of Array, but works around bugs in IE8's splice method and is often more convenient
973 * to call because it accepts an array of items to insert rather than use a variadic
976 * @param {Array} array The Array on which to replace.
977 * @param {Number} index The index in the array at which to operate.
978 * @param {Number} removeCount The number of items to remove at index (can be 0).
979 * @param {Array} insert (optional) An array of items to insert at index.
980 * @return {Array} The array passed.
986 * Replaces items in an array. This is equivalent to the splice method of Array, but
987 * works around bugs in IE8's splice method. The signature is exactly the same as the
988 * splice method except that the array is the first argument. All arguments following
989 * removeCount are inserted in the array at index.
991 * @param {Array} array The Array on which to replace.
992 * @param {Number} index The index in the array at which to operate.
993 * @param {Number} removeCount The number of items to remove at index (can be 0).
994 * @return {Array} An array containing the removed items.
1003 * @alias Ext.Array#each
1005 Ext.each = ExtArray.each;
1010 * @alias Ext.Array#merge
1012 ExtArray.union = ExtArray.merge;
1015 * Old alias to {@link Ext.Array#min}
1016 * @deprecated 4.0.0 Use {@link Ext.Array#min} instead
1019 * @alias Ext.Array#min
1021 Ext.min = ExtArray.min;
1024 * Old alias to {@link Ext.Array#max}
1025 * @deprecated 4.0.0 Use {@link Ext.Array#max} instead
1028 * @alias Ext.Array#max
1030 Ext.max = ExtArray.max;
1033 * Old alias to {@link Ext.Array#sum}
1034 * @deprecated 4.0.0 Use {@link Ext.Array#sum} instead
1037 * @alias Ext.Array#sum
1039 Ext.sum = ExtArray.sum;
1042 * Old alias to {@link Ext.Array#mean}
1043 * @deprecated 4.0.0 Use {@link Ext.Array#mean} instead
1046 * @alias Ext.Array#mean
1048 Ext.mean = ExtArray.mean;
1051 * Old alias to {@link Ext.Array#flatten}
1052 * @deprecated 4.0.0 Use {@link Ext.Array#flatten} instead
1055 * @alias Ext.Array#flatten
1057 Ext.flatten = ExtArray.flatten;
1060 * Old alias to {@link Ext.Array#clean}
1061 * @deprecated 4.0.0 Use {@link Ext.Array#clean} instead
1064 * @alias Ext.Array#clean
1066 Ext.clean = ExtArray.clean;
1069 * Old alias to {@link Ext.Array#unique}
1070 * @deprecated 4.0.0 Use {@link Ext.Array#unique} instead
1073 * @alias Ext.Array#unique
1075 Ext.unique = ExtArray.unique;
1078 * Old alias to {@link Ext.Array#pluck Ext.Array.pluck}
1079 * @deprecated 4.0.0 Use {@link Ext.Array#pluck Ext.Array.pluck} instead
1082 * @alias Ext.Array#pluck
1084 Ext.pluck = ExtArray.pluck;
1089 * @alias Ext.Array#toArray
1091 Ext.toArray = function() {
1092 return ExtArray.toArray.apply(ExtArray, arguments);