wacomink
Version:
711 lines (556 loc) • 21.9 kB
JavaScript
/*
window.debug = true;
window.onerror = function(message, url, line) {
var body = url +
"\n\n" + message +
"\n" + "Line #: " + line;
if (window.debug) {
alert(body);
throw Error(message);
}
};
*/
if (!String.prototype.contains) String.prototype.contains = function(str) {return (this.indexOf(str) != -1)}
if (!String.prototype.startsWith) String.prototype.startsWith = function(str) {return (this.length >= str.length && this.substring(0, str.length) == str)}
if (!String.prototype.endsWith) String.prototype.endsWith = function(str) {return (this.length >= str.length && this.substring(this.length-str.length, this.length) == str)}
String.prototype.charsCode = function() {return this.split("").reduce(function(previous, current) {return previous + current.charCodeAt(0);}, 0);}
String.prototype.containsIgnoreCase = function(str) {return (this.toUpperCase().indexOf(str.toUpperCase()) != -1)}
String.prototype.toCharArray = function(bytes) {var list = bytes?new Uint8Array(this.length):new Array(this.length); list.bytes = true; for (var i = 0; i < this.length; i++) {var code = this.charCodeAt(i); if (code > 255) list.bytes = false; list[i] = code;} return list;}
String.fromCharArray = function(arr) {var binary = ""; try {binary = String.fromCharCode.apply(null, arr);} catch(e) {for (var i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);} return binary;}
String.prototype.pad = function(length, char) {return (this.length < length)?new Array(length - this.length + 1).join(char || "-") + this:this.toString();}
Number.prototype.pad = function(length) {return (String(this).length < length)?new Array(length - String(this).length + 1).join(0) + String(this):this.toString();}
Number.prototype.toFloat32 = function() {var fa32 = new Float32Array(1); fa32[0] = this; return fa32[0];}
Object.defineProperty(Array.prototype, "first", {get: function() {return this[0];}});
Object.defineProperty(Array.prototype, "last", {get: function() {return this[this.length-1];}});
Array.prototype.contains = function(value) {return this.indexOf(value) > -1;}
Array.prototype.clone = function() {var result = new Array(); this.forEach(function(value) {result.push(Object.clone(value));}); return result;}
Array.prototype.pushArray = function() {this.push.apply(this, this.concat.apply([], arguments));}
Array.prototype.add = function(item) {if (!this.contains(item)) return this.push(item);}
Array.prototype.remove = function(element) {return this.removeAt(this.indexOf(element));}
Array.prototype.removeAt = function(idx) {if (idx > -1) this.splice(idx, 1); return this;}
Array.prototype.replace = function(element, replaceWith) {
var index = this.indexOf(element);
if (index > -1) {
if (replaceWith instanceof Array) {
var args = [index, 1];
for (var i = 0; i < replaceWith.length; i++)
args.push(replaceWith[i]);
this.splice.apply(this, args);
}
else
this.splice(index, 1, replaceWith);
}
return this;
}
Array.protoTypedArrays = function() {
["Int8", "Uint8", "Uint8Clamped", "Int16", "Uint16", "Int32", "Uint32", "Float32", "Float64"].forEach(function(type) {
var typedArray = eval(type + "Array");
if (typedArray.from)
Array.prototype["to" + type + "Array"] = function() {return typedArray.from(this);}
else
Array.prototype["to" + type + "Array"] = function() {return new typedArray(this);}
if (Array.from)
typedArray.prototype.toArray = function() {return Array.from(this);}
else
typedArray.prototype.toArray = function() {return Array.prototype.slice.call(this);}
typedArray.prototype.clone = function() {return new typedArray(this, this.byteOffset, this.length);}
// Safari fix, remove when possible
if (!typedArray.prototype.forEach) typedArray.prototype.forEach = Array.prototype.forEach;
});
}
Array.protoTypedArrays();
delete Array.protoTypedArrays;
ArrayBuffer.isTypedArray = function(o) {
return ArrayBuffer.isView(o) && !(o instanceof DataView);
// return !!(
// o instanceof Int8Array || o instanceof Uint8Array || o instanceof Uint8ClampedArray ||
// o instanceof Int16Array || o instanceof Uint16Array ||
// o instanceof Int32Array || o instanceof Uint32Array ||
// o instanceof Float32Array || o instanceof Float64Array
// );
}
if (!Function.name) Function.name = "Function";
if (!Array.prototype.constructor.name) Array.prototype.constructor.name = "Array";
Function.create = function(name, body) {
if (!body) body = function() {};
var args = body.getArguments();
var f = new Function("body", "return function " + name + "(" + args + ") {return body.apply(this, arguments);};")(body);
f.toString = function() {return body.toString();}
f.toSource = function() {return body.toSource();}
return f;
// return new Function("body", "return function " + name + "() {return body.apply(this, arguments);};")(body || function() {});
}
if (!("name" in Function.prototype)) Object.defineProperty(Function.prototype, "name", {configurable: true, get: function() {var m = this.toString().match(/^function\s([\w$]+)/); return m?m[1]:"";}});
Function.prototype.getArguments = function() {var m = this.toString().match(/\((.*?)\)/)[1].replace(/\s*/g, ""); return (m.length == 0)?[]:m.split(",");}
Function.prototype.getBody = function() {return this.toString().match(/\{([\s\S]*)\}/m)[1].replace(/^\s*\/\/.*$/mg, "");}
Function.prototype.construct = function(oThis) {
var fnArguments = arguments.callee.caller.arguments;
this.getArguments().forEach(function(name, i) {
this[name] = fnArguments[i];
}, oThis);
}
Function.prototype.createEnum = function(name, keys) {
if (this[name]) throw new Error("Already exists key: " + name);
this[name] = new Object();
for (var i = 0; i < keys.length; i++) {
var value = name + "_" + keys[i];
var type = this[name];
type[keys[i]] = (function() {
var enm = Object.create(Object.prototype, {
constructor: {value: Function.create(value)},
type: {value: name},
name: {value: keys[i]},
value: {value: i}
});
Object.defineProperty(type, i, {get: function() {return enm;}});
return enm;
})();
}
}
Function.prototype.argsToJSON = function(defaults) {
var json = {};
if (!defaults) defaults = {};
var fnArguments = arguments.callee.caller.arguments;
this.getArguments().forEach(function(name, i) {
json[name] = fnArguments[i];
if (typeof json[name] == "undefined" && name in defaults) json[name] = defaults[name];
});
return json;
}
Function.prototype.getInheritanceChain = function() {
var result = new Array();
var parent = this.constructor;
result.push(this.prototype.constructor);
while (parent.name != "Function") {
result.push(parent);
parent = parent.constructor;
}
if (parent != this.prototype.constructor)
result.push(parent);
return result;
}
Function.prototype.isClassMethod = function(method) {
var result = false;
if (method.name)
result = this.prototype[method.name] == method;
else {
for (var name in this.prototype) {
if (this.prototype[name] == method) {
result = true;
break;
}
}
}
return result;
}
Function.prototype.extends = function(superClass) {
this.prototype = Object.create(superClass.prototype);
this.prototype.constructor = this;
this.constructor = superClass.prototype.constructor;
for (var property in superClass) {
if (superClass.hasOwnProperty(property))
this[property] = superClass[property];
}
if (!this.prototype.$parent) {
Object.defineProperty(this.prototype, "super", {
get: function() {
var result;
var self = this;
var chain = this.constructor.getInheritanceChain();
var caller = arguments.callee.caller;
if (!caller) return null;
if (chain.contains(caller)) {
var parent = this.constructor.constructor;
var depth = chain.indexOf(caller);
while (depth > 0) {
parent = parent.constructor;
depth--;
}
result = function() {
parent.apply(self, arguments)
};
result.bind = function(name) {
var method = parent.prototype[name];
if (!method) throw new Error("super function with name '" + name + "' not found");
return function() {
return method.apply(self, arguments);
};
};
}
else {
var callerClass;
for (var i = 0; i < chain.length; i++) {
var clazz = chain[i];
if (clazz.isClassMethod(caller)) {
callerClass = clazz;
break;
}
}
if (!callerClass) throw new Error("super call is outside of inheritance chain");
var bind = function(name) {
var caller = callerClass.prototype[name];
var parent = callerClass.constructor;
while (parent && parent.prototype[name] == caller) {
parent = parent.constructor;
if (parent.name == "Function") parent = null;
}
if (!parent) throw new Error("super not found");
var method = parent.prototype[name];
if (!method) throw new Error("super function with name '" + name + "' not found");
return function() {
return method.apply(self, arguments);
};
};
result = function(name) {
if (!name || (typeof name != "string")) throw new Error("super function 'name' is required");
var method = bind(name);
return method.apply(self, Array.prototype.splice.call(arguments, 1));
};
result.bind = bind;
}
return result;
}
});
}
}
Object.extend = function(o, data, replace) {
var override = false;
var parent = replace?o.$parent:null;
if (!parent && !replace) {
parent = new Object();
parent["$$"] = new Object();
}
for (property in data) {
if (!replace && typeof o[property] == "function") {
parent["$$"][property] = o[property];
(function(property) {
parent[property] = function() {
var context = this["$$"].context;
if (!context) throw new Error("Context not found in \"" + arguments.callee.caller.name + "\".");
return this["$$"][property].apply(context, arguments);
};
})(property);
o[property] = data[property];
override = true;
}
else if (typeof o[property] == "object")
Object.extend(o[property], data[property], replace);
else
o[property] = data[property];
}
if (override && !replace) {
if (!o.hasOwnProperty("super")) {
Object.defineProperty(o, "super", {
get: function() {
var result;
var caller = arguments.callee.caller;
if (!caller)
throw "\"super\" not applicable for root";
var lvl = caller.lvl;
if (lvl > 0) {
var result = this.$parent;
while (result["$$"].lvl > lvl - 1)
result = result.$parent;
}
else
result = this.$parent;
result["$$"].context = this;
return result;
}
});
}
if (o.$parent) {
parent.$parent = o.$parent;
parent["$$"].lvl = o.$parent["$$"].lvl + 1;
for (property in parent.$parent) {
if (typeof parent.$parent[property] == "function" && typeof parent[property] == "undefined") {
(function(property) {
parent[property] = function() {
if (!this.$parent["$$"].context) this.$parent["$$"].context = this["$$"].context;
return this.$parent[property].apply(this.$parent, arguments);
};
})(property);
}
}
}
else
parent["$$"].lvl = 1;
for (property in parent["$$"]) {
if (typeof parent["$$"][property] == "function")
parent["$$"][property].lvl = parent["$$"].lvl;
}
o.$parent = parent;
}
}
Object.equals = function(x, y) {
// if both x and y are null or undefined and exactly the same
if (x === y) return true;
// if they are not strictly equal, they both need to be Objects
if (!(x instanceof Object && y instanceof Object)) return false;
// they must have the exact same prototype chain, the closest we can do is test there constructor.
if (x.constructor !== y.constructor) return false;
for (var p in x) {
// other properties were tested using x.constructor === y.constructor
if (!x.hasOwnProperty(p)) continue;
// allows to compare x[p] and y[p] when set to undefined
if (!y.hasOwnProperty(p)) return false;
// if they have the same strict value or identity then they are equal
if (x[p] === y[p]) continue;
// Numbers, Strings, Functions, Booleans must be strictly equal
if (typeof(x[p]) !== "object") return false;
// Objects and Arrays must be tested recursively
if (!Object.equals(x[p], y[p])) return false;
}
for (p in y) {
// allows x[p] to be set to undefined
if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false;
}
return true;
}
Object.clone = function(oReferance, bDataOnly) {
var aReferances = new Array();
function deepCopy(oSource) {
if (oSource === null) return null;
if (typeof(oSource) !== "object" || oSource.mutable) return oSource;
if (typeof oSource.clone === "function") return oSource.clone();
for (var i = 0; i < aReferances.length; i++) {
if (aReferances[i][0] === oSource)
return aReferances[i][1];
}
var oCopy = Object.create(Object.getPrototypeOf(oSource));
aReferances.push([oSource, oCopy]);
for (sPropertyName in oSource) {
if (bDataOnly && typeof oSource[sPropertyName] === "function")
continue;
if (oSource.hasOwnProperty(sPropertyName))
oCopy[sPropertyName] = deepCopy(oSource[sPropertyName]);
}
return oCopy;
}
return deepCopy(oReferance);
}
Object.nameAnonymousFunctions = function(o, constructorName) {
for (var name in o) {
if (typeof o[name] == "function" && !o[name].name) {
if (name == "constructor" && constructorName)
Object.defineProperty(o[name], "name", {value: constructorName});
else
Object.defineProperty(o[name], "name", {value: name});
}
}
}
JSON.toBase64 = function(json) {
return btoa(JSON.stringify(json));
}
JSON.fromBase64 = function(base64) {
return JSON.parse(atob(base64));
}
JSON.encode = function(json) {
var base64 = JSON.toBase64(json);
return base64.toCharArray(true);
}
JSON.decode = function(bytes) {
var base64 = String.fromCharArray(bytes);
return JSON.fromBase64(base64);
}
Math.toDegrees = function(angle) {return angle * (180 / this.PI);}
Math.toRadians = function(angle) {return angle * (this.PI / 180);}
Math.randomInt = function(min, max) {return Math.floor(this.random() * (max - min + 1)) + min;}
var ENVIRONMENT = (function() {
var WEB = typeof window === "object";
var WORKER = typeof importScripts === "function";
var NODE = typeof process === "object" && typeof require === "function" && !WEB && !WORKER;
Function.prototype.createEnum.call(this, "EnvironmentType", ["WEB", "WORKER", "NODE", "SHELL"]);
if (WEB)
return EnvironmentType.WEB;
else if (WORKER)
return EnvironmentType.WORKER;
else if (NODE)
return EnvironmentType.NODE;
else
return this.EnvironmentType.SHELL;
})();
if (ENVIRONMENT == EnvironmentType.WEB) {
HTMLElement.prototype.getInlineStyle = function(property) {
return this.style[property] || this.style["-webkit-" + property] || this.style["-khtml-" + property] || this.style["-moz-" + property] || this.style["-ms-" + property] || this.style["-o-" + property] || "";
}
HTMLElement.prototype.setStyle = function(property, value) {
var prefixList = ["-webkit", "-khtml", "-moz", "-ms", "-o"];
prefixList.forEach(function(prefix) {
this.style[prefix + "-" + property] = value;
}, this);
this.style[property] = value;
}
HTMLElement.prototype.getStyle = function(property) {
var value = property;
var vendorPrefixed = property.startsWith("-");
if (vendorPrefixed) value = property.substring(1);
var arr = value.split("-");
for (var i = arr.length-1; i > 0; i--) arr[i] = arr[i].substring(0, 1).toUpperCase() + arr[i].substring(1);
value = arr.join("");
// Firefox else IE
var result = window.getComputedStyle?document.defaultView.getComputedStyle(this, null)[value]:this.currentStyle[value];
if (!vendorPrefixed && typeof result === "undefined") {
var prefixList = ["-webkit", "-khtml", "-moz", "-ms", "-o"];
for (var i = 0; i < prefixList.length; i++) {
result = this.getStyle(prefixList[i] + "-" + property);
if (result != "undefined") break;
}
}
return result;
}
HTMLElement.prototype.getMathStyle = function(property, inline) {
var value = inline?this.getInlineStyle(property):this.getStyle(property);
if (value == "auto") value = 0;
return parseFloat(value);
}
HTMLElement.prototype.getTransformStyle = function() {
var result = {
translate: {x: 0, y: 0},
scale: {x: 1, y: 1},
rotate: {angle: 0},
skew: {angleX: 0, angleY: 0},
matrix: {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0}
};
var transform = this.getStyle("transform");
if (transform != "none") {
var values = transform.substring(transform.indexOf("(")+1, transform.indexOf(")")).split(/,\s*/g);
var a = parseFloat(values[0]);
var b = parseFloat(values[1]);
var c = parseFloat(values[2]);
var d = parseFloat(values[3]);
var tx = parseFloat(values[4]);
var ty = parseFloat(values[5]);
result.scale = {x: Math.sqrt(a*a + c*c), y: Math.sqrt(d*d + b*b)};
result.skew = {angleX: Math.tan(c), angleY: Math.tan(b)};
result.rotate = {angle: Math.atan2(b, a)};
result.translate = {x: tx, y: ty};
result.matrix = {a: a, b: b, c: c, d: d, tx: tx, ty: ty};
}
return result;
}
/**
* type xy location possible values: TL, BR, TR, BL, default is TL
*/
HTMLElement.prototype.toRect = function(type) {
var rect = new Object();
var alpha = this.getTransformStyle().rotate.angle;
var clientRect = this.getBoundingClientRect();
rect.width = this.offsetWidth;
rect.height = this.offsetHeight;
rect.left = this.offsetLeft;
rect.top = this.offsetTop;
rect.right = rect.left + rect.width;
rect.bottom = rect.top + rect.height;
rect.scaleFactor = Math.max(rect.width, rect.height) / Math.min(rect.width, rect.height);
rect.offsetWidth = this.offsetWidth;
rect.offsetHeight = this.offsetHeight;
rect.fullWidth = this.offsetWidth + this.getMathStyle("margin-left") + this.getMathStyle("margin-right");
rect.fullHeight = this.offsetHeight + this.getMathStyle("margin-top") + this.getMathStyle("margin-bottom");
rect.center = {x: rect.width/2, y: rect.height / 2};
// rect.rotationFrameWidth = rect.width*Math.abs(Math.cos(alpha)) + rect.height*Math.abs(Math.sin(alpha));
// rect.rotationFrameHeight = rect.height*Math.abs(Math.sin(alpha)) + rect.height*Math.abs(Math.cos(alpha));
// rect.rotationCenter = {x: rect.rotationFrameWidth/2, y: rect.rotationFrameHeight / 2};
rect.rotationFrameWidth = clientRect.width;
rect.rotationFrameHeight = clientRect.height;
rect.rotationCenter = {x: clientRect.width/2, y: clientRect.height / 2};
Object.defineProperty(rect, "x", {get: function() {return this.left;}});
Object.defineProperty(rect, "y", {get: function() {return this.top;}});
rect.centerOnParent = {x: rect.left + rect.rotationCenter.x, y: rect.top + rect.rotationCenter.y};
rect.centerOnScreen = {x: clientRect.left + rect.rotationCenter.x, y: clientRect.top + rect.rotationCenter.y};
return rect;
}
HTMLImageElement.prototype.toDataURL = function(type) {
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
canvas.getContext("2d").drawImage(this, 0, 0);
return canvas.toDataURL(type || "image/png");
}
HTMLImageElement.prototype.toBlob = function(type) {
return new Blob([this.getBytes(type).buffer], {type: type || "image/png"});
}
HTMLImageElement.prototype.getBytes = function(type) {
var dataURL = this.toDataURL(type);
var base64 = dataURL.split(",")[1];
// var mime = dataURL.split(",")[0].split(":")[1].split(";")[0];
return atob(base64).toCharArray(true);
}
Image.fromBytes = function(bytes, callback, type) {
var image = new Image();
image.onload = function () {
URL.revokeObjectURL(this.src);
if (callback) callback.call(this);
}
image.src = URL.createObjectURL(new Blob([bytes.buffer], {type : "image/" + (type || "png")}));
return image;
}
CanvasRenderingContext2D.prototype.clearCanvas = function(color) {
this.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (color) {
this.fillStyle = color;
this.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
}
Object.defineProperty(Screen.prototype, "deviceWidth", {get: function() {
if (window.orientation == 90 || window.orientation == -90) {
if (this.orientation)
delete this.orientation;
else {
this.orientation = true;
return this.deviceHeight;
}
}
var width = this.width;
if (!window.matchMedia("(-webkit-device-pixel-ratio)").matches) {
width = Math.ceil(width * window.devicePixelRatio);
if (width % 10 != 0) {
if (width % 10 > 5)
width += (10 - width % 10);
else
width -= width % 10;
}
}
return width;
}});
Object.defineProperty(Screen.prototype, "deviceHeight", {get: function() {
if (window.orientation == 90 || window.orientation == -90) {
if (this.orientation)
delete this.orientation;
else {
this.orientation = true;
return this.deviceWidth;
}
}
var height = this.height;
if (!window.matchMedia("(-webkit-device-pixel-ratio)").matches) {
height = Math.ceil(height * window.devicePixelRatio);
if (height % 10 != 0) {
if (height % 10 > 5)
height += (10 - height % 10);
else
height -= height % 10;
}
}
return height;
}});
// Safari FIX
(function() {
try {
var clientRect = document.createElement("div").getBoundingClientRect();
if (!("x" in clientRect)) {
Object.extend(HTMLElement.prototype, {
getBoundingClientRect: function() {
var clientRect = this.super.getBoundingClientRect();
clientRect.x = clientRect.left;
clientRect.y = clientRect.top;
return clientRect;
}
});
}
}
catch(e) {
// IE throws exception
}
})();
}