Skip to content

Instantly share code, notes, and snippets.

@bryanforbes
Created August 12, 2011 17:29
Show Gist options
  • Select an option

  • Save bryanforbes/1142512 to your computer and use it in GitHub Desktop.

Select an option

Save bryanforbes/1142512 to your computer and use it in GitHub Desktop.
Dojo es5-shim for 2.0
define(["./has"], function(has){
// An ES5 shim for older browsers for Dojo 2.0.
// Please note that this is much larger than dojo/array in 1.7 for a few reasons:
// * Feature tests
// * Addition of Array#reduce, Array#reduceRight, Function#bind
var ap = Array.prototype,
fp = Function.prototype;
has.add("array-indexof", !!ap.indexOf);
has.add("array-foreach", !!ap.forEach);
has.add("array-every", !!ap.every);
has.add("array-reduce", !!ap.reduce);
has.add("array-isarray", !!Array.isArray);
has.add("function-bind", !!fp.bind);
function ToInteger(value){
// From John David Dalton.
value = +value;
return (value === 0 || !isFinite(value)) ?
(value || 0) :
((value > 0 || -1) * Math.floor(Math.abs(value)));
}
function prep(o){
// If it's a string, determine if we have to call split on it
if(typeof o == "string" && o && !(0 in o)){
return o.split("");
}
return o;
}
// NOTE: `o.length >>> 0` applies the same length constraints to array-like objects
// as are applied to arrays (Math.pow(2, 32) - 1).
var u;
function index(up){
var delta = 1, over = 0;
if(!up){
delta = over = -1;
}
return function(value){
var o = prep(this),
fromIndex = arguments[1],
len = o.length >>> 0,
end = up ? len + 0 : -1,
k;
if(len === 0){ return -1; }
if(fromIndex === u){
k = up ? 0 : len - 1;
}else{
fromIndex = ToInteger(fromIndex);
if(fromIndex < 0){
k = len + fromIndex;
if(k < 0){
k = 0;
}
}else{
k = fromIndex >= len ? len + over : fromIndex;
}
}
for(; k!=end; k += delta){
if((k in o) && o[k] === value){
return k;
}
}
return -1;
};
}
if(!has("array-indexof")){
ap.indexOf = index(true);
ap.lastIndexOf = index(false);
}
function everyOrSome(some){
var every = !some;
return function(callback){
var o = prep(this),
thisArg = arguments[1],
len = o.length >>> 0,
k = -1, result;
if(thisArg){
while(++k<len){
if((k in o) && (some ^ (result = !callback.call(thisArg, o[k], k, o)))){
return !result;
}
}
}else{
while(++k<len){
if((k in o) && (some ^ (result = !callback(o[k], k, o)))){
return !result;
}
}
}
return every;
};
}
if(!has("array-every")){
ap.every = everyOrSome(false);
ap.some = everyOrSome(true);
}
if(!has("array-foreach")){
ap.forEach = function forEach(callback){
var o = prep(this),
thisArg = arguments[1],
len = o.length >>> 0,
k = -1;
if(thisArg){
while(++k<len){
(k in o) && callback.call(thisArg, o[k], k, o);
}
}else{
while(++k<len){
(k in o) && callback(o[k], k, o);
}
}
};
ap.map = function map(callback){
var o = prep(this),
thisArg = arguments[1],
len = o.length >>> 0,
arr = Array(len),
k = -1;
if(thisArg){
while(++k<len){
(k in o) && (arr[k] = callback.call(thisArg, o[k], k, o));
}
}else{
while(++k<len){
(k in o) && (arr[k] = callback(o[k], k, o));
}
}
return arr;
};
ap.filter = function filter(callback){
var o = prep(this),
thisArg = arguments[1],
len = o.length >>> 0,
arr = [],
k = -1,
kValue;
if(thisArg){
while(++k<len){
kValue = o[k];
(k in o) && !!callback.call(thisArg, kValue, k, o) && arr.push(kValue);
}
}else{
while(++k<len){
kValue = o[k];
(k in o) && !!callback(kValue, k, o) && arr.push(kValue);
}
}
return arr;
};
}
function reduce(left){
var delta = 1;
if(!left){
delta = -1;
}
return function(callback){
var o = prep(this),
initialValue = arguments[1],
len = o.length >>> 0,
k, end, acc;
if(len === 0 && arguments.length < 2){
throw new Error();
}
k = left ? 0 : len - 1;
end = left ? len : -1;
if(initialValue !== u){
acc = initialValue;
}else{
var kPresent = false;
for(;!kPresent && k!=end; k+=delta){
(kPresent = (k in o)) && (acc = o[k]);
}
if(!kPresent){
throw new Error();
}
}
for(;k!=end; k+=delta){
(k in o) && (acc = callback(acc, o[k], k, o));
}
return acc;
};
}
if(!has("array-reduce")){
ap.reduce = reduce(true);
ap.reduceRight = reduce(false);
}
if(!has("array-isarray")){
var toString = Object.prototype.toString;
Array.isArray = function isArray(arr){
return toString.call(arr) == "[object Array]";
};
}
if(!has("function-bind")){
var delegate = (function(){
// boodman/crockford delegation w/ cornford optimization
function TMP(){}
return function(obj, props){
TMP.prototype = obj;
var tmp = new TMP();
TMP.prototype = null;
return tmp; // Object
};
})();
var slice = ap.slice;
fp.bind = function bind(scope){
var pre = slice.call(arguments, 1), f = this;
function b(){
var args = pre.concat(slice.call(arguments));
obj = scope;
return (this instanceof b) ?
(f.apply((obj = delegate(f.prototype)), args) || obj) :
f.apply(obj, args);
}
// override .call and .apply so passing in an instance of
// "b" as newScope won't trigger an incorrect response
b.call = function(newScope){
f.apply(scope, pre.concat(slice.call(arguments, 1)));
};
b.apply = function(newScope, args){
f.apply(scope, pre.concat(args));
};
return b;
};
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment