quixote
Version:
CSS unit and integration testing
294 lines (215 loc) • 8.04 kB
JavaScript
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
/*eslint eqeqeq: "off", no-eq-null: "off", no-bitwise: "off" */
;
exports.Array = {
// WORKAROUND IE 8: no Array.isArray
isArray: function isArray(thing) {
if (Array.isArray) return Array.isArray(thing);
return Object.prototype.toString.call(thing) === '[object Array]';
},
// WORKAROUND IE 8: no Array.every
every: function every(obj, callbackfn, thisArg) {
/*jshint bitwise:false, eqeqeq:false, -W041:false */
if (Array.prototype.every) return obj.every(callbackfn, thisArg);
// This workaround based on polyfill code from MDN:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
var T, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the this
// value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method
// of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (typeof callbackfn !== 'function') {
throw new TypeError();
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0.
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method
// of O with argument Pk.
kValue = O[k];
// ii. Let testResult be the result of calling the Call internal method
// of callbackfn with T as the this value and argument list
// containing kValue, k, and O.
var testResult = callbackfn.call(T, kValue, k, O);
// iii. If ToBoolean(testResult) is false, return false.
if (!testResult) {
return false;
}
}
k++;
}
return true;
},
// WORKAROUND IE 8: no Array.forEach
forEach: function forEach(obj, callback, thisArg) {
/*jshint bitwise:false, eqeqeq:false, -W041:false */
if (Array.prototype.forEach) return obj.forEach(callback, thisArg);
// This workaround based on polyfill code from MDN:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
var T, k;
if (obj == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(obj);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
}
};
exports.Document = {
// WORKAROUND IE 8: no document.head
head: function head(doc) {
if (doc.head) return doc.head;
return doc.querySelector("head");
}
};
exports.Element = {
// WORKAROUND IE 8, IE 9, IE 10, IE 11: no Element.remove()
remove: function remove(element) {
element.parentNode.removeChild(element);
}
};
exports.EventTarget = {
// WORKAROUND IE 8: no EventTarget.addEventListener()
addEventListener: function addEventListener(element, event, callback) {
if (element.addEventListener) return element.addEventListener(event, callback);
element.attachEvent("on" + event, callback);
}
};
exports.Function = {
// WORKAROUND IE 8, IE 9, IE 10, IE 11: no function.name
name: function name(fn) {
if (fn.name) return fn.name;
// Based on code by Jason Bunting et al, http://stackoverflow.com/a/332429
var funcNameRegex = /function\s+(.{1,})\s*\(/;
var results = (funcNameRegex).exec((fn).toString());
return (results && results.length > 1) ? results[1] : "<anon>";
},
};
exports.Object = {
// WORKAROUND IE 8: no Object.create()
create: function create(prototype) {
if (Object.create) return Object.create(prototype);
var Temp = function Temp() {};
Temp.prototype = prototype;
return new Temp();
},
// WORKAROUND IE 8: no Object.getPrototypeOf
// Caution: Doesn't work on IE 8 if constructor has been changed, as is the case with a subclass.
getPrototypeOf: function getPrototypeOf(obj) {
if (Object.getPrototypeOf) return Object.getPrototypeOf(obj);
var result = obj.constructor ? obj.constructor.prototype : null;
return result || null;
},
// WORKAROUND IE 8: No Object.keys
keys: function keys(obj) {
if (Object.keys) return Object.keys(obj);
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
}
};
exports.String = {
// WORKAROUND IE 8: No String.trim()
trim: function(str) {
if (str.trim !== undefined) return str.trim();
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}
};
exports.Window = {
// WORKAROUND IE 8: No Window.pageXOffset
pageXOffset: function(window, document) {
if (window.pageXOffset !== undefined) return window.pageXOffset;
// Based on https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
return isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
},
// WORKAROUND IE 8: No Window.pageYOffset
pageYOffset: function(window, document) {
if (window.pageYOffset !== undefined) return window.pageYOffset;
// Based on https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
return isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
}
};