MDL-32843 import YUI 3.5.1
[moodle.git] / lib / yui / 3.5.1 / build / array-extras / array-extras.js
blob4f32c0fc4e720fa4c014b1637e280d22a96155c9
1 /*
2 YUI 3.5.1 (build 22)
3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
7 YUI.add('array-extras', function(Y) {
9 /**
10 Adds additional utility methods to the `Y.Array` class.
12 @module collection
13 @submodule array-extras
14 **/
16 var A          = Y.Array,
17     L          = Y.Lang,
18     ArrayProto = Array.prototype;
20 /**
21 Returns the index of the last item in the array that contains the specified
22 value, or `-1` if the value isn't found.
24 @method lastIndexOf
25 @param {Array} a Array to search in.
26 @param {Any} val Value to search for.
27 @param {Number} [fromIndex] Index at which to start searching backwards.
28   Defaults to the array's length - 1. If negative, it will be taken as an offset
29   from the end of the array. If the calculated index is less than 0, the array
30   will not be searched and `-1` will be returned.
31 @return {Number} Index of the item that contains the value, or `-1` if not
32   found.
33 @static
34 @for Array
35 **/
36 A.lastIndexOf = L._isNative(ArrayProto.lastIndexOf) ?
37     function(a, val, fromIndex) {
38         // An undefined fromIndex is still considered a value by some (all?)
39         // native implementations, so we can't pass it unless it's actually
40         // specified.
41         return fromIndex || fromIndex === 0 ? a.lastIndexOf(val, fromIndex) :
42                 a.lastIndexOf(val);
43     } :
44     function(a, val, fromIndex) {
45         var len = a.length,
46             i   = len - 1;
48         if (fromIndex || fromIndex === 0) {
49             i = Math.min(fromIndex < 0 ? len + fromIndex : fromIndex, len);
50         }
52         if (i > -1 && len > 0) {
53             for (; i > -1; --i) {
54                 if (i in a && a[i] === val) {
55                     return i;
56                 }
57             }
58         }
60         return -1;
61     };
63 /**
64 Returns a copy of the specified array with duplicate items removed.
66 @method unique
67 @param {Array} a Array to dedupe.
68 @return {Array} Copy of the array with duplicate items removed.
69 @static
70 **/
71 A.unique = function(a, sort) {
72     // Note: the sort param is deprecated and intentionally undocumented since
73     // YUI 3.3.0. It never did what the API docs said it did (see the older
74     // comment below as well).
75     var i       = 0,
76         len     = a.length,
77         results = [],
78         item, j;
80     for (; i < len; ++i) {
81         item = a[i];
83         // This loop iterates over the results array in reverse order and stops
84         // if it finds an item that matches the current input array item (a
85         // dupe). If it makes it all the way through without finding a dupe, the
86         // current item is pushed onto the results array.
87         for (j = results.length; j > -1; --j) {
88             if (item === results[j]) {
89                 break;
90             }
91         }
93         if (j === -1) {
94             results.push(item);
95         }
96     }
98     // Note: the sort option doesn't really belong here... I think it was added
99     // because there was a way to fast path the two operations together.  That
100     // implementation was not working, so I replaced it with the following.
101     // Leaving it in so that the API doesn't get broken.
102     if (sort) {
104         if (L.isNumber(results[0])) {
105             results.sort(A.numericSort);
106         } else {
107             results.sort();
108         }
109     }
111     return results;
115 Executes the supplied function on each item in the array. Returns a new array
116 containing the items for which the supplied function returned a truthy value.
118 @method filter
119 @param {Array} a Array to filter.
120 @param {Function} f Function to execute on each item.
121 @param {Object} [o] Optional context object.
122 @return {Array} Array of items for which the supplied function returned a
123   truthy value (empty if it never returned a truthy value).
124 @static
126 A.filter = L._isNative(ArrayProto.filter) ?
127     function(a, f, o) {
128         return a.filter(f, o);
129     } :
130     function(a, f, o) {
131         var i       = 0,
132             len     = a.length,
133             results = [],
134             item;
136         for (; i < len; ++i) {
137             if (i in a) {
138                 item = a[i];
140                 if (f.call(o, item, i, a)) {
141                     results.push(item);
142                 }
143             }
144         }
146         return results;
147     };
150 The inverse of `Array.filter()`. Executes the supplied function on each item.
151 Returns a new array containing the items for which the supplied function
152 returned `false`.
154 @method reject
155 @param {Array} a the array to iterate.
156 @param {Function} f the function to execute on each item.
157 @param {object} [o] Optional context object.
158 @return {Array} The items for which the supplied function returned `false`.
159 @static
161 A.reject = function(a, f, o) {
162     return A.filter(a, function(item, i, a) {
163         return !f.call(o, item, i, a);
164     });
168 Executes the supplied function on each item in the array. Iteration stops if the
169 supplied function does not return a truthy value.
171 @method every
172 @param {Array} a the array to iterate.
173 @param {Function} f the function to execute on each item.
174 @param {Object} [o] Optional context object.
175 @return {Boolean} `true` if every item in the array returns `true` from the
176   supplied function, `false` otherwise.
177 @static
179 A.every = L._isNative(ArrayProto.every) ?
180     function(a, f, o) {
181         return a.every(f, o);
182     } :
183     function(a, f, o) {
184         for (var i = 0, l = a.length; i < l; ++i) {
185             if (i in a && !f.call(o, a[i], i, a)) {
186                 return false;
187             }
188         }
190         return true;
191     };
194 Executes the supplied function on each item in the array and returns a new array
195 containing all the values returned by the supplied function.
197 @example
199     // Convert an array of numbers into an array of strings.
200     Y.Array.map([1, 2, 3, 4], function (item) {
201       return '' + item;
202     });
203     // => ['1', '2', '3', '4']
205 @method map
206 @param {Array} a the array to iterate.
207 @param {Function} f the function to execute on each item.
208 @param {object} [o] Optional context object.
209 @return {Array} A new array containing the return value of the supplied function
210   for each item in the original array.
211 @static
213 A.map = L._isNative(ArrayProto.map) ?
214     function(a, f, o) {
215         return a.map(f, o);
216     } :
217     function(a, f, o) {
218         var i       = 0,
219             len     = a.length,
220             results = a.concat();
222         for (; i < len; ++i) {
223             if (i in a) {
224                 results[i] = f.call(o, a[i], i, a);
225             }
226         }
228         return results;
229     };
233 Executes the supplied function on each item in the array, "folding" the array
234 into a single value.
236 @method reduce
237 @param {Array} a Array to iterate.
238 @param {Any} init Initial value to start with.
239 @param {Function} f Function to execute on each item. This function should
240   update and return the value of the computation. It will receive the following
241   arguments:
242     @param {Any} f.previousValue Value returned from the previous iteration,
243       or the initial value if this is the first iteration.
244     @param {Any} f.currentValue Value of the current item being iterated.
245     @param {Number} f.index Index of the current item.
246     @param {Array} f.array Array being iterated.
247 @param {Object} [o] Optional context object.
248 @return {Any} Final result from iteratively applying the given function to each
249   element in the array.
250 @static
252 A.reduce = L._isNative(ArrayProto.reduce) ?
253     function(a, init, f, o) {
254         // ES5 Array.reduce doesn't support a thisObject, so we need to
255         // implement it manually.
256         return a.reduce(function(init, item, i, a) {
257             return f.call(o, init, item, i, a);
258         }, init);
259     } :
260     function(a, init, f, o) {
261         var i      = 0,
262             len    = a.length,
263             result = init;
265         for (; i < len; ++i) {
266             if (i in a) {
267                 result = f.call(o, result, a[i], i, a);
268             }
269         }
271         return result;
272     };
275 Executes the supplied function on each item in the array, searching for the
276 first item that matches the supplied function.
278 @method find
279 @param {Array} a the array to search.
280 @param {Function} f the function to execute on each item. Iteration is stopped
281   as soon as this function returns `true`.
282 @param {Object} [o] Optional context object.
283 @return {Object} the first item that the supplied function returns `true` for,
284   or `null` if it never returns `true`.
285 @static
287 A.find = function(a, f, o) {
288     for (var i = 0, l = a.length; i < l; i++) {
289         if (i in a && f.call(o, a[i], i, a)) {
290             return a[i];
291         }
292     }
293     return null;
297 Iterates over an array, returning a new array of all the elements that match the
298 supplied regular expression.
300 @method grep
301 @param {Array} a Array to iterate over.
302 @param {RegExp} pattern Regular expression to test against each item.
303 @return {Array} All the items in the array that produce a match against the
304   supplied regular expression. If no items match, an empty array is returned.
305 @static
307 A.grep = function(a, pattern) {
308     return A.filter(a, function(item, index) {
309         return pattern.test(item);
310     });
314 Partitions an array into two new arrays, one with the items for which the
315 supplied function returns `true`, and one with the items for which the function
316 returns `false`.
318 @method partition
319 @param {Array} a Array to iterate over.
320 @param {Function} f Function to execute for each item in the array. It will
321   receive the following arguments:
322     @param {Any} f.item Current item.
323     @param {Number} f.index Index of the current item.
324     @param {Array} f.array The array being iterated.
325 @param {Object} [o] Optional execution context.
326 @return {Object} An object with two properties: `matches` and `rejects`. Each is
327   an array containing the items that were selected or rejected by the test
328   function (or an empty array if none).
329 @static
331 A.partition = function(a, f, o) {
332     var results = {
333         matches: [],
334         rejects: []
335     };
337     A.each(a, function(item, index) {
338         var set = f.call(o, item, index, a) ? results.matches : results.rejects;
339         set.push(item);
340     });
342     return results;
346 Creates an array of arrays by pairing the corresponding elements of two arrays
347 together into a new array.
349 @method zip
350 @param {Array} a Array to iterate over.
351 @param {Array} a2 Another array whose values will be paired with values of the
352   first array.
353 @return {Array} An array of arrays formed by pairing each element of the first
354   array with an item in the second array having the corresponding index.
355 @static
357 A.zip = function(a, a2) {
358     var results = [];
359     A.each(a, function(item, index) {
360         results.push([item, a2[index]]);
361     });
362     return results;
366 }, '3.5.1' ,{requires:['yui-base']});