<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js">// @tag foundation,core
|
// @require Number.js
|
// @define Ext.Array
|
|
<span id='Ext-Array'>/**
|
</span> * @class Ext.Array
|
* @singleton
|
* @author Jacky Nguyen <jacky@sencha.com>
|
* @docauthor Jacky Nguyen <jacky@sencha.com>
|
*
|
* A set of useful static methods to deal with arrays; provide missing methods for older browsers.
|
*/
|
(function() {
|
|
var arrayPrototype = Array.prototype,
|
slice = arrayPrototype.slice,
|
supportsSplice = (function () {
|
var array = [],
|
lengthBefore,
|
j = 20;
|
|
if (!array.splice) {
|
return false;
|
}
|
|
// This detects a bug in IE8 splice method:
|
// see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/
|
|
while (j--) {
|
array.push("A");
|
}
|
|
array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
|
|
lengthBefore = array.length; //41
|
array.splice(13, 0, "XXX"); // add one element
|
|
if (lengthBefore+1 != array.length) {
|
return false;
|
}
|
// end IE8 bug
|
|
return true;
|
}()),
|
supportsForEach = 'forEach' in arrayPrototype,
|
supportsMap = 'map' in arrayPrototype,
|
supportsIndexOf = 'indexOf' in arrayPrototype,
|
supportsEvery = 'every' in arrayPrototype,
|
supportsSome = 'some' in arrayPrototype,
|
supportsFilter = 'filter' in arrayPrototype,
|
supportsSort = (function() {
|
var a = [1,2,3,4,5].sort(function(){ return 0; });
|
return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
|
}()),
|
supportsSliceOnNodeList = true,
|
ExtArray,
|
erase,
|
replace,
|
splice;
|
|
try {
|
// IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList
|
if (typeof document !== 'undefined') {
|
slice.call(document.getElementsByTagName('body'));
|
}
|
} catch (e) {
|
supportsSliceOnNodeList = false;
|
}
|
|
function fixArrayIndex (array, index) {
|
return (index < 0) ? Math.max(0, array.length + index)
|
: Math.min(array.length, index);
|
}
|
|
/*
|
Does the same work as splice, but with a slightly more convenient signature. The splice
|
method has bugs in IE8, so this is the implementation we use on that platform.
|
|
The rippling of items in the array can be tricky. Consider two use cases:
|
|
index=2
|
removeCount=2
|
/=====\
|
+---+---+---+---+---+---+---+---+
|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
+---+---+---+---+---+---+---+---+
|
/ \/ \/ \/ \
|
/ /\ /\ /\ \
|
/ / \/ \/ \ +--------------------------+
|
/ / /\ /\ +--------------------------+ \
|
/ / / \/ +--------------------------+ \ \
|
/ / / /+--------------------------+ \ \ \
|
/ / / / \ \ \ \
|
v v v v v v v v
|
+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
|
| 0 | 1 | 4 | 5 | 6 | 7 | | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
|
+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
|
A B \=========/
|
insert=[a,b,c]
|
|
In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
|
that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
|
must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].
|
*/
|
function replaceSim (array, index, removeCount, insert) {
|
var add = insert ? insert.length : 0,
|
length = array.length,
|
pos = fixArrayIndex(array, index),
|
remove,
|
tailOldPos,
|
tailNewPos,
|
tailCount,
|
lengthAfterRemove,
|
i;
|
|
// we try to use Array.push when we can for efficiency...
|
if (pos === length) {
|
if (add) {
|
array.push.apply(array, insert);
|
}
|
} else {
|
remove = Math.min(removeCount, length - pos);
|
tailOldPos = pos + remove;
|
tailNewPos = tailOldPos + add - remove;
|
tailCount = length - tailOldPos;
|
lengthAfterRemove = length - remove;
|
|
if (tailNewPos < tailOldPos) { // case A
|
for (i = 0; i < tailCount; ++i) {
|
array[tailNewPos+i] = array[tailOldPos+i];
|
}
|
} else if (tailNewPos > tailOldPos) { // case B
|
for (i = tailCount; i--; ) {
|
array[tailNewPos+i] = array[tailOldPos+i];
|
}
|
} // else, add == remove (nothing to do)
|
|
if (add && pos === lengthAfterRemove) {
|
array.length = lengthAfterRemove; // truncate array
|
array.push.apply(array, insert);
|
} else {
|
array.length = lengthAfterRemove + add; // reserves space
|
for (i = 0; i < add; ++i) {
|
array[pos+i] = insert[i];
|
}
|
}
|
}
|
|
return array;
|
}
|
|
function replaceNative (array, index, removeCount, insert) {
|
if (insert && insert.length) {
|
// Inserting at index zero with no removing: use unshift
|
if (index === 0 && !removeCount) {
|
array.unshift.apply(array, insert);
|
}
|
// Inserting/replacing in middle of array
|
else if (index < array.length) {
|
array.splice.apply(array, [index, removeCount].concat(insert));
|
}
|
// Appending to array
|
else {
|
array.push.apply(array, insert);
|
}
|
} else {
|
array.splice(index, removeCount);
|
}
|
return array;
|
}
|
|
function eraseSim (array, index, removeCount) {
|
return replaceSim(array, index, removeCount);
|
}
|
|
function eraseNative (array, index, removeCount) {
|
array.splice(index, removeCount);
|
return array;
|
}
|
|
function spliceSim (array, index, removeCount) {
|
var pos = fixArrayIndex(array, index),
|
removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
|
|
if (arguments.length < 4) {
|
replaceSim(array, pos, removeCount);
|
} else {
|
replaceSim(array, pos, removeCount, slice.call(arguments, 3));
|
}
|
|
return removed;
|
}
|
|
function spliceNative (array) {
|
return array.splice.apply(array, slice.call(arguments, 1));
|
}
|
|
erase = supportsSplice ? eraseNative : eraseSim;
|
replace = supportsSplice ? replaceNative : replaceSim;
|
splice = supportsSplice ? spliceNative : spliceSim;
|
|
// NOTE: from here on, use erase, replace or splice (not native methods)...
|
|
ExtArray = Ext.Array = {
|
<span id='Ext-Array-method-each'> /**
|
</span> * Iterates an array or an iterable value and invoke the given callback function for each item.
|
*
|
* var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
|
*
|
* Ext.Array.each(countries, function(name, index, countriesItSelf) {
|
* console.log(name);
|
* });
|
*
|
* var sum = function() {
|
* var sum = 0;
|
*
|
* Ext.Array.each(arguments, function(value) {
|
* sum += value;
|
* });
|
*
|
* return sum;
|
* };
|
*
|
* sum(1, 2, 3); // returns 6
|
*
|
* The iteration can be stopped by returning false in the function callback.
|
*
|
* Ext.Array.each(countries, function(name, index, countriesItSelf) {
|
* if (name === 'Singapore') {
|
* return false; // break here
|
* }
|
* });
|
*
|
* {@link Ext#each Ext.each} is alias for {@link Ext.Array#each Ext.Array.each}
|
*
|
* @param {Array/NodeList/Object} iterable The value to be iterated. If this
|
* argument is not iterable, the callback function is called once.
|
* @param {Function} fn The callback function. If it returns false, the iteration stops and this method returns
|
* the current `index`.
|
* @param {Object} fn.item The item at the current `index` in the passed `array`
|
* @param {Number} fn.index The current `index` within the `array`
|
* @param {Array} fn.allItems The `array` itself which was passed as the first argument
|
* @param {Boolean} fn.return Return false to stop iteration.
|
* @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
|
* @param {Boolean} reverse (Optional) Reverse the iteration order (loop from the end to the beginning)
|
* Defaults false
|
* @return {Boolean} See description for the `fn` parameter.
|
*/
|
each: function(array, fn, scope, reverse) {
|
array = ExtArray.from(array);
|
|
var i,
|
ln = array.length;
|
|
if (reverse !== true) {
|
for (i = 0; i < ln; i++) {
|
if (fn.call(scope || array[i], array[i], i, array) === false) {
|
return i;
|
}
|
}
|
}
|
else {
|
for (i = ln - 1; i > -1; i--) {
|
if (fn.call(scope || array[i], array[i], i, array) === false) {
|
return i;
|
}
|
}
|
}
|
|
return true;
|
},
|
|
<span id='Ext-Array-method-forEach'> /**
|
</span> * Iterates an array and invoke the given callback function for each item. Note that this will simply
|
* delegate to the native Array.prototype.forEach method if supported. It doesn't support stopping the
|
* iteration by returning false in the callback function like {@link Ext.Array#each}. However, performance
|
* could be much better in modern browsers comparing with {@link Ext.Array#each}
|
*
|
* @param {Array} array The array to iterate
|
* @param {Function} fn The callback function.
|
* @param {Object} fn.item The item at the current `index` in the passed `array`
|
* @param {Number} fn.index The current `index` within the `array`
|
* @param {Array} fn.allItems The `array` itself which was passed as the first argument
|
* @param {Object} scope (Optional) The execution scope (`this`) in which the specified function is executed.
|
*/
|
forEach: supportsForEach ? function(array, fn, scope) {
|
array.forEach(fn, scope);
|
} : function(array, fn, scope) {
|
var i = 0,
|
ln = array.length;
|
|
for (; i < ln; i++) {
|
fn.call(scope, array[i], i, array);
|
}
|
},
|
|
<span id='Ext-Array-method-indexOf'> /**
|
</span> * Get the index of the provided `item` in the given `array`, a supplement for the
|
* missing arrayPrototype.indexOf in Internet Explorer.
|
*
|
* @param {Array} array The array to check
|
* @param {Object} item The item to look for
|
* @param {Number} from (Optional) The index at which to begin the search
|
* @return {Number} The index of item in the array (or -1 if it is not found)
|
*/
|
indexOf: supportsIndexOf ? function(array, item, from) {
|
return arrayPrototype.indexOf.call(array, item, from);
|
} : function(array, item, from) {
|
var i, length = array.length;
|
|
for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
|
if (array[i] === item) {
|
return i;
|
}
|
}
|
|
return -1;
|
},
|
|
<span id='Ext-Array-method-contains'> /**
|
</span> * Checks whether or not the given `array` contains the specified `item`
|
*
|
* @param {Array} array The array to check
|
* @param {Object} item The item to look for
|
* @return {Boolean} True if the array contains the item, false otherwise
|
*/
|
contains: supportsIndexOf ? function(array, item) {
|
return arrayPrototype.indexOf.call(array, item) !== -1;
|
} : function(array, item) {
|
var i, ln;
|
|
for (i = 0, ln = array.length; i < ln; i++) {
|
if (array[i] === item) {
|
return true;
|
}
|
}
|
|
return false;
|
},
|
|
<span id='Ext-Array-method-toArray'> /**
|
</span> * Converts any iterable (numeric indices and a length property) into a true array.
|
*
|
* function test() {
|
* var args = Ext.Array.toArray(arguments),
|
* fromSecondToLastArgs = Ext.Array.toArray(arguments, 1);
|
*
|
* alert(args.join(' '));
|
* alert(fromSecondToLastArgs.join(' '));
|
* }
|
*
|
* test('just', 'testing', 'here'); // alerts 'just testing here';
|
* // alerts 'testing here';
|
*
|
* Ext.Array.toArray(document.getElementsByTagName('div')); // will convert the NodeList into an array
|
* Ext.Array.toArray('splitted'); // returns ['s', 'p', 'l', 'i', 't', 't', 'e', 'd']
|
* Ext.Array.toArray('splitted', 0, 3); // returns ['s', 'p', 'l']
|
*
|
* {@link Ext#toArray Ext.toArray} is alias for {@link Ext.Array#toArray Ext.Array.toArray}
|
*
|
* @param {Object} iterable the iterable object to be turned into a true Array.
|
* @param {Number} start (Optional) a zero-based index that specifies the start of extraction. Defaults to 0
|
* @param {Number} end (Optional) a 1-based index that specifies the end of extraction. Defaults to the last
|
* index of the iterable value
|
* @return {Array} array
|
*/
|
toArray: function(iterable, start, end){
|
if (!iterable || !iterable.length) {
|
return [];
|
}
|
|
if (typeof iterable === 'string') {
|
iterable = iterable.split('');
|
}
|
|
if (supportsSliceOnNodeList) {
|
return slice.call(iterable, start || 0, end || iterable.length);
|
}
|
|
var array = [],
|
i;
|
|
start = start || 0;
|
end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
|
|
for (i = start; i < end; i++) {
|
array.push(iterable[i]);
|
}
|
|
return array;
|
},
|
|
<span id='Ext-Array-method-pluck'> /**
|
</span> * Plucks the value of a property from each item in the Array. Example:
|
*
|
* Ext.Array.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
|
*
|
* @param {Array/NodeList} array The Array of items to pluck the value from.
|
* @param {String} propertyName The property name to pluck from each element.
|
* @return {Array} The value from each item in the Array.
|
*/
|
pluck: function(array, propertyName) {
|
var ret = [],
|
i, ln, item;
|
|
for (i = 0, ln = array.length; i < ln; i++) {
|
item = array[i];
|
|
ret.push(item[propertyName]);
|
}
|
|
return ret;
|
},
|
|
<span id='Ext-Array-method-map'> /**
|
</span> * Creates a new array with the results of calling a provided function on every element in this array.
|
*
|
* @param {Array} array
|
* @param {Function} fn Callback function for each item
|
* @param {Mixed} fn.item Current item.
|
* @param {Number} fn.index Index of the item.
|
* @param {Array} fn.array The whole array that's being iterated.
|
* @param {Object} [scope] Callback function scope
|
* @return {Array} results
|
*/
|
map: supportsMap ? function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.map must have a callback function passed as second argument.');
|
}
|
//</debug>
|
return array.map(fn, scope);
|
} : function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.map must have a callback function passed as second argument.');
|
}
|
//</debug>
|
var results = [],
|
i = 0,
|
len = array.length;
|
|
for (; i < len; i++) {
|
results[i] = fn.call(scope, array[i], i, array);
|
}
|
|
return results;
|
},
|
|
<span id='Ext-Array-method-every'> /**
|
</span> * Executes the specified function for each array element until the function returns a falsy value.
|
* If such an item is found, the function will return false immediately.
|
* Otherwise, it will return true.
|
*
|
* @param {Array} array
|
* @param {Function} fn Callback function for each item
|
* @param {Mixed} fn.item Current item.
|
* @param {Number} fn.index Index of the item.
|
* @param {Array} fn.array The whole array that's being iterated.
|
* @param {Object} scope Callback function scope
|
* @return {Boolean} True if no false value is returned by the callback function.
|
*/
|
every: supportsEvery ? function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
|
}
|
//</debug>
|
return array.every(fn, scope);
|
} : function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
|
}
|
//</debug>
|
var i = 0,
|
ln = array.length;
|
|
for (; i < ln; ++i) {
|
if (!fn.call(scope, array[i], i, array)) {
|
return false;
|
}
|
}
|
|
return true;
|
},
|
|
<span id='Ext-Array-method-some'> /**
|
</span> * Executes the specified function for each array element until the function returns a truthy value.
|
* If such an item is found, the function will return true immediately. Otherwise, it will return false.
|
*
|
* @param {Array} array
|
* @param {Function} fn Callback function for each item
|
* @param {Mixed} fn.item Current item.
|
* @param {Number} fn.index Index of the item.
|
* @param {Array} fn.array The whole array that's being iterated.
|
* @param {Object} scope Callback function scope
|
* @return {Boolean} True if the callback function returns a truthy value.
|
*/
|
some: supportsSome ? function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
|
}
|
//</debug>
|
return array.some(fn, scope);
|
} : function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
|
}
|
//</debug>
|
var i = 0,
|
ln = array.length;
|
|
for (; i < ln; ++i) {
|
if (fn.call(scope, array[i], i, array)) {
|
return true;
|
}
|
}
|
|
return false;
|
},
|
|
<span id='Ext-Array-method-equals'> /**
|
</span> * Shallow compares the contents of 2 arrays using strict equality.
|
* @param {Array} array1
|
* @param {Array} array2
|
* @return {Boolean} `true` if the arrays are equal.
|
*/
|
equals: function(array1, array2) {
|
var len1 = array1.length,
|
len2 = array2.length,
|
i;
|
|
// Short circuit if the same array is passed twice
|
if (array1 === array2) {
|
return true;
|
}
|
|
if (len1 !== len2) {
|
return false;
|
}
|
|
for (i = 0; i < len1; ++i) {
|
if (array1[i] !== array2[i]) {
|
return false;
|
}
|
}
|
|
return true;
|
},
|
|
<span id='Ext-Array-method-clean'> /**
|
</span> * Filter through an array and remove empty item as defined in {@link Ext#isEmpty Ext.isEmpty}
|
*
|
* See {@link Ext.Array#filter}
|
*
|
* @param {Array} array
|
* @return {Array} results
|
*/
|
clean: function(array) {
|
var results = [],
|
i = 0,
|
ln = array.length,
|
item;
|
|
for (; i < ln; i++) {
|
item = array[i];
|
|
if (!Ext.isEmpty(item)) {
|
results.push(item);
|
}
|
}
|
|
return results;
|
},
|
|
<span id='Ext-Array-method-unique'> /**
|
</span> * Returns a new array with unique items
|
*
|
* @param {Array} array
|
* @return {Array} results
|
*/
|
unique: function(array) {
|
var clone = [],
|
i = 0,
|
ln = array.length,
|
item;
|
|
for (; i < ln; i++) {
|
item = array[i];
|
|
if (ExtArray.indexOf(clone, item) === -1) {
|
clone.push(item);
|
}
|
}
|
|
return clone;
|
},
|
|
<span id='Ext-Array-method-filter'> /**
|
</span> * Creates a new array with all of the elements of this array for which
|
* the provided filtering function returns true.
|
*
|
* @param {Array} array
|
* @param {Function} fn Callback function for each item
|
* @param {Mixed} fn.item Current item.
|
* @param {Number} fn.index Index of the item.
|
* @param {Array} fn.array The whole array that's being iterated.
|
* @param {Object} scope Callback function scope
|
* @return {Array} results
|
*/
|
filter: supportsFilter ? function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.filter must have a filter function passed as second argument.');
|
}
|
//</debug>
|
return array.filter(fn, scope);
|
} : function(array, fn, scope) {
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('Ext.Array.filter must have a filter function passed as second argument.');
|
}
|
//</debug>
|
var results = [],
|
i = 0,
|
ln = array.length;
|
|
for (; i < ln; i++) {
|
if (fn.call(scope, array[i], i, array)) {
|
results.push(array[i]);
|
}
|
}
|
|
return results;
|
},
|
|
<span id='Ext-Array-method-findBy'> /**
|
</span> * Returns the first item in the array which elicits a true return value from the
|
* passed selection function.
|
* @param {Array} array The array to search
|
* @param {Function} fn The selection function to execute for each item.
|
* @param {Mixed} fn.item The array item.
|
* @param {String} fn.index The index of the array item.
|
* @param {Object} scope (optional) The scope (<code>this</code> reference) in which the
|
* function is executed. Defaults to the array
|
* @return {Object} The first item in the array which returned true from the selection
|
* function, or null if none was found.
|
*/
|
findBy : function(array, fn, scope) {
|
var i = 0,
|
len = array.length;
|
|
for (; i < len; i++) {
|
if (fn.call(scope || array, array[i], i)) {
|
return array[i];
|
}
|
}
|
return null;
|
},
|
|
<span id='Ext-Array-method-from'> /**
|
</span> * Converts a value to an array if it's not already an array; returns:
|
*
|
* - An empty array if given value is `undefined` or `null`
|
* - Itself if given value is already an array
|
* - An array copy if given value is {@link Ext#isIterable iterable} (arguments, NodeList and alike)
|
* - An array with one item which is the given value, otherwise
|
*
|
* @param {Object} value The value to convert to an array if it's not already is an array
|
* @param {Boolean} newReference (Optional) True to clone the given array and return a new reference if necessary,
|
* defaults to false
|
* @return {Array} array
|
*/
|
from: function(value, newReference) {
|
if (value === undefined || value === null) {
|
return [];
|
}
|
|
if (Ext.isArray(value)) {
|
return (newReference) ? slice.call(value) : value;
|
}
|
|
var type = typeof value;
|
// Both strings and functions will have a length property. In phantomJS, NodeList
|
// instances report typeof=='function' but don't have an apply method...
|
if (value && value.length !== undefined && type !== 'string' && (type !== 'function' || !value.apply)) {
|
return ExtArray.toArray(value);
|
}
|
|
return [value];
|
},
|
|
<span id='Ext-Array-method-remove'> /**
|
</span> * Removes the specified item from the array if it exists
|
*
|
* @param {Array} array The array
|
* @param {Object} item The item to remove
|
* @return {Array} The passed array itself
|
*/
|
remove: function(array, item) {
|
var index = ExtArray.indexOf(array, item);
|
|
if (index !== -1) {
|
erase(array, index, 1);
|
}
|
|
return array;
|
},
|
|
<span id='Ext-Array-method-include'> /**
|
</span> * Push an item into the array only if the array doesn't contain it yet
|
*
|
* @param {Array} array The array
|
* @param {Object} item The item to include
|
*/
|
include: function(array, item) {
|
if (!ExtArray.contains(array, item)) {
|
array.push(item);
|
}
|
},
|
|
<span id='Ext-Array-method-clone'> /**
|
</span> * Clone a flat array without referencing the previous one. Note that this is different
|
* from Ext.clone since it doesn't handle recursive cloning. It's simply a convenient, easy-to-remember method
|
* for Array.prototype.slice.call(array)
|
*
|
* @param {Array} array The array
|
* @return {Array} The clone array
|
*/
|
clone: function(array) {
|
return slice.call(array);
|
},
|
|
<span id='Ext-Array-method-merge'> /**
|
</span> * Merge multiple arrays into one with unique items.
|
*
|
* {@link Ext.Array#union} is alias for {@link Ext.Array#merge}
|
*
|
* @param {Array} array1
|
* @param {Array} array2
|
* @param {Array} etc
|
* @return {Array} merged
|
*/
|
merge: function() {
|
var args = slice.call(arguments),
|
array = [],
|
i, ln;
|
|
for (i = 0, ln = args.length; i < ln; i++) {
|
array = array.concat(args[i]);
|
}
|
|
return ExtArray.unique(array);
|
},
|
|
<span id='Ext-Array-method-intersect'> /**
|
</span> * Merge multiple arrays into one with unique items that exist in all of the arrays.
|
*
|
* @param {Array} array1
|
* @param {Array} array2
|
* @param {Array} etc
|
* @return {Array} intersect
|
*/
|
intersect: function() {
|
var intersection = [],
|
arrays = slice.call(arguments),
|
arraysLength,
|
array,
|
arrayLength,
|
minArray,
|
minArrayIndex,
|
minArrayCandidate,
|
minArrayLength,
|
element,
|
elementCandidate,
|
elementCount,
|
i, j, k;
|
|
if (!arrays.length) {
|
return intersection;
|
}
|
|
// Find the smallest array
|
arraysLength = arrays.length;
|
for (i = minArrayIndex = 0; i < arraysLength; i++) {
|
minArrayCandidate = arrays[i];
|
if (!minArray || minArrayCandidate.length < minArray.length) {
|
minArray = minArrayCandidate;
|
minArrayIndex = i;
|
}
|
}
|
|
minArray = ExtArray.unique(minArray);
|
erase(arrays, minArrayIndex, 1);
|
|
// Use the smallest unique'd array as the anchor loop. If the other array(s) do contain
|
// an item in the small array, we're likely to find it before reaching the end
|
// of the inner loop and can terminate the search early.
|
minArrayLength = minArray.length;
|
arraysLength = arrays.length;
|
for (i = 0; i < minArrayLength; i++) {
|
element = minArray[i];
|
elementCount = 0;
|
|
for (j = 0; j < arraysLength; j++) {
|
array = arrays[j];
|
arrayLength = array.length;
|
for (k = 0; k < arrayLength; k++) {
|
elementCandidate = array[k];
|
if (element === elementCandidate) {
|
elementCount++;
|
break;
|
}
|
}
|
}
|
|
if (elementCount === arraysLength) {
|
intersection.push(element);
|
}
|
}
|
|
return intersection;
|
},
|
|
<span id='Ext-Array-method-difference'> /**
|
</span> * Perform a set difference A-B by subtracting all items in array B from array A.
|
*
|
* @param {Array} arrayA
|
* @param {Array} arrayB
|
* @return {Array} difference
|
*/
|
difference: function(arrayA, arrayB) {
|
var clone = slice.call(arrayA),
|
ln = clone.length,
|
i, j, lnB;
|
|
for (i = 0,lnB = arrayB.length; i < lnB; i++) {
|
for (j = 0; j < ln; j++) {
|
if (clone[j] === arrayB[i]) {
|
erase(clone, j, 1);
|
j--;
|
ln--;
|
}
|
}
|
}
|
|
return clone;
|
},
|
|
<span id='Ext-Array-method-slice'> /**
|
</span> * Returns a shallow copy of a part of an array. This is equivalent to the native
|
* call "Array.prototype.slice.call(array, begin, end)". This is often used when "array"
|
* is "arguments" since the arguments object does not supply a slice method but can
|
* be the context object to Array.prototype.slice.
|
*
|
* @param {Array} array The array (or arguments object).
|
* @param {Number} begin The index at which to begin. Negative values are offsets from
|
* the end of the array.
|
* @param {Number} end The index at which to end. The copied items do not include
|
* end. Negative values are offsets from the end of the array. If end is omitted,
|
* all items up to the end of the array are copied.
|
* @return {Array} The copied piece of the array.
|
* @method slice
|
*/
|
// Note: IE6 will return [] on slice.call(x, undefined).
|
slice: ([1,2].slice(1, undefined).length ?
|
function (array, begin, end) {
|
return slice.call(array, begin, end);
|
} :
|
// at least IE6 uses arguments.length for variadic signature
|
function (array, begin, end) {
|
// After tested for IE 6, the one below is of the best performance
|
// see http://jsperf.com/slice-fix
|
if (typeof begin === 'undefined') {
|
return slice.call(array);
|
}
|
if (typeof end === 'undefined') {
|
return slice.call(array, begin);
|
}
|
return slice.call(array, begin, end);
|
}
|
),
|
|
<span id='Ext-Array-method-sort'> /**
|
</span> * Sorts the elements of an Array.
|
* By default, this method sorts the elements alphabetically and ascending.
|
*
|
* @param {Array} array The array to sort.
|
* @param {Function} sortFn (optional) The comparison function.
|
* @param {Mixed} sortFn.a An item to compare.
|
* @param {Mixed} sortFn.b Another item to compare.
|
* @return {Array} The sorted array.
|
*/
|
sort: supportsSort ? function(array, sortFn) {
|
if (sortFn) {
|
return array.sort(sortFn);
|
} else {
|
return array.sort();
|
}
|
} : function(array, sortFn) {
|
var length = array.length,
|
i = 0,
|
comparison,
|
j, min, tmp;
|
|
for (; i < length; i++) {
|
min = i;
|
for (j = i + 1; j < length; j++) {
|
if (sortFn) {
|
comparison = sortFn(array[j], array[min]);
|
if (comparison < 0) {
|
min = j;
|
}
|
} else if (array[j] < array[min]) {
|
min = j;
|
}
|
}
|
if (min !== i) {
|
tmp = array[i];
|
array[i] = array[min];
|
array[min] = tmp;
|
}
|
}
|
|
return array;
|
},
|
|
<span id='Ext-Array-method-flatten'> /**
|
</span> * Recursively flattens into 1-d Array. Injects Arrays inline.
|
*
|
* @param {Array} array The array to flatten
|
* @return {Array} The 1-d array.
|
*/
|
flatten: function(array) {
|
var worker = [];
|
|
function rFlatten(a) {
|
var i, ln, v;
|
|
for (i = 0, ln = a.length; i < ln; i++) {
|
v = a[i];
|
|
if (Ext.isArray(v)) {
|
rFlatten(v);
|
} else {
|
worker.push(v);
|
}
|
}
|
|
return worker;
|
}
|
|
return rFlatten(array);
|
},
|
|
<span id='Ext-Array-method-min'> /**
|
</span> * Returns the minimum value in the Array.
|
*
|
* @param {Array/NodeList} array The Array from which to select the minimum value.
|
* @param {Function} comparisonFn (optional) a function to perform the comparision which determines minimization.
|
* If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
|
* @param {Mixed} comparisonFn.min Current minimum value.
|
* @param {Mixed} comparisonFn.item The value to compare with the current minimum.
|
* @return {Object} minValue The minimum value
|
*/
|
min: function(array, comparisonFn) {
|
var min = array[0],
|
i, ln, item;
|
|
for (i = 0, ln = array.length; i < ln; i++) {
|
item = array[i];
|
|
if (comparisonFn) {
|
if (comparisonFn(min, item) === 1) {
|
min = item;
|
}
|
}
|
else {
|
if (item < min) {
|
min = item;
|
}
|
}
|
}
|
|
return min;
|
},
|
|
<span id='Ext-Array-method-max'> /**
|
</span> * Returns the maximum value in the Array.
|
*
|
* @param {Array/NodeList} array The Array from which to select the maximum value.
|
* @param {Function} comparisonFn (optional) a function to perform the comparision which determines maximization.
|
* If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
|
* @param {Mixed} comparisonFn.max Current maximum value.
|
* @param {Mixed} comparisonFn.item The value to compare with the current maximum.
|
* @return {Object} maxValue The maximum value
|
*/
|
max: function(array, comparisonFn) {
|
var max = array[0],
|
i, ln, item;
|
|
for (i = 0, ln = array.length; i < ln; i++) {
|
item = array[i];
|
|
if (comparisonFn) {
|
if (comparisonFn(max, item) === -1) {
|
max = item;
|
}
|
}
|
else {
|
if (item > max) {
|
max = item;
|
}
|
}
|
}
|
|
return max;
|
},
|
|
<span id='Ext-Array-method-mean'> /**
|
</span> * Calculates the mean of all items in the array.
|
*
|
* @param {Array} array The Array to calculate the mean value of.
|
* @return {Number} The mean.
|
*/
|
mean: function(array) {
|
return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
|
},
|
|
<span id='Ext-Array-method-sum'> /**
|
</span> * Calculates the sum of all items in the given array.
|
*
|
* @param {Array} array The Array to calculate the sum value of.
|
* @return {Number} The sum.
|
*/
|
sum: function(array) {
|
var sum = 0,
|
i, ln, item;
|
|
for (i = 0,ln = array.length; i < ln; i++) {
|
item = array[i];
|
|
sum += item;
|
}
|
|
return sum;
|
},
|
|
<span id='Ext-Array-method-toMap'> /**
|
</span> * Creates a map (object) keyed by the elements of the given array. The values in
|
* the map are the index+1 of the array element. For example:
|
*
|
* var map = Ext.Array.toMap(['a','b','c']);
|
*
|
* // map = { a: 1, b: 2, c: 3 };
|
*
|
* Or a key property can be specified:
|
*
|
* var map = Ext.Array.toMap([
|
* { name: 'a' },
|
* { name: 'b' },
|
* { name: 'c' }
|
* ], 'name');
|
*
|
* // map = { a: 1, b: 2, c: 3 };
|
*
|
* Lastly, a key extractor can be provided:
|
*
|
* var map = Ext.Array.toMap([
|
* { name: 'a' },
|
* { name: 'b' },
|
* { name: 'c' }
|
* ], function (obj) { return obj.name.toUpperCase(); });
|
*
|
* // map = { A: 1, B: 2, C: 3 };
|
*
|
* @param {Array} array The Array to create the map from.
|
* @param {String/Function} [getKey] Name of the object property to use
|
* as a key or a function to extract the key.
|
* @param {Object} [scope] Value of this inside callback.
|
* @return {Object} The resulting map.
|
*/
|
toMap: function(array, getKey, scope) {
|
var map = {},
|
i = array.length;
|
|
if (!getKey) {
|
while (i--) {
|
map[array[i]] = i+1;
|
}
|
} else if (typeof getKey == 'string') {
|
while (i--) {
|
map[array[i][getKey]] = i+1;
|
}
|
} else {
|
while (i--) {
|
map[getKey.call(scope, array[i])] = i+1;
|
}
|
}
|
|
return map;
|
},
|
|
<span id='Ext-Array-method-toValueMap'> /**
|
</span> * Creates a map (object) keyed by a property of elements of the given array. The values in
|
* the map are the array element. For example:
|
*
|
* var map = Ext.Array.toMap(['a','b','c']);
|
*
|
* // map = { a: 'a', b: 'b', c: 'c' };
|
*
|
* Or a key property can be specified:
|
*
|
* var map = Ext.Array.toMap([
|
* { name: 'a' },
|
* { name: 'b' },
|
* { name: 'c' }
|
* ], 'name');
|
*
|
* // map = { a: {name: 'a'}, b: {name: 'b'}, c: {name: 'c'} };
|
*
|
* Lastly, a key extractor can be provided:
|
*
|
* var map = Ext.Array.toMap([
|
* { name: 'a' },
|
* { name: 'b' },
|
* { name: 'c' }
|
* ], function (obj) { return obj.name.toUpperCase(); });
|
*
|
* // map = { A: {name: 'a'}, B: {name: 'b'}, C: {name: 'c'} };
|
*
|
* @param {Array} array The Array to create the map from.
|
* @param {String/Function} [getKey] Name of the object property to use
|
* as a key or a function to extract the key.
|
* @param {Object} [scope] Value of this inside callback.
|
* @return {Object} The resulting map.
|
*/
|
toValueMap: function(array, getKey, scope) {
|
var map = {},
|
i = array.length;
|
|
if (!getKey) {
|
while (i--) {
|
map[array[i]] = array[i];
|
}
|
} else if (typeof getKey == 'string') {
|
while (i--) {
|
map[array[i][getKey]] = array[i];
|
}
|
} else {
|
while (i--) {
|
map[getKey.call(scope, array[i])] = array[i];
|
}
|
}
|
|
return map;
|
},
|
|
//<debug>
|
_replaceSim: replaceSim, // for unit testing
|
_spliceSim: spliceSim,
|
//</debug>
|
|
<span id='Ext-Array-method-erase'> /**
|
</span> * Removes items from an array. This is functionally equivalent to the splice method
|
* of Array, but works around bugs in IE8's splice method and does not copy the
|
* removed elements in order to return them (because very often they are ignored).
|
*
|
* @param {Array} array The Array on which to replace.
|
* @param {Number} index The index in the array at which to operate.
|
* @param {Number} removeCount The number of items to remove at index.
|
* @return {Array} The array passed.
|
* @method
|
*/
|
erase: erase,
|
|
<span id='Ext-Array-method-insert'> /**
|
</span> * Inserts items in to an array.
|
*
|
* @param {Array} array The Array in which to insert.
|
* @param {Number} index The index in the array at which to operate.
|
* @param {Array} items The array of items to insert at index.
|
* @return {Array} The array passed.
|
*/
|
insert: function (array, index, items) {
|
return replace(array, index, 0, items);
|
},
|
|
<span id='Ext-Array-method-replace'> /**
|
</span> * Replaces items in an array. This is functionally equivalent to the splice method
|
* of Array, but works around bugs in IE8's splice method and is often more convenient
|
* to call because it accepts an array of items to insert rather than use a variadic
|
* argument list.
|
*
|
* @param {Array} array The Array on which to replace.
|
* @param {Number} index The index in the array at which to operate.
|
* @param {Number} removeCount The number of items to remove at index (can be 0).
|
* @param {Array} insert (optional) An array of items to insert at index.
|
* @return {Array} The array passed.
|
* @method
|
*/
|
replace: replace,
|
|
<span id='Ext-Array-method-splice'> /**
|
</span> * Replaces items in an array. This is equivalent to the splice method of Array, but
|
* works around bugs in IE8's splice method. The signature is exactly the same as the
|
* splice method except that the array is the first argument. All arguments following
|
* removeCount are inserted in the array at index.
|
*
|
* @param {Array} array The Array on which to replace.
|
* @param {Number} index The index in the array at which to operate.
|
* @param {Number} removeCount The number of items to remove at index (can be 0).
|
* @param {Object...} elements The elements to add to the array. If you don't specify
|
* any elements, splice simply removes elements from the array.
|
* @return {Array} An array containing the removed items.
|
* @method
|
*/
|
splice: splice,
|
|
<span id='Ext-Array-method-push'> /**
|
</span> * Pushes new items onto the end of an Array.
|
*
|
* Passed parameters may be single items, or arrays of items. If an Array is found in the argument list, all its
|
* elements are pushed into the end of the target Array.
|
*
|
* @param {Array} target The Array onto which to push new items
|
* @param {Object...} elements The elements to add to the array. Each parameter may
|
* be an Array, in which case all the elements of that Array will be pushed into the end of the
|
* destination Array.
|
* @return {Array} An array containing all the new items push onto the end.
|
*
|
*/
|
push: function(array) {
|
var len = arguments.length,
|
i = 1,
|
newItem;
|
|
if (array === undefined) {
|
array = [];
|
} else if (!Ext.isArray(array)) {
|
array = [array];
|
}
|
for (; i < len; i++) {
|
newItem = arguments[i];
|
Array.prototype.push[Ext.isIterable(newItem) ? 'apply' : 'call'](array, newItem);
|
}
|
return array;
|
}
|
};
|
|
<span id='Ext-method-each'> /**
|
</span> * @method
|
* @member Ext
|
* @inheritdoc Ext.Array#each
|
*/
|
Ext.each = ExtArray.each;
|
|
<span id='Ext-Array-method-union'> /**
|
</span> * @method
|
* @member Ext.Array
|
* @inheritdoc Ext.Array#merge
|
*/
|
ExtArray.union = ExtArray.merge;
|
|
<span id='Ext-method-min'> /**
|
</span> * Old alias to {@link Ext.Array#min}
|
* @deprecated 4.0.0 Use {@link Ext.Array#min} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#min
|
*/
|
Ext.min = ExtArray.min;
|
|
<span id='Ext-method-max'> /**
|
</span> * Old alias to {@link Ext.Array#max}
|
* @deprecated 4.0.0 Use {@link Ext.Array#max} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#max
|
*/
|
Ext.max = ExtArray.max;
|
|
<span id='Ext-method-sum'> /**
|
</span> * Old alias to {@link Ext.Array#sum}
|
* @deprecated 4.0.0 Use {@link Ext.Array#sum} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#sum
|
*/
|
Ext.sum = ExtArray.sum;
|
|
<span id='Ext-method-mean'> /**
|
</span> * Old alias to {@link Ext.Array#mean}
|
* @deprecated 4.0.0 Use {@link Ext.Array#mean} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#mean
|
*/
|
Ext.mean = ExtArray.mean;
|
|
<span id='Ext-method-flatten'> /**
|
</span> * Old alias to {@link Ext.Array#flatten}
|
* @deprecated 4.0.0 Use {@link Ext.Array#flatten} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#flatten
|
*/
|
Ext.flatten = ExtArray.flatten;
|
|
<span id='Ext-method-clean'> /**
|
</span> * Old alias to {@link Ext.Array#clean}
|
* @deprecated 4.0.0 Use {@link Ext.Array#clean} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#clean
|
*/
|
Ext.clean = ExtArray.clean;
|
|
<span id='Ext-method-unique'> /**
|
</span> * Old alias to {@link Ext.Array#unique}
|
* @deprecated 4.0.0 Use {@link Ext.Array#unique} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#unique
|
*/
|
Ext.unique = ExtArray.unique;
|
|
<span id='Ext-method-pluck'> /**
|
</span> * Old alias to {@link Ext.Array#pluck Ext.Array.pluck}
|
* @deprecated 4.0.0 Use {@link Ext.Array#pluck Ext.Array.pluck} instead
|
* @method
|
* @member Ext
|
* @inheritdoc Ext.Array#pluck
|
*/
|
Ext.pluck = ExtArray.pluck;
|
|
<span id='Ext-method-toArray'> /**
|
</span> * @method
|
* @member Ext
|
* @inheritdoc Ext.Array#toArray
|
*/
|
Ext.toArray = function() {
|
return ExtArray.toArray.apply(ExtArray, arguments);
|
};
|
}());
|
</pre>
|
</body>
|
</html>
|