]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dojo/_base/array", ["./kernel", "../has", "./lang"], function(dojo, has, lang){ |
2 | // module: | |
3 | // dojo/_base/array | |
4 | ||
5 | // our old simple function builder stuff | |
6 | var cache = {}, u; | |
7 | ||
8 | function buildFn(fn){ | |
9 | return cache[fn] = new Function("item", "index", "array", fn); // Function | |
10 | } | |
11 | // magic snippet: if(typeof fn == "string") fn = cache[fn] || buildFn(fn); | |
12 | ||
13 | // every & some | |
14 | ||
15 | function everyOrSome(some){ | |
16 | var every = !some; | |
17 | return function(a, fn, o){ | |
18 | var i = 0, l = a && a.length || 0, result; | |
19 | if(l && typeof a == "string") a = a.split(""); | |
20 | if(typeof fn == "string") fn = cache[fn] || buildFn(fn); | |
21 | if(o){ | |
22 | for(; i < l; ++i){ | |
23 | result = !fn.call(o, a[i], i, a); | |
24 | if(some ^ result){ | |
25 | return !result; | |
26 | } | |
27 | } | |
28 | }else{ | |
29 | for(; i < l; ++i){ | |
30 | result = !fn(a[i], i, a); | |
31 | if(some ^ result){ | |
32 | return !result; | |
33 | } | |
34 | } | |
35 | } | |
36 | return every; // Boolean | |
37 | }; | |
38 | } | |
39 | ||
40 | // indexOf, lastIndexOf | |
41 | ||
42 | function index(up){ | |
43 | var delta = 1, lOver = 0, uOver = 0; | |
44 | if(!up){ | |
45 | delta = lOver = uOver = -1; | |
46 | } | |
47 | return function(a, x, from, last){ | |
48 | if(last && delta > 0){ | |
49 | // TODO: why do we use a non-standard signature? why do we need "last"? | |
50 | return array.lastIndexOf(a, x, from); | |
51 | } | |
52 | var l = a && a.length || 0, end = up ? l + uOver : lOver, i; | |
53 | if(from === u){ | |
54 | i = up ? lOver : l + uOver; | |
55 | }else{ | |
56 | if(from < 0){ | |
57 | i = l + from; | |
58 | if(i < 0){ | |
59 | i = lOver; | |
60 | } | |
61 | }else{ | |
62 | i = from >= l ? l + uOver : from; | |
63 | } | |
64 | } | |
65 | if(l && typeof a == "string") a = a.split(""); | |
66 | for(; i != end; i += delta){ | |
67 | if(a[i] == x){ | |
68 | return i; // Number | |
69 | } | |
70 | } | |
71 | return -1; // Number | |
72 | }; | |
73 | } | |
74 | ||
75 | var array = { | |
76 | // summary: | |
77 | // The Javascript v1.6 array extensions. | |
78 | ||
79 | every: everyOrSome(false), | |
80 | /*===== | |
81 | every: function(arr, callback, thisObject){ | |
82 | // summary: | |
83 | // Determines whether or not every item in arr satisfies the | |
84 | // condition implemented by callback. | |
85 | // arr: Array|String | |
86 | // the array to iterate on. If a string, operates on individual characters. | |
87 | // callback: Function|String | |
88 | // a function is invoked with three arguments: item, index, | |
89 | // and array and returns true if the condition is met. | |
90 | // thisObject: Object? | |
91 | // may be used to scope the call to callback | |
92 | // returns: Boolean | |
93 | // description: | |
94 | // This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when | |
95 | // run over sparse arrays, this implementation passes the "holes" in the sparse array to | |
96 | // the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array. | |
97 | // For more details, see: | |
98 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every | |
99 | // example: | |
100 | // | // returns false | |
101 | // | array.every([1, 2, 3, 4], function(item){ return item>1; }); | |
102 | // example: | |
103 | // | // returns true | |
104 | // | array.every([1, 2, 3, 4], function(item){ return item>0; }); | |
105 | }, | |
106 | =====*/ | |
107 | ||
108 | some: everyOrSome(true), | |
109 | /*===== | |
110 | some: function(arr, callback, thisObject){ | |
111 | // summary: | |
112 | // Determines whether or not any item in arr satisfies the | |
113 | // condition implemented by callback. | |
114 | // arr: Array|String | |
115 | // the array to iterate over. If a string, operates on individual characters. | |
116 | // callback: Function|String | |
117 | // a function is invoked with three arguments: item, index, | |
118 | // and array and returns true if the condition is met. | |
119 | // thisObject: Object? | |
120 | // may be used to scope the call to callback | |
121 | // returns: Boolean | |
122 | // description: | |
123 | // This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when | |
124 | // run over sparse arrays, this implementation passes the "holes" in the sparse array to | |
125 | // the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array. | |
126 | // For more details, see: | |
127 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some | |
128 | // example: | |
129 | // | // is true | |
130 | // | array.some([1, 2, 3, 4], function(item){ return item>1; }); | |
131 | // example: | |
132 | // | // is false | |
133 | // | array.some([1, 2, 3, 4], function(item){ return item<1; }); | |
134 | }, | |
135 | =====*/ | |
136 | ||
137 | indexOf: index(true), | |
138 | /*===== | |
139 | indexOf: function(arr, value, fromIndex, findLast){ | |
140 | // summary: | |
141 | // locates the first index of the provided value in the | |
142 | // passed array. If the value is not found, -1 is returned. | |
143 | // description: | |
144 | // This method corresponds to the JavaScript 1.6 Array.indexOf method, with one difference: when | |
145 | // run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript | |
146 | // 1.6's indexOf skips the holes in the sparse array. | |
147 | // For details on this method, see: | |
148 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf | |
149 | // arr: Array | |
150 | // value: Object | |
151 | // fromIndex: Integer? | |
152 | // findLast: Boolean? | |
153 | // returns: Number | |
154 | }, | |
155 | =====*/ | |
156 | ||
157 | lastIndexOf: index(false), | |
158 | /*===== | |
159 | lastIndexOf: function(arr, value, fromIndex){ | |
160 | // summary: | |
161 | // locates the last index of the provided value in the passed | |
162 | // array. If the value is not found, -1 is returned. | |
163 | // description: | |
164 | // This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with one difference: when | |
165 | // run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript | |
166 | // 1.6's lastIndexOf skips the holes in the sparse array. | |
167 | // For details on this method, see: | |
168 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf | |
169 | // arr: Array, | |
170 | // value: Object, | |
171 | // fromIndex: Integer? | |
172 | // returns: Number | |
173 | }, | |
174 | =====*/ | |
175 | ||
176 | forEach: function(arr, callback, thisObject){ | |
177 | // summary: | |
178 | // for every item in arr, callback is invoked. Return values are ignored. | |
179 | // If you want to break out of the loop, consider using array.every() or array.some(). | |
180 | // forEach does not allow breaking out of the loop over the items in arr. | |
181 | // arr: | |
182 | // the array to iterate over. If a string, operates on individual characters. | |
183 | // callback: | |
184 | // a function is invoked with three arguments: item, index, and array | |
185 | // thisObject: | |
186 | // may be used to scope the call to callback | |
187 | // description: | |
188 | // This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when | |
189 | // run over sparse arrays, this implementation passes the "holes" in the sparse array to | |
190 | // the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array. | |
191 | // For more details, see: | |
192 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach | |
193 | // example: | |
194 | // | // log out all members of the array: | |
195 | // | array.forEach( | |
196 | // | [ "thinger", "blah", "howdy", 10 ], | |
197 | // | function(item){ | |
198 | // | console.log(item); | |
199 | // | } | |
200 | // | ); | |
201 | // example: | |
202 | // | // log out the members and their indexes | |
203 | // | array.forEach( | |
204 | // | [ "thinger", "blah", "howdy", 10 ], | |
205 | // | function(item, idx, arr){ | |
206 | // | console.log(item, "at index:", idx); | |
207 | // | } | |
208 | // | ); | |
209 | // example: | |
210 | // | // use a scoped object member as the callback | |
211 | // | | |
212 | // | var obj = { | |
213 | // | prefix: "logged via obj.callback:", | |
214 | // | callback: function(item){ | |
215 | // | console.log(this.prefix, item); | |
216 | // | } | |
217 | // | }; | |
218 | // | | |
219 | // | // specifying the scope function executes the callback in that scope | |
220 | // | array.forEach( | |
221 | // | [ "thinger", "blah", "howdy", 10 ], | |
222 | // | obj.callback, | |
223 | // | obj | |
224 | // | ); | |
225 | // | | |
226 | // | // alternately, we can accomplish the same thing with lang.hitch() | |
227 | // | array.forEach( | |
228 | // | [ "thinger", "blah", "howdy", 10 ], | |
229 | // | lang.hitch(obj, "callback") | |
230 | // | ); | |
231 | // arr: Array|String | |
232 | // callback: Function|String | |
233 | // thisObject: Object? | |
234 | ||
235 | var i = 0, l = arr && arr.length || 0; | |
236 | if(l && typeof arr == "string") arr = arr.split(""); | |
237 | if(typeof callback == "string") callback = cache[callback] || buildFn(callback); | |
238 | if(thisObject){ | |
239 | for(; i < l; ++i){ | |
240 | callback.call(thisObject, arr[i], i, arr); | |
241 | } | |
242 | }else{ | |
243 | for(; i < l; ++i){ | |
244 | callback(arr[i], i, arr); | |
245 | } | |
246 | } | |
247 | }, | |
248 | ||
249 | map: function(arr, callback, thisObject, Ctr){ | |
250 | // summary: | |
251 | // applies callback to each element of arr and returns | |
252 | // an Array with the results | |
253 | // arr: Array|String | |
254 | // the array to iterate on. If a string, operates on | |
255 | // individual characters. | |
256 | // callback: Function|String | |
257 | // a function is invoked with three arguments, (item, index, | |
258 | // array), and returns a value | |
259 | // thisObject: Object? | |
260 | // may be used to scope the call to callback | |
261 | // returns: Array | |
262 | // description: | |
263 | // This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when | |
264 | // run over sparse arrays, this implementation passes the "holes" in the sparse array to | |
265 | // the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array. | |
266 | // For more details, see: | |
267 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map | |
268 | // example: | |
269 | // | // returns [2, 3, 4, 5] | |
270 | // | array.map([1, 2, 3, 4], function(item){ return item+1 }); | |
271 | ||
272 | // TODO: why do we have a non-standard signature here? do we need "Ctr"? | |
273 | var i = 0, l = arr && arr.length || 0, out = new (Ctr || Array)(l); | |
274 | if(l && typeof arr == "string") arr = arr.split(""); | |
275 | if(typeof callback == "string") callback = cache[callback] || buildFn(callback); | |
276 | if(thisObject){ | |
277 | for(; i < l; ++i){ | |
278 | out[i] = callback.call(thisObject, arr[i], i, arr); | |
279 | } | |
280 | }else{ | |
281 | for(; i < l; ++i){ | |
282 | out[i] = callback(arr[i], i, arr); | |
283 | } | |
284 | } | |
285 | return out; // Array | |
286 | }, | |
287 | ||
288 | filter: function(arr, callback, thisObject){ | |
289 | // summary: | |
290 | // Returns a new Array with those items from arr that match the | |
291 | // condition implemented by callback. | |
292 | // arr: Array | |
293 | // the array to iterate over. | |
294 | // callback: Function|String | |
295 | // a function that is invoked with three arguments (item, | |
296 | // index, array). The return of this function is expected to | |
297 | // be a boolean which determines whether the passed-in item | |
298 | // will be included in the returned array. | |
299 | // thisObject: Object? | |
300 | // may be used to scope the call to callback | |
301 | // returns: Array | |
302 | // description: | |
303 | // This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when | |
304 | // run over sparse arrays, this implementation passes the "holes" in the sparse array to | |
305 | // the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array. | |
306 | // For more details, see: | |
307 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter | |
308 | // example: | |
309 | // | // returns [2, 3, 4] | |
310 | // | array.filter([1, 2, 3, 4], function(item){ return item>1; }); | |
311 | ||
312 | // TODO: do we need "Ctr" here like in map()? | |
313 | var i = 0, l = arr && arr.length || 0, out = [], value; | |
314 | if(l && typeof arr == "string") arr = arr.split(""); | |
315 | if(typeof callback == "string") callback = cache[callback] || buildFn(callback); | |
316 | if(thisObject){ | |
317 | for(; i < l; ++i){ | |
318 | value = arr[i]; | |
319 | if(callback.call(thisObject, value, i, arr)){ | |
320 | out.push(value); | |
321 | } | |
322 | } | |
323 | }else{ | |
324 | for(; i < l; ++i){ | |
325 | value = arr[i]; | |
326 | if(callback(value, i, arr)){ | |
327 | out.push(value); | |
328 | } | |
329 | } | |
330 | } | |
331 | return out; // Array | |
332 | }, | |
333 | ||
334 | clearCache: function(){ | |
335 | cache = {}; | |
336 | } | |
337 | }; | |
338 | ||
339 | ||
340 | 1 && lang.mixin(dojo, array); | |
341 | ||
342 | return array; | |
343 | }); |