src/cm/media/js/lib/yui/yui3-3.15.0/build/array-extras/array-extras.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('array-extras', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4 Adds additional utility methods to the `Y.Array` class.
       
     5 
       
     6 @module collection
       
     7 @submodule array-extras
       
     8 **/
       
     9 
       
    10 var A          = Y.Array,
       
    11     L          = Y.Lang,
       
    12     ArrayProto = Array.prototype;
       
    13 
       
    14 /**
       
    15 Returns the index of the last item in the array that contains the specified
       
    16 value, or `-1` if the value isn't found.
       
    17 
       
    18 @method lastIndexOf
       
    19 @param {Array} a Array to search in.
       
    20 @param {Any} val Value to search for.
       
    21 @param {Number} [fromIndex] Index at which to start searching backwards.
       
    22   Defaults to the array's length - 1. If negative, it will be taken as an offset
       
    23   from the end of the array. If the calculated index is less than 0, the array
       
    24   will not be searched and `-1` will be returned.
       
    25 @return {Number} Index of the item that contains the value, or `-1` if not
       
    26   found.
       
    27 @static
       
    28 @for Array
       
    29 **/
       
    30 A.lastIndexOf = L._isNative(ArrayProto.lastIndexOf) ?
       
    31     function(a, val, fromIndex) {
       
    32         // An undefined fromIndex is still considered a value by some (all?)
       
    33         // native implementations, so we can't pass it unless it's actually
       
    34         // specified.
       
    35         return fromIndex || fromIndex === 0 ? a.lastIndexOf(val, fromIndex) :
       
    36                 a.lastIndexOf(val);
       
    37     } :
       
    38     function(a, val, fromIndex) {
       
    39         var len = a.length,
       
    40             i   = len - 1;
       
    41 
       
    42         if (fromIndex || fromIndex === 0) {
       
    43             i = Math.min(fromIndex < 0 ? len + fromIndex : fromIndex, len);
       
    44         }
       
    45 
       
    46         if (i > -1 && len > 0) {
       
    47             for (; i > -1; --i) {
       
    48                 if (i in a && a[i] === val) {
       
    49                     return i;
       
    50                 }
       
    51             }
       
    52         }
       
    53 
       
    54         return -1;
       
    55     };
       
    56 
       
    57 /**
       
    58 Returns a copy of the input array with duplicate items removed.
       
    59 
       
    60 Note: If the input array only contains strings, the `Y.Array.dedupe()` method is
       
    61 a much faster alternative.
       
    62 
       
    63 @method unique
       
    64 @param {Array} array Array to dedupe.
       
    65 @param {Function} [testFn] Custom function to use to test the equality of two
       
    66     values. A truthy return value indicates that the values are equal. A falsy
       
    67     return value indicates that the values are not equal.
       
    68 
       
    69     @param {Any} testFn.a First value to compare.
       
    70     @param {Any} testFn.b Second value to compare.
       
    71     @param {Number} testFn.index Index of the current item in the original
       
    72         array.
       
    73     @param {Array} testFn.array The original array.
       
    74     @return {Boolean} _true_ if the items are equal, _false_ otherwise.
       
    75 
       
    76 @return {Array} Copy of the input array with duplicate items removed.
       
    77 @static
       
    78 **/
       
    79 A.unique = function (array, testFn) {
       
    80     var i       = 0,
       
    81         len     = array.length,
       
    82         results = [],
       
    83         j, result, resultLen, value;
       
    84 
       
    85     // Note the label here. It's used to jump out of the inner loop when a value
       
    86     // is not unique.
       
    87     outerLoop: for (; i < len; i++) {
       
    88         value = array[i];
       
    89 
       
    90         // For each value in the input array, iterate through the result array
       
    91         // and check for uniqueness against each result value.
       
    92         for (j = 0, resultLen = results.length; j < resultLen; j++) {
       
    93             result = results[j];
       
    94 
       
    95             // If the test function returns true or there's no test function and
       
    96             // the value equals the current result item, stop iterating over the
       
    97             // results and continue to the next value in the input array.
       
    98             if (testFn) {
       
    99                 if (testFn.call(array, value, result, i, array)) {
       
   100                     continue outerLoop;
       
   101                 }
       
   102             } else if (value === result) {
       
   103                 continue outerLoop;
       
   104             }
       
   105         }
       
   106 
       
   107         // If we get this far, that means the current value is not already in
       
   108         // the result array, so add it.
       
   109         results.push(value);
       
   110     }
       
   111 
       
   112     return results;
       
   113 };
       
   114 
       
   115 /**
       
   116 Executes the supplied function on each item in the array. Returns a new array
       
   117 containing the items for which the supplied function returned a truthy value.
       
   118 
       
   119 @method filter
       
   120 @param {Array} a Array to filter.
       
   121 @param {Function} f Function to execute on each item.
       
   122 @param {Object} [o] Optional context object.
       
   123 @return {Array} Array of items for which the supplied function returned a
       
   124   truthy value (empty if it never returned a truthy value).
       
   125 @static
       
   126 */
       
   127 A.filter = L._isNative(ArrayProto.filter) ?
       
   128     function(a, f, o) {
       
   129         return ArrayProto.filter.call(a, f, o);
       
   130     } :
       
   131     function(a, f, o) {
       
   132         var i       = 0,
       
   133             len     = a.length,
       
   134             results = [],
       
   135             item;
       
   136 
       
   137         for (; i < len; ++i) {
       
   138             if (i in a) {
       
   139                 item = a[i];
       
   140 
       
   141                 if (f.call(o, item, i, a)) {
       
   142                     results.push(item);
       
   143                 }
       
   144             }
       
   145         }
       
   146 
       
   147         return results;
       
   148     };
       
   149 
       
   150 /**
       
   151 The inverse of `Array.filter()`. Executes the supplied function on each item.
       
   152 Returns a new array containing the items for which the supplied function
       
   153 returned `false`.
       
   154 
       
   155 @method reject
       
   156 @param {Array} a the array to iterate.
       
   157 @param {Function} f the function to execute on each item.
       
   158 @param {object} [o] Optional context object.
       
   159 @return {Array} The items for which the supplied function returned `false`.
       
   160 @static
       
   161 */
       
   162 A.reject = function(a, f, o) {
       
   163     return A.filter(a, function(item, i, a) {
       
   164         return !f.call(o, item, i, a);
       
   165     });
       
   166 };
       
   167 
       
   168 /**
       
   169 Executes the supplied function on each item in the array. Iteration stops if the
       
   170 supplied function does not return a truthy value.
       
   171 
       
   172 @method every
       
   173 @param {Array} a the array to iterate.
       
   174 @param {Function} f the function to execute on each item.
       
   175 @param {Object} [o] Optional context object.
       
   176 @return {Boolean} `true` if every item in the array returns `true` from the
       
   177   supplied function, `false` otherwise.
       
   178 @static
       
   179 */
       
   180 A.every = L._isNative(ArrayProto.every) ?
       
   181     function(a, f, o) {
       
   182         return ArrayProto.every.call(a, f, o);
       
   183     } :
       
   184     function(a, f, o) {
       
   185         for (var i = 0, l = a.length; i < l; ++i) {
       
   186             if (i in a && !f.call(o, a[i], i, a)) {
       
   187                 return false;
       
   188             }
       
   189         }
       
   190 
       
   191         return true;
       
   192     };
       
   193 
       
   194 /**
       
   195 Executes the supplied function on each item in the array and returns a new array
       
   196 containing all the values returned by the supplied function.
       
   197 
       
   198 @example
       
   199 
       
   200     // Convert an array of numbers into an array of strings.
       
   201     Y.Array.map([1, 2, 3, 4], function (item) {
       
   202       return '' + item;
       
   203     });
       
   204     // => ['1', '2', '3', '4']
       
   205 
       
   206 @method map
       
   207 @param {Array} a the array to iterate.
       
   208 @param {Function} f the function to execute on each item.
       
   209 @param {object} [o] Optional context object.
       
   210 @return {Array} A new array containing the return value of the supplied function
       
   211   for each item in the original array.
       
   212 @static
       
   213 */
       
   214 A.map = L._isNative(ArrayProto.map) ?
       
   215     function(a, f, o) {
       
   216         return ArrayProto.map.call(a, f, o);
       
   217     } :
       
   218     function(a, f, o) {
       
   219         var i       = 0,
       
   220             len     = a.length,
       
   221             results = ArrayProto.concat.call(a);
       
   222 
       
   223         for (; i < len; ++i) {
       
   224             if (i in a) {
       
   225                 results[i] = f.call(o, a[i], i, a);
       
   226             }
       
   227         }
       
   228 
       
   229         return results;
       
   230     };
       
   231 
       
   232 
       
   233 /**
       
   234 Executes the supplied function on each item in the array, "folding" the array
       
   235 into a single value.
       
   236 
       
   237 @method reduce
       
   238 @param {Array} a Array to iterate.
       
   239 @param {Any} init Initial value to start with.
       
   240 @param {Function} f Function to execute on each item. This function should
       
   241   update and return the value of the computation. It will receive the following
       
   242   arguments:
       
   243     @param {Any} f.previousValue Value returned from the previous iteration,
       
   244       or the initial value if this is the first iteration.
       
   245     @param {Any} f.currentValue Value of the current item being iterated.
       
   246     @param {Number} f.index Index of the current item.
       
   247     @param {Array} f.array Array being iterated.
       
   248 @param {Object} [o] Optional context object.
       
   249 @return {Any} Final result from iteratively applying the given function to each
       
   250   element in the array.
       
   251 @static
       
   252 */
       
   253 A.reduce = L._isNative(ArrayProto.reduce) ?
       
   254     function(a, init, f, o) {
       
   255         // ES5 Array.reduce doesn't support a thisObject, so we need to
       
   256         // implement it manually.
       
   257         return ArrayProto.reduce.call(a, function(init, item, i, a) {
       
   258             return f.call(o, init, item, i, a);
       
   259         }, init);
       
   260     } :
       
   261     function(a, init, f, o) {
       
   262         var i      = 0,
       
   263             len    = a.length,
       
   264             result = init;
       
   265 
       
   266         for (; i < len; ++i) {
       
   267             if (i in a) {
       
   268                 result = f.call(o, result, a[i], i, a);
       
   269             }
       
   270         }
       
   271 
       
   272         return result;
       
   273     };
       
   274 
       
   275 /**
       
   276 Executes the supplied function on each item in the array, searching for the
       
   277 first item that matches the supplied function.
       
   278 
       
   279 @method find
       
   280 @param {Array} a the array to search.
       
   281 @param {Function} f the function to execute on each item. Iteration is stopped
       
   282   as soon as this function returns `true`.
       
   283 @param {Object} [o] Optional context object.
       
   284 @return {Object} the first item that the supplied function returns `true` for,
       
   285   or `null` if it never returns `true`.
       
   286 @static
       
   287 */
       
   288 A.find = function(a, f, o) {
       
   289     for (var i = 0, l = a.length; i < l; i++) {
       
   290         if (i in a && f.call(o, a[i], i, a)) {
       
   291             return a[i];
       
   292         }
       
   293     }
       
   294     return null;
       
   295 };
       
   296 
       
   297 /**
       
   298 Iterates over an array, returning a new array of all the elements that match the
       
   299 supplied regular expression.
       
   300 
       
   301 @method grep
       
   302 @param {Array} a Array to iterate over.
       
   303 @param {RegExp} pattern Regular expression to test against each item.
       
   304 @return {Array} All the items in the array that produce a match against the
       
   305   supplied regular expression. If no items match, an empty array is returned.
       
   306 @static
       
   307 */
       
   308 A.grep = function(a, pattern) {
       
   309     return A.filter(a, function(item, index) {
       
   310         return pattern.test(item);
       
   311     });
       
   312 };
       
   313 
       
   314 /**
       
   315 Partitions an array into two new arrays, one with the items for which the
       
   316 supplied function returns `true`, and one with the items for which the function
       
   317 returns `false`.
       
   318 
       
   319 @method partition
       
   320 @param {Array} a Array to iterate over.
       
   321 @param {Function} f Function to execute for each item in the array. It will
       
   322   receive the following arguments:
       
   323     @param {Any} f.item Current item.
       
   324     @param {Number} f.index Index of the current item.
       
   325     @param {Array} f.array The array being iterated.
       
   326 @param {Object} [o] Optional execution context.
       
   327 @return {Object} An object with two properties: `matches` and `rejects`. Each is
       
   328   an array containing the items that were selected or rejected by the test
       
   329   function (or an empty array if none).
       
   330 @static
       
   331 */
       
   332 A.partition = function(a, f, o) {
       
   333     var results = {
       
   334         matches: [],
       
   335         rejects: []
       
   336     };
       
   337 
       
   338     A.each(a, function(item, index) {
       
   339         var set = f.call(o, item, index, a) ? results.matches : results.rejects;
       
   340         set.push(item);
       
   341     });
       
   342 
       
   343     return results;
       
   344 };
       
   345 
       
   346 /**
       
   347 Creates an array of arrays by pairing the corresponding elements of two arrays
       
   348 together into a new array.
       
   349 
       
   350 @method zip
       
   351 @param {Array} a Array to iterate over.
       
   352 @param {Array} a2 Another array whose values will be paired with values of the
       
   353   first array.
       
   354 @return {Array} An array of arrays formed by pairing each element of the first
       
   355   array with an item in the second array having the corresponding index.
       
   356 @static
       
   357 */
       
   358 A.zip = function(a, a2) {
       
   359     var results = [];
       
   360     A.each(a, function(item, index) {
       
   361         results.push([item, a2[index]]);
       
   362     });
       
   363     return results;
       
   364 };
       
   365 
       
   366 /**
       
   367 Flattens an array of nested arrays at any abitrary depth into a single, flat
       
   368 array.
       
   369 
       
   370 @method flatten
       
   371 @param {Array} a Array with nested arrays to flatten.
       
   372 @return {Array} An array whose nested arrays have been flattened.
       
   373 @static
       
   374 @since 3.7.0
       
   375 **/
       
   376 A.flatten = function(a) {
       
   377     var result = [],
       
   378         i, len, val;
       
   379 
       
   380     // Always return an array.
       
   381     if (!a) {
       
   382         return result;
       
   383     }
       
   384 
       
   385     for (i = 0, len = a.length; i < len; ++i) {
       
   386         val = a[i];
       
   387 
       
   388         if (L.isArray(val)) {
       
   389             // Recusively flattens any nested arrays.
       
   390             result.push.apply(result, A.flatten(val));
       
   391         } else {
       
   392             result.push(val);
       
   393         }
       
   394     }
       
   395 
       
   396     return result;
       
   397 };
       
   398 
       
   399 
       
   400 }, '@VERSION@', {"requires": ["yui-base"]});