/*!
* util
* https://github.com/Voliware/Util
* Licensed under the MIT license.
*/
/**
* General utility functions
*/
class Util {
/**
* Wraps a for in loop.
* For each object it will pass the
* property name and value to a callback.
* @param {object} data - data to loop through
* @param {function} cb - callback
*/
static each(data, cb){
for(var i in data){
var e = data[i];
cb(i, e);
}
}
}
// helpers
if(typeof isDefined === 'undefined'){
window.isDefined = function(x){
return typeof x !== 'undefined';
}
}
if(typeof isNull === 'undefined'){
window.isNull = function(x){
return x === null;
}
}
if(typeof isNullOrUndefined === 'undefined'){
window.isNullOrUndefined = function(x){
return x === null || x === 'undefined';
}
}
if(typeof isFunction === 'undefined'){
window.isFunction = function(x){
return typeof x === 'function';
}
}
if(typeof isString === 'undefined'){
window.isString = function(x){
return typeof x === 'string';
}
}
if(typeof isNumber === 'undefined'){
window.isNumber = function(x){
return typeof x === 'number';
}
}
if(typeof isObject === 'undefined'){
window.isObject = function(x){
return x !== null && typeof x === 'object';
}
}
if(typeof isArray === 'undefined'){
window.isArray = function(x){
return x !== null && Array.isArray(x);
}
}
if(typeof getType === 'undefined') {
//http://stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript
window.getType = function (x) {
if (x === null)
return "[object Null]";
return Object.prototype.toString.call(x);
}
}
if(typeof createGuid === 'undefined'){
window.createGuid = function createGuid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
}
// array
if(typeof Array.diff === 'undefined'){
Array.diff = function(a, b) {
return a.filter(function(i) {
return b.indexOf(i) < 0;
});
};
}
if(typeof Array.min === 'undefined'){
Array.min = function(array){
return Math.min.apply(Math, array)
}
}
if(typeof Array.max === 'undefined'){
Array.max = function(array){
return Math.max.apply(Math, array)
}
}
if (typeof Object.set === 'undefined') {
Object.set = function (obj, data) {
for (var key in data) {
if (obj.hasOwnProperty(key)) {
obj[key] = data[key];
}
}
};
}
//https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
if (typeof Object.assign != 'function') {
Object.assign = function(target) {
'use strict';
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
target = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source != null) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
}
/**
* Deep copy an object (make copies of all its object properties, sub-properties, etc.)
* An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
* that doesn't break if the constructor has required parameters
*
* It also borrows some code from http://stackoverflow.com/a/11621004/560114
*/
function deepCopy(src, /* INTERNAL */ _visited, _copiesVisited) {
if(src === null || typeof(src) !== 'object'){
return src;
}
//Honor native/custom clone methods
if(typeof src.clone == 'function'){
return src.clone(true);
}
//Special cases:
//Date
if(src instanceof Date){
return new Date(src.getTime());
}
//RegExp
if(src instanceof RegExp){
return new RegExp(src);
}
//DOM Element
if(src.nodeType && typeof src.cloneNode == 'function'){
return src.cloneNode(true);
}
// Initialize the visited objects arrays if needed.
// This is used to detect cyclic references.
if (_visited === undefined){
_visited = [];
_copiesVisited = [];
}
// Check if this object has already been visited
var i, len = _visited.length;
for (i = 0; i < len; i++) {
// If so, get the copy we already made
if (src === _visited[i]) {
return _copiesVisited[i];
}
}
//Array
if (Object.prototype.toString.call(src) == '[object Array]') {
//[].slice() by itself would soft clone
var ret = src.slice();
//add it to the visited array
_visited.push(src);
_copiesVisited.push(ret);
i = ret.length;
while (i--) {
ret[i] = deepCopy(ret[i], _visited, _copiesVisited);
}
return ret;
}
//If we've reached here, we have a regular object
//make sure the returned object has the same prototype as the original
var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
if (!proto) {
proto = src.constructor.prototype; //this line would probably only be reached by very old browsers
}
var dest = object_create(proto);
//add this object to the visited array
_visited.push(src);
_copiesVisited.push(dest);
for (var key in src) {
//Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
//For an example of how this could be modified to do so, see the singleMixin() function
dest[key] = deepCopy(src[key], _visited, _copiesVisited);
}
return dest;
}
//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
object_create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}