oxjs/source/Ox/js/Polyfill.js

409 lines
13 KiB
JavaScript
Raw Normal View History

2011-11-05 16:46:53 +00:00
'use strict';
2012-05-29 10:20:50 +00:00
Ox.polyfill = {};
2012-06-15 08:39:22 +00:00
(function() {
var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
/*@
Ox.polyfill.atob <f> see https://developer.mozilla.org/en/DOM/window.atob
> Ox.polyfill.atob('Cg==')
'\n'
> Ox.polyfill.atob('Zm9v')
'foo'
@*/
Ox.polyfill.atob = function(string) {
var binary = '', ret = '';
String(string).replace(/=/g, '').split('').forEach(function(char) {
binary += Ox.pad(digits.indexOf(char).toString(2), 'left', 6, '0');
});
while (binary.length >= 8) {
ret += Ox.char(parseInt(binary.slice(0, 8), 2));
binary = binary.slice(8);
}
return ret;
};
/*@
Ox.polyfill.btoa <f> see https://developer.mozilla.org/en/DOM/window.btoa
> Ox.polyfill.btoa('\n')
'Cg=='
> Ox.polyfill.btoa('foo')
'Zm9v'
@*/
Ox.polyfill.btoa = function(string) {
var binary = '', ret = '';
String(string).split('').forEach(function(char) {
binary += Ox.pad(char.charCodeAt(0).toString(2), 'left', 8, '0');
});
binary = Ox.pad(binary, Math.ceil(binary.length / 6) * 6, '0')
while (binary) {
ret += digits[parseInt(binary.slice(0, 6), 2)];
binary = binary.slice(6);
}
return Ox.pad(ret, Math.ceil(ret.length / 4) * 4, '=');
};
}());
(function(window) {
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.bind <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
<script>
Ox.test.object = {
get: function() {
return this.value;
},
value: 'foo'
};
Ox.test.get = Ox.test.object.get;
Ox.test.value = 'bar';
</script>
> Ox.test.object.get()
'foo'
> Ox.test.get()
'bar'
2012-05-29 10:20:50 +00:00
> Ox.polyfill.bind.call(Ox.test.get, Ox.test.object)()
'foo'
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.bind = function(that) {
if (typeof this !== 'function') {
throw new TypeError();
}
var args = Array.prototype.slice.call(arguments, 1),
fn = function() {},
this_ = this,
ret = function() {
return this_.apply(
this instanceof fn ? this : that || window,
args.concat(Array.prototype.slice.call(arguments))
);
};
fn.prototype = this.prototype;
ret.prototype = new fn();
return ret;
};
})(this);
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.every <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
> Ox.polyfill.every.call([0, 1, 2], function(v, i) { return v == i; })
2012-05-25 14:25:41 +00:00
true
2012-05-29 10:20:50 +00:00
> Ox.polyfill.every.call([true, true, false], Ox.identity)
2012-05-25 14:25:41 +00:00
false
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.every = function(iterator, that) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0, ret = true;
for (i = 0; i < length; i++) {
if (i in array && !iterator.call(that, array[i], i, array)) {
ret = false;
break;
}
2012-05-25 14:25:41 +00:00
}
return ret;
};
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.filter <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
> Ox.polyfill.filter.call([2, 1, 0], function(v, i) { return v == i; })
2012-05-25 14:25:41 +00:00
[1]
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.filter = function(iterator, that) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0, ret = [], value;
for (i = 0; i < length; i++) {
// save value in case iterator mutates it
if (i in array && iterator.call(that, value = array[i], i, array)) {
ret.push(value);
}
2012-05-25 14:25:41 +00:00
}
return ret;
};
2012-05-25 12:49:47 +00:00
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.forEach <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
2012-05-25 14:25:41 +00:00
<script>
Ox.test.array = [];
2012-05-29 10:20:50 +00:00
Ox.polyfill.forEach.call([1, 2, 3], function(v, i) { Ox.test.array.push([v, i])})
2012-05-25 14:25:41 +00:00
</script>
> Ox.test.array
[[1, 0], [2, 1], [3, 2]]
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.forEach = function(iterator, that) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0;
for (i = 0; i < length; i++) {
if (i in array) {
iterator.call(that, array[i], i, array);
}
}
};
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.indexOf <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
> Ox.polyfill.indexOf.call([1, 2, 3, 2, 1], 2)
2012-05-25 14:25:41 +00:00
1
2012-05-29 10:20:50 +00:00
> Ox.polyfill.indexOf.call([1, 2, 3, 2, 1], 4)
2012-05-25 14:25:41 +00:00
-1
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.indexOf = function(value) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null) {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0, ret = -1;
for (i = 0; i < length; i++) {
if (i in array && array[i] === value) {
ret = i;
break;
}
}
return ret;
};
2012-05-25 15:45:01 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.isArray <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
> Ox.polyfill.isArray([])
2012-05-25 15:45:01 +00:00
true
2012-05-29 10:20:50 +00:00
> Ox.polyfill.isArray((function() { return arguments; }()))
2012-05-25 15:45:01 +00:00
false
2012-05-29 10:20:50 +00:00
> Ox.polyfill.isArray({0: 0, length: 1})
2012-05-25 15:45:01 +00:00
false
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.isArray = function(value) {
2012-05-25 15:45:01 +00:00
return Object.prototype.toString.call(value) == '[object Array]';
};
2012-05-26 12:33:50 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.JSON <o> see https://github.com/douglascrockford/JSON-js
> Ox.polyfill.JSON.parse('{"a": [1, 2], "b": [3, 4]}')
2012-05-26 12:33:50 +00:00
{a: [1, 2], b: [3, 4]}
2012-06-15 07:43:27 +00:00
> Ox.polyfill.JSON.stringify([(function(){ return arguments; }()), false, null, 0, -0, Infinity, NaN, / /, void 0])
'[{},false,null,0,0,null,null,{},null]'
2012-05-29 10:20:50 +00:00
> Ox.polyfill.JSON.stringify(new Date()).length
2012-05-26 13:05:35 +00:00
24
2012-05-26 12:33:50 +00:00
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.JSON = (function() {
2012-05-26 12:33:50 +00:00
var replace = {
'"': '\\"',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\\': '\\\\'
};
function quote(value) {
return '"' + value.split('').map(function(char) {
return replace[char] || char;
}).join('') + '"';
};
return {
parse: function parse(string) {
2012-05-26 13:09:57 +00:00
return eval('(' + string + ')');
2012-05-26 12:33:50 +00:00
},
stringify: function stringify(value) {
var ret = 'null', type = Ox.typeOf(value);
if (type == 'arguments' || type == 'regexp') {
ret = '{}';
} else if (type == 'array') {
ret = ['[', ']'].join(
value.map(function(v) {
return stringify(v);
}).join(',')
);
} else if (type == 'boolean') {
ret = String(value);
} else if (type == 'date') {
2012-05-26 13:05:35 +00:00
ret = Ox.splice(
Ox.getISODate(value, true), 19, 0,
'.' + String(+value).slice(-3)
);
2012-05-26 12:33:50 +00:00
} else if (type == 'number') {
ret = isFinite(value) ? String(value) : 'null';
} else if (type == 'object') {
ret = ['{', '}'].join(
2012-05-26 15:47:41 +00:00
Object.keys(value).map(function(k) {
return quote(k) + ': ' + stringify(value[k]);
2012-05-26 12:33:50 +00:00
}).join(',')
);
} else if (type == 'string') {
2012-05-27 19:33:36 +00:00
ret = quote(value);
2012-05-26 12:33:50 +00:00
}
return ret;
}
};
}());
2012-05-25 15:46:54 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.keys <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
> Ox.polyfill.keys({a: 1, b: 2, c: 3})
2012-05-25 15:46:54 +00:00
['a', 'b', 'c']
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.keys = function(object) {
2012-05-25 15:46:54 +00:00
if (object !== Object(object)) {
throw new TypeError();
}
var key, ret = [];
for (key in object) {
2012-06-15 07:43:27 +00:00
Object.prototype.hasOwnProperty.call(object, key) && ret.push(key);
2012-05-25 15:46:54 +00:00
}
return ret;
};
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.lastIndexOf <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
> Ox.polyfill.lastIndexOf.call([1, 2, 3, 2, 1], 2)
2012-05-25 14:25:41 +00:00
3
2012-05-29 10:20:50 +00:00
> Ox.polyfill.lastIndexOf.call([1, 2, 3, 2, 1], 4)
2012-05-25 14:25:41 +00:00
-1
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.lastIndexOf = function(value) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null) {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0, ret = -1;
for (i = length - 1; i >= 0; i--) {
if (i in array && array[i] === value) {
ret = i;
break;
}
}
return ret;
};
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.map <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
> Ox.polyfill.map.call([2, 1, 0], function(v, i) { return v == i; })
2012-05-25 14:25:41 +00:00
[false, true, false]
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.map = function(iterator, that) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0,
ret = new Array(length);
for (i = 0; i < length; i++) {
if (i in array) {
ret[i] = iterator.call(that, array[i], i, array);
}
}
return ret;
};
2012-05-25 13:16:21 +00:00
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.reduce <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
> Ox.polyfill.reduce.call([1, 2, 3], function(p, c, i) { return p + c + i; }, 1)
2012-05-25 14:25:41 +00:00
10
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.reduce = function(iterator, ret) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length;
if (!length && ret === void 0) {
throw new TypeError();
}
if (ret === void 0) {
ret = array[0];
i = 1;
}
for (i = i || 0; i < length; i++) {
if (i in array) {
ret = iterator.call(void 0, ret, array[i], i, array);
}
}
return ret;
};
2012-05-25 14:25:41 +00:00
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.reduceRight <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduceRight
> Ox.polyfill.reduceRight.call([1, 2, 3], function(p, c, i) { return p + c + i; }, 1)
2012-05-25 14:25:41 +00:00
10
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.reduceRight = function(iterator, ret) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length;
if (!length && ret === void 0) {
throw new TypeError();
}
if (ret === void 0) {
ret = array[length - 1];
i = length - 2;
}
for (i = i || length - 1; i >= 0; i--) {
if (i in array) {
ret = iterator.call(void 0, ret, array[i], i, array);
}
}
return ret;
};
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.some <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
> Ox.polyfill.some.call([2, 1, 0], function(v, i) { return v == i; })
2012-05-25 14:25:41 +00:00
true
2012-05-29 10:20:50 +00:00
> Ox.polyfill.some.call([false, false, false], Ox.identity)
2012-05-25 14:25:41 +00:00
false
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.some = function(iterator, that) {
2012-05-25 14:25:41 +00:00
if (this === void 0 || this === null || typeof iterator !== 'function') {
throw new TypeError();
}
var array = Object(this), i, length = array.length >>> 0, ret = false;
for (i = 0; i < length; i++) {
if (i in array && iterator.call(that, array[i], i, array)) {
ret = true;
break;
}
2012-05-25 14:25:41 +00:00
}
return ret;
};
/*@
2012-05-29 10:20:50 +00:00
Ox.polyfill.trim <f> see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim
> Ox.polyfill.trim.call(' foo ')
2012-05-25 14:25:41 +00:00
'foo'
@*/
2012-05-29 10:20:50 +00:00
Ox.polyfill.trim = function() {
if (this === void 0 || this === null) {
throw new TypeError();
}
2012-05-25 14:25:41 +00:00
return this.replace(/^\s+|\s+$/g, '');
};
(function(window) {
2012-05-26 12:33:50 +00:00
var key, log, object;
2012-05-29 10:20:50 +00:00
for (key in Ox.polyfill) {
2012-05-26 12:33:50 +00:00
object = key == 'bind' ? Function.prototype
: key == 'isArray' ? Array
2012-07-05 17:47:33 +00:00
: key == 'atob' || key == 'btoa' || key == 'JSON' ? window
2012-05-26 12:33:50 +00:00
: key == 'keys' ? Object
: key == 'trim' ? String.prototype
2012-05-25 14:25:41 +00:00
: Array.prototype;
2012-05-26 12:33:50 +00:00
if (!object[key]) {
2012-05-29 10:20:50 +00:00
object[key] = Ox.polyfill[key];
}
2012-05-25 14:25:41 +00:00
}
2012-05-25 16:33:12 +00:00
// In IE8, window.console.log is an object,
// in IE9, window.console.log.apply is undefined
// see http://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function
if (window.console) {
if (typeof window.console.log !== 'function') {
log = window.console.log;
window.console.log = function() {
2012-05-25 16:03:02 +00:00
log(Array.prototype.slice.call(arguments).join(' '));
2012-05-27 19:33:36 +00:00
};
} else if (!window.console.log.apply) {
window.console.log = Function.prototype.bind.call(
window.console.log, window.console
2012-05-25 16:03:02 +00:00
);
}
}
2012-05-25 16:33:12 +00:00
})(this);