924 lines
32 KiB
JavaScript
924 lines
32 KiB
JavaScript
var C_EMPTY_GUID = '00000000-0000-0000-0000-000000000000';
|
|
var app; // Variable declaration for angular app
|
|
|
|
var _lockers = 0;
|
|
function increaseLockers() {
|
|
if (_lockers < 0)
|
|
_lockers = 0;
|
|
_lockers++;
|
|
}
|
|
function decreaseLockers() {
|
|
if (_lockers > 0)
|
|
_lockers--;
|
|
if (_lockers < 0)
|
|
_lockers = 0;
|
|
}
|
|
function canUnblockUI() {
|
|
return _lockers === 0;
|
|
}
|
|
function isUIBlocked() {
|
|
return _lockers > 0;
|
|
}
|
|
function showErrorModal(title, message, errorCode) {
|
|
title = title || 'Oops!';
|
|
message = message || 'An error occurred while processing your request. Please, try again later.';
|
|
if (errorCode)
|
|
message += ' ErrorCode = ' + errorCode;
|
|
var modal = $("#modal-error");
|
|
if (modal != null) {
|
|
var divTitle = $("#modal-error .modal-title");
|
|
if (divTitle != null)
|
|
divTitle.text(title);
|
|
var divMessage = $("#modal-error .modal-body");
|
|
if (divMessage != null) {
|
|
divMessage.text($.trim(message));
|
|
if (divMessage.text().length > 0) {
|
|
$("#modal-error").modal();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function enableElement(obj, enable) {
|
|
if (enable) {
|
|
$(obj).removeAttr('disabled');
|
|
} else {
|
|
$(obj).attr('disabled', 'disabled');
|
|
}
|
|
}
|
|
function blockUI() {
|
|
increaseLockers();
|
|
$.blockUI({ message: "<div class='spinner2'>Loading...</div>", ignoreIfBlocked: true });
|
|
}
|
|
function blockUIRace() {
|
|
increaseLockers();
|
|
$.blockUI({ message: "<div class='spinnerRace'>Loading...</div>", ignoreIfBlocked: true });
|
|
}
|
|
function unblockUI() {
|
|
decreaseLockers();
|
|
if (canUnblockUI())
|
|
$.unblockUI();
|
|
|
|
}
|
|
|
|
(function ($) {
|
|
$.validator.unobtrusive.parseDynamicContent = function (selector) {
|
|
//use the normal unobstrusive.parse method
|
|
$.validator.unobtrusive.parse(selector);
|
|
|
|
//get the relevant form
|
|
var form = $(selector).first().closest('form');
|
|
|
|
//get the collections of unobstrusive validators, and jquery validators
|
|
//and compare the two
|
|
var unobtrusiveValidation = form.data('unobtrusiveValidation');
|
|
var validator = form.validate();
|
|
|
|
$.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
|
|
if (validator.settings.rules[elname] == undefined) {
|
|
var args = {};
|
|
$.extend(args, elrules);
|
|
args.messages = unobtrusiveValidation.options.messages[elname];
|
|
//edit:use quoted strings for the name selector
|
|
$(form).find("[name='" + elname + "']").rules("add", args);
|
|
} else {
|
|
$.each(elrules, function (rulename, data) {
|
|
if (validator.settings.rules[elname][rulename] == undefined) {
|
|
var args = {};
|
|
args[rulename] = data;
|
|
args.messages = unobtrusiveValidation.options.messages[elname];
|
|
//edit:use quoted strings for the name selector
|
|
$(form).find("[name='" + elname + "']").rules("add", args);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
if (validator.settings.errorPlacement == undefined)
|
|
validator.settings.errorPlacement = unobtrusiveValidation.options.errorPlacement;
|
|
};
|
|
})($);
|
|
(function ($) {
|
|
$.QueryString = (function (a) {
|
|
if (a == "") return {};
|
|
var b = {};
|
|
for (var i = 0; i < a.length; ++i) {
|
|
var p = a[i].split('=');
|
|
if (p.length != 2) continue;
|
|
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
|
|
}
|
|
return b;
|
|
})(window.location.search.substr(1).split('&'));
|
|
})($);
|
|
Number.prototype.formatNumber = function (c, d, t) {
|
|
var n = this,
|
|
c = isNaN(c = Math.abs(c)) ? 2 : c,
|
|
d = d == undefined ? "." : d,
|
|
t = t == undefined ? "," : t,
|
|
s = n < 0 ? "-" : "",
|
|
i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
|
|
j = (j = i.length) > 3 ? j % 3 : 0;
|
|
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
|
|
};
|
|
Number.prototype.formatDuration = function () {
|
|
var result = this;
|
|
if (this > 0) { // get years
|
|
|
|
}
|
|
if (this > 0) { // get days
|
|
|
|
}
|
|
if (this > 0) { // get hours
|
|
|
|
}
|
|
return result;
|
|
};
|
|
function union(arr1, arr2) {
|
|
var result = new Array();
|
|
|
|
var fa = (arr1 || []);
|
|
for (var i = 0; i < fa.length; i++) {
|
|
if (result.indexOf(fa[i]) < 0)
|
|
result.push(fa[i]);
|
|
}
|
|
|
|
var sa = (arr2 || []);
|
|
for (var i = 0; i < sa.length; i++) {
|
|
if (result.indexOf(sa[i]) < 0)
|
|
result.push(sa[i]);
|
|
}
|
|
|
|
return result;
|
|
};
|
|
function binarySearch(ar, x, left, right, searchIndex4Insert, key) {
|
|
if (!ar || !$.isArray(ar))
|
|
throw 'ar is not array!';
|
|
|
|
if (left > right || ar.length <= 0)
|
|
return -1;
|
|
|
|
var mid = Math.floor((left + right) / 2);
|
|
if (mid == ar.length) {
|
|
return searchIndex4Insert === true ? ar.length : -1;
|
|
}
|
|
|
|
var arMid = key ? ar[mid][key] : ar[mid];
|
|
if (arMid == x)
|
|
return mid;
|
|
|
|
if (searchIndex4Insert === true) {
|
|
var prev = Number.MIN_VALUE,
|
|
next = Number.MAX_VALUE;
|
|
|
|
if (mid > 0 && mid < ar.length) {
|
|
prev = (key ? ar[mid - 1][key] : ar[mid - 1]) || Number.MIN_VALUE;
|
|
}
|
|
if (mid >= 0 && (mid + 1) < ar.length) {
|
|
next = ((key ? ar[mid + 1][key] : ar[mid + 1]) || Number.MAX_VALUE);
|
|
}
|
|
|
|
if (prev == x)
|
|
return mid - 1;
|
|
if (next == x)
|
|
return mid + 1;
|
|
if (prev < x && x < arMid)
|
|
return mid;
|
|
if (arMid < x && x < next)
|
|
return mid + 1;
|
|
}
|
|
if (arMid < x)
|
|
return binarySearch(ar, x, mid + 1, right, searchIndex4Insert, key);
|
|
if (arMid > x)
|
|
return binarySearch(ar, x, left, mid - 1, searchIndex4Insert, key);
|
|
};
|
|
/*
|
|
* Generate a random uuid.
|
|
*
|
|
* USAGE: Math.uuid(length, radix)
|
|
* length - the desired number of characters
|
|
* radix - the number of allowable values for each character.
|
|
*
|
|
* EXAMPLES:
|
|
* // No arguments - returns RFC4122, version 4 ID
|
|
* >>> Math.uuid()
|
|
* "92329D39-6F5C-4520-ABFC-AAB64544E172"
|
|
*
|
|
* // One argument - returns ID of the specified length
|
|
* >>> Math.uuid(15) // 15 character ID (default base=62)
|
|
* "VcydxgltxrVZSTV"
|
|
*
|
|
* // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
|
|
* >>> Math.uuid(8, 2) // 8 character ID (base=2)
|
|
* "01001010"
|
|
* >>> Math.uuid(8, 10) // 8 character ID (base=10)
|
|
* "47473046"
|
|
* >>> Math.uuid(8, 16) // 8 character ID (base=16)
|
|
* "098F4D35"
|
|
*/
|
|
Math.uuid = (function () {
|
|
// Private array of chars to use
|
|
var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
|
|
|
return function (len, radix) {
|
|
var chars = CHARS, uuid = [], rnd = Math.random;
|
|
radix = radix || chars.length;
|
|
|
|
if (len) {
|
|
// Compact form
|
|
for (var i = 0; i < len; i++) uuid[i] = chars[0 | rnd() * radix];
|
|
} else {
|
|
// rfc4122, version 4 form
|
|
var r;
|
|
|
|
// rfc4122 requires these characters
|
|
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
|
uuid[14] = '4';
|
|
|
|
// Fill in random data. At i==19 set the high bits of clock sequence as
|
|
// per rfc4122, sec. 4.1.5
|
|
for (var i = 0; i < 36; i++) {
|
|
if (!uuid[i]) {
|
|
r = 0 | rnd() * 16;
|
|
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
|
|
}
|
|
}
|
|
}
|
|
|
|
return uuid.join('');
|
|
};
|
|
})();
|
|
function initMainJS() {
|
|
$("select").on("select2-focus", function (e) {
|
|
$(".minicolors-panel").css('display', 'none');
|
|
$(".datepicker-dropdown").css('display', 'none');
|
|
});
|
|
|
|
}
|
|
//todo: remove other instances
|
|
$.fn.modal.Constructor.prototype.enforceFocus = function () {
|
|
var that = this;
|
|
$(document).on('focusin.modal', function (e) {
|
|
if ($(e.target).hasClass('select2-input')) {
|
|
return true;
|
|
}
|
|
|
|
if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
|
|
that.$element.focus();
|
|
}
|
|
});
|
|
};
|
|
|
|
|
|
|
|
function setDropdownProps(button, dropdown, liHeight) {
|
|
|
|
|
|
var clientid = $(dropdown)[0].id;
|
|
var rows = $("#" + clientid + " li").length;
|
|
if (rows > 3)
|
|
rows = rows - 1;
|
|
|
|
var menumax = rows * liHeight;
|
|
if (rows >= 2)
|
|
menumax = menumax + 25;
|
|
dropdown.css('overflow', 'hidden');
|
|
var curmaxheight = 300;
|
|
var totalMaxheight = 400;
|
|
var menumax_keep = menumax;
|
|
var y = $(window.top).height();
|
|
var bOffset = button.offset().top - window.pageYOffset;
|
|
|
|
var y1 = bOffset + button.outerHeight();
|
|
var dropDownLeft = button.offset().left - window.pageXOffset;
|
|
var dropDownTop = bOffset + button.outerHeight();
|
|
var sc1 = y - y1;
|
|
|
|
if (curmaxheight + dropDownTop > window.innerHeight)
|
|
sc1 = bOffset;
|
|
|
|
if (menumax > sc1)
|
|
menumax = (sc1 - 50);
|
|
|
|
if (menumax > totalMaxheight)
|
|
menumax = totalMaxheight;
|
|
var direction = 'bottom';
|
|
if (menumax + dropDownTop > window.innerHeight) {
|
|
if (menumax_keep < menumax)
|
|
dropDownTop = (bOffset - menumax_keep);
|
|
else
|
|
dropDownTop = (bOffset - menumax);
|
|
direction = 'top'
|
|
}
|
|
|
|
if (menumax < menumax_keep) {
|
|
var delta = menumax_keep - menumax
|
|
if (delta > 25)
|
|
dropdown.css('overflow', 'auto');
|
|
if (curmaxheight > menumax) {
|
|
menumax = curmaxheight;
|
|
}
|
|
}
|
|
if (direction === 'top') {
|
|
dropdown.css('max-height', menumax + "px");
|
|
if (menumax < curmaxheight)
|
|
menumaxdph = $(dropdown).outerHeight();
|
|
dropDownTop = (bOffset - menumax);
|
|
|
|
} else {
|
|
dropdown.css('max-height', menumax + "px");
|
|
}
|
|
dropdown.css('position', 'fixed');
|
|
dropdown.css('top', dropDownTop + "px");
|
|
dropdown.css('left', dropDownLeft + "px");
|
|
dropdown.css('z-index', '499');
|
|
setDropDownHorizontalPosition(button, dropdown)
|
|
}
|
|
setDropDownHorizontalPosition = function (button, dropdown) {
|
|
|
|
var clientid = $(dropdown)[0].id;
|
|
var rows = $("#" + clientid + " li").length;
|
|
if (rows > 0) {
|
|
var l = button.offset().left + $(button).parent().width();
|
|
var w = $(dropdown).innerWidth();
|
|
var docW = window.innerWidth;
|
|
|
|
var isEntirelyVisible = (l + w <= docW);
|
|
|
|
if (!isEntirelyVisible) {
|
|
var totheright = l - w;
|
|
dropdown.css('left', totheright + 'px');
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
jQuery.getScrollBarWidthHeight = function () {
|
|
var inner = $('<p></p>').css({
|
|
'width': '100%',
|
|
'height': '100%'
|
|
});
|
|
var outer = $('<div></div>').css({
|
|
'position': 'absolute',
|
|
'width': '100px',
|
|
'height': '100px',
|
|
'top': '0',
|
|
'left': '0',
|
|
'visibility': 'hidden',
|
|
'overflow': 'hidden'
|
|
}).append(inner);
|
|
|
|
$(document.body).append(outer);
|
|
|
|
var w1 = inner.width(), h1 = inner.height();
|
|
outer.css('overflow', 'scroll');
|
|
var w2 = inner.width(), h2 = inner.height();
|
|
if (w1 == w2 && outer[0].clientWidth) {
|
|
w2 = outer[0].clientWidth;
|
|
}
|
|
if (h1 == h2 && outer[0].clientHeight) {
|
|
h2 = outer[0].clientHeight;
|
|
}
|
|
|
|
outer.detach();
|
|
|
|
var pixelRatioMultiplier = 1.00;
|
|
//AG: I've commented out the lines below because window.devicePixelRatio is a bad practice to determine the zoom although it works
|
|
//correctly on the desktop browsers - this supposed to show HIDPI screens and will not work correctly on tablets and phones and probably HIDPI desktop screens as well
|
|
|
|
//if (window.devicePixelRatio != null && window.devicePixelRatio != 0)
|
|
// pixelRatioMultiplier = window.devicePixelRatio.toFixed(2);
|
|
|
|
return [Math.round((w1 - w2) * pixelRatioMultiplier), Math.round((h1 - h2) * pixelRatioMultiplier)];
|
|
};
|
|
|
|
initMainJS();
|
|
|
|
Object.size = function (obj) {
|
|
var size = 0, key;
|
|
for (key in obj) {
|
|
if (obj.hasOwnProperty(key)) size++;
|
|
}
|
|
return size;
|
|
};
|
|
var _bigColorPalette = ["#67B7DC", "#FDD400", "#CC4748", "#CD82AD", "#2F4074", "#448E4D", "#B7B83F", "#B9783F",
|
|
"#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87",
|
|
"#5A0007", "#809693", "#92896B", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80",
|
|
"#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100",
|
|
"#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F",
|
|
"#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09",
|
|
"#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66",
|
|
"#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C",
|
|
"#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059",
|
|
|
|
"#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81",
|
|
"#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00",
|
|
"#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700",
|
|
"#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329",
|
|
"#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C",
|
|
"#83AB58", "#001C1E", "#D1F7CE", "#004B28", "#C8D0F6", "#A3A489", "#806C66", "#222800",
|
|
"#BF5650", "#E83000", "#66796D", "#DA007C", "#FF1A59", "#8ADBB4", "#1E0200", "#5B4E51",
|
|
"#C895C5", "#320033", "#FF6832", "#66E1D3", "#CFCDAC", "#D0AC94", "#7ED379", "#012C58",
|
|
|
|
"#7A7BFF", "#D68E01", "#353339", "#78AFA1", "#FEB2C6", "#75797C", "#837393", "#943A4D",
|
|
"#B5F4FF", "#D2DCD5", "#9556BD", "#6A714A", "#001325", "#02525F", "#0AA3F7", "#E98176",
|
|
"#DBD5DD", "#5EBCD1", "#3D4F44", "#7E6405", "#02684E", "#962B75", "#8D8546", "#9695C5",
|
|
"#E773CE", "#D86A78", "#3E89BE", "#CA834E", "#518A87", "#5B113C", "#55813B", "#E704C4",
|
|
"#00005F", "#A97399", "#4B8160", "#59738A", "#FF5DA7", "#F7C9BF", "#643127", "#513A01",
|
|
"#6B94AA", "#51A058", "#A45B02", "#1D1702", "#E20027", "#E7AB63", "#4C6001", "#9C6966",
|
|
"#64547B", "#97979E", "#006A66", "#391406", "#F4D749", "#0045D2", "#006C31", "#DDB6D0",
|
|
"#7C6571", "#9FB2A4", "#00D891", "#15A08A", "#BC65E9", "#000000", "#C6DC99", "#203B3C",
|
|
|
|
"#671190", "#6B3A64", "#F5E1FF", "#FFA0F2", "#CCAA35", "#374527", "#8BB400", "#797868",
|
|
"#C6005A", "#3B000A", "#C86240", "#29607C", "#402334", "#7D5A44", "#CCB87C", "#B88183",
|
|
"#AA5199", "#B5D6C3", "#A38469", "#9F94F0", "#A74571", "#B894A6", "#71BB8C", "#00B433",
|
|
"#789EC9", "#6D80BA", "#953F00", "#5EFF03", "#E4FFFC", "#1BE177", "#BCB1E5", "#76912F",
|
|
"#003109", "#0060CD", "#D20096", "#895563", "#29201D", "#5B3213", "#A76F42", "#89412E",
|
|
"#1A3A2A", "#494B5A", "#A88C85", "#F4ABAA", "#A3F3AB", "#00C6C8", "#EA8B66", "#958A9F",
|
|
"#BDC9D2", "#9FA064", "#BE4700", "#658188", "#83A485", "#453C23", "#47675D", "#3A3F00",
|
|
"#061203", "#DFFB71", "#868E7E", "#98D058", "#6C8F7D", "#D7BFC2", "#3C3E6E", "#D83D66",
|
|
|
|
];
|
|
|
|
// it needs for sending XSRF-Token in the form to the server
|
|
function getAntiXSRFRequest(url, data, tokenFieldId) {
|
|
var tokenField = null;
|
|
if (tokenFieldId && tokenFieldId.length && tokenFieldId.val)
|
|
tokenField = tokenFieldId;
|
|
else {
|
|
tokenFieldId = tokenFieldId || '__RequestVerificationToken';
|
|
tokenField = $('input[name=' + tokenFieldId + ']');
|
|
}
|
|
if (tokenField.length == 0) {
|
|
throw 'There is no token field with id: ' + tokenFieldId;
|
|
return null;
|
|
}
|
|
return {
|
|
method: 'POST',
|
|
url: url,
|
|
contentType: 'application/json; charset=utf-8',
|
|
data: JSON.stringify({ model: data }),
|
|
dataType: 'JSON',
|
|
headers: {
|
|
"__RequestVerificationToken": tokenField.val()
|
|
}
|
|
};
|
|
}
|
|
function compileDynamicAngularHtml(container) {
|
|
var injector = $('[ng-app]').injector();
|
|
injector.invoke([
|
|
"$compile", "$rootScope", function ($compile, $rootScope) {
|
|
$compile(container)($rootScope);
|
|
$rootScope.$apply();
|
|
}
|
|
]);
|
|
}
|
|
function destroyAngularForm(event) {
|
|
if (!event)
|
|
return;
|
|
|
|
var controllers = angular.element(event.currentTarget).find('[ng-controller]');
|
|
for (var i = 0; i < controllers.length; i++) {
|
|
if (angular.isElement(controllers[i])) {
|
|
var scope = angular.element(controllers[i]).scope();
|
|
if (!!scope)
|
|
scope.$destroy();
|
|
}
|
|
}
|
|
}
|
|
function triggerBroadcastFromRootScope(eventName, eventData) {
|
|
if (!eventName || !eventData)
|
|
return;
|
|
|
|
var injector = $('[ng-app]').injector();
|
|
if (!injector)
|
|
return;
|
|
|
|
var rootScope = injector.get('$rootScope');
|
|
if (!rootScope)
|
|
return;
|
|
|
|
rootScope.$broadcast(eventName, eventData);
|
|
}
|
|
|
|
function CalculateMonthSpread(graphId, data) {
|
|
if (!data) return 1;
|
|
if (data.length == 0) return 1;
|
|
var length = data.length; //number of x data points
|
|
if (data[data.length - 1][0] - data[0][0] < 31449600000) length = length / 4.33; //if period less then a year we just draw months weekly, if over - we display years by months
|
|
if (length < 13) return 1; //do not toch rerids for less then a year
|
|
var width = $('#' + graphId).width();
|
|
var mult = 50 / ((width - 100) / length); // divide desired length of average label by length of actual
|
|
return Math.ceil(mult);
|
|
}
|
|
|
|
function formatDateRange(startDate, endDate, includeBoth) {
|
|
startDate = new Date(startDate);
|
|
endDate = new Date(endDate);
|
|
if ((startDate.getTime() || 0) <= 0 || (endDate.getTime() || 0) <= 0)
|
|
return '';
|
|
|
|
var totalDays = Math.ceil(Math.max((endDate - startDate) / (1000 * 60 * 60 * 24), 0)) + (includeBoth && (endDate >= startDate) ? 1 : 0);
|
|
var weeks = Math.floor((totalDays / 7.0));
|
|
var days = totalDays % 7;
|
|
|
|
var weeksFormat = '',
|
|
daysFormat = days + ' day' + (days > 1 ? 's' : '');
|
|
|
|
if (weeks > 0) {
|
|
weeksFormat = weeks + ' wk' + (weeks > 1 ? 's' : '');
|
|
if (days <= 0)
|
|
daysFormat = '';
|
|
}
|
|
|
|
return (weeksFormat + ' ' + daysFormat).trim();
|
|
}
|
|
function formatUniversalDate(date) {
|
|
return date.getFullYear() + "-" + (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1) + "-" + (date.getDate() < 10 ? '0' : '') + date.getDate();
|
|
}
|
|
|
|
function addDaysToDate(date, days) {
|
|
date = new Date(date);
|
|
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
};
|
|
function isGuidEmpty(guid) {
|
|
if (!guid || typeof guid !== 'string')
|
|
return true;
|
|
|
|
return guid.replace(/0/g, '').replace(/-/g, '').trim().length <= 0;
|
|
};
|
|
function htmlEncode(text) {
|
|
return String(text)
|
|
.replace(/&/g, '&')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>');
|
|
}
|
|
function htmlDecode(text) {
|
|
return String(text)
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, "'")
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/&/g, '&');
|
|
}
|
|
function hideRedundantPopovers(container, currentBtn) {
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
var id = null;
|
|
if (currentBtn) {
|
|
if (currentBtn.is('[data-toggle="popover"]'))
|
|
id = currentBtn.attr('id');
|
|
else
|
|
id = currentBtn.closest('[data-toggle="popover"]').attr('id');
|
|
}
|
|
|
|
container.find('a.popover-warning:data(bs.popover)' + (!!id ? ('[id!="' + id + '"]') : '')).popover('destroy');
|
|
}
|
|
function checkBrowser() {
|
|
|
|
var userAgent = window.navigator.userAgent;
|
|
var browsers = { chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i, ie1: /trident/i };
|
|
|
|
for (var key in browsers) {
|
|
if (browsers[key].test(userAgent)) {
|
|
return key;
|
|
}
|
|
};
|
|
|
|
return 'unknown';
|
|
}
|
|
function getUniqueColor(idx, usedColors) {
|
|
var palette = PixelAdmin.settings.consts.COLORS;
|
|
if (palette.length < 1)
|
|
return null;
|
|
if (palette.length == 1)
|
|
return palette[0];
|
|
var clr;
|
|
for (var i = idx; i < palette.length; i++) {
|
|
clr = palette[i % (palette.length - 1)];
|
|
if (usedColors.indexOf(clr) < 0) {
|
|
usedColors.push(clr);
|
|
break;
|
|
}
|
|
}
|
|
return clr;
|
|
}
|
|
function handleAjaxResponse(result, successCallback, errorCallback, finalCallback, form, prefix) {
|
|
var resultStatus = result != null ? result.Status : undefined;
|
|
if (resultStatus) {
|
|
if (successCallback)
|
|
successCallback(result);
|
|
|
|
// hide summary validation messages
|
|
form.find("[data-valmsg-summary=true]")
|
|
.addClass("validation-summary-valid")
|
|
.removeClass("validation-summary-errors");
|
|
} else {
|
|
var errors = result != null && result.Errors ? result.Errors : undefined;
|
|
displayValidationErrors(errors, form, prefix);
|
|
if (errorCallback) {
|
|
errorCallback(result);
|
|
}
|
|
}
|
|
}
|
|
function displayValidationErrors(errors, form, prefix) {
|
|
if (!errors)
|
|
return;
|
|
var $form = form;
|
|
var $ul = $form.find("[data-valmsg-summary=true] > ul");
|
|
var $validator = $form.validate();
|
|
var fldErrors = {};
|
|
var generalErrors = [];
|
|
$ul.empty();
|
|
$.each(errors, function (idx, error) {
|
|
if (error.ErrorMessages) {
|
|
$.each(error.ErrorMessages, function (msgIdx, msg) {
|
|
if (!msg || msg.length == 0)
|
|
return;
|
|
$ul.append('<li>' + msg + '</li>');
|
|
if (error.FieldName) {
|
|
var fieldName = prefix ? error.FieldName.substring(prefix.length) : error.FieldName;
|
|
if ($form.find('[name="'+ fieldName + '"]').length)
|
|
fldErrors[fieldName] = msg;
|
|
else
|
|
generalErrors.push(msg);
|
|
} else {
|
|
generalErrors.push(msg);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
if (Object.keys(fldErrors).length > 0) {
|
|
// force to mark fields as invalid and display field validation messages
|
|
$validator.showErrors(fldErrors);
|
|
}
|
|
$form.find("[data-valmsg-summary=true]")
|
|
.addClass("validation-summary-errors")
|
|
.removeClass("validation-summary-valid");
|
|
}
|
|
function pageReload() {
|
|
var url = document.location.href;
|
|
var hashPos = url.indexOf('#');
|
|
if (hashPos > 0)
|
|
url = url.substr(0, hashPos);
|
|
document.location.href = url;
|
|
}
|
|
function reloadDataTable(tableSelector) {
|
|
// refresh data in the table without reseting of user's current page
|
|
$(tableSelector).DataTable().ajax.reload(null, false);
|
|
};
|
|
|
|
/* ======= Date conversion function ======== */
|
|
function DateTimeConverter() {
|
|
}
|
|
|
|
DateTimeConverter.msFormatAsLocalString = function (dateUtcMilliseconds) {
|
|
if (!dateUtcMilliseconds || !$.isNumeric(dateUtcMilliseconds))
|
|
throw "DateTimeConverter: Unable to convert UTC milliseconds to local date string (value: " + dateUtcMilliseconds + ")";
|
|
|
|
var localDate = new Date(dateUtcMilliseconds);
|
|
if (isNaN(localDate.getTime()))
|
|
throw "DateTimeConverter: Argument " + dateUtcMilliseconds + " is not valid date";
|
|
|
|
var year = localDate.getFullYear();
|
|
var month = localDate.getMonth() + 1;
|
|
var day = localDate.getDate();
|
|
var result =
|
|
(month > 9 ? String(month) : '0' + String(month)) + '/' +
|
|
(day > 9 ? String(day) : '0' + String(day)) + '/' +
|
|
String(year);
|
|
|
|
return result;
|
|
};
|
|
DateTimeConverter.msFormatAsUtcString = function (dateUtcMilliseconds) {
|
|
if (!dateUtcMilliseconds || !$.isNumeric(dateUtcMilliseconds))
|
|
throw "DateTimeConverter: Unable to convert UTC milliseconds to date string (value: " + dateUtcMilliseconds + ")";
|
|
|
|
var date = new Date(dateUtcMilliseconds);
|
|
if (isNaN(date.getTime()))
|
|
throw "DateTimeConverter: Argument " + dateUtcMilliseconds + " is not valid date";
|
|
|
|
var year = date.getUTCFullYear();
|
|
var month = date.getUTCMonth() + 1;
|
|
var day = date.getUTCDate();
|
|
var result =
|
|
(month > 9 ? String(month) : '0' + String(month)) + '/' +
|
|
(day > 9 ? String(day) : '0' + String(day)) + '/' +
|
|
String(year);
|
|
|
|
return result;
|
|
};
|
|
DateTimeConverter.msToUtcDate = function (dateAsMs) {
|
|
if (!dateAsMs || !$.isNumeric(dateAsMs) || (Number(dateAsMs) < 0))
|
|
throw "DateTimeConverter: Unable to convert UTC milliseconds to UTC date. Incoming value is invalid";
|
|
|
|
var date = new Date(Number(dateAsMs));
|
|
var utcYear = date.getUTCFullYear();
|
|
var utcMonth = date.getUTCMonth();
|
|
var utcDay = date.getUTCDate();
|
|
|
|
var result = new Date(utcYear, utcMonth, utcDay);
|
|
return result;
|
|
};
|
|
DateTimeConverter.msToLocalDate = function (dateAsMs) {
|
|
if (!dateAsMs || !$.isNumeric(dateAsMs) || (Number(dateAsMs) < 0))
|
|
throw "DateTimeConverter: Unable to convert UTC milliseconds to local date. Incoming value is invalid";
|
|
|
|
var result = new Date(Number(dateAsMs));
|
|
return result;
|
|
};
|
|
DateTimeConverter.stringToMs = function (localDateAsText) {
|
|
if (!localDateAsText || (localDateAsText.length < 6) || ((new Date(localDateAsText)).getTime() < 1))
|
|
throw "DateTimeConverter: Unable to convert local string date to local milliseconds. Incoming value is invalid";
|
|
|
|
var localDate = new Date(localDateAsText);
|
|
var year = localDate.getFullYear();
|
|
var month = localDate.getMonth();
|
|
var day = localDate.getDate();
|
|
|
|
var result = Date.UTC(year, month, day);
|
|
return result;
|
|
};
|
|
DateTimeConverter.dateToMs = function (localDateAsDate) {
|
|
if (!localDateAsDate || isNaN(localDateAsDate.getTime()))
|
|
throw "DateTimeConverter: Unable to convert local date to UTC milliseconds. Incoming date value is invalid";
|
|
|
|
var utcYear = localDateAsDate.getUTCFullYear();
|
|
var utcMonth = localDateAsDate.getUTCMonth();
|
|
var utcDay = localDateAsDate.getUTCDate();
|
|
|
|
var result = Date.UTC(utcYear, utcMonth, utcDay);
|
|
return result;
|
|
};
|
|
|
|
DateTimeConverter.jsonDateToMs = function (jsonDate) {
|
|
if (!jsonDate || typeof jsonDate !== 'string')
|
|
throw "DateTimeConverter: Unable to convert jsonDate to milliseconds. Incoming value is invalid";
|
|
|
|
var d = /\/Date\((\d*)\)\//.exec(jsonDate);
|
|
var date = (d) ? new Date(+d[1]) : jsonDate;
|
|
return DateTimeConverter.dateToMs(date);
|
|
}
|
|
|
|
DateTimeConverter.getUtcNowMs = function () {
|
|
var localNow = new Date();
|
|
var utcYear = localNow.getUTCFullYear();
|
|
var utcMonth = localNow.getUTCMonth();
|
|
var utcDay = localNow.getUTCDate();
|
|
var utcHours = localNow.getUTCHours();
|
|
var utcMinutes = localNow.getUTCMinutes();
|
|
var utcSeconds = localNow.getUTCSeconds();
|
|
|
|
var result = Date.UTC(utcYear, utcMonth, utcDay, utcHours, utcMinutes, utcSeconds);
|
|
return result;
|
|
};
|
|
DateTimeConverter.getLocalNowMs = function () {
|
|
var localNow = new Date();
|
|
var result = localNow.getTime();
|
|
return result;
|
|
};
|
|
Object.values = function (obj) {
|
|
if (!obj || (typeof obj !== 'object')) {
|
|
return [];
|
|
}
|
|
|
|
var values = [];
|
|
for (var key in obj) {
|
|
values.push(obj[key]);
|
|
}
|
|
|
|
return values;
|
|
};
|
|
Object.keysInObject = function (keys, obj) {
|
|
if (!keys || !keys.length) {
|
|
throw 'keys collection is empty';
|
|
}
|
|
|
|
if (!obj || (typeof obj !== 'object')) {
|
|
return false;
|
|
}
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
if (!(keys[i] in obj)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
Object.parseBoolean = function (value) {
|
|
if (value == null || value == undefined) {
|
|
return false;
|
|
}
|
|
|
|
if (typeof value === 'boolean') {
|
|
return value;
|
|
}
|
|
|
|
return value.toLowerCase() === 'true';
|
|
};
|
|
Math.quantityPrecision = 1000000;
|
|
Math.costPrecision = 10000;
|
|
Math.roundQuantity = function (value, decimals) {
|
|
var denominator = decimals == null ? Math.quantityPrecision : (10*decimals);
|
|
return Math.round(value * denominator) / denominator;
|
|
};
|
|
Math.roundCost = function (value) {
|
|
return Math.round(value * Math.costPrecision) / Math.costPrecision;
|
|
};
|
|
/* ======= Number distribution along array items ======== */
|
|
function calculateDistribution() {}
|
|
// sums values of "sourceValues" array for the specified index range "targetIndexes"
|
|
calculateDistribution.calculateSumOnRange = function (sourceValues, targetIndexes) {
|
|
if (!sourceValues || !sourceValues.length || !targetIndexes || !targetIndexes.length) {
|
|
return 0;
|
|
}
|
|
var result = 0;
|
|
for (var i = 0; i < targetIndexes.length; i++) {
|
|
result += (sourceValues[targetIndexes[i]] || 0);
|
|
}
|
|
return result;
|
|
};
|
|
// distributes provided "total" value between sourceValues array values with the specified index range "targetIndexes"
|
|
calculateDistribution.distributeValue = function (sourceValues, targetIndexes, total, decimals) {
|
|
if (!sourceValues || !sourceValues.length) {
|
|
return null;
|
|
}
|
|
|
|
// if targetIndexes collection is not passed we need to align total on all sourceValues collection
|
|
targetIndexes = targetIndexes || Array.apply(null, { length: sourceValues.length }).map(Number.call, Number);
|
|
var result = {};
|
|
var oldTotal = Math.roundQuantity(this.calculateSumOnRange(sourceValues, targetIndexes) || 0);
|
|
var newTotal = parseFloat(total) || 0;
|
|
|
|
var distributedNewValue = 0;
|
|
var lastIndex = targetIndexes[targetIndexes.length - 1];
|
|
|
|
if (oldTotal == 0) {
|
|
var newValue = Math.roundQuantity(newTotal / targetIndexes.length, decimals);
|
|
|
|
for (var i = 0; i < targetIndexes.length - 1; i++) {
|
|
// Example: we need to distribute 0.000002 between 4 cells.
|
|
// newValue will be 0.000002 / 4 = 0.0000005 ~ 0.000001
|
|
// if we distribute this value in targetIndexes.length - 1 cells (3) we get distributedNewValue = 0.000003
|
|
// and -0.000001 in the last cell: newTotal - distributedNewValue = (0.000002 - 0.000003)
|
|
// so we should check over allocation and break distribution
|
|
var tempResult = Math.roundQuantity(distributedNewValue + newValue, decimals);
|
|
if (tempResult <= newTotal) {
|
|
result[targetIndexes[i]] = newValue;
|
|
distributedNewValue = tempResult;
|
|
}
|
|
else {
|
|
lastIndex = targetIndexes[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
var factor = newTotal / oldTotal;
|
|
var distributedOldValue = 0;
|
|
|
|
for (var i = 0; i < targetIndexes.length - 1; i++) {
|
|
var oldValue = (sourceValues[targetIndexes[i]] || 0);
|
|
var newValue = Math.roundQuantity(oldValue * factor, decimals);
|
|
|
|
distributedOldValue = Math.roundQuantity(distributedOldValue + oldValue, decimals);
|
|
// example: passed 31 cells, but only 5 of them have values; so we should affect only these cells
|
|
if (distributedOldValue == oldTotal) {
|
|
lastIndex = targetIndexes[i];
|
|
break;
|
|
}
|
|
else {
|
|
result[targetIndexes[i]] = newValue;
|
|
distributedNewValue = Math.roundQuantity(distributedNewValue + newValue, decimals);
|
|
}
|
|
}
|
|
}
|
|
|
|
result[lastIndex] = Math.roundQuantity(newTotal - distributedNewValue, decimals);
|
|
|
|
return result;
|
|
};
|
|
(function ($) {
|
|
$.extend($.fn, {
|
|
busyIndicator: function (c) {
|
|
b = $(this);
|
|
var d = b.find(".k-loading-mask");
|
|
c ? d.length || (d = $("<div class='k-loading-mask'><span class='k-loading-text'>Loading...</span><div class='k-loading-image'/><div class='k-loading-color'/></div>").width(b.outerWidth()).height(b.outerHeight()).prependTo(b)) : d && d.remove()
|
|
}
|
|
});
|
|
})($);
|
|
|
|
HandleSSOAjaxReAuth = function ($xhr, retrycallBackfn, _retryCounter) {
|
|
if ($xhr.responseText && _retryCounter <=5) {
|
|
var newWindow = window.open('/Account/ssoAuthRefresh', 'ssoRefresh', "height=200,width=400,status=yes,toolbar=no,menubar=no,location=no");
|
|
setTimeout(retrycallBackfn, 5000);
|
|
} else {
|
|
//log the error message/display oops error
|
|
console.log("Failed ajax call for datarefresh!");
|
|
}
|
|
} |