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