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; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-Array'>/**
19 </span> * @author Jacky Nguyen <jacky@sencha.com>
20 * @docauthor Jacky Nguyen <jacky@sencha.com>
23 * A set of useful static methods to deal with arrays; provide missing methods for older browsers.
30 var arrayPrototype = Array.prototype,
31 slice = arrayPrototype.slice,
32 supportsForEach = 'forEach' in arrayPrototype,
33 supportsMap = 'map' in arrayPrototype,
34 supportsIndexOf = 'indexOf' in arrayPrototype,
35 supportsEvery = 'every' in arrayPrototype,
36 supportsSome = 'some' in arrayPrototype,
37 supportsFilter = 'filter' in arrayPrototype,
38 supportsSort = function() {
39 var a = [1,2,3,4,5].sort(function(){ return 0; });
40 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
42 supportsSliceOnNodeList = true,
45 // IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList
46 if (typeof document !== 'undefined') {
47 slice.call(document.getElementsByTagName('body'));
50 supportsSliceOnNodeList = false;
53 ExtArray = Ext.Array = {
54 <span id='Ext-Array-method-each'> /**
55 </span> * Iterates an array or an iterable value and invoke the given callback function for each item.
57 var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
59 Ext.Array.each(countries, function(name, index, countriesItSelf) {
63 var sum = function() {
66 Ext.Array.each(arguments, function(value) {
73 sum(1, 2, 3); // returns 6
75 * The iteration can be stopped by returning false in the function callback.
77 Ext.Array.each(countries, function(name, index, countriesItSelf) {
78 if (name === 'Singapore') {
79 return false; // break here
83 * @param {Array/NodeList/Mixed} iterable The value to be iterated. If this
84 * argument is not iterable, the callback function is called once.
85 * @param {Function} fn The callback function. If it returns false, the iteration stops and this method returns
86 * the current `index`. Arguments passed to this callback function are:
88 - `item`: {Mixed} The item at the current `index` in the passed `array`
89 - `index`: {Number} The current `index` within the `array`
90 - `allItems`: {Array/NodeList/Mixed} The `array` passed as the first argument to `Ext.Array.each`
92 * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
93 * @param {Boolean} reverse (Optional) Reverse the iteration order (loop from the end to the beginning)
95 * @return {Boolean} See description for the `fn` parameter.
98 each: function(array, fn, scope, reverse) {
99 array = ExtArray.from(array);
104 if (reverse !== true) {
105 for (i = 0; i < ln; i++) {
106 if (fn.call(scope || array[i], array[i], i, array) === false) {
112 for (i = ln - 1; i > -1; i--) {
113 if (fn.call(scope || array[i], array[i], i, array) === false) {
122 <span id='Ext-Array-method-forEach'> /**
123 </span> * Iterates an array and invoke the given callback function for each item. Note that this will simply
124 * delegate to the native Array.prototype.forEach method if supported.
125 * It doesn't support stopping the iteration by returning false in the callback function like
126 * {@link Ext.Array#each}. However, performance could be much better in modern browsers comparing with
127 * {@link Ext.Array#each}
129 * @param {Array} array The array to iterate
130 * @param {Function} fn The function callback, to be invoked these arguments:
132 - `item`: {Mixed} The item at the current `index` in the passed `array`
133 - `index`: {Number} The current `index` within the `array`
134 - `allItems`: {Array} The `array` itself which was passed as the first argument
136 * @param {Object} scope (Optional) The execution scope (`this`) in which the specified function is executed.
139 forEach: function(array, fn, scope) {
140 if (supportsForEach) {
141 return array.forEach(fn, scope);
147 for (; i < ln; i++) {
148 fn.call(scope, array[i], i, array);
152 <span id='Ext-Array-method-indexOf'> /**
153 </span> * Get the index of the provided `item` in the given `array`, a supplement for the
154 * missing arrayPrototype.indexOf in Internet Explorer.
156 * @param {Array} array The array to check
157 * @param {Mixed} item The item to look for
158 * @param {Number} from (Optional) The index at which to begin the search
159 * @return {Number} The index of item in the array (or -1 if it is not found)
162 indexOf: function(array, item, from) {
163 if (supportsIndexOf) {
164 return array.indexOf(item, from);
167 var i, length = array.length;
169 for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
170 if (array[i] === item) {
178 <span id='Ext-Array-method-contains'> /**
179 </span> * Checks whether or not the given `array` contains the specified `item`
181 * @param {Array} array The array to check
182 * @param {Mixed} item The item to look for
183 * @return {Boolean} True if the array contains the item, false otherwise
186 contains: function(array, item) {
187 if (supportsIndexOf) {
188 return array.indexOf(item) !== -1;
193 for (i = 0, ln = array.length; i < ln; i++) {
194 if (array[i] === item) {
202 <span id='Ext-Array-method-toArray'> /**
203 </span> * Converts any iterable (numeric indices and a length property) into a true array.
206 var args = Ext.Array.toArray(arguments),
207 fromSecondToLastArgs = Ext.Array.toArray(arguments, 1);
209 alert(args.join(' '));
210 alert(fromSecondToLastArgs.join(' '));
213 test('just', 'testing', 'here'); // alerts 'just testing here';
214 // alerts 'testing here';
216 Ext.Array.toArray(document.getElementsByTagName('div')); // will convert the NodeList into an array
217 Ext.Array.toArray('splitted'); // returns ['s', 'p', 'l', 'i', 't', 't', 'e', 'd']
218 Ext.Array.toArray('splitted', 0, 3); // returns ['s', 'p', 'l', 'i']
220 * @param {Mixed} iterable the iterable object to be turned into a true Array.
221 * @param {Number} start (Optional) a zero-based index that specifies the start of extraction. Defaults to 0
222 * @param {Number} end (Optional) a zero-based index that specifies the end of extraction. Defaults to the last
223 * index of the iterable value
224 * @return {Array} array
227 toArray: function(iterable, start, end){
228 if (!iterable || !iterable.length) {
232 if (typeof iterable === 'string') {
233 iterable = iterable.split('');
236 if (supportsSliceOnNodeList) {
237 return slice.call(iterable, start || 0, end || iterable.length);
244 end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
246 for (i = start; i < end; i++) {
247 array.push(iterable[i]);
253 <span id='Ext-Array-method-pluck'> /**
254 </span> * Plucks the value of a property from each item in the Array. Example:
256 Ext.Array.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
258 * @param {Array|NodeList} array The Array of items to pluck the value from.
259 * @param {String} propertyName The property name to pluck from each element.
260 * @return {Array} The value from each item in the Array.
262 pluck: function(array, propertyName) {
266 for (i = 0, ln = array.length; i < ln; i++) {
269 ret.push(item[propertyName]);
275 <span id='Ext-Array-method-map'> /**
276 </span> * Creates a new array with the results of calling a provided function on every element in this array.
277 * @param {Array} array
278 * @param {Function} fn Callback function for each item
279 * @param {Object} scope Callback function scope
280 * @return {Array} results
282 map: function(array, fn, scope) {
284 return array.map(fn, scope);
291 for (; i < len; i++) {
292 results[i] = fn.call(scope, array[i], i, array);
298 <span id='Ext-Array-method-every'> /**
299 </span> * Executes the specified function for each array element until the function returns a falsy value.
300 * If such an item is found, the function will return false immediately.
301 * Otherwise, it will return true.
303 * @param {Array} array
304 * @param {Function} fn Callback function for each item
305 * @param {Object} scope Callback function scope
306 * @return {Boolean} True if no false value is returned by the callback function.
308 every: function(array, fn, scope) {
311 Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
315 return array.every(fn, scope);
321 for (; i < ln; ++i) {
322 if (!fn.call(scope, array[i], i, array)) {
330 <span id='Ext-Array-method-some'> /**
331 </span> * Executes the specified function for each array element until the function returns a truthy value.
332 * If such an item is found, the function will return true immediately. Otherwise, it will return false.
334 * @param {Array} array
335 * @param {Function} fn Callback function for each item
336 * @param {Object} scope Callback function scope
337 * @return {Boolean} True if the callback function returns a truthy value.
339 some: function(array, fn, scope) {
342 Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
346 return array.some(fn, scope);
352 for (; i < ln; ++i) {
353 if (fn.call(scope, array[i], i, array)) {
361 <span id='Ext-Array-method-clean'> /**
362 </span> * Filter through an array and remove empty item as defined in {@link Ext#isEmpty Ext.isEmpty}
364 * @see Ext.Array.filter
365 * @param {Array} array
366 * @return {Array} results
368 clean: function(array) {
374 for (; i < ln; i++) {
377 if (!Ext.isEmpty(item)) {
385 <span id='Ext-Array-method-unique'> /**
386 </span> * Returns a new array with unique items
388 * @param {Array} array
389 * @return {Array} results
391 unique: function(array) {
397 for (; i < ln; i++) {
400 if (ExtArray.indexOf(clone, item) === -1) {
408 <span id='Ext-Array-method-filter'> /**
409 </span> * Creates a new array with all of the elements of this array for which
410 * the provided filtering function returns true.
411 * @param {Array} array
412 * @param {Function} fn Callback function for each item
413 * @param {Object} scope Callback function scope
414 * @return {Array} results
416 filter: function(array, fn, scope) {
417 if (supportsFilter) {
418 return array.filter(fn, scope);
425 for (; i < ln; i++) {
426 if (fn.call(scope, array[i], i, array)) {
427 results.push(array[i]);
434 <span id='Ext-Array-method-from'> /**
435 </span> * Converts a value to an array if it's not already an array; returns:
437 * - An empty array if given value is `undefined` or `null`
438 * - Itself if given value is already an array
439 * - An array copy if given value is {@link Ext#isIterable iterable} (arguments, NodeList and alike)
440 * - An array with one item which is the given value, otherwise
442 * @param {Array/Mixed} value The value to convert to an array if it's not already is an array
443 * @param {Boolean} (Optional) newReference True to clone the given array and return a new reference if necessary,
445 * @return {Array} array
448 from: function(value, newReference) {
449 if (value === undefined || value === null) {
453 if (Ext.isArray(value)) {
454 return (newReference) ? slice.call(value) : value;
457 if (value && value.length !== undefined && typeof value !== 'string') {
458 return Ext.toArray(value);
464 <span id='Ext-Array-method-remove'> /**
465 </span> * Removes the specified item from the array if it exists
467 * @param {Array} array The array
468 * @param {Mixed} item The item to remove
469 * @return {Array} The passed array itself
471 remove: function(array, item) {
472 var index = ExtArray.indexOf(array, item);
475 array.splice(index, 1);
481 <span id='Ext-Array-method-include'> /**
482 </span> * Push an item into the array only if the array doesn't contain it yet
484 * @param {Array} array The array
485 * @param {Mixed} item The item to include
486 * @return {Array} The passed array itself
488 include: function(array, item) {
489 if (!ExtArray.contains(array, item)) {
494 <span id='Ext-Array-method-clone'> /**
495 </span> * Clone a flat array without referencing the previous one. Note that this is different
496 * from Ext.clone since it doesn't handle recursive cloning. It's simply a convenient, easy-to-remember method
497 * for Array.prototype.slice.call(array)
499 * @param {Array} array The array
500 * @return {Array} The clone array
502 clone: function(array) {
503 return slice.call(array);
506 <span id='Ext-Array-method-merge'> /**
507 </span> * Merge multiple arrays into one with unique items. Alias to {@link Ext.Array#union}.
509 * @param {Array} array,...
510 * @return {Array} merged
513 var args = slice.call(arguments),
517 for (i = 0, ln = args.length; i < ln; i++) {
518 array = array.concat(args[i]);
521 return ExtArray.unique(array);
524 <span id='Ext-Array-method-intersect'> /**
525 </span> * Merge multiple arrays into one with unique items that exist in all of the arrays.
527 * @param {Array} array,...
528 * @return {Array} intersect
530 intersect: function() {
532 arrays = slice.call(arguments),
533 i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
535 if (!arrays.length) {
539 // Find the smallest array
540 for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
541 if (!minArray || array.length < minArray.length) {
547 minArray = Ext.Array.unique(minArray);
550 // Use the smallest unique'd array as the anchor loop. If the other array(s) do contain
551 // an item in the small array, we're likely to find it before reaching the end
552 // of the inner loop and can terminate the search early.
553 for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
556 for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
557 for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
565 if (count === arraysLn) {
573 <span id='Ext-Array-method-difference'> /**
574 </span> * Perform a set difference A-B by subtracting all items in array B from array A.
576 * @param {Array} array A
577 * @param {Array} array B
578 * @return {Array} difference
580 difference: function(arrayA, arrayB) {
581 var clone = slice.call(arrayA),
585 for (i = 0,lnB = arrayB.length; i < lnB; i++) {
586 for (j = 0; j < ln; j++) {
587 if (clone[j] === arrayB[i]) {
598 <span id='Ext-Array-method-sort'> /**
599 </span> * Sorts the elements of an Array.
600 * By default, this method sorts the elements alphabetically and ascending.
602 * @param {Array} array The array to sort.
603 * @param {Function} sortFn (optional) The comparison function.
604 * @return {Array} The sorted array.
606 sort: function(array, sortFn) {
609 return array.sort(sortFn);
615 var length = array.length,
620 for (; i < length; i++) {
622 for (j = i + 1; j < length; j++) {
624 comparison = sortFn(array[j], array[min]);
625 if (comparison < 0) {
628 } else if (array[j] < array[min]) {
634 array[i] = array[min];
642 <span id='Ext-Array-method-flatten'> /**
643 </span> * Recursively flattens into 1-d Array. Injects Arrays inline.
644 * @param {Array} array The array to flatten
645 * @return {Array} The new, flattened array.
647 flatten: function(array) {
650 function rFlatten(a) {
653 for (i = 0, ln = a.length; i < ln; i++) {
656 if (Ext.isArray(v)) {
666 return rFlatten(array);
669 <span id='Ext-Array-method-min'> /**
670 </span> * Returns the minimum value in the Array.
671 * @param {Array|NodeList} array The Array from which to select the minimum value.
672 * @param {Function} comparisonFn (optional) a function to perform the comparision which determines minimization.
673 * If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
674 * @return {Mixed} minValue The minimum value
676 min: function(array, comparisonFn) {
680 for (i = 0, ln = array.length; i < ln; i++) {
684 if (comparisonFn(min, item) === 1) {
698 <span id='Ext-Array-method-max'> /**
699 </span> * Returns the maximum value in the Array
700 * @param {Array|NodeList} array The Array from which to select the maximum value.
701 * @param {Function} comparisonFn (optional) a function to perform the comparision which determines maximization.
702 * If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
703 * @return {Mixed} maxValue The maximum value
705 max: function(array, comparisonFn) {
709 for (i = 0, ln = array.length; i < ln; i++) {
713 if (comparisonFn(max, item) === -1) {
727 <span id='Ext-Array-method-mean'> /**
728 </span> * Calculates the mean of all items in the array
729 * @param {Array} array The Array to calculate the mean value of.
730 * @return {Number} The mean.
732 mean: function(array) {
733 return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
736 <span id='Ext-Array-method-sum'> /**
737 </span> * Calculates the sum of all items in the given array
738 * @param {Array} array The Array to calculate the sum value of.
739 * @return {Number} The sum.
741 sum: function(array) {
745 for (i = 0,ln = array.length; i < ln; i++) {
756 <span id='Ext-method-each'> /**
757 </span> * Convenient alias to {@link Ext.Array#each}
761 Ext.each = Ext.Array.each;
763 <span id='Ext-Array-method-union'> /**
764 </span> * Alias to {@link Ext.Array#merge}.
768 Ext.Array.union = Ext.Array.merge;
770 <span id='Ext-method-min'> /**
771 </span> * Old alias to {@link Ext.Array#min}
772 * @deprecated 4.0.0 Use {@link Ext.Array#min} instead
776 Ext.min = Ext.Array.min;
778 <span id='Ext-method-max'> /**
779 </span> * Old alias to {@link Ext.Array#max}
780 * @deprecated 4.0.0 Use {@link Ext.Array#max} instead
784 Ext.max = Ext.Array.max;
786 <span id='Ext-method-sum'> /**
787 </span> * Old alias to {@link Ext.Array#sum}
788 * @deprecated 4.0.0 Use {@link Ext.Array#sum} instead
792 Ext.sum = Ext.Array.sum;
794 <span id='Ext-method-mean'> /**
795 </span> * Old alias to {@link Ext.Array#mean}
796 * @deprecated 4.0.0 Use {@link Ext.Array#mean} instead
800 Ext.mean = Ext.Array.mean;
802 <span id='Ext-method-flatten'> /**
803 </span> * Old alias to {@link Ext.Array#flatten}
804 * @deprecated 4.0.0 Use {@link Ext.Array#flatten} instead
808 Ext.flatten = Ext.Array.flatten;
810 <span id='Ext-method-clean'> /**
811 </span> * Old alias to {@link Ext.Array#clean Ext.Array.clean}
812 * @deprecated 4.0.0 Use {@link Ext.Array.clean} instead
816 Ext.clean = Ext.Array.clean;
818 <span id='Ext-method-unique'> /**
819 </span> * Old alias to {@link Ext.Array#unique Ext.Array.unique}
820 * @deprecated 4.0.0 Use {@link Ext.Array.unique} instead
824 Ext.unique = Ext.Array.unique;
826 <span id='Ext-method-pluck'> /**
827 </span> * Old alias to {@link Ext.Array#pluck Ext.Array.pluck}
828 * @deprecated 4.0.0 Use {@link Ext.Array#pluck Ext.Array.pluck} instead
832 Ext.pluck = Ext.Array.pluck;
834 <span id='Ext-method-toArray'> /**
835 </span> * Convenient alias to {@link Ext.Array#toArray Ext.Array.toArray}
836 * @param {Iterable} the iterable object to be turned into a true Array.
839 * @return {Array} array
841 Ext.toArray = function() {
842 return ExtArray.toArray.apply(ExtArray, arguments);