Skip to content

Instantly share code, notes, and snippets.

@tborychowski
Last active September 13, 2018 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tborychowski/3799025 to your computer and use it in GitHub Desktop.
Save tborychowski/3799025 to your computer and use it in GitHub Desktop.
JS :: Utils - helper library
/**
* https://gist.github.com/tborychowski/3799025
*/
var UTILS = {
/*jshint maxlen: 500, onevar: false */
isTouch : (/iPhone|iPod|iPad/ig).test(navigator.userAgent),
/**
* Modified & lintified version of https://gist.github.com/527683
* @return {mixed} if IE version number or false
*/
isIE : (function (i, p, undef) {
var br = p.getElementsByTagName('br');
do { p.innerHTML = '<!--[if gt IE ' + (++i) + ']><br><![endif]-->'; } while (br[0]);
return i > 4 ? i : undef;
}(3, document.createElement('p'), false)),
/* better typeof */
getType : function (obj) { return obj ? Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() : 'undefined'; },
/**
* Converts flat objects, e.g.: { a: 1, b:2, c:[1,2,3] } to "a=1&b=2&c=1,2,3"
*/
objToUrl : function (obj) {
if (this.getType(obj) !== 'object') return '';
var a = null, str = [];
for (a in obj) { if (obj.hasOwnProperty(a)) str.push(window.escape(a) + '=' + window.escape(obj[a])); }
return str.join('&');
},
/**
* Converts: "?a=1&b=2&c=3" to { a:'1', b:'2', c:'3' }
* @param url {string} url string to convert
* @param convert {boolean} true to convert vars to real types (e.g. '1' to 1, 'true' to true)
*/
urlToObj : function (url, convert) {
if (!url || !url.length) return {};
var params = {}, vars = url.ltrim('\\?').split('&'), pair = null, i = 0, vr = null, n = null, v = null;
for (; vr = vars[i++] ;) {
pair = vr.split('=');
n = window.unescape(pair[0]);
v = window.unescape(pair[1]);
if (v.indexOf(',') > -1) v = v.split(','); // if commas in value - split to array
if (convert) v = this.varToRealType(v);
if (params[n] === undefined) params[n] = v; // if first entry with this name
else if (typeof params[n] === 'string' || typeof params[n] === 'number') params[n] = [ params[n], v ]; // if second entry with this name
else params[n].push(v); // if third or more with this name
}
return params;
},
/**
* Returns the parameter value from address bar
* @param param parameter name
* @param url url string can be given
* @param convert true to convert vars to real types (e.g. '1' to 1)
* @returns parameter value
*/
getParam : function (param, url, convert) {
var obj = this.urlToObj(url || location.search, convert);
if (obj[param] !== undefined) return obj[param];
return false;
},
/**
* Check whether a string might be a number
* @param v {string} a stringified number
* @returns {boolean} true or false
*/
isNumber : function (v) {
if (typeof v === 'number') return true;
if (typeof v !== 'string') return false;
return (/^[\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?$/).test(v);
},
/**
* Convert string variable to its real type, e.g. '1' to 1
* @param v string var
* @return typed var
*/
varToRealType : function (v) {
var originalv, i = 0, il;
if (this.isNumber(v)) {
originalv = v;
v = parseFloat('' + v);
if (('' + v) !== originalv) v = originalv;
}
else if (v === 'true') v = true;
else if (v === 'false') v = false;
if (v === '') v = undefined;
if (this.getType(v) === 'array') {
il = v.length;
for (; i < il; i++) v[i] = this.varToRealType(v[i]);
}
return v;
},
/**
* Compares 2 objects
* @param x object 1
* @param y object 2
* @returns true if they are identical, false if they are different
*/
areObjectsEqual : function (x, y) {
if (x === y) return true; // if both x and y are null or undefined and exactly the same
if (!(x instanceof Object) || !(y instanceof Object)) return false; // if they are not strictly equal, they both need to be Objects
if (x.constructor !== y.constructor) return false; // they must have the exact same prototype chain, the closest we can do is test there constructor.
for (var p in x) {
if (!x.hasOwnProperty(p)) continue; // other properties were tested using x.constructor === y.constructor
if (!y.hasOwnProperty(p)) return false; // allows to compare x[ p ] and y[ p ] when set to undefined
if (x[p] === y[p]) continue; // if they have the same strict value or identity then they are equal
if (typeof(x[p]) !== 'object') return false; // Numbers, Strings, Functions, Booleans must be strictly equal
if (!this.areObjectsEqual(x[p], y[p])) return false; // Objects and Arrays must be tested recursively
}
for (p in y) if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false; // allows x[ p ] to be set to undefined
return true;
},
/**
* Checks if object is empty (has no own properties)
* @param x object
* @returns true if object is empty, false if it has any own properties
*/
isObjectEmpty : function (x) {
if (!x || typeof x !== 'object') return true;
for (var a in x) if (x.hasOwnProperty(a)) return false;
return true;
},
/**
* Clean empty or null properties from an object
* @param [required] 1 first parameter is an object to clean
* @param [optional] 2,3,... names of additional properties to remove from the object
* @returns clean object
*/
clearProperties : function () {
if (arguments.length < 1) return {};
var obj = arguments[0], newO = {}, name = '', val, props = [];
if (arguments.length > 1) props = Array.prototype.slice.call(arguments, 1);
for (name in obj) {
if (!obj.hasOwnProperty(name)) continue;
val = obj[name];
if (val === undefined || val === null) continue; // if null or undefined
if (this.getType(val) === 'array' && !val.length) continue; // if empty array
if (this.getType(val) === 'object' && this.isObjectEmpty(val)) continue; // if empty object
if (typeof val === 'string' && !val.length) continue; // if empty string
if (this.inArray(props, name) > -1) continue; // if name is in disabled properties list
newO[name] = val;
}
return newO;
},
/**
* Formats numbers (or string numbers)
* @param number int or int-parsable string
* @param prec decimal precision
* @returns formatted number as string
*/
numberFormat : function (number, prec) {
var ext, name, numS, rgx = /(\d+)(\d{3})/;
number = number || '0';
prec = prec || 0;
numS = ('' + number).split('.');
name = numS[0];
ext = numS[1];
if (prec > 0) ext = ((ext || '') + new Array(prec + 1).join('0')).substr(0, prec);
else ext = '';
while (rgx.test(name)) name = name.replace(rgx, '$1' + ',' + '$2');
return name + (ext ? '.' + ext : '');
},
/**
* Normalised rand function
*/
rand : function (max, min) { min = min || 0; return Math.floor(Math.random() * (max - min + 1) + min); },
inArray : function (a, v) {
if (this.getType(a) !== 'array') return false;
var i = 0, e;
if (typeof v === 'object') { for (i = 0; e = a[i++] ;) if (this.areObjectsEqual(e, v)) return i - 1; }
else { for (i = 0; e = a[i++] ;) if (e === v) return i - 1; }
return -1;
},
removeFromArray : function (a, v) {
var nA = [], i = 0, el;
if (typeof v === 'object') { for (; el = a[i++] ;) if (!this.areObjectsEqual(el, v)) nA.push(el); }
else { for (; el = a[i++] ;) if (el !== v) nA.push(el); }
return nA;
},
uniqueArray : function (a) {
var b = [], l = a.length, i = 0, j;
for (; i < l; i++) {
for (j = i + 1; j < l; j++) {
if (typeof a[i] === 'object' && this.areObjectsEqual(a[i], a[j])) j = ++i;
else if (a[i] === a[j]) j = ++i;
}
b.push(a[i]);
}
return b;
},
stripTags = function () {
var tmp = document.createElement('DIV');
tmp.innerHTML = '' + this;
return tmp.textContent || tmp.innerText || '';
};
decodeEntities : function (str) {
if (!str) return '';
if (('' + str).indexOf('&') === -1) return str;
var d = document.createElement('div');
if (this.isIE) str = str.replace(/&apos;/g, '&#39'); // IE does not recognise &apos;
d.innerHTML = str;
return d.innerText || d.textContent;
}
};
/**
* Manage storage (session or local)
*/
UTILS.Storage = {
/**
* Retrieve value from the browser storage
* @param name - name of the parameter to get
* @param val - value (objects will be serialized) assigned to the name
* @param storage - type of the storage: [ session | local ], default: 'session'
*/
get : function (name, storage) {
storage = (storage || 'session') + 'Storage';
if (!window[storage]) return window.log('Browser does not support ' + storage + '!');
var json = window[storage][name];
if (json) return JSON.parse(json);
},
/**
* Save value to the browser storage
* @param name - name of the parameter to save
* @param val - value (objects will be serialized) to assign to the name
* @param storage - type of the storage: [ session | local ], default: 'session'
*/
set : function (name, val, storage) {
storage = (storage || 'session') + 'Storage';
if (!window[storage]) return window.log('Browser does not support ' + storage + '!');
window[storage][name] = JSON.stringify(val);
},
del : function (name, storage) {
storage = (storage || 'session') + 'Storage';
if (!window[storage]) return window.log('Browser does not support ' + storage + '!');
if (window[storage][name]) delete window[storage][name];
}
};
/*** JS OVERRIDES ***************************************************************************************************************/
String.prototype.trim = function (str) {return this.ltrim(str).rtrim(str); };
String.prototype.ltrim = function (str) { if (str) return this.replace(new RegExp('^' + str + '+'), ''); return this.replace(/^\s+/, ''); };
String.prototype.rtrim = function (str) { if (str) return this.replace(new RegExp(str + '+$'), ''); return this.replace(/\s+$/, ''); };
String.prototype.ucfirst = function () { return this.toLowerCase().replace(/\b([a-z])/gi, function (c) { return c.toUpperCase(); }); };
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProp = Object.prototype.hasOwnProperty, hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [], i = 0;
for (var prop in obj) if (hasOwnProp.call(obj, prop)) result.push(prop);
if (hasDontEnumBug) for (; i < dontEnumsLength; i++) if (hasOwnProp.call(obj, dontEnums[i])) result.push(dontEnums[i]);
return result;
};
})();
}
// firebug short-cuts
window.log = (window.console && window.console.log && window.console.log.bind) ? window.console.log.bind(window.console) :
function (e) { window.alert(JSON.stringify(e)); };
window.dir = (window.console && window.console.dir && window.console.dir.bind) ? window.console.dir.bind(window.console) :
function (e) { window.alert(JSON.stringify(e)); };
/*** JS OVERRIDES ***************************************************************************************************************/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment