/*
____________________
< What amazing code! >
--------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
*/
/**
* Some helpful functions I made. all in SEF to make sure object scope is kept.
*
* All objects are static
**/
/**********************************/
/* JQUERY FUNCTIONS
/**********************************/
"use strict";
(function ($) { // lets pass this jQuery so we know nothing else has messed with it
/**
* Add functions to jQuery
*/
$.fn.extend({
/**
* Sort a given list.
* You may pass in any amount of {String} parameters as you like, passing these in will be ingored by the sorting method.
* The first parameter MUST be a boolean. this specifies if you want the ignored elements to be at the bottom of the list (top by default)
*
*
* for example. sort a list, but ignore "Logout":
* $("#myList").sortList(false,"Logout");
* This will make "Logout" appear first in the list as it has been ignored by the sort function.
*
* to make logout appear last:
* $("#myList").sortList(true,"Logout");
*
* Arguments are optinal and do not need to be supplied (to sort the whole list)
*
* parameters:
* {boolean} pushToBottom
* {String} elements to ignore
*/
sortList: function () {
return function () {
if (this.length === 0) {
return;
}
if (!this.is("ul, ol")) {
throw "Error: sortList can only be used on a ul or ol tag!";
}
var args = arguments;
var pushToBottom = false;
if (typeof args[0] !== "undefined") {
if (typeof args[0] !== "boolean") {
throw "the first argument must be a boolean";
}
pushToBottom = args[0];
}
var excludedResults = []; // keep array of excluded li elements
for (var x = 0; x < this.length; x++) {
var currentList = $(this.get(x));
var listitems = currentList.children('li').not(function (i, e) {
for (var i = 1; i < args.length; i++) {
var currentArg = args[i];
if ($.trim($(this).text()) === currentArg) {
excludedResults.push($(this));
return true;
} else {
continue;
}
}
return false;
}).get();
listitems.sort(function (a, b) {
return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
});
$.each(listitems, function (k, v) {
currentList.append(v);
});
if (pushToBottom === true) {
$.each(excludedResults, function (k, v) {
$(this).parent().append(this);
});
}
}
return this;
}.apply(this, arguments);
},
sortSelect: function () {
if (!this.is("select")) {
throw "SortSelect can only be used on a select node";
}
var ignore = [];
$.each(this.children(), function (k, v) {
if (typeof $(this).data("sort-ignore") === "string") {
ignore.push(this);
}
})
var options = this.children("option").not(function (el) {
if ($.inArray(this, ignore) >= 0) {
return true;
}
return false;
});
options.sort(function (a, b) {
return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
});
for (var i = 0; i < options.length; i++) {
this.append(options[i]);
}
return this;
},
center: function () {
this.css("position", "absolute");
this.css("top", Math.max(0, (($(window).height() - $(this).outerHeight()) / 2) + $(window).scrollTop()) + "px");
this.css("left", Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) + $(window).scrollLeft()) + "px");
return this;
},
/**
* Add sortTable function to jQuery
* Using jQuery for this is highly inefficient, but I do not know any pure JS to do the same thing.
* to use do $("#myTable").sortTable(1);
*/
sortTable: function (col) {
typeof col === ("undefined") ? col = -1 : col = col;
if (this.length === 0) {
return;
}
if (typeof col !== "number") {
throw "col must be of type number. Got type" + typeof col + " instead";
}
if (!this.is("table")) {
throw "Error: sortList can only be used on a table!";
}
var rows = $(this).find("tbody").children('tr').get();;
if (col === -1) {
rows.sort(function (a, b) {
return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
});
} else {
rows.sort(function (a, b) {
var textA = $(a).children('td').eq(col).text().toUpperCase();
var textB = $(b).children('td').eq(col).text().toUpperCase();
return textA.localeCompare(textB);
});
}
for (var i = 0; i < rows.length; i++) {
$(this).find("tbody").append(rows[i]); // .append() will move them for you
}
return this;
},
/**
* Will change the text of anything passed in, even if the node is a text node
*/
changetext: function (text) {
if (this.length === 0) {
return;
}
this.contents().filter(function () {
return this.nodeType === 3;
})[0].nodeValue = text;
return this;
},
/**
* Enables a given anchor or button depending on the specified parameter.
* If true is specified then the button / anchor is enabled, otherwise the button / anchor is disabled
*/
enableButton: function (enable) {
if (this.length === 0) {
return;
}
if (!this.is("a, button")) {
throw "This function may only be used on a button or anchor tag";
}
if (typeof enable === "undefined" || enable === null) {
throw "The argument passed to this function must be a boolean";
}
if (enable === true) {
this.prop('disabled', false).removeClass("disabled");
} else {
this.prop('disabled', true).addClass("disabled");
}
return this;
}
});
overrideMethods();
customFilters();
customEvents();
function overrideMethods() {
hide();
show();
function hide() {
var originalHideMethod = jQuery.fn.hide;
$.fn.hide = function () {
originalHideMethod.apply(this, arguments);
if (!this.is(":hidden")) {
this.addClass("hide");
}
return this;
};
}
/**
* Because bootstrap's 3 hide class has an important in the display (display: none !important), any attempt to call the native "show()" in jquery will fail to show the tag
* This will show the tag using the native function, if it is still hidden, it will strip the hide class off the element and apply inline css
*/
function show() {
var originalShowMethod = jQuery.fn.show;
$.fn.show = function () {
originalShowMethod.apply(this, arguments);
var type = getElementDefaultDisplay(this.prop("nodeName"));
if (this.is(":hidden")) { // if still hidden, then bootstrap's hide class was used
this.removeClass("hide").css("display", type);
}
return this;
};
}
/**
* Get the default style of a tag (div = block, span = inline, etc...)
* @param {String} tag Tag name
* @returns {String} Default style
*/
function getElementDefaultDisplay(tag) {
var cStyle;
var t = document.createElement(tag);
var gcs = "getComputedStyle" in window;
document.body.appendChild(t);
cStyle = (gcs ? window.getComputedStyle(t, "") : t.currentStyle).display;
document.body.removeChild(t);
return cStyle;
}
}
function customFilters() {
offScreen();
function offScreen() {
Object.defineProperty(jQuery.expr.filters, "offscreen", {
value: function (_el) {
var el = $(_el);
var win = $(window);
var viewport = {
top: win.scrollTop(),
left: win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = el.offset();
bounds.right = bounds.left + el.outerWidth();
bounds.bottom = bounds.top + el.outerHeight();
return (viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom);
}
})
}
}
function customEvents() {
classChanged();
function classChanged() {
var originalAddClassMethod = jQuery.fn.addClass;
jQuery.fn.addClass = function () {
var result = originalAddClassMethod.apply(this, arguments);
jQuery(this).trigger('cssClassChanged');
return result;
}
};
}
}(jQuery));
/**********************************/
/* NON-JQUERY FUNCTIONS
/**********************************/
/**********************************/
/* MODULE FUNCTIONS
/**********************************/
/**
* Generic object functions
*/
var ObjectUtil = (function () {
"use strict";
/**
* Return true or false if the current object is an instance of jQuery
*/
var isjQuery = function (obj) {
if (obj instanceof jQuery || 'jquery' in Object(obj)) {
return true;
} else {
return false;
}
};
/**
* Returns a jquery element from a jquery object array
* @throws {TypeError} If the supplied parameters are not the correct type
* @param {Object} elm The Jquery element to use
* @param {Number} index The index to use for the array
* @returns {Object} Jquery object from the array
*/
var getElementFromJqueryArray = function (elm, index) {
if (!isjQuery(elm)) {
throw new TypeError("element must be an instance of Jquery");
}
if (typeof index !== "number") {
throw new TypeError("element must be a number");
}
return elm.filter(function (i) {
return i === index;
});
};
var guid = function () {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
};
/**
* Given an array of arguments {Strings} this will return whether all of the strings are not null and have a length of greater than zero
* after trimming the leading and trailing whitespace.
* Throws an exception if argument is not of type string
*/
var validString = function () {
return _validString.apply(this, arguments);
};
var stringContains = function (string, contains) {
return ~string.indexOf(contains) < 0;
};
var deepCompare = function deepCompare() {
var i, l, leftChain, rightChain;
function compare2Objects(x, y) {
var p;
if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
return true;
}
if (x === y) {
return true;
}
if ((typeof x === 'function' && typeof y === 'function') ||
(x instanceof Date && y instanceof Date) ||
(x instanceof RegExp && y instanceof RegExp) ||
(x instanceof String && y instanceof String) ||
(x instanceof Number && y instanceof Number)) {
return x.toString() === y.toString();
}
if (!(x instanceof Object && y instanceof Object)) {
return false;
}
if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
return false;
}
if (x.constructor !== y.constructor) {
return false;
}
if (x.prototype !== y.prototype) {
return false;
}
if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
return false;
}
for (p in y) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
} else if (typeof y[p] !== typeof x[p]) {
return false;
}
}
for (p in x) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
} else if (typeof y[p] !== typeof x[p]) {
return false;
}
switch (typeof (x[p])) {
case 'object':
case 'function':
leftChain.push(x);
rightChain.push(y);
if (!compare2Objects(x[p], y[p])) {
return false;
}
leftChain.pop();
rightChain.pop();
break;
default:
if (x[p] !== y[p]) {
return false;
}
break;
}
}
return true;
}
if (arguments.length < 1) {
return true;
}
for (i = 1, l = arguments.length; i < l; i++) {
leftChain = [];
rightChain = [];
if (!compare2Objects(arguments[0], arguments[i])) {
return false;
}
}
return true;
};
/**
* Extend an object from the base object
* @throws {Error} If none of the supplied objects are constructors
* @param {Function} base Constructor of the base object (to extend from)
* @param {Function} sub Constructor of the sub Object (this object will be the one to be extended)
* @returns {Function} Chained constructor of the sub object
*/
var extendObj = function (base, sub) {
if (typeof sub !== "function") {
throw new Error("sub must be a Constructor");
}
if (typeof base !== "function") {
throw new Error("base must be a Constructor");
}
sub.prototype = Object.create(base.prototype);
sub.prototype.constructor = sub;
// sub.base = base.prototype;
return sub;
}
/**
* PRIVATE
* this is called by the public validString because it takes varargs because apply can't be called on the revealing pattern
*/
var _validString = function () {
if (arguments == null || arguments.length === 0) {
return false;
}
for (var i = 0; i < arguments.length; i++) {
var currString = arguments[i];
if (currString === undefined || currString === null || currString.length === 0) {
return false
}
if (typeof currString !== "string") {
return false;
}
if ($.trim(currString).length === 0) {
return false;
}
}
return true;
};
/**
* Return an object of public functions
*/
return {
isjQuery: isjQuery,
validString: validString,
extendObj: extendObj,
stringContains: stringContains,
getElementFromJqueryArray: getElementFromJqueryArray,
deepCompare: deepCompare,
guid: guid
};
}());
var DomUtil = (function DomUtil() {
var injectCss = function (css) {
if (_isUrl(css)) {
$("<link>").prop({
"type": "text/css",
"rel": "stylesheet"
}).attr("href", css).appendTo("head");
} else {
$("<style>").prop("type", "text/css").html(css).appendTo("head");
}
};
var _isUrl = function (url) {
var matcher = new RegExp(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/);
return matcher.test(url);
};
return {
injectCss: injectCss
};
}());
/**
* Generic XML functions
*/
var XmlUtil = (function () {
"use strict";
/**
* Encode XML nodes into HTML entities
*/
var encodeXml = function (xml) {
if (typeof xml !== "string") {
return;
}
return xml.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
/**
* Decode encoded HTML Entities.
* Note: The jQuery method "html" will do this automatically.
*/
var decodeXml = function (xml) {
if (typeof xml !== "string") {
return;
}
return xml.replace(/'/g, "'")
.replace(/"/g, '"')
.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/&/g, '&');
};
return {
encodeXml: encodeXml,
decodeXml: decodeXml
};
}());
var XssEncoder = (function (_super) {
return _super;
}(XmlUtil || {}));
/**
* static object containing helpful file functions
* functions include:
*
* supportsFileApi
* getFileExt
* getFileNameFromInput
*
*/
var fileUtil = (function () {
"use strict";
var getFileNameFromInput = function (input) {
var currentFile = null;
// convert jQuery to pure JS
var input = (function () {
if (ObjectUtil.isjQuery(input)) {
if (input.length === 0) {
throw "Input does not exist";
}
return input[0];
} else {
return input;
}
}());
if (input === null) {
throw "Input does not exist";
}
// if the input is a URL
if (input.getAttribute("type") === "url") {
return _getFileNameFromUrl(input.value);
}
// use the old way of getting a file (not guaranteed to be correct)
if (!supportsFileApi()) {
return _getFileNameFromUrl(input.value);
}
currentFile = input.files[0];
return currentFile.name;
};
var supportsFileApi = function () {
if (window.File && window.FileReader && window.FileList && window.Blob) {
return true;
} else {
return false;
}
};
var _getFileNameFromUrl = function (path) {
if (typeof path !== "string") {
throw "path does not contain a value, this maybe because you did not pass in an object that represents an input";
}
return path.replace(/^C:\\fakepath\\/i, "").split('\\').pop().split('/').pop();
};
/**
* PUBLIC
*
* Will return the file extension from a given filename
* @param {String} Name of the file
*/
var getFileExt = function (fullFileName) {
if (ObjectUtil.isjQuery(fullFileName)) {
fullFileName = fullFileName.val();
}
var ext = fullFileName.substr(fullFileName.lastIndexOf('.') + 1);
if (ext === "") {
throw "No file extension";
} else {
return ext.toLowerCase();
}
};
var _getHumanReadableSize = function (bytes, decimals) {
if (bytes == 0) {
return '0 Byte';
}
var k = 1024;
var dm = decimals + 1 || 3;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toPrecision(dm) + ' ' + sizes[i];
};
var ImageUtils = (function () {
/**
* Get the image info from a file select input
* @param {object} input The Jquery or pure dom element representing the input
* @param {function} callBack The callback function will supply 2 values: the first is an object containing the image infomation and the second is the actual image as a dom element you can use for image preview
* @throws {ImageBoundException} If there was an unsupported filetype
*/
var getImageInfoFromInput = function getImageInfoFromInput(input, callBack) {
if (!supportsFileApi()) {
return;
}
var input = (function () {
if (ObjectUtil.isjQuery(input)) {
if (input.length === 0) {
throw "Input does not exist";
}
return input[0];
} else {
return input;
}
}());
if (BrowserUtils.isChrome()) { // chrome does not support createObjectURL on URL but does on webkitURL... Chrome conplains that you use webkitURL
window.URL = window.webkitURL;
}
var useBlob = true && window.URL;
var files = input.files;
if (!files) {
throw new TypeError("File upload not supported by your browser.");
}
if (files.length > 0) {
var file = files[0];
if ((/\.(png|jpg|gif)$/i).test(file.name)) {
var deferred = $.Deferred();
$.when(readImage(file, deferred)).done(function (value, img) {
callBack.call(img, value, img);
});
} else {
throw new ImageBoundException("Unsupported Image extension: '" + getFileExt(file.name) + "' file name: '" + file.name + "'");
}
}
function readImage(file, defer) {
var reader = new FileReader();
reader.addEventListener("load", function () {
var image = new Image();
image.addEventListener("load", function () {
var returnObj = {};
Object.defineProperties(returnObj, {
"fileName": {
value: file.name
},
"imageWidth": {
value: image.width
},
"imageHeight": {
value: image.height
},
"imageType": {
value: file.type
},
"fileSize": {
value: _getHumanReadableSize(file.size)
},
"base64": {
value: reader.result
}
})
Object.freeze(returnObj); // stop anything from changing anything in this object
defer.resolve(returnObj, this);
});
image.src = useBlob ? window.URL.createObjectURL(file) : reader.result;
if (useBlob) {
window.URL.revokeObjectURL(file);
}
});
reader.readAsDataURL(file);
return defer.promise();
}
}
return {
getImageInfoFromInput: getImageInfoFromInput
};
}());
/**
* Get the image info from a file select input
* @param {String} b64Data The base 64 data
* @param {String} contentType The content type of this blob example : (image/png)
* @param {String} sliceSize The slices of the array to use, this is optinal and if omited will default to 512bits per array. this acts as a buffer
*/
var b64toBlob = function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {
type: contentType
});
return blob;
}
/**
* Return an object of public functions
*/
return {
getFileExt: getFileExt,
getFileNameFromInput: getFileNameFromInput,
supportsFileApi: supportsFileApi,
ImageUtils: ImageUtils,
b64toBlob: b64toBlob
};
}());
/**
* Drag and drop object
* Extends the fileUtil object
*/
var dragDrop = (function (_super, window) {
var canSupportDragAndDrop = function () {
return _super.supportsFileApi();
};
return {
fileUtil: _super,
canSupportDragAndDrop: canSupportDragAndDrop
};
}(fileUtil || {}, window));
var ArrayUtils = (function () {
"use strict";
/**
* DEPRICATED!! Used yourArray._remove_(itemToRemove);
*/
var removeFromArray = function (arr, obj) {
if (console) {
console.warn("The use of 'removeFromArray' is depricated, please use 'yourArray._remove_(item)' instead");
}
var i = arr.length;
while (i--) {
if (ObjectUtil.isjQuery(obj)) {
if ($(arr[i]).is(obj)) {
arr.splice(i, 1);
}
} else {
if (arr[i] === obj) {
arr.splice(i, 1);
}
}
}
};
var arrayCopy = function (array, deep) {
if (!Array.isArray(array)) {
throw new TypeError("array to copy must be of type 'Array'");
}
deep = typeof deep === "undefined" ? false : deep;
return $.extend(deep, [], array);
};
return {
removeFromArray: removeFromArray,
arrayCopy: arrayCopy
};
}());
var ColourUtils = (function () {
"use strict";
var h = Math.random();
var golden_ratio_conjugate = 0.618033988749895;
//http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
var getRandomColour = function () {
//Used to generate random colors
h += golden_ratio_conjugate
h %= 1
function hsv_to_rgb(h, s, v) {
var h_i = parseInt(h * 6);
var f = h * 6 - h_i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
var r, g, b;
if (h_i == 0) {
r = v;
g = t;
b = p;
} else if (h_i == 1) {
r = q;
g = v;
b = p;
} else if (h_i == 2) {
r = p;
g = v;
b = t;
} else if (h_i == 3) {
r = p;
g = q;
b = v;
} else if (h_i == 4) {
r = t;
g = p;
b = v;
} else if (h_i == 5) {
r = v;
g = p;
b = q;
}
return "rgb(" + parseInt(r * 256) + "," + parseInt(g * 256) + "," + parseInt(b * 256) + ")";
}
return hsv_to_rgb(h, 0.7, 0.75);
};
return {
getRandomColour: getRandomColour
};
}());
var BrowserUtils = (function () {
"use strict";
var detectMobile = function () {
var check = false;
(function (a) {
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) {
check = true;
}
})(navigator.userAgent || navigator.vendor || window.opera);
return check;
};
var isChrome = function () {
if (window.chrome !== null && window.navigator.vendor === 'Google Inc.') {
return true;
} else {
return false;
}
};
var isFireFox = function () {
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
return true;
} else {
return false;
}
};
var isWebkit = function () {
return /webkit/.test(navigator.userAgent.toLowerCase());
};
var isEdgeOrIe = function isEdgeOrIe() {
return Edge.isEdge() || IeUtils.isIe();
};
var Edge = (function () {
var getVersion = function getVersion() {
var ua = window.navigator.userAgent;
var edge = ua.indexOf('Edge/');
if (edge > 0) {
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
} else {
return null;
}
};
var isEdge = function isEdge() {
return getVersion() !== null;
};
return {
getVersion: getVersion,
isEdge: isEdge
}
}());
return {
detectMobile: detectMobile,
isChrome: isChrome,
isFireFox: isFireFox,
isWebkit: isWebkit,
isEdgeOrIe: isEdgeOrIe,
Edge: Edge
};
}());
/**
* An object for detecting ie versions
* Functions available are:
*
* isIe
* getIeVersion
*/
var IeUtils = (function () {
"use strict";
/**
* returns true or false if using IE10
*/
var _isIE10 = function () {
return navigator.appVersion.indexOf("MSIE 10") !== -1;
};
/**
* returns true or false if using IE11
*/
var _isIE11 = function () {
return !!navigator.userAgent.match(/Trident.*rv[ :]*11\./);
};
var _isIE9 = function () {
return navigator.appVersion.indexOf("MSIE 9.") != -1;
};
/**
* Returns if using ie
* returns boolean
*/
var isIe = function () {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 | _isIE11() || _isIE10()) {
return true;
} else {
return false;
}
};
/**
* returns the version of IE used by the client
* returns string or null if not using IE
*/
var getIeVersion = function () {
if (!isIe()) {
return null;
}
var actualVersion = "unknown";
var jscriptMap = {
"5.5": 5.5,
"5.6": 6,
"5.7": 7,
"5.8": 8,
"9": 9,
};
var jscriptVersion = new Function("/*@cc_on return @_jscript_version; @*/")();
if (typeof jscriptVersion !== "undefined") {
actualVersion = jscriptMap[jscriptVersion];
// Somehow, the script version was retrived but not known (emulation mode can cause this issue)
if (typeof actualVersion === "undefined") {
if (_isIE10()) {
actualVersion = 10;
} else if (_isIE11()) {
actualVersion = 11;
} else if (_isIE9()) {
actualVersion = 9;
} else {
actualVersion = "unknown";
}
}
} else {
if (_isIE10()) {
actualVersion = 10;
} else if (_isIE11()) {
actualVersion = 11;
}
}
return actualVersion;
};
/**
* Returns an object of public functions
*/
return {
isIe: isIe,
getIeVersion: getIeVersion
};
}());
var VersionUtil = (function () {
var isHigherVersion = function (version1, version2) {
if (typeof version1 !== "string" && typeof version2 !== "string") {
throw "versions must be strings";
}
var v1Comps = version1.split(".");
var v2Comps = version2.split(".");
var limit = (v1Comps.length > v2Comps.length) ? v2Comps.length : v1Comps.length;
for (var i = 0; i < limit; i++) {
var v1part = parseInt(v1Comps[i]);
var v2part = parseInt(v2Comps[i]);
if (v1part > v2part) {
return true;
}
if (v2part > v1part) {
return false;
}
}
return v1Comps.length >= v2Comps.length;
};
return {
isHigherVersion: isHigherVersion
};
}());
var QueryString = (function () {
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = pair[1];
} else if (typeof query_string[pair[0]] === "string") {
var arr = [query_string[pair[0]], pair[1]];
query_string[pair[0]] = arr;
} else {
query_string[pair[0]].push(pair[1]);
}
}
return query_string;
}());
/**********************************/
/* PROTOTYPE FUNCTIONS
/**********************************/
/**
* Adding sort array of objects to the prototype.
* To use this. call sortBy on an array of objects. for example given this object:
* var arr= [
* {
* AgencyId:"SDMX",
* Id:"AGENCIES",
* Name:"SDMX Agency Scheme"
* },
* {
* AgencyId:"METATECH",
* Id:"AGENCIES",
* Name:"Agencies"
* },
* ]
* this is an array of 2 objects.
* if we want to sort this by the property "Name" we can do this
* arr.sortBy("Name");
* if you want to sort by "name" and "Id", you can just do
* arr.sortBy("Name", "Id");
* this takes an unlimited amount of args.
*
* If you wish to sort Descending, append a "-" to your argument
*
* sort by "Name" Descending: arr.sortBy("-Name");
*/
(function () {
function _sortByAttr(attr) {
var sortOrder = 1;
if (attr[0] == "-") {
sortOrder = -1;
attr = attr.substr(1);
}
return function (a, b) {
if (typeof a[attr] === "undefined" || typeof b[attr] === "undefined") {
throw "There is no property with the value of " + attr.toString() + " inside this object";
}
var result = a[attr].toUpperCase().localeCompare(b[attr].toUpperCase());
return result * sortOrder;
}
}
function _getSortFunc() {
if (arguments.length == 0) {
throw "Zero length arguments not allowed for Array.sortBy()";
}
var args = arguments;
return function (a, b) {
for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
result = _sortByAttr(args[i])(a, b);
}
return result;
}
}
Object.defineProperty(Array.prototype, "sortBy", {
enumerable: false,
writable: true,
value: function () {
return this.sort(_getSortFunc.apply(null, arguments));
}
});
}());
(function () {
if (Array.prototype._remove_) {
return;
}
Object.defineProperty(Array.prototype, "_remove_", {
enumerable: false,
/**
* Removes all occurence of specified item from array
* @param this Array
* @param itemToRemove Item to remove from array
*/
value: function (itemToRemove) {
var i = this.length;
try {
var itemToRemoveStr = null
itemToRemoveStr = JSON.stringify(itemToRemove);
} catch (e) {}
while (i--) {
var currentItem = this[i];
var currentItemStr = null;
if (itemToRemoveStr !== null) {
try {
currentItemStr = JSON.stringify(currentItem);
} catch (e) {}
}
if (ObjectUtil.isjQuery(itemToRemove)) {
if ($(currentItem).is(itemToRemove)) {
this.splice(i, 1);
}
} else {
if (currentItemStr !== null && itemToRemoveStr !== null) {
if (currentItemStr === itemToRemoveStr) {
this.splice(i, 1);
continue;
}
}
if (ObjectUtil.deepCompare(itemToRemove, currentItem)) {
this.splice(i, 1);
continue;
}
continue;
}
}
}
});
if (Array.prototype.moveItem) {
return;
}
Object.defineProperty(Array.prototype, "moveItem", {
value: function (old_index, new_index) {
while (old_index < 0) {
old_index += this.length;
}
while (new_index < 0) {
new_index += this.length;
}
if (new_index >= this.length) {
var k = new_index - this.length;
while ((k--) + 1) {
this.push(undefined);
}
}
this.splice(new_index, 0, this.splice(old_index, 1)[0]);
}
})
}());
(function () {
Object.defineProperty(Function.prototype, "getName", {
value: function () {
try {
return /^function\s+([\w\$]+)\s*\(/.exec(this.toString())[1];
} catch (e) {
return null;
}
}
})
}());
var LinkedArray = (function () {
var LinkedArray = function LinkedArray(type) {
if (typeof type === "undefined") {
throw new TypeError("a type must be supplied");
}
var arr = [];
Object.setPrototypeOf(arr, LinkedArray.prototype); // this is bad. however, this is one of them "if it's last resort" things. becase this truly is last resort, we must edit the __proto__ directly to extend array, object.create will not work
Object.defineProperty(arr, "_type", {
value: type
});
return arr;
};
LinkedArray.prototype = new Array;
LinkedArray.prototype.push = function push() {
var argarr = arguments;
var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
for (var i = 0; i < args.length; i++) {
var carrArg = args[i];
if (Array.isArray(this._type)) {
if (!Array.isArray(carrArg)) {
throw new TypeError("this array only accepts instance of arrays");
}
} else if (typeof this._type === "object" || typeof this._type === "function") {
if (typeof carrArg === "undefined") {
break;
}
if (!(carrArg instanceof this._type)) {
var msg = "This array only accepts instance of {supplied object}";
if (this._type.name !== "") {
msg = "This array only accepts instance of " + this._type.name;
} else {
try {
msg = "This array only accepts instance of " + this._type.getName();
} catch (e) {}
}
throw new TypeError(msg);
}
} else if (typeof this._type === "number" && typeof carrArg !== "number") {
throw new TypeError("this array only accepts " + typeof this._type);
} else if (typeof this._type === "boolean" && typeof carrArg !== "boolean") {
throw new TypeError("this array only accepts " + typeof this._type);
} else if (typeof this._type === "string" && typeof carrArg !== "string") {
throw new TypeError("this array only accepts " + typeof this._type);
}
}
args.forEach(function (element, index, array) {
Array.prototype.push.call(this, element);
}, this);
};
LinkedArray.prototype.getType = function getType() {
if (typeof this._type === "function") {
return new(this._type);
} else if (typeof this._type === "object") {
return this._type
} else {
return typeof this._type;
}
};
return LinkedArray;
}());
/**********************************/
/* Custom Exceptions
/**********************************/
var ImageBoundException = (function () {
function ImageBoundException(message) {
this.name = 'ImageBoundException';
this.message = message || 'An error occured with this image';
this.stack = (new Error()).stack;
}
ImageBoundException.prototype = Object.create(Error.prototype);
ImageBoundException.prototype.constructor = ImageBoundException;
return ImageBoundException;
}());
/**********************************/
/* PROTOTYPE FUNCTIONS END
/**********************************/