- /**
- @module yui
- @submodule yui-base
- */
-
- var Lang = Y.Lang,
- Native = Array.prototype,
-
- hasOwn = Object.prototype.hasOwnProperty;
-
- /**
- Provides utility methods for working with arrays. Additional array helpers can
- be found in the `collection` and `array-extras` modules.
-
- `Y.Array(thing)` returns a native array created from _thing_. Depending on
- _thing_'s type, one of the following will happen:
-
- * Arrays are returned unmodified unless a non-zero _startIndex_ is
- specified.
- * Array-like collections (see `Array.test()`) are converted to arrays.
- * For everything else, a new array is created with _thing_ as the sole
- item.
-
- Note: elements that are also collections, such as `<form>` and `<select>`
- elements, are not automatically converted to arrays. To force a conversion,
- pass `true` as the value of the _force_ parameter.
-
- @class Array
- @constructor
- @param {Any} thing The thing to arrayify.
- @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
- collection, a subset of items starting at the specified index will be
- returned.
- @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
- array-like collection no matter what.
- @return {Array} A native array created from _thing_, according to the rules
- described above.
- **/
- function YArray(thing, startIndex, force) {
- var len, result;
-
- /*jshint expr: true*/
- startIndex || (startIndex = 0);
-
- if (force || YArray.test(thing)) {
- // IE throws when trying to slice HTMLElement collections.
- try {
- return Native.slice.call(thing, startIndex);
- } catch (ex) {
- result = [];
-
- for (len = thing.length; startIndex < len; ++startIndex) {
- result.push(thing[startIndex]);
- }
-
- return result;
- }
- }
-
- return [thing];
- }
-
- Y.Array = YArray;
-
- /**
- Dedupes an array of strings, returning an array that's guaranteed to contain
- only one copy of a given string.
-
- This method differs from `Array.unique()` in that it's optimized for use only
- with strings, whereas `unique` may be used with other types (but is slower).
- Using `dedupe()` with non-string values may result in unexpected behavior.
-
- @method dedupe
- @param {String[]} array Array of strings to dedupe.
- @return {Array} Deduped copy of _array_.
- @static
- @since 3.4.0
- **/
- YArray.dedupe = function (array) {
- var hash = {},
- results = [],
- i, item, len;
-
- for (i = 0, len = array.length; i < len; ++i) {
- item = array[i];
-
- if (!hasOwn.call(hash, item)) {
- hash[item] = 1;
- results.push(item);
- }
- }
-
- return results;
- };
-
- /**
- Executes the supplied function on each item in the array. This method wraps
- the native ES5 `Array.forEach()` method if available.
-
- @method each
- @param {Array} array Array to iterate.
- @param {Function} fn Function to execute on each item in the array. The function
- will receive the following arguments:
- @param {Any} fn.item Current array item.
- @param {Number} fn.index Current array index.
- @param {Array} fn.array Array being iterated.
- @param {Object} [thisObj] `this` object to use when calling _fn_.
- @return {YUI} The YUI instance.
- @static
- **/
- YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
- Native.forEach.call(array || [], fn, thisObj || Y);
- return Y;
- } : function (array, fn, thisObj) {
- for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
- if (i in array) {
- fn.call(thisObj || Y, array[i], i, array);
- }
- }
-
- return Y;
- };
-
- /**
- Alias for `each()`.
-
- @method forEach
- @static
- **/
-
- /**
- Returns an object using the first array as keys and the second as values. If
- the second array is not provided, or if it doesn't contain the same number of
- values as the first array, then `true` will be used in place of the missing
- values.
-
- @example
-
- Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
- // => {a: 'foo', b: 'bar', c: true}
-
- @method hash
- @param {String[]} keys Array of strings to use as keys.
- @param {Array} [values] Array to use as values.
- @return {Object} Hash using the first array as keys and the second as values.
- @static
- **/
- YArray.hash = function (keys, values) {
- var hash = {},
- vlen = (values && values.length) || 0,
- i, len;
-
- for (i = 0, len = keys.length; i < len; ++i) {
- if (i in keys) {
- hash[keys[i]] = vlen > i && i in values ? values[i] : true;
- }
- }
-
- return hash;
- };
-
- /**
- Returns the index of the first item in the array that's equal (using a strict
- equality check) to the specified _value_, or `-1` if the value isn't found.
-
- This method wraps the native ES5 `Array.indexOf()` method if available.
-
- @method indexOf
- @param {Array} array Array to search.
- @param {Any} value Value to search for.
- @param {Number} [from=0] The index at which to begin the search.
- @return {Number} Index of the item strictly equal to _value_, or `-1` if not
- found.
- @static
- **/
- YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
- return Native.indexOf.call(array, value, from);
- } : function (array, value, from) {
- // http://es5.github.com/#x15.4.4.14
- var len = array.length;
-
- from = +from || 0;
- from = (from > 0 || -1) * Math.floor(Math.abs(from));
-
- if (from < 0) {
- from += len;
-
- if (from < 0) {
- from = 0;
- }
- }
-
- for (; from < len; ++from) {
- if (from in array && array[from] === value) {
- return from;
- }
- }
-
- return -1;
- };
-
- /**
- Numeric sort convenience function.
-
- The native `Array.prototype.sort()` function converts values to strings and
- sorts them in lexicographic order, which is unsuitable for sorting numeric
- values. Provide `Array.numericSort` as a custom sort function when you want
- to sort values in numeric order.
-
- @example
-
- [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
- // => [4, 8, 15, 16, 23, 42]
-
- @method numericSort
- @param {Number} a First value to compare.
- @param {Number} b Second value to compare.
- @return {Number} Difference between _a_ and _b_.
- @static
- **/
- YArray.numericSort = function (a, b) {
- return a - b;
- };
-
- /**
- Executes the supplied function on each item in the array. Returning a truthy
- value from the function will stop the processing of remaining items.
-
- @method some
- @param {Array} array Array to iterate over.
- @param {Function} fn Function to execute on each item. The function will receive
- the following arguments:
- @param {Any} fn.value Current array item.
- @param {Number} fn.index Current array index.
- @param {Array} fn.array Array being iterated over.
- @param {Object} [thisObj] `this` object to use when calling _fn_.
- @return {Boolean} `true` if the function returns a truthy value on any of the
- items in the array; `false` otherwise.
- @static
- **/
- YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
- return Native.some.call(array, fn, thisObj);
- } : function (array, fn, thisObj) {
- for (var i = 0, len = array.length; i < len; ++i) {
- if (i in array && fn.call(thisObj, array[i], i, array)) {
- return true;
- }
- }
-
- return false;
- };
-
- /**
- Evaluates _obj_ to determine if it's an array, an array-like collection, or
- something else. This is useful when working with the function `arguments`
- collection and `HTMLElement` collections.
-
- Note: This implementation doesn't consider elements that are also
- collections, such as `<form>` and `<select>`, to be array-like.
-
- @method test
- @param {Object} obj Object to test.
- @return {Number} A number indicating the results of the test:
-
- * 0: Neither an array nor an array-like collection.
- * 1: Real array.
- * 2: Array-like collection.
-
- @static
- **/
- YArray.test = function (obj) {
- var result = 0;
-
- if (Lang.isArray(obj)) {
- result = 1;
- } else if (Lang.isObject(obj)) {
- try {
- // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
- // or functions without apply/call (Safari
- // HTMLElementCollection bug).
- if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
- result = 2;
- }
- } catch (ex) {}
- }
-
- return result;
- };
-
-