343 lines
11 KiB
JavaScript
343 lines
11 KiB
JavaScript
define("dojo/_base/array", ["./kernel", "../has", "./lang"], function(dojo, has, lang){
|
|
// module:
|
|
// dojo/_base/array
|
|
|
|
// our old simple function builder stuff
|
|
var cache = {}, u;
|
|
|
|
function buildFn(fn){
|
|
return cache[fn] = new Function("item", "index", "array", fn); // Function
|
|
}
|
|
// magic snippet: if(typeof fn == "string") fn = cache[fn] || buildFn(fn);
|
|
|
|
// every & some
|
|
|
|
function everyOrSome(some){
|
|
var every = !some;
|
|
return function(a, fn, o){
|
|
var i = 0, l = a && a.length || 0, result;
|
|
if(l && typeof a == "string") a = a.split("");
|
|
if(typeof fn == "string") fn = cache[fn] || buildFn(fn);
|
|
if(o){
|
|
for(; i < l; ++i){
|
|
result = !fn.call(o, a[i], i, a);
|
|
if(some ^ result){
|
|
return !result;
|
|
}
|
|
}
|
|
}else{
|
|
for(; i < l; ++i){
|
|
result = !fn(a[i], i, a);
|
|
if(some ^ result){
|
|
return !result;
|
|
}
|
|
}
|
|
}
|
|
return every; // Boolean
|
|
};
|
|
}
|
|
|
|
// indexOf, lastIndexOf
|
|
|
|
function index(up){
|
|
var delta = 1, lOver = 0, uOver = 0;
|
|
if(!up){
|
|
delta = lOver = uOver = -1;
|
|
}
|
|
return function(a, x, from, last){
|
|
if(last && delta > 0){
|
|
// TODO: why do we use a non-standard signature? why do we need "last"?
|
|
return array.lastIndexOf(a, x, from);
|
|
}
|
|
var l = a && a.length || 0, end = up ? l + uOver : lOver, i;
|
|
if(from === u){
|
|
i = up ? lOver : l + uOver;
|
|
}else{
|
|
if(from < 0){
|
|
i = l + from;
|
|
if(i < 0){
|
|
i = lOver;
|
|
}
|
|
}else{
|
|
i = from >= l ? l + uOver : from;
|
|
}
|
|
}
|
|
if(l && typeof a == "string") a = a.split("");
|
|
for(; i != end; i += delta){
|
|
if(a[i] == x){
|
|
return i; // Number
|
|
}
|
|
}
|
|
return -1; // Number
|
|
};
|
|
}
|
|
|
|
var array = {
|
|
// summary:
|
|
// The Javascript v1.6 array extensions.
|
|
|
|
every: everyOrSome(false),
|
|
/*=====
|
|
every: function(arr, callback, thisObject){
|
|
// summary:
|
|
// Determines whether or not every item in arr satisfies the
|
|
// condition implemented by callback.
|
|
// arr: Array|String
|
|
// the array to iterate on. If a string, operates on individual characters.
|
|
// callback: Function|String
|
|
// a function is invoked with three arguments: item, index,
|
|
// and array and returns true if the condition is met.
|
|
// thisObject: Object?
|
|
// may be used to scope the call to callback
|
|
// returns: Boolean
|
|
// description:
|
|
// This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when
|
|
// run over sparse arrays, this implementation passes the "holes" in the sparse array to
|
|
// the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array.
|
|
// For more details, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every
|
|
// example:
|
|
// | // returns false
|
|
// | array.every([1, 2, 3, 4], function(item){ return item>1; });
|
|
// example:
|
|
// | // returns true
|
|
// | array.every([1, 2, 3, 4], function(item){ return item>0; });
|
|
},
|
|
=====*/
|
|
|
|
some: everyOrSome(true),
|
|
/*=====
|
|
some: function(arr, callback, thisObject){
|
|
// summary:
|
|
// Determines whether or not any item in arr satisfies the
|
|
// condition implemented by callback.
|
|
// arr: Array|String
|
|
// the array to iterate over. If a string, operates on individual characters.
|
|
// callback: Function|String
|
|
// a function is invoked with three arguments: item, index,
|
|
// and array and returns true if the condition is met.
|
|
// thisObject: Object?
|
|
// may be used to scope the call to callback
|
|
// returns: Boolean
|
|
// description:
|
|
// This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when
|
|
// run over sparse arrays, this implementation passes the "holes" in the sparse array to
|
|
// the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array.
|
|
// For more details, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some
|
|
// example:
|
|
// | // is true
|
|
// | array.some([1, 2, 3, 4], function(item){ return item>1; });
|
|
// example:
|
|
// | // is false
|
|
// | array.some([1, 2, 3, 4], function(item){ return item<1; });
|
|
},
|
|
=====*/
|
|
|
|
indexOf: index(true),
|
|
/*=====
|
|
indexOf: function(arr, value, fromIndex, findLast){
|
|
// summary:
|
|
// locates the first index of the provided value in the
|
|
// passed array. If the value is not found, -1 is returned.
|
|
// description:
|
|
// This method corresponds to the JavaScript 1.6 Array.indexOf method, with one difference: when
|
|
// run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript
|
|
// 1.6's indexOf skips the holes in the sparse array.
|
|
// For details on this method, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
|
|
// arr: Array
|
|
// value: Object
|
|
// fromIndex: Integer?
|
|
// findLast: Boolean?
|
|
// returns: Number
|
|
},
|
|
=====*/
|
|
|
|
lastIndexOf: index(false),
|
|
/*=====
|
|
lastIndexOf: function(arr, value, fromIndex){
|
|
// summary:
|
|
// locates the last index of the provided value in the passed
|
|
// array. If the value is not found, -1 is returned.
|
|
// description:
|
|
// This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with one difference: when
|
|
// run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript
|
|
// 1.6's lastIndexOf skips the holes in the sparse array.
|
|
// For details on this method, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf
|
|
// arr: Array,
|
|
// value: Object,
|
|
// fromIndex: Integer?
|
|
// returns: Number
|
|
},
|
|
=====*/
|
|
|
|
forEach: function(arr, callback, thisObject){
|
|
// summary:
|
|
// for every item in arr, callback is invoked. Return values are ignored.
|
|
// If you want to break out of the loop, consider using array.every() or array.some().
|
|
// forEach does not allow breaking out of the loop over the items in arr.
|
|
// arr:
|
|
// the array to iterate over. If a string, operates on individual characters.
|
|
// callback:
|
|
// a function is invoked with three arguments: item, index, and array
|
|
// thisObject:
|
|
// may be used to scope the call to callback
|
|
// description:
|
|
// This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when
|
|
// run over sparse arrays, this implementation passes the "holes" in the sparse array to
|
|
// the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array.
|
|
// For more details, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
|
|
// example:
|
|
// | // log out all members of the array:
|
|
// | array.forEach(
|
|
// | [ "thinger", "blah", "howdy", 10 ],
|
|
// | function(item){
|
|
// | console.log(item);
|
|
// | }
|
|
// | );
|
|
// example:
|
|
// | // log out the members and their indexes
|
|
// | array.forEach(
|
|
// | [ "thinger", "blah", "howdy", 10 ],
|
|
// | function(item, idx, arr){
|
|
// | console.log(item, "at index:", idx);
|
|
// | }
|
|
// | );
|
|
// example:
|
|
// | // use a scoped object member as the callback
|
|
// |
|
|
// | var obj = {
|
|
// | prefix: "logged via obj.callback:",
|
|
// | callback: function(item){
|
|
// | console.log(this.prefix, item);
|
|
// | }
|
|
// | };
|
|
// |
|
|
// | // specifying the scope function executes the callback in that scope
|
|
// | array.forEach(
|
|
// | [ "thinger", "blah", "howdy", 10 ],
|
|
// | obj.callback,
|
|
// | obj
|
|
// | );
|
|
// |
|
|
// | // alternately, we can accomplish the same thing with lang.hitch()
|
|
// | array.forEach(
|
|
// | [ "thinger", "blah", "howdy", 10 ],
|
|
// | lang.hitch(obj, "callback")
|
|
// | );
|
|
// arr: Array|String
|
|
// callback: Function|String
|
|
// thisObject: Object?
|
|
|
|
var i = 0, l = arr && arr.length || 0;
|
|
if(l && typeof arr == "string") arr = arr.split("");
|
|
if(typeof callback == "string") callback = cache[callback] || buildFn(callback);
|
|
if(thisObject){
|
|
for(; i < l; ++i){
|
|
callback.call(thisObject, arr[i], i, arr);
|
|
}
|
|
}else{
|
|
for(; i < l; ++i){
|
|
callback(arr[i], i, arr);
|
|
}
|
|
}
|
|
},
|
|
|
|
map: function(arr, callback, thisObject, Ctr){
|
|
// summary:
|
|
// applies callback to each element of arr and returns
|
|
// an Array with the results
|
|
// arr: Array|String
|
|
// the array to iterate on. If a string, operates on
|
|
// individual characters.
|
|
// callback: Function|String
|
|
// a function is invoked with three arguments, (item, index,
|
|
// array), and returns a value
|
|
// thisObject: Object?
|
|
// may be used to scope the call to callback
|
|
// returns: Array
|
|
// description:
|
|
// This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when
|
|
// run over sparse arrays, this implementation passes the "holes" in the sparse array to
|
|
// the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array.
|
|
// For more details, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
|
|
// example:
|
|
// | // returns [2, 3, 4, 5]
|
|
// | array.map([1, 2, 3, 4], function(item){ return item+1 });
|
|
|
|
// TODO: why do we have a non-standard signature here? do we need "Ctr"?
|
|
var i = 0, l = arr && arr.length || 0, out = new (Ctr || Array)(l);
|
|
if(l && typeof arr == "string") arr = arr.split("");
|
|
if(typeof callback == "string") callback = cache[callback] || buildFn(callback);
|
|
if(thisObject){
|
|
for(; i < l; ++i){
|
|
out[i] = callback.call(thisObject, arr[i], i, arr);
|
|
}
|
|
}else{
|
|
for(; i < l; ++i){
|
|
out[i] = callback(arr[i], i, arr);
|
|
}
|
|
}
|
|
return out; // Array
|
|
},
|
|
|
|
filter: function(arr, callback, thisObject){
|
|
// summary:
|
|
// Returns a new Array with those items from arr that match the
|
|
// condition implemented by callback.
|
|
// arr: Array
|
|
// the array to iterate over.
|
|
// callback: Function|String
|
|
// a function that is invoked with three arguments (item,
|
|
// index, array). The return of this function is expected to
|
|
// be a boolean which determines whether the passed-in item
|
|
// will be included in the returned array.
|
|
// thisObject: Object?
|
|
// may be used to scope the call to callback
|
|
// returns: Array
|
|
// description:
|
|
// This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when
|
|
// run over sparse arrays, this implementation passes the "holes" in the sparse array to
|
|
// the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array.
|
|
// For more details, see:
|
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
|
|
// example:
|
|
// | // returns [2, 3, 4]
|
|
// | array.filter([1, 2, 3, 4], function(item){ return item>1; });
|
|
|
|
// TODO: do we need "Ctr" here like in map()?
|
|
var i = 0, l = arr && arr.length || 0, out = [], value;
|
|
if(l && typeof arr == "string") arr = arr.split("");
|
|
if(typeof callback == "string") callback = cache[callback] || buildFn(callback);
|
|
if(thisObject){
|
|
for(; i < l; ++i){
|
|
value = arr[i];
|
|
if(callback.call(thisObject, value, i, arr)){
|
|
out.push(value);
|
|
}
|
|
}
|
|
}else{
|
|
for(; i < l; ++i){
|
|
value = arr[i];
|
|
if(callback(value, i, arr)){
|
|
out.push(value);
|
|
}
|
|
}
|
|
}
|
|
return out; // Array
|
|
},
|
|
|
|
clearCache: function(){
|
|
cache = {};
|
|
}
|
|
};
|
|
|
|
|
|
1 && lang.mixin(dojo, array);
|
|
|
|
return array;
|
|
});
|