mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Using revision b27f7a936e115788d88c8b7b125efc879e8c993a at the https://github.com/inexorabletash/polyfill repository.
1226 lines
37 KiB
JavaScript
1226 lines
37 KiB
JavaScript
//----------------------------------------------------------------------
|
|
//
|
|
// ECMAScript 5 Polyfills
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------
|
|
// ES5 15.2 Object Objects
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
// ES5 15.2.3 Properties of the Object Constructor
|
|
//
|
|
|
|
// ES5 15.2.3.2 Object.getPrototypeOf ( O )
|
|
// From http://ejohn.org/blog/objectgetprototypeof/
|
|
// NOTE: won't work for typical function T() {}; T.prototype = {}; new T; case
|
|
// since the constructor property is destroyed.
|
|
if (!Object.getPrototypeOf) {
|
|
Object.getPrototypeOf = function (o) {
|
|
if (o !== Object(o)) { throw TypeError("Object.getPrototypeOf called on non-object"); }
|
|
return o.__proto__ || o.constructor.prototype || Object.prototype;
|
|
};
|
|
}
|
|
|
|
// // ES5 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
|
|
// if (typeof Object.getOwnPropertyDescriptor !== "function") {
|
|
// Object.getOwnPropertyDescriptor = function (o, name) {
|
|
// if (o !== Object(o)) { throw TypeError(); }
|
|
// if (o.hasOwnProperty(name)) {
|
|
// return {
|
|
// value: o[name],
|
|
// enumerable: true,
|
|
// writable: true,
|
|
// configurable: true
|
|
// };
|
|
// }
|
|
// };
|
|
// }
|
|
|
|
// ES5 15.2.3.4 Object.getOwnPropertyNames ( O )
|
|
if (typeof Object.getOwnPropertyNames !== "function") {
|
|
Object.getOwnPropertyNames = function (o) {
|
|
if (o !== Object(o)) { throw TypeError("Object.getOwnPropertyNames called on non-object"); }
|
|
var props = [], p;
|
|
for (p in o) {
|
|
if (Object.prototype.hasOwnProperty.call(o, p)) {
|
|
props.push(p);
|
|
}
|
|
}
|
|
return props;
|
|
};
|
|
}
|
|
|
|
// ES5 15.2.3.5 Object.create ( O [, Properties] )
|
|
if (typeof Object.create !== "function") {
|
|
Object.create = function (prototype, properties) {
|
|
if (typeof prototype !== "object") { throw TypeError(); }
|
|
/** @constructor */
|
|
function Ctor() {}
|
|
Ctor.prototype = prototype;
|
|
var o = new Ctor();
|
|
if (prototype) { o.constructor = Ctor; }
|
|
if (properties !== undefined) {
|
|
if (properties !== Object(properties)) { throw TypeError(); }
|
|
Object.defineProperties(o, properties);
|
|
}
|
|
return o;
|
|
};
|
|
}
|
|
|
|
// ES 15.2.3.6 Object.defineProperty ( O, P, Attributes )
|
|
// Partial support for most common case - getters, setters, and values
|
|
(function() {
|
|
if (!Object.defineProperty ||
|
|
!(function () { try { Object.defineProperty({}, 'x', {}); return true; } catch (e) { return false; } } ())) {
|
|
var orig = Object.defineProperty;
|
|
Object.defineProperty = function (o, prop, desc) {
|
|
// In IE8 try built-in implementation for defining properties on DOM prototypes.
|
|
if (orig) { try { return orig(o, prop, desc); } catch (e) {} }
|
|
|
|
if (o !== Object(o)) { throw TypeError("Object.defineProperty called on non-object"); }
|
|
if (Object.prototype.__defineGetter__ && ('get' in desc)) {
|
|
Object.prototype.__defineGetter__.call(o, prop, desc.get);
|
|
}
|
|
if (Object.prototype.__defineSetter__ && ('set' in desc)) {
|
|
Object.prototype.__defineSetter__.call(o, prop, desc.set);
|
|
}
|
|
if ('value' in desc) {
|
|
o[prop] = desc.value;
|
|
}
|
|
return o;
|
|
};
|
|
}
|
|
}());
|
|
|
|
// ES 15.2.3.7 Object.defineProperties ( O, Properties )
|
|
if (typeof Object.defineProperties !== "function") {
|
|
Object.defineProperties = function (o, properties) {
|
|
if (o !== Object(o)) { throw TypeError("Object.defineProperties called on non-object"); }
|
|
var name;
|
|
for (name in properties) {
|
|
if (Object.prototype.hasOwnProperty.call(properties, name)) {
|
|
Object.defineProperty(o, name, properties[name]);
|
|
}
|
|
}
|
|
return o;
|
|
};
|
|
}
|
|
|
|
|
|
// ES5 15.2.3.14 Object.keys ( O )
|
|
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
|
|
if (!Object.keys) {
|
|
Object.keys = function (o) {
|
|
if (o !== Object(o)) { throw TypeError('Object.keys called on non-object'); }
|
|
var ret = [], p;
|
|
for (p in o) {
|
|
if (Object.prototype.hasOwnProperty.call(o, p)) {
|
|
ret.push(p);
|
|
}
|
|
}
|
|
return ret;
|
|
};
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// ES5 15.3 Function Objects
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
// ES5 15.3.4 Properties of the Function Prototype Object
|
|
//
|
|
|
|
// ES5 15.3.4.5 Function.prototype.bind ( thisArg [, arg1 [, arg2, ... ]] )
|
|
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
|
|
if (!Function.prototype.bind) {
|
|
Function.prototype.bind = function (o) {
|
|
if (typeof this !== 'function') { throw TypeError("Bind must be called on a function"); }
|
|
var slice = [].slice,
|
|
args = slice.call(arguments, 1),
|
|
self = this,
|
|
bound = function () {
|
|
return self.apply(this instanceof nop ? this : (o || {}),
|
|
args.concat(slice.call(arguments)));
|
|
};
|
|
|
|
/** @constructor */
|
|
function nop() {}
|
|
nop.prototype = self.prototype;
|
|
|
|
bound.prototype = new nop();
|
|
|
|
return bound;
|
|
};
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// ES5 15.4 Array Objects
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
// ES5 15.4.3 Properties of the Array Constructor
|
|
//
|
|
|
|
|
|
// ES5 15.4.3.2 Array.isArray ( arg )
|
|
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
|
|
Array.isArray = Array.isArray || function (o) { return Boolean(o && Object.prototype.toString.call(Object(o)) === '[object Array]'); };
|
|
|
|
|
|
//
|
|
// ES5 15.4.4 Properties of the Array Prototype Object
|
|
//
|
|
|
|
// ES5 15.4.4.14 Array.prototype.indexOf ( searchElement [ , fromIndex ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
|
|
if (!Array.prototype.indexOf) {
|
|
Array.prototype.indexOf = function (searchElement /*, fromIndex */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (len === 0) { return -1; }
|
|
|
|
var n = 0;
|
|
if (arguments.length > 0) {
|
|
n = Number(arguments[1]);
|
|
if (isNaN(n)) {
|
|
n = 0;
|
|
} else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
|
|
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
|
}
|
|
}
|
|
|
|
if (n >= len) { return -1; }
|
|
|
|
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
|
|
|
|
for (; k < len; k++) {
|
|
if (k in t && t[k] === searchElement) {
|
|
return k;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
}
|
|
|
|
// ES5 15.4.4.15 Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
|
|
if (!Array.prototype.lastIndexOf) {
|
|
Array.prototype.lastIndexOf = function (searchElement /*, fromIndex*/) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (len === 0) { return -1; }
|
|
|
|
var n = len;
|
|
if (arguments.length > 1) {
|
|
n = Number(arguments[1]);
|
|
if (n !== n) {
|
|
n = 0;
|
|
} else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
|
|
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
|
}
|
|
}
|
|
|
|
var k = n >= 0 ? Math.min(n, len - 1) : len - Math.abs(n);
|
|
|
|
for (; k >= 0; k--) {
|
|
if (k in t && t[k] === searchElement) {
|
|
return k;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
}
|
|
|
|
// ES5 15.4.4.16 Array.prototype.every ( callbackfn [ , thisArg ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
|
|
if (!Array.prototype.every) {
|
|
Array.prototype.every = function (fun /*, thisp */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun !== "function") { throw TypeError(); }
|
|
|
|
var thisp = arguments[1], i;
|
|
for (i = 0; i < len; i++) {
|
|
if (i in t && !fun.call(thisp, t[i], i, t)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
}
|
|
|
|
// ES5 15.4.4.17 Array.prototype.some ( callbackfn [ , thisArg ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
|
|
if (!Array.prototype.some) {
|
|
Array.prototype.some = function (fun /*, thisp */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun !== "function") { throw TypeError(); }
|
|
|
|
var thisp = arguments[1], i;
|
|
for (i = 0; i < len; i++) {
|
|
if (i in t && fun.call(thisp, t[i], i, t)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
}
|
|
|
|
// ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
|
|
if (!Array.prototype.forEach) {
|
|
Array.prototype.forEach = function (fun /*, thisp */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun !== "function") { throw TypeError(); }
|
|
|
|
var thisp = arguments[1], i;
|
|
for (i = 0; i < len; i++) {
|
|
if (i in t) {
|
|
fun.call(thisp, t[i], i, t);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
// ES5 15.4.4.19 Array.prototype.map ( callbackfn [ , thisArg ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Map
|
|
if (!Array.prototype.map) {
|
|
Array.prototype.map = function (fun /*, thisp */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun !== "function") { throw TypeError(); }
|
|
|
|
var res = []; res.length = len;
|
|
var thisp = arguments[1], i;
|
|
for (i = 0; i < len; i++) {
|
|
if (i in t) {
|
|
res[i] = fun.call(thisp, t[i], i, t);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
}
|
|
|
|
// ES5 15.4.4.20 Array.prototype.filter ( callbackfn [ , thisArg ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Filter
|
|
if (!Array.prototype.filter) {
|
|
Array.prototype.filter = function (fun /*, thisp */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun !== "function") { throw TypeError(); }
|
|
|
|
var res = [];
|
|
var thisp = arguments[1], i;
|
|
for (i = 0; i < len; i++) {
|
|
if (i in t) {
|
|
var val = t[i]; // in case fun mutates this
|
|
if (fun.call(thisp, val, i, t)) {
|
|
res.push(val);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
}
|
|
|
|
|
|
// ES5 15.4.4.21 Array.prototype.reduce ( callbackfn [ , initialValue ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Reduce
|
|
if (!Array.prototype.reduce) {
|
|
Array.prototype.reduce = function (fun /*, initialValue */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun !== "function") { throw TypeError(); }
|
|
|
|
// no value to return if no initial value and an empty array
|
|
if (len === 0 && arguments.length === 1) { throw TypeError(); }
|
|
|
|
var k = 0;
|
|
var accumulator;
|
|
if (arguments.length >= 2) {
|
|
accumulator = arguments[1];
|
|
} else {
|
|
do {
|
|
if (k in t) {
|
|
accumulator = t[k++];
|
|
break;
|
|
}
|
|
|
|
// if array contains no values, no initial value to return
|
|
if (++k >= len) { throw TypeError(); }
|
|
}
|
|
while (true);
|
|
}
|
|
|
|
while (k < len) {
|
|
if (k in t) {
|
|
accumulator = fun.call(undefined, accumulator, t[k], k, t);
|
|
}
|
|
k++;
|
|
}
|
|
|
|
return accumulator;
|
|
};
|
|
}
|
|
|
|
|
|
// ES5 15.4.4.22 Array.prototype.reduceRight ( callbackfn [, initialValue ] )
|
|
// From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/ReduceRight
|
|
if (!Array.prototype.reduceRight) {
|
|
Array.prototype.reduceRight = function (callbackfn /*, initialValue */) {
|
|
if (this === void 0 || this === null) { throw TypeError(); }
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof callbackfn !== "function") { throw TypeError(); }
|
|
|
|
// no value to return if no initial value, empty array
|
|
if (len === 0 && arguments.length === 1) { throw TypeError(); }
|
|
|
|
var k = len - 1;
|
|
var accumulator;
|
|
if (arguments.length >= 2) {
|
|
accumulator = arguments[1];
|
|
} else {
|
|
do {
|
|
if (k in this) {
|
|
accumulator = this[k--];
|
|
break;
|
|
}
|
|
|
|
// if array contains no values, no initial value to return
|
|
if (--k < 0) { throw TypeError(); }
|
|
}
|
|
while (true);
|
|
}
|
|
|
|
while (k >= 0) {
|
|
if (k in t) {
|
|
accumulator = callbackfn.call(undefined, accumulator, t[k], k, t);
|
|
}
|
|
k--;
|
|
}
|
|
|
|
return accumulator;
|
|
};
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// ES5 15.5 String Objects
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
// ES5 15.5.4 Properties of the String Prototype Object
|
|
//
|
|
|
|
|
|
// ES5 15.5.4.20 String.prototype.trim()
|
|
if (!String.prototype.trim) {
|
|
String.prototype.trim = function () {
|
|
return String(this).replace(/^\s+/, '').replace(/\s+$/, '');
|
|
};
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// ES5 15.9 Date Objects
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
//
|
|
// ES 15.9.4 Properties of the Date Constructor
|
|
//
|
|
|
|
// ES5 15.9.4.4 Date.now ( )
|
|
// From https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/now
|
|
if (!Date.now) {
|
|
Date.now = function now() {
|
|
return Number(new Date());
|
|
};
|
|
}
|
|
|
|
|
|
//
|
|
// ES5 15.9.5 Properties of the Date Prototype Object
|
|
//
|
|
|
|
// ES5 15.9.4.43 Date.prototype.toISOString ( )
|
|
// Inspired by http://www.json.org/json2.js
|
|
if (!Date.prototype.toISOString) {
|
|
Date.prototype.toISOString = function () {
|
|
function pad2(n) { return ('00' + n).slice(-2); }
|
|
function pad3(n) { return ('000' + n).slice(-3); }
|
|
|
|
return this.getUTCFullYear() + '-' +
|
|
pad2(this.getUTCMonth() + 1) + '-' +
|
|
pad2(this.getUTCDate()) + 'T' +
|
|
pad2(this.getUTCHours()) + ':' +
|
|
pad2(this.getUTCMinutes()) + ':' +
|
|
pad2(this.getUTCSeconds()) + '.' +
|
|
pad3(this.getUTCMilliseconds()) + 'Z';
|
|
};
|
|
}
|
|
//----------------------------------------------------------------------
|
|
//
|
|
// Browser Polyfills
|
|
//
|
|
// This assumes ES5 or ES3 + es5.js
|
|
// (polyfill.js is es5.js + web.js for convenience)
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
if ('window' in this && 'document' in this) {
|
|
|
|
//----------------------------------------------------------------------
|
|
//
|
|
// Web Standards Polyfills
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
// document.head (HTML5)
|
|
//
|
|
document.head = document.head || document.getElementsByTagName('head')[0];
|
|
|
|
//
|
|
// XMLHttpRequest (http://www.w3.org/TR/XMLHttpRequest/)
|
|
//
|
|
window.XMLHttpRequest = window.XMLHttpRequest || function () {
|
|
/*global ActiveXObject*/
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) { }
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) { }
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) { }
|
|
throw Error("This browser does not support XMLHttpRequest.");
|
|
};
|
|
XMLHttpRequest.UNSENT = 0;
|
|
XMLHttpRequest.OPENED = 1;
|
|
XMLHttpRequest.HEADERS_RECEIVED = 2;
|
|
XMLHttpRequest.LOADING = 3;
|
|
XMLHttpRequest.DONE = 4;
|
|
|
|
//
|
|
// FormData (http://www.w3.org/TR/XMLHttpRequest2/#interface-formdata)
|
|
//
|
|
if (!('FormData' in window)) {
|
|
(function(global) {
|
|
function FormData(form) {
|
|
this._data = [];
|
|
if (!form) return;
|
|
for (var i = 0; i < form.elements.length; ++i)
|
|
this.append(form.elements[i].name, form.elements[i].value);
|
|
}
|
|
|
|
FormData.prototype.append = function(name, value /*, filename */) {
|
|
if ('Blob' in global && value instanceof global.Blob) throw TypeError("Blob not supported");
|
|
name = String(name);
|
|
this._data.push([name, value]);
|
|
};
|
|
|
|
FormData.prototype.toString = function() {
|
|
return this._data.map(function(pair) {
|
|
return encodeURIComponent(pair[0]) + '=' + encodeURIComponent(pair[1]);
|
|
}).join('&');
|
|
};
|
|
|
|
global.FormData = FormData;
|
|
var send = global.XMLHttpRequest.prototype.send;
|
|
global.XMLHttpRequest.prototype.send = function(body) {
|
|
if (body instanceof FormData) {
|
|
this.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
arguments[0] = body.toString();
|
|
}
|
|
return send.apply(this, arguments);
|
|
};
|
|
}(this));
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//
|
|
// Performance
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
// requestAnimationFrame
|
|
// http://www.w3.org/TR/animation-timing/
|
|
(function(global) {
|
|
var TARGET_FPS = 60,
|
|
requests = Object.create(null),
|
|
raf_handle = 1,
|
|
timeout_handle = -1;
|
|
|
|
function isVisible(element) {
|
|
return element.offsetWidth > 0 && element.offsetHeight > 0;
|
|
}
|
|
|
|
function onFrameTimer() {
|
|
var cur_requests = requests;
|
|
|
|
requests = Object.create(null);
|
|
timeout_handle = -1;
|
|
|
|
Object.keys(cur_requests).forEach(function(id) {
|
|
var request = cur_requests[id];
|
|
if (!request.element || isVisible(request.element)) {
|
|
request.callback(Date.now());
|
|
}
|
|
});
|
|
}
|
|
|
|
function requestAnimationFrame(callback, element) {
|
|
var cb_handle = raf_handle++;
|
|
requests[cb_handle] = {callback: callback, element: element};
|
|
|
|
if (timeout_handle === -1) {
|
|
timeout_handle = global.setTimeout(onFrameTimer, 1000 / TARGET_FPS);
|
|
}
|
|
|
|
return cb_handle;
|
|
}
|
|
|
|
function cancelAnimationFrame(handle) {
|
|
delete requests[handle];
|
|
|
|
if (Object.keys(requests).length === 0) {
|
|
global.clearTimeout(timeout_handle);
|
|
timeout_handle = -1;
|
|
}
|
|
}
|
|
|
|
global.requestAnimationFrame =
|
|
global.requestAnimationFrame ||
|
|
global.webkitRequestAnimationFrame ||
|
|
global.mozRequestAnimationFrame ||
|
|
global.oRequestAnimationFrame ||
|
|
global.msRequestAnimationFrame ||
|
|
requestAnimationFrame;
|
|
|
|
// NOTE: Older versions of the spec called this "cancelRequestAnimationFrame"
|
|
global.cancelAnimationFrame = global.cancelRequestAnimationFrame =
|
|
global.cancelAnimationFrame || global.cancelRequestAnimationFrame ||
|
|
global.webkitCancelAnimationFrame || global.webkitCancelRequestAnimationFrame ||
|
|
global.mozCancelAnimationFrame || global.mozCancelRequestAnimationFrame ||
|
|
global.oCancelAnimationFrame || global.oCancelRequestAnimationFrame ||
|
|
global.msCancelAnimationFrame || global.msCancelRequestAnimationFrame ||
|
|
cancelAnimationFrame;
|
|
}(this));
|
|
|
|
// setImmediate
|
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html
|
|
(function (global) {
|
|
function setImmediate(callback/*, args*/) {
|
|
var params = [].slice.call(arguments, 1);
|
|
return global.setTimeout(function() {
|
|
callback.apply(null, params);
|
|
}, 0);
|
|
}
|
|
|
|
function clearImmediate(handle) {
|
|
global.clearTimeout(handle);
|
|
}
|
|
|
|
global.setImmediate =
|
|
global.setImmediate ||
|
|
global.msSetImmediate ||
|
|
setImmediate;
|
|
|
|
global.clearImmediate =
|
|
global.clearImmediate ||
|
|
global.msClearImmediate ||
|
|
clearImmediate;
|
|
}(this));
|
|
|
|
//----------------------------------------------------------------------
|
|
//
|
|
// DOM
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
//
|
|
// Selectors API Level 1 (http://www.w3.org/TR/selectors-api/)
|
|
// http://ajaxian.com/archives/creating-a-queryselector-for-ie-that-runs-at-native-speed
|
|
//
|
|
if (!document.querySelectorAll) {
|
|
document.querySelectorAll = function (selectors) {
|
|
var style = document.createElement('style'), elements = [], element;
|
|
document.documentElement.firstChild.appendChild(style);
|
|
document._qsa = [];
|
|
|
|
style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
|
|
window.scrollBy(0, 0);
|
|
style.parentNode.removeChild(style);
|
|
|
|
while (document._qsa.length) {
|
|
element = document._qsa.shift();
|
|
element.style.removeAttribute('x-qsa');
|
|
elements.push(element);
|
|
}
|
|
document._qsa = null;
|
|
return elements;
|
|
};
|
|
}
|
|
|
|
if (!document.querySelector) {
|
|
document.querySelector = function (selectors) {
|
|
var elements = document.querySelectorAll(selectors);
|
|
return (elements.length) ? elements[0] : null;
|
|
};
|
|
}
|
|
|
|
if (!document.getElementsByClassName) {
|
|
document.getElementsByClassName = function (classNames) {
|
|
classNames = String(classNames).replace(/^|\s+/g, '.');
|
|
return document.querySelectorAll(classNames);
|
|
};
|
|
}
|
|
|
|
// Fix for IE8-'s Element.getBoundingClientRect()
|
|
if ('TextRectangle' in this && !('width' in TextRectangle.prototype)) {
|
|
Object.defineProperties(TextRectangle.prototype, {
|
|
'width': { get: function() { return this.right - this.left; } },
|
|
'height': { get: function() { return this.bottom - this.top; } }
|
|
});
|
|
}
|
|
|
|
//
|
|
// DOM Enumerations (http://www.w3.org/TR/DOM-Level-2-Core/)
|
|
//
|
|
window.Node = window.Node || function Node() { throw TypeError("Illegal constructor"); };
|
|
Node.ELEMENT_NODE = 1;
|
|
Node.ATTRIBUTE_NODE = 2;
|
|
Node.TEXT_NODE = 3;
|
|
Node.CDATA_SECTION_NODE = 4;
|
|
Node.ENTITY_REFERENCE_NODE = 5;
|
|
Node.ENTITY_NODE = 6;
|
|
Node.PROCESSING_INSTRUCTION_NODE = 7;
|
|
Node.COMMENT_NODE = 8;
|
|
Node.DOCUMENT_NODE = 9;
|
|
Node.DOCUMENT_TYPE_NODE = 10;
|
|
Node.DOCUMENT_FRAGMENT_NODE = 11;
|
|
Node.NOTATION_NODE = 12;
|
|
|
|
window.DOMException = window.DOMException || function DOMException() { throw TypeError("Illegal constructor"); };
|
|
DOMException.INDEX_SIZE_ERR = 1;
|
|
DOMException.DOMSTRING_SIZE_ERR = 2;
|
|
DOMException.HIERARCHY_REQUEST_ERR = 3;
|
|
DOMException.WRONG_DOCUMENT_ERR = 4;
|
|
DOMException.INVALID_CHARACTER_ERR = 5;
|
|
DOMException.NO_DATA_ALLOWED_ERR = 6;
|
|
DOMException.NO_MODIFICATION_ALLOWED_ERR = 7;
|
|
DOMException.NOT_FOUND_ERR = 8;
|
|
DOMException.NOT_SUPPORTED_ERR = 9;
|
|
DOMException.INUSE_ATTRIBUTE_ERR = 10;
|
|
DOMException.INVALID_STATE_ERR = 11;
|
|
DOMException.SYNTAX_ERR = 12;
|
|
DOMException.INVALID_MODIFICATION_ERR = 13;
|
|
DOMException.NAMESPACE_ERR = 14;
|
|
DOMException.INVALID_ACCESS_ERR = 15;
|
|
|
|
//
|
|
// Events and EventTargets
|
|
//
|
|
|
|
(function(){
|
|
if (!('Element' in window) || Element.prototype.addEventListener || !Object.defineProperty)
|
|
return;
|
|
|
|
// interface Event
|
|
|
|
// PhaseType (const unsigned short)
|
|
Event.CAPTURING_PHASE = 1;
|
|
Event.AT_TARGET = 2;
|
|
Event.BUBBLING_PHASE = 3;
|
|
|
|
Object.defineProperties(Event.prototype, {
|
|
CAPTURING_PHASE: { get: function() { return 1; } },
|
|
AT_TARGET: { get: function() { return 2; } },
|
|
BUBBLING_HASE: { get: function() { return 3; } },
|
|
target: {
|
|
get: function() {
|
|
return this.srcElement;
|
|
}},
|
|
currentTarget: {
|
|
get: function() {
|
|
return this._currentTarget;
|
|
}},
|
|
eventPhase: {
|
|
get: function() {
|
|
return (this.srcElement === this.currentTarget) ? Event.AT_TARGET : Event.BUBBLING_PHASE;
|
|
}},
|
|
bubbles: {
|
|
get: function() {
|
|
switch (this.type) {
|
|
// Mouse
|
|
case 'click':
|
|
case 'dblclick':
|
|
case 'mousedown':
|
|
case 'mouseup':
|
|
case 'mouseover':
|
|
case 'mousemove':
|
|
case 'mouseout':
|
|
case 'mousewheel':
|
|
// Keyboard
|
|
case 'keydown':
|
|
case 'keypress':
|
|
case 'keyup':
|
|
// Frame/Object
|
|
case 'resize':
|
|
case 'scroll':
|
|
// Form
|
|
case 'select':
|
|
case 'change':
|
|
case 'submit':
|
|
case 'reset':
|
|
return true;
|
|
}
|
|
return false;
|
|
}},
|
|
cancelable: {
|
|
get: function() {
|
|
switch (this.type) {
|
|
// Mouse
|
|
case 'click':
|
|
case 'dblclick':
|
|
case 'mousedown':
|
|
case 'mouseup':
|
|
case 'mouseover':
|
|
case 'mouseout':
|
|
case 'mousewheel':
|
|
// Keyboard
|
|
case 'keydown':
|
|
case 'keypress':
|
|
case 'keyup':
|
|
// Form
|
|
case 'submit':
|
|
return true;
|
|
}
|
|
return false;
|
|
}},
|
|
timeStamp: {
|
|
get: function() {
|
|
return this._timeStamp;
|
|
}},
|
|
stopPropagation: {
|
|
value: function() {
|
|
this.cancelBubble = true;
|
|
}},
|
|
preventDefault: {
|
|
value: function() {
|
|
this.returnValue = false;
|
|
}},
|
|
defaultPrevented: {
|
|
get: function() {
|
|
return this.returnValue === false;
|
|
}}
|
|
});
|
|
|
|
// interface EventTarget
|
|
|
|
function addEventListener(type, listener, useCapture) {
|
|
if (type === 'DOMContentLoaded') type = 'load';
|
|
var target = this;
|
|
var f = function(e) {
|
|
e._timeStamp = Date.now();
|
|
e._currentTarget = target;
|
|
listener.call(this, e);
|
|
e._currentTarget = null;
|
|
};
|
|
this['_' + type + listener] = f;
|
|
this.attachEvent('on' + type, f);
|
|
}
|
|
|
|
function removeEventListener(type, listener, useCapture) {
|
|
if (type === 'DOMContentLoaded') type = 'load';
|
|
var f = this['_' + type + listener];
|
|
if (f) {
|
|
this.detachEvent('on' + type, f);
|
|
this['_' + type + listener] = null;
|
|
}
|
|
}
|
|
|
|
[Window, HTMLDocument, Element].forEach(function(o) {
|
|
o.prototype.addEventListener = addEventListener;
|
|
o.prototype.removeEventListener = removeEventListener;
|
|
});
|
|
|
|
}());
|
|
|
|
// Shim for DOM Events for IE7-
|
|
// http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
|
|
// Use addEvent(object, event, handler) instead of object.addEventListener(event, handler)
|
|
|
|
window.addEvent = function (obj, type, fn) {
|
|
if (obj.addEventListener) {
|
|
obj.addEventListener(type, fn, false);
|
|
} else if (obj.attachEvent) {
|
|
obj["e" + type + fn] = fn;
|
|
obj[type + fn] = function () {
|
|
var e = window.event;
|
|
e.currentTarget = obj;
|
|
e.preventDefault = function () { e.returnValue = false; };
|
|
e.stopPropagation = function () { e.cancelBubble = true; };
|
|
e.target = e.srcElement;
|
|
e.timeStamp = Date.now();
|
|
obj["e" + type + fn].call(this, e);
|
|
};
|
|
obj.attachEvent("on" + type, obj[type + fn]);
|
|
}
|
|
};
|
|
|
|
window.removeEvent = function (obj, type, fn) {
|
|
if (obj.removeEventListener) {
|
|
obj.removeEventListener(type, fn, false);
|
|
} else if (obj.detachEvent) {
|
|
obj.detachEvent("on" + type, obj[type + fn]);
|
|
obj[type + fn] = null;
|
|
obj["e" + type + fn] = null;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
//
|
|
// DOMTokenList - classList and relList shims
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
// Shim for http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#dom-classlist
|
|
// Use getClassList(elem) instead of elem.classList() if IE7- support is needed
|
|
// Use getRelList(elem) instead of elem.relList() if IE7- support is needed
|
|
|
|
(function () {
|
|
|
|
/** @constructor */
|
|
function DOMTokenListShim(o, p) {
|
|
function split(s) { return s.length ? s.split(/\s+/g) : []; }
|
|
|
|
// NOTE: This does not exactly match the spec.
|
|
function removeTokenFromString(token, string) {
|
|
var tokens = split(string),
|
|
index = tokens.indexOf(token);
|
|
if (index !== -1) {
|
|
tokens.splice(index, 1);
|
|
}
|
|
return tokens.join(' ');
|
|
}
|
|
|
|
Object.defineProperties(
|
|
this,
|
|
{
|
|
length: {
|
|
get: function () { return split(o[p]).length; }
|
|
},
|
|
|
|
item: {
|
|
value: function (idx) {
|
|
var tokens = split(o[p]);
|
|
return 0 <= idx && idx < tokens.length ? tokens[idx] : null;
|
|
}
|
|
},
|
|
|
|
contains: {
|
|
value: function (token) {
|
|
token = String(token);
|
|
if (token.length === 0) { throw SyntaxError(); }
|
|
if (/\s/.test(token)) { throw Error("InvalidCharacterError"); }
|
|
var tokens = split(o[p]);
|
|
|
|
return tokens.indexOf(token) !== -1;
|
|
}
|
|
},
|
|
|
|
add: {
|
|
value: function (/*tokens...*/) {
|
|
var tokens = Array.prototype.slice.call(arguments).map(String);
|
|
if (tokens.some(function(token) { return token.length === 0; })) {
|
|
throw SyntaxError();
|
|
}
|
|
if (tokens.some(function(token) { return (/\s/).test(token); })) {
|
|
throw Error("InvalidCharacterError");
|
|
}
|
|
|
|
try {
|
|
var underlying_string = o[p];
|
|
var token_list = split(underlying_string);
|
|
tokens = tokens.filter(function(token) { return token_list.indexOf(token) === -1; });
|
|
if (tokens.length === 0) {
|
|
return;
|
|
}
|
|
if (underlying_string.length !== 0 && !(/\s$/).test(underlying_string)) {
|
|
underlying_string += ' ';
|
|
}
|
|
underlying_string += tokens.join(' ');
|
|
o[p] = underlying_string;
|
|
} finally {
|
|
var length = split(o[p]).length;
|
|
if (this.length !== length) { this.length = length; }
|
|
}
|
|
}
|
|
},
|
|
|
|
remove: {
|
|
value: function (/*tokens...*/) {
|
|
var tokens = Array.prototype.slice.call(arguments).map(String);
|
|
if (tokens.some(function(token) { return token.length === 0; })) {
|
|
throw SyntaxError();
|
|
}
|
|
if (tokens.some(function(token) { return (/\s/).test(token); })) {
|
|
throw Error("InvalidCharacterError");
|
|
}
|
|
|
|
try {
|
|
var underlying_string = o[p];
|
|
tokens.forEach(function(token) {
|
|
underlying_string = removeTokenFromString(token, underlying_string);
|
|
});
|
|
o[p] = underlying_string;
|
|
} finally {
|
|
var length = split(o[p]).length;
|
|
if (this.length !== length) { this.length = length; }
|
|
}
|
|
}
|
|
},
|
|
|
|
toggle: {
|
|
value: function (token, force) {
|
|
try {
|
|
token = String(token);
|
|
if (token.length === 0) { throw SyntaxError(); }
|
|
if (/\s/.test(token)) { throw Error("InvalidCharacterError"); }
|
|
var tokens = split(o[p]),
|
|
index = tokens.indexOf(token);
|
|
|
|
if (index !== -1 && (!force || force === (void 0))) {
|
|
o[p] = removeTokenFromString(token, o[p]);
|
|
return false;
|
|
}
|
|
if (index !== -1 && force) {
|
|
return true;
|
|
}
|
|
var underlying_string = o[p];
|
|
if (underlying_string.length !== 0 && !/\s$/.test(underlying_string)) {
|
|
underlying_string += ' ';
|
|
}
|
|
underlying_string += token;
|
|
o[p] = underlying_string;
|
|
return true;
|
|
} finally {
|
|
var length = split(o[p]).length;
|
|
if (this.length !== length) { this.length = length; }
|
|
}
|
|
}
|
|
},
|
|
|
|
toString: {
|
|
value: function () {
|
|
return o[p];
|
|
}
|
|
}
|
|
});
|
|
if (!('length' in this)) {
|
|
// In case getters are not supported
|
|
this.length = split(o[p]).length;
|
|
} else {
|
|
// If they are, shim in index getters (up to 100)
|
|
for (var i = 0; i < 100; ++i) {
|
|
Object.defineProperty(this, String(i), {
|
|
get: (function(n) { return function () { return this.item(n); }; }(i))
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function addToElementPrototype(p, f) {
|
|
if ('Element' in window && Element.prototype && Object.defineProperty) {
|
|
Object.defineProperty(Element.prototype, p, { get: f });
|
|
}
|
|
}
|
|
|
|
if ('classList' in document.createElement('span')) {
|
|
window.getClassList = function (elem) { return elem.classList; };
|
|
} else {
|
|
window.getClassList = function (elem) { return new DOMTokenListShim(elem, 'className'); };
|
|
addToElementPrototype('classList', function() { return new DOMTokenListShim(this, 'className'); } );
|
|
}
|
|
|
|
if ('relList' in document.createElement('link')) {
|
|
window.getRelList = function (elem) { return elem.relList; };
|
|
} else {
|
|
window.getRelList = function (elem) { return new DOMTokenListShim(elem, 'rel'); };
|
|
addToElementPrototype('relList', function() { return new DOMTokenListShim(this, 'rel'); } );
|
|
}
|
|
}());
|
|
|
|
if (!('dataset' in document.createElement('span')) &&
|
|
'Element' in window && Element.prototype && Object.defineProperty) {
|
|
Object.defineProperty(Element.prototype, 'dataset', { get: function() {
|
|
var result = Object.create(null);
|
|
for (var i = 0; i < this.attributes.length; ++i) {
|
|
var attr = this.attributes[i];
|
|
if (attr.specified && attr.name.substring(0, 5) === 'data-') {
|
|
(function(element, name) {
|
|
result[name] = element.getAttribute('data-' + name); // Read-only, for IE8-
|
|
Object.defineProperty(result, name, {
|
|
get: function() {
|
|
return element.getAttribute('data-' + name);
|
|
},
|
|
set: function(value) {
|
|
element.setAttribute('data-' + name, value);
|
|
}});
|
|
}(this, attr.name.substring(5)));
|
|
}
|
|
}
|
|
return result;
|
|
}});
|
|
}
|
|
}
|
|
|
|
//
|
|
// Base64 utility methods (HTML5)
|
|
//
|
|
(function (global) {
|
|
var B64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
global.atob = global.atob || function (input) {
|
|
input = String(input);
|
|
var position = 0,
|
|
output = [],
|
|
buffer = 0, bits = 0, n;
|
|
|
|
input = input.replace(/\s/g, '');
|
|
if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); }
|
|
if ((input.length % 4) === 1) { throw Error("InvalidCharacterError"); }
|
|
if (/[^+/0-9A-Za-z]/.test(input)) { throw Error("InvalidCharacterError"); }
|
|
|
|
while (position < input.length) {
|
|
n = B64_ALPHABET.indexOf(input.charAt(position));
|
|
buffer = (buffer << 6) | n;
|
|
bits += 6;
|
|
|
|
if (bits === 24) {
|
|
output.push(String.fromCharCode((buffer >> 16) & 0xFF));
|
|
output.push(String.fromCharCode((buffer >> 8) & 0xFF));
|
|
output.push(String.fromCharCode(buffer & 0xFF));
|
|
bits = 0;
|
|
buffer = 0;
|
|
}
|
|
position += 1;
|
|
}
|
|
|
|
if (bits === 12) {
|
|
buffer = buffer >> 4;
|
|
output.push(String.fromCharCode(buffer & 0xFF));
|
|
} else if (bits === 18) {
|
|
buffer = buffer >> 2;
|
|
output.push(String.fromCharCode((buffer >> 8) & 0xFF));
|
|
output.push(String.fromCharCode(buffer & 0xFF));
|
|
}
|
|
|
|
return output.join('');
|
|
};
|
|
|
|
global.btoa = global.btoa || function (input) {
|
|
input = String(input);
|
|
var position = 0,
|
|
out = [],
|
|
o1, o2, o3,
|
|
e1, e2, e3, e4;
|
|
|
|
if (/[^\x00-\xFF]/.test(input)) { throw Error("InvalidCharacterError"); }
|
|
|
|
while (position < input.length) {
|
|
o1 = input.charCodeAt(position++);
|
|
o2 = input.charCodeAt(position++);
|
|
o3 = input.charCodeAt(position++);
|
|
|
|
// 111111 112222 222233 333333
|
|
e1 = o1 >> 2;
|
|
e2 = ((o1 & 0x3) << 4) | (o2 >> 4);
|
|
e3 = ((o2 & 0xf) << 2) | (o3 >> 6);
|
|
e4 = o3 & 0x3f;
|
|
|
|
if (position === input.length + 2) {
|
|
e3 = 64; e4 = 64;
|
|
}
|
|
else if (position === input.length + 1) {
|
|
e4 = 64;
|
|
}
|
|
|
|
out.push(B64_ALPHABET.charAt(e1),
|
|
B64_ALPHABET.charAt(e2),
|
|
B64_ALPHABET.charAt(e3),
|
|
B64_ALPHABET.charAt(e4));
|
|
}
|
|
|
|
return out.join('');
|
|
};
|
|
}(this));
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//
|
|
// Non-standard JavaScript (Mozilla) functions
|
|
//
|
|
//----------------------------------------------------------------------
|
|
|
|
(function () {
|
|
// JavaScript 1.8.1
|
|
String.prototype.trimLeft = String.prototype.trimLeft || function () {
|
|
return String(this).replace(/^\s+/, '');
|
|
};
|
|
|
|
// JavaScript 1.8.1
|
|
String.prototype.trimRight = String.prototype.trimRight || function () {
|
|
return String(this).replace(/\s+$/, '');
|
|
};
|
|
|
|
// JavaScript 1.?
|
|
var ESCAPES = {
|
|
//'\x00': '\\0', Special case in FF3.6, removed by FF10
|
|
'\b': '\\b',
|
|
'\t': '\\t',
|
|
'\n': '\\n',
|
|
'\f': '\\f',
|
|
'\r': '\\r',
|
|
'"' : '\\"',
|
|
'\\': '\\\\'
|
|
};
|
|
String.prototype.quote = String.prototype.quote || function() {
|
|
return '"' + String(this).replace(/[\x00-\x1F"\\\x7F-\uFFFF]/g, function(c) {
|
|
if (Object.prototype.hasOwnProperty.call(ESCAPES, c)) {
|
|
return ESCAPES[c];
|
|
} else if (c.charCodeAt(0) <= 0xFF) {
|
|
return '\\x' + ('00' + c.charCodeAt(0).toString(16).toUpperCase()).slice(-2);
|
|
} else {
|
|
return '\\u' + ('0000' + c.charCodeAt(0).toString(16).toUpperCase()).slice(-4);
|
|
}
|
|
}) + '"';
|
|
};
|
|
}());
|