Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Array2.html
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="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../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-Array'>/**
19 </span> * @author Jacky Nguyen &lt;jacky@sencha.com&gt;
20  * @docauthor Jacky Nguyen &lt;jacky@sencha.com&gt;
21  * @class Ext.Array
22  *
23  * A set of useful static methods to deal with arrays; provide missing methods for older browsers.
24
25  * @singleton
26  * @markdown
27  */
28 (function() {
29
30     var arrayPrototype = Array.prototype,
31         slice = arrayPrototype.slice,
32         supportsSplice = function () {
33             var array = [],
34                 lengthBefore,
35                 j = 20;
36
37             if (!array.splice) {
38                 return false;
39             }
40
41             // This detects a bug in IE8 splice method:
42             // see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/
43
44             while (j--) {
45                 array.push(&quot;A&quot;);
46             }
47
48             array.splice(15, 0, &quot;F&quot;, &quot;F&quot;, &quot;F&quot;, &quot;F&quot;, &quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;,&quot;F&quot;);
49
50             lengthBefore = array.length; //41
51             array.splice(13, 0, &quot;XXX&quot;); // add one element
52
53             if (lengthBefore+1 != array.length) {
54                 return false;
55             }
56             // end IE8 bug
57
58             return true;
59         }(),
60         supportsForEach = 'forEach' in arrayPrototype,
61         supportsMap = 'map' in arrayPrototype,
62         supportsIndexOf = 'indexOf' in arrayPrototype,
63         supportsEvery = 'every' in arrayPrototype,
64         supportsSome = 'some' in arrayPrototype,
65         supportsFilter = 'filter' in arrayPrototype,
66         supportsSort = function() {
67             var a = [1,2,3,4,5].sort(function(){ return 0; });
68             return a[0] === 1 &amp;&amp; a[1] === 2 &amp;&amp; a[2] === 3 &amp;&amp; a[3] === 4 &amp;&amp; a[4] === 5;
69         }(),
70         supportsSliceOnNodeList = true,
71         ExtArray;
72
73     try {
74         // IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList
75         if (typeof document !== 'undefined') {
76             slice.call(document.getElementsByTagName('body'));
77         }
78     } catch (e) {
79         supportsSliceOnNodeList = false;
80     }
81
82     function fixArrayIndex (array, index) {
83         return (index &lt; 0) ? Math.max(0, array.length + index)
84                            : Math.min(array.length, index);
85     }
86
87     /*
88     Does the same work as splice, but with a slightly more convenient signature. The splice
89     method has bugs in IE8, so this is the implementation we use on that platform.
90
91     The rippling of items in the array can be tricky. Consider two use cases:
92
93                   index=2
94                   removeCount=2
95                  /=====\
96         +---+---+---+---+---+---+---+---+
97         | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
98         +---+---+---+---+---+---+---+---+
99                          /  \/  \/  \/  \
100                         /   /\  /\  /\   \
101                        /   /  \/  \/  \   +--------------------------+
102                       /   /   /\  /\   +--------------------------+   \
103                      /   /   /  \/  +--------------------------+   \   \
104                     /   /   /   /+--------------------------+   \   \   \
105                    /   /   /   /                             \   \   \   \
106                   v   v   v   v                               v   v   v   v
107         +---+---+---+---+---+---+       +---+---+---+---+---+---+---+---+---+
108         | 0 | 1 | 4 | 5 | 6 | 7 |       | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
109         +---+---+---+---+---+---+       +---+---+---+---+---+---+---+---+---+
110         A                               B        \=========/
111                                                  insert=[a,b,c]
112
113     In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
114     that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
115     must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].
116     */
117     function replaceSim (array, index, removeCount, insert) {
118         var add = insert ? insert.length : 0,
119             length = array.length,
120             pos = fixArrayIndex(array, index);
121
122         // we try to use Array.push when we can for efficiency...
123         if (pos === length) {
124             if (add) {
125                 array.push.apply(array, insert);
126             }
127         } else {
128             var remove = Math.min(removeCount, length - pos),
129                 tailOldPos = pos + remove,
130                 tailNewPos = tailOldPos + add - remove,
131                 tailCount = length - tailOldPos,
132                 lengthAfterRemove = length - remove,
133                 i;
134
135             if (tailNewPos &lt; tailOldPos) { // case A
136                 for (i = 0; i &lt; tailCount; ++i) {
137                     array[tailNewPos+i] = array[tailOldPos+i];
138                 }
139             } else if (tailNewPos &gt; tailOldPos) { // case B
140                 for (i = tailCount; i--; ) {
141                     array[tailNewPos+i] = array[tailOldPos+i];
142                 }
143             } // else, add == remove (nothing to do)
144
145             if (add &amp;&amp; pos === lengthAfterRemove) {
146                 array.length = lengthAfterRemove; // truncate array
147                 array.push.apply(array, insert);
148             } else {
149                 array.length = lengthAfterRemove + add; // reserves space
150                 for (i = 0; i &lt; add; ++i) {
151                     array[pos+i] = insert[i];
152                 }
153             }
154         }
155
156         return array;
157     }
158
159     function replaceNative (array, index, removeCount, insert) {
160         if (insert &amp;&amp; insert.length) {
161             if (index &lt; array.length) {
162                 array.splice.apply(array, [index, removeCount].concat(insert));
163             } else {
164                 array.push.apply(array, insert);
165             }
166         } else {
167             array.splice(index, removeCount);
168         }
169         return array;
170     }
171
172     function eraseSim (array, index, removeCount) {
173         return replaceSim(array, index, removeCount);
174     }
175
176     function eraseNative (array, index, removeCount) {
177         array.splice(index, removeCount);
178         return array;
179     }
180
181     function spliceSim (array, index, removeCount) {
182         var pos = fixArrayIndex(array, index),
183             removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
184
185         if (arguments.length &lt; 4) {
186             replaceSim(array, pos, removeCount);
187         } else {
188             replaceSim(array, pos, removeCount, slice.call(arguments, 3));
189         }
190
191         return removed;
192     }
193
194     function spliceNative (array) {
195         return array.splice.apply(array, slice.call(arguments, 1));
196     }
197
198     var erase = supportsSplice ? eraseNative : eraseSim,
199         replace = supportsSplice ? replaceNative : replaceSim,
200         splice = supportsSplice ? spliceNative : spliceSim;
201
202     // NOTE: from here on, use erase, replace or splice (not native methods)...
203
204     ExtArray = Ext.Array = {
205 <span id='Ext-Array-method-each'>        /**
206 </span>         * Iterates an array or an iterable value and invoke the given callback function for each item.
207          *
208          *     var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
209          *
210          *     Ext.Array.each(countries, function(name, index, countriesItSelf) {
211          *         console.log(name);
212          *     });
213          *
214          *     var sum = function() {
215          *         var sum = 0;
216          *
217          *         Ext.Array.each(arguments, function(value) {
218          *             sum += value;
219          *         });
220          *
221          *         return sum;
222          *     };
223          *
224          *     sum(1, 2, 3); // returns 6
225          *
226          * The iteration can be stopped by returning false in the function callback.
227          *
228          *     Ext.Array.each(countries, function(name, index, countriesItSelf) {
229          *         if (name === 'Singapore') {
230          *             return false; // break here
231          *         }
232          *     });
233          *
234          * {@link Ext#each Ext.each} is alias for {@link Ext.Array#each Ext.Array.each}
235          *
236          * @param {Array/NodeList/Mixed} iterable The value to be iterated. If this
237          * argument is not iterable, the callback function is called once.
238          * @param {Function} fn The callback function. If it returns false, the iteration stops and this method returns
239          * the current `index`. Arguments passed to this callback function are:
240          *
241          * - `item` : Mixed - The item at the current `index` in the passed `array`
242          * - `index` : Number - The current `index` within the `array`
243          * - `allItems` : Array/NodeList/Mixed - The `array` passed as the first argument to `Ext.Array.each`
244          *
245          * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
246          * @param {Boolean} reverse (Optional) Reverse the iteration order (loop from the end to the beginning)
247          * Defaults false
248          * @return {Boolean} See description for the `fn` parameter.
249          */
250         each: function(array, fn, scope, reverse) {
251             array = ExtArray.from(array);
252
253             var i,
254                 ln = array.length;
255
256             if (reverse !== true) {
257                 for (i = 0; i &lt; ln; i++) {
258                     if (fn.call(scope || array[i], array[i], i, array) === false) {
259                         return i;
260                     }
261                 }
262             }
263             else {
264                 for (i = ln - 1; i &gt; -1; i--) {
265                     if (fn.call(scope || array[i], array[i], i, array) === false) {
266                         return i;
267                     }
268                 }
269             }
270
271             return true;
272         },
273
274 <span id='Ext-Array-method-forEach'>        /**
275 </span>         * Iterates an array and invoke the given callback function for each item. Note that this will simply
276          * delegate to the native Array.prototype.forEach method if supported.
277          * It doesn't support stopping the iteration by returning false in the callback function like
278          * {@link Ext.Array#each}. However, performance could be much better in modern browsers comparing with
279          * {@link Ext.Array#each}
280          *
281          * @param {Array} array The array to iterate
282          * @param {Function} fn The function callback, to be invoked these arguments:
283          *
284          * - `item` : Mixed - The item at the current `index` in the passed `array`
285          * - `index` : Number - The current `index` within the `array`
286          * - `allItems` : Array - The `array` itself which was passed as the first argument
287          *
288          * @param {Object} scope (Optional) The execution scope (`this`) in which the specified function is executed.
289          */
290         forEach: function(array, fn, scope) {
291             if (supportsForEach) {
292                 return array.forEach(fn, scope);
293             }
294
295             var i = 0,
296                 ln = array.length;
297
298             for (; i &lt; ln; i++) {
299                 fn.call(scope, array[i], i, array);
300             }
301         },
302
303 <span id='Ext-Array-method-indexOf'>        /**
304 </span>         * Get the index of the provided `item` in the given `array`, a supplement for the
305          * missing arrayPrototype.indexOf in Internet Explorer.
306          *
307          * @param {Array} array The array to check
308          * @param {Mixed} item The item to look for
309          * @param {Number} from (Optional) The index at which to begin the search
310          * @return {Number} The index of item in the array (or -1 if it is not found)
311          */
312         indexOf: function(array, item, from) {
313             if (supportsIndexOf) {
314                 return array.indexOf(item, from);
315             }
316
317             var i, length = array.length;
318
319             for (i = (from &lt; 0) ? Math.max(0, length + from) : from || 0; i &lt; length; i++) {
320                 if (array[i] === item) {
321                     return i;
322                 }
323             }
324
325             return -1;
326         },
327
328 <span id='Ext-Array-method-contains'>        /**
329 </span>         * Checks whether or not the given `array` contains the specified `item`
330          *
331          * @param {Array} array The array to check
332          * @param {Mixed} item The item to look for
333          * @return {Boolean} True if the array contains the item, false otherwise
334          */
335         contains: function(array, item) {
336             if (supportsIndexOf) {
337                 return array.indexOf(item) !== -1;
338             }
339
340             var i, ln;
341
342             for (i = 0, ln = array.length; i &lt; ln; i++) {
343                 if (array[i] === item) {
344                     return true;
345                 }
346             }
347
348             return false;
349         },
350
351 <span id='Ext-Array-method-toArray'>        /**
352 </span>         * Converts any iterable (numeric indices and a length property) into a true array.
353          *
354          *     function test() {
355          *         var args = Ext.Array.toArray(arguments),
356          *             fromSecondToLastArgs = Ext.Array.toArray(arguments, 1);
357          *
358          *         alert(args.join(' '));
359          *         alert(fromSecondToLastArgs.join(' '));
360          *     }
361          *
362          *     test('just', 'testing', 'here'); // alerts 'just testing here';
363          *                                      // alerts 'testing here';
364          *
365          *     Ext.Array.toArray(document.getElementsByTagName('div')); // will convert the NodeList into an array
366          *     Ext.Array.toArray('splitted'); // returns ['s', 'p', 'l', 'i', 't', 't', 'e', 'd']
367          *     Ext.Array.toArray('splitted', 0, 3); // returns ['s', 'p', 'l', 'i']
368          *
369          * {@link Ext#toArray Ext.toArray} is alias for {@link Ext.Array#toArray Ext.Array.toArray}
370          *
371          * @param {Mixed} iterable the iterable object to be turned into a true Array.
372          * @param {Number} start (Optional) a zero-based index that specifies the start of extraction. Defaults to 0
373          * @param {Number} end (Optional) a zero-based index that specifies the end of extraction. Defaults to the last
374          * index of the iterable value
375          * @return {Array} array
376          */
377         toArray: function(iterable, start, end){
378             if (!iterable || !iterable.length) {
379                 return [];
380             }
381
382             if (typeof iterable === 'string') {
383                 iterable = iterable.split('');
384             }
385
386             if (supportsSliceOnNodeList) {
387                 return slice.call(iterable, start || 0, end || iterable.length);
388             }
389
390             var array = [],
391                 i;
392
393             start = start || 0;
394             end = end ? ((end &lt; 0) ? iterable.length + end : end) : iterable.length;
395
396             for (i = start; i &lt; end; i++) {
397                 array.push(iterable[i]);
398             }
399
400             return array;
401         },
402
403 <span id='Ext-Array-method-pluck'>        /**
404 </span>         * Plucks the value of a property from each item in the Array. Example:
405          *
406          *     Ext.Array.pluck(Ext.query(&quot;p&quot;), &quot;className&quot;); // [el1.className, el2.className, ..., elN.className]
407          *
408          * @param {Array|NodeList} array The Array of items to pluck the value from.
409          * @param {String} propertyName The property name to pluck from each element.
410          * @return {Array} The value from each item in the Array.
411          */
412         pluck: function(array, propertyName) {
413             var ret = [],
414                 i, ln, item;
415
416             for (i = 0, ln = array.length; i &lt; ln; i++) {
417                 item = array[i];
418
419                 ret.push(item[propertyName]);
420             }
421
422             return ret;
423         },
424
425 <span id='Ext-Array-method-map'>        /**
426 </span>         * Creates a new array with the results of calling a provided function on every element in this array.
427          *
428          * @param {Array} array
429          * @param {Function} fn Callback function for each item
430          * @param {Object} scope Callback function scope
431          * @return {Array} results
432          */
433         map: function(array, fn, scope) {
434             if (supportsMap) {
435                 return array.map(fn, scope);
436             }
437
438             var results = [],
439                 i = 0,
440                 len = array.length;
441
442             for (; i &lt; len; i++) {
443                 results[i] = fn.call(scope, array[i], i, array);
444             }
445
446             return results;
447         },
448
449 <span id='Ext-Array-method-every'>        /**
450 </span>         * Executes the specified function for each array element until the function returns a falsy value.
451          * If such an item is found, the function will return false immediately.
452          * Otherwise, it will return true.
453          *
454          * @param {Array} array
455          * @param {Function} fn Callback function for each item
456          * @param {Object} scope Callback function scope
457          * @return {Boolean} True if no false value is returned by the callback function.
458          */
459         every: function(array, fn, scope) {
460             //&lt;debug&gt;
461             if (!fn) {
462                 Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
463             }
464             //&lt;/debug&gt;
465             if (supportsEvery) {
466                 return array.every(fn, scope);
467             }
468
469             var i = 0,
470                 ln = array.length;
471
472             for (; i &lt; ln; ++i) {
473                 if (!fn.call(scope, array[i], i, array)) {
474                     return false;
475                 }
476             }
477
478             return true;
479         },
480
481 <span id='Ext-Array-method-some'>        /**
482 </span>         * Executes the specified function for each array element until the function returns a truthy value.
483          * If such an item is found, the function will return true immediately. Otherwise, it will return false.
484          *
485          * @param {Array} array
486          * @param {Function} fn Callback function for each item
487          * @param {Object} scope Callback function scope
488          * @return {Boolean} True if the callback function returns a truthy value.
489          */
490         some: function(array, fn, scope) {
491             //&lt;debug&gt;
492             if (!fn) {
493                 Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
494             }
495             //&lt;/debug&gt;
496             if (supportsSome) {
497                 return array.some(fn, scope);
498             }
499
500             var i = 0,
501                 ln = array.length;
502
503             for (; i &lt; ln; ++i) {
504                 if (fn.call(scope, array[i], i, array)) {
505                     return true;
506                 }
507             }
508
509             return false;
510         },
511
512 <span id='Ext-Array-method-clean'>        /**
513 </span>         * Filter through an array and remove empty item as defined in {@link Ext#isEmpty Ext.isEmpty}
514          *
515          * See {@link Ext.Array#filter}
516          *
517          * @param {Array} array
518          * @return {Array} results
519          */
520         clean: function(array) {
521             var results = [],
522                 i = 0,
523                 ln = array.length,
524                 item;
525
526             for (; i &lt; ln; i++) {
527                 item = array[i];
528
529                 if (!Ext.isEmpty(item)) {
530                     results.push(item);
531                 }
532             }
533
534             return results;
535         },
536
537 <span id='Ext-Array-method-unique'>        /**
538 </span>         * Returns a new array with unique items
539          *
540          * @param {Array} array
541          * @return {Array} results
542          */
543         unique: function(array) {
544             var clone = [],
545                 i = 0,
546                 ln = array.length,
547                 item;
548
549             for (; i &lt; ln; i++) {
550                 item = array[i];
551
552                 if (ExtArray.indexOf(clone, item) === -1) {
553                     clone.push(item);
554                 }
555             }
556
557             return clone;
558         },
559
560 <span id='Ext-Array-method-filter'>        /**
561 </span>         * Creates a new array with all of the elements of this array for which
562          * the provided filtering function returns true.
563          *
564          * @param {Array} array
565          * @param {Function} fn Callback function for each item
566          * @param {Object} scope Callback function scope
567          * @return {Array} results
568          */
569         filter: function(array, fn, scope) {
570             if (supportsFilter) {
571                 return array.filter(fn, scope);
572             }
573
574             var results = [],
575                 i = 0,
576                 ln = array.length;
577
578             for (; i &lt; ln; i++) {
579                 if (fn.call(scope, array[i], i, array)) {
580                     results.push(array[i]);
581                 }
582             }
583
584             return results;
585         },
586
587 <span id='Ext-Array-method-from'>        /**
588 </span>         * Converts a value to an array if it's not already an array; returns:
589          *
590          * - An empty array if given value is `undefined` or `null`
591          * - Itself if given value is already an array
592          * - An array copy if given value is {@link Ext#isIterable iterable} (arguments, NodeList and alike)
593          * - An array with one item which is the given value, otherwise
594          *
595          * @param {Array/Mixed} value The value to convert to an array if it's not already is an array
596          * @param {Boolean} (Optional) newReference True to clone the given array and return a new reference if necessary,
597          * defaults to false
598          * @return {Array} array
599          */
600         from: function(value, newReference) {
601             if (value === undefined || value === null) {
602                 return [];
603             }
604
605             if (Ext.isArray(value)) {
606                 return (newReference) ? slice.call(value) : value;
607             }
608
609             if (value &amp;&amp; value.length !== undefined &amp;&amp; typeof value !== 'string') {
610                 return Ext.toArray(value);
611             }
612
613             return [value];
614         },
615
616 <span id='Ext-Array-method-remove'>        /**
617 </span>         * Removes the specified item from the array if it exists
618          *
619          * @param {Array} array The array
620          * @param {Mixed} item The item to remove
621          * @return {Array} The passed array itself
622          */
623         remove: function(array, item) {
624             var index = ExtArray.indexOf(array, item);
625
626             if (index !== -1) {
627                 erase(array, index, 1);
628             }
629
630             return array;
631         },
632
633 <span id='Ext-Array-method-include'>        /**
634 </span>         * Push an item into the array only if the array doesn't contain it yet
635          *
636          * @param {Array} array The array
637          * @param {Mixed} item The item to include
638          */
639         include: function(array, item) {
640             if (!ExtArray.contains(array, item)) {
641                 array.push(item);
642             }
643         },
644
645 <span id='Ext-Array-method-clone'>        /**
646 </span>         * Clone a flat array without referencing the previous one. Note that this is different
647          * from Ext.clone since it doesn't handle recursive cloning. It's simply a convenient, easy-to-remember method
648          * for Array.prototype.slice.call(array)
649          *
650          * @param {Array} array The array
651          * @return {Array} The clone array
652          */
653         clone: function(array) {
654             return slice.call(array);
655         },
656
657 <span id='Ext-Array-method-merge'>        /**
658 </span>         * Merge multiple arrays into one with unique items.
659          *
660          * {@link Ext.Array#union} is alias for {@link Ext.Array#merge}
661          *
662          * @param {Array} array1
663          * @param {Array} array2
664          * @param {Array} etc
665          * @return {Array} merged
666          */
667         merge: function() {
668             var args = slice.call(arguments),
669                 array = [],
670                 i, ln;
671
672             for (i = 0, ln = args.length; i &lt; ln; i++) {
673                 array = array.concat(args[i]);
674             }
675
676             return ExtArray.unique(array);
677         },
678
679 <span id='Ext-Array-method-intersect'>        /**
680 </span>         * Merge multiple arrays into one with unique items that exist in all of the arrays.
681          *
682          * @param {Array} array1
683          * @param {Array} array2
684          * @param {Array} etc
685          * @return {Array} intersect
686          */
687         intersect: function() {
688             var intersect = [],
689                 arrays = slice.call(arguments),
690                 i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
691
692             if (!arrays.length) {
693                 return intersect;
694             }
695
696             // Find the smallest array
697             for (i = x = 0,ln = arrays.length; i &lt; ln,array = arrays[i]; i++) {
698                 if (!minArray || array.length &lt; minArray.length) {
699                     minArray = array;
700                     x = i;
701                 }
702             }
703
704             minArray = ExtArray.unique(minArray);
705             erase(arrays, x, 1);
706
707             // Use the smallest unique'd array as the anchor loop. If the other array(s) do contain
708             // an item in the small array, we're likely to find it before reaching the end
709             // of the inner loop and can terminate the search early.
710             for (i = 0,ln = minArray.length; i &lt; ln,x = minArray[i]; i++) {
711                 var count = 0;
712
713                 for (j = 0,arraysLn = arrays.length; j &lt; arraysLn,array = arrays[j]; j++) {
714                     for (k = 0,arrayLn = array.length; k &lt; arrayLn,y = array[k]; k++) {
715                         if (x === y) {
716                             count++;
717                             break;
718                         }
719                     }
720                 }
721
722                 if (count === arraysLn) {
723                     intersect.push(x);
724                 }
725             }
726
727             return intersect;
728         },
729
730 <span id='Ext-Array-method-difference'>        /**
731 </span>         * Perform a set difference A-B by subtracting all items in array B from array A.
732          *
733          * @param {Array} arrayA
734          * @param {Array} arrayB
735          * @return {Array} difference
736          */
737         difference: function(arrayA, arrayB) {
738             var clone = slice.call(arrayA),
739                 ln = clone.length,
740                 i, j, lnB;
741
742             for (i = 0,lnB = arrayB.length; i &lt; lnB; i++) {
743                 for (j = 0; j &lt; ln; j++) {
744                     if (clone[j] === arrayB[i]) {
745                         erase(clone, j, 1);
746                         j--;
747                         ln--;
748                     }
749                 }
750             }
751
752             return clone;
753         },
754
755 <span id='Ext-Array-method-slice'>        /**
756 </span>         * Returns a shallow copy of a part of an array. This is equivalent to the native
757          * call &quot;Array.prototype.slice.call(array, begin, end)&quot;. This is often used when &quot;array&quot;
758          * is &quot;arguments&quot; since the arguments object does not supply a slice method but can
759          * be the context object to Array.prototype.slice.
760          *
761          * @param {Array} array The array (or arguments object).
762          * @param {Number} begin The index at which to begin. Negative values are offsets from
763          * the end of the array.
764          * @param {Number} end The index at which to end. The copied items do not include
765          * end. Negative values are offsets from the end of the array. If end is omitted,
766          * all items up to the end of the array are copied.
767          * @return {Array} The copied piece of the array.
768          */
769         slice: function(array, begin, end) {
770             return slice.call(array, begin, end);
771         },
772
773 <span id='Ext-Array-method-sort'>        /**
774 </span>         * Sorts the elements of an Array.
775          * By default, this method sorts the elements alphabetically and ascending.
776          *
777          * @param {Array} array The array to sort.
778          * @param {Function} sortFn (optional) The comparison function.
779          * @return {Array} The sorted array.
780          */
781         sort: function(array, sortFn) {
782             if (supportsSort) {
783                 if (sortFn) {
784                     return array.sort(sortFn);
785                 } else {
786                     return array.sort();
787                 }
788             }
789
790             var length = array.length,
791                 i = 0,
792                 comparison,
793                 j, min, tmp;
794
795             for (; i &lt; length; i++) {
796                 min = i;
797                 for (j = i + 1; j &lt; length; j++) {
798                     if (sortFn) {
799                         comparison = sortFn(array[j], array[min]);
800                         if (comparison &lt; 0) {
801                             min = j;
802                         }
803                     } else if (array[j] &lt; array[min]) {
804                         min = j;
805                     }
806                 }
807                 if (min !== i) {
808                     tmp = array[i];
809                     array[i] = array[min];
810                     array[min] = tmp;
811                 }
812             }
813
814             return array;
815         },
816
817 <span id='Ext-Array-method-flatten'>        /**
818 </span>         * Recursively flattens into 1-d Array. Injects Arrays inline.
819          *
820          */
821         flatten: function(array) {
822             var worker = [];
823
824             function rFlatten(a) {
825                 var i, ln, v;
826
827                 for (i = 0, ln = a.length; i &lt; ln; i++) {
828                     v = a[i];
829
830                     if (Ext.isArray(v)) {
831                         rFlatten(v);
832                     } else {
833                         worker.push(v);
834                     }
835                 }
836
837                 return worker;
838             }
839
840             return rFlatten(array);
841         },
842
843 <span id='Ext-Array-method-min'>        /**
844 </span>         * Returns the minimum value in the Array.
845          *
846          * @param {Array|NodeList} array The Array from which to select the minimum value.
847          * @param {Function} comparisonFn (optional) a function to perform the comparision which determines minimization.
848          * If omitted the &quot;&lt;&quot; operator will be used. Note: gt = 1; eq = 0; lt = -1
849          * @return {Mixed} minValue The minimum value
850          */
851         min: function(array, comparisonFn) {
852             var min = array[0],
853                 i, ln, item;
854
855             for (i = 0, ln = array.length; i &lt; ln; i++) {
856                 item = array[i];
857
858                 if (comparisonFn) {
859                     if (comparisonFn(min, item) === 1) {
860                         min = item;
861                     }
862                 }
863                 else {
864                     if (item &lt; min) {
865                         min = item;
866                     }
867                 }
868             }
869
870             return min;
871         },
872
873 <span id='Ext-Array-method-max'>        /**
874 </span>         * Returns the maximum value in the Array.
875          *
876          * @param {Array|NodeList} array The Array from which to select the maximum value.
877          * @param {Function} comparisonFn (optional) a function to perform the comparision which determines maximization.
878          * If omitted the &quot;&gt;&quot; operator will be used. Note: gt = 1; eq = 0; lt = -1
879          * @return {Mixed} maxValue The maximum value
880          */
881         max: function(array, comparisonFn) {
882             var max = array[0],
883                 i, ln, item;
884
885             for (i = 0, ln = array.length; i &lt; ln; i++) {
886                 item = array[i];
887
888                 if (comparisonFn) {
889                     if (comparisonFn(max, item) === -1) {
890                         max = item;
891                     }
892                 }
893                 else {
894                     if (item &gt; max) {
895                         max = item;
896                     }
897                 }
898             }
899
900             return max;
901         },
902
903 <span id='Ext-Array-method-mean'>        /**
904 </span>         * Calculates the mean of all items in the array.
905          *
906          * @param {Array} array The Array to calculate the mean value of.
907          * @return {Number} The mean.
908          */
909         mean: function(array) {
910             return array.length &gt; 0 ? ExtArray.sum(array) / array.length : undefined;
911         },
912
913 <span id='Ext-Array-method-sum'>        /**
914 </span>         * Calculates the sum of all items in the given array.
915          *
916          * @param {Array} array The Array to calculate the sum value of.
917          * @return {Number} The sum.
918          */
919         sum: function(array) {
920             var sum = 0,
921                 i, ln, item;
922
923             for (i = 0,ln = array.length; i &lt; ln; i++) {
924                 item = array[i];
925
926                 sum += item;
927             }
928
929             return sum;
930         },
931
932         //&lt;debug&gt;
933         _replaceSim: replaceSim, // for unit testing
934         _spliceSim: spliceSim,
935         //&lt;/debug&gt;
936
937 <span id='Ext-Array-method-erase'>        /**
938 </span>         * Removes items from an array. This is functionally equivalent to the splice method
939          * of Array, but works around bugs in IE8's splice method and does not copy the
940          * removed elements in order to return them (because very often they are ignored).
941          *
942          * @param {Array} array The Array on which to replace.
943          * @param {Number} index The index in the array at which to operate.
944          * @param {Number} removeCount The number of items to remove at index.
945          * @return {Array} The array passed.
946          * @method
947          */
948         erase: erase,
949
950 <span id='Ext-Array-method-insert'>        /**
951 </span>         * Inserts items in to an array.
952          * 
953          * @param {Array} array The Array on which to replace.
954          * @param {Number} index The index in the array at which to operate.
955          * @param {Array} items The array of items to insert at index.
956          * @return {Array} The array passed.
957          */
958         insert: function (array, index, items) {
959             return replace(array, index, 0, items);
960         },
961
962 <span id='Ext-Array-method-replace'>        /**
963 </span>         * Replaces items in an array. This is functionally equivalent to the splice method
964          * of Array, but works around bugs in IE8's splice method and is often more convenient
965          * to call because it accepts an array of items to insert rather than use a variadic
966          * argument list.
967          * 
968          * @param {Array} array The Array on which to replace.
969          * @param {Number} index The index in the array at which to operate.
970          * @param {Number} removeCount The number of items to remove at index (can be 0).
971          * @param {Array} insert An optional array of items to insert at index.
972          * @return {Array} The array passed.
973          * @method
974          */
975         replace: replace,
976
977 <span id='Ext-Array-method-splice'>        /**
978 </span>         * Replaces items in an array. This is equivalent to the splice method of Array, but
979          * works around bugs in IE8's splice method. The signature is exactly the same as the
980          * splice method except that the array is the first argument. All arguments following
981          * removeCount are inserted in the array at index.
982          *
983          * @param {Array} array The Array on which to replace.
984          * @param {Number} index The index in the array at which to operate.
985          * @param {Number} removeCount The number of items to remove at index (can be 0).
986          * @return {Array} An array containing the removed items.
987          * @method
988          */
989         splice: splice
990     };
991
992 <span id='Ext-method-each'>    /**
993 </span>     * @method
994      * @member Ext
995      * @alias Ext.Array#each
996      */
997     Ext.each = ExtArray.each;
998
999 <span id='Ext-Array-method-union'>    /**
1000 </span>     * @method
1001      * @member Ext.Array
1002      * @alias Ext.Array#merge
1003      */
1004     ExtArray.union = ExtArray.merge;
1005
1006 <span id='Ext-method-min'>    /**
1007 </span>     * Old alias to {@link Ext.Array#min}
1008      * @deprecated 4.0.0 Use {@link Ext.Array#min} instead
1009      * @method
1010      * @member Ext
1011      * @alias Ext.Array#min
1012      */
1013     Ext.min = ExtArray.min;
1014
1015 <span id='Ext-method-max'>    /**
1016 </span>     * Old alias to {@link Ext.Array#max}
1017      * @deprecated 4.0.0 Use {@link Ext.Array#max} instead
1018      * @method
1019      * @member Ext
1020      * @alias Ext.Array#max
1021      */
1022     Ext.max = ExtArray.max;
1023
1024 <span id='Ext-method-sum'>    /**
1025 </span>     * Old alias to {@link Ext.Array#sum}
1026      * @deprecated 4.0.0 Use {@link Ext.Array#sum} instead
1027      * @method
1028      * @member Ext
1029      * @alias Ext.Array#sum
1030      */
1031     Ext.sum = ExtArray.sum;
1032
1033 <span id='Ext-method-mean'>    /**
1034 </span>     * Old alias to {@link Ext.Array#mean}
1035      * @deprecated 4.0.0 Use {@link Ext.Array#mean} instead
1036      * @method
1037      * @member Ext
1038      * @alias Ext.Array#mean
1039      */
1040     Ext.mean = ExtArray.mean;
1041
1042 <span id='Ext-method-flatten'>    /**
1043 </span>     * Old alias to {@link Ext.Array#flatten}
1044      * @deprecated 4.0.0 Use {@link Ext.Array#flatten} instead
1045      * @method
1046      * @member Ext
1047      * @alias Ext.Array#flatten
1048      */
1049     Ext.flatten = ExtArray.flatten;
1050
1051 <span id='Ext-method-clean'>    /**
1052 </span>     * Old alias to {@link Ext.Array#clean}
1053      * @deprecated 4.0.0 Use {@link Ext.Array#clean} instead
1054      * @method
1055      * @member Ext
1056      * @alias Ext.Array#clean
1057      */
1058     Ext.clean = ExtArray.clean;
1059
1060 <span id='Ext-method-unique'>    /**
1061 </span>     * Old alias to {@link Ext.Array#unique}
1062      * @deprecated 4.0.0 Use {@link Ext.Array#unique} instead
1063      * @method
1064      * @member Ext
1065      * @alias Ext.Array#unique
1066      */
1067     Ext.unique = ExtArray.unique;
1068
1069 <span id='Ext-method-pluck'>    /**
1070 </span>     * Old alias to {@link Ext.Array#pluck Ext.Array.pluck}
1071      * @deprecated 4.0.0 Use {@link Ext.Array#pluck Ext.Array.pluck} instead
1072      * @method
1073      * @member Ext
1074      * @alias Ext.Array#pluck
1075      */
1076     Ext.pluck = ExtArray.pluck;
1077
1078 <span id='Ext-method-toArray'>    /**
1079 </span>     * @method
1080      * @member Ext
1081      * @alias Ext.Array#toArray
1082      */
1083     Ext.toArray = function() {
1084         return ExtArray.toArray.apply(ExtArray, arguments);
1085     };
1086 })();
1087 </pre>
1088 </body>
1089 </html>