{"version":3,"file":"tios.js","names":["tios","_u","_f","_o","_localStorage","_sessionStorage","jQ","jQuery","vars","$","cdn","blob","version","isTouchScreen","isMobile","isMac","debug","is","util","utility","contextWindow","log","console","bind","window","warn","regexIso8601","regexEmail","regexEmailDelimited","regexPhone","regexPostcode","regexPassword","regexNonEmpty","regexSearchClean","titles","getGuid","d","Date","getTime","replace","c","r","Math","random","floor","toString","getRegexSearch","searchString","splitsearch","trim","split","map","x","join","RegExp","replaceRegexGroups","originalString","regexGroups","replacement","result","forEach","item","idx","match","offset","string","opt","charAt","getShortRandomString","substr","getApplicationWindow","currentWindow","tiosName","parent","appWindow","top","absUrl","relative","SiteUrl","cdnUrl","path","noversion","blobUrl","versionUrl","indexOf","goBack","history","back","clientTimeInfo","overridedate","time","adjustedTime","setHours","getHours","getMinutes","getSeconds","getMilliseconds","UTCString","JSON","stringify","getTimezoneOffset","dateOnly","dateTime","timeParam","localDateTime","dateIsNullOrMin","UTC","LocalOffset","mimeIcon","contentType","startsWith","find","enableByCss","element","$CurrentElement","length","removeAttr","removeClass","OnClick","attr","Href","$skin","parents","disableByCss","addClass","flagValuesString","val","enumerator","joinstring","proparray","prop","enumIsNullOrNoValue","Value","push","Description","arrayContainsEmptyProperty","list","property","some","stringIsJSON","test","arrayGroupBy","groupValueProperty","groupIdentifiers","Set","tmpList","listItem","add","items","filter","p","key","values","fillArray","start","increment","newarray","removeEmptyFromArray","arrayObject","Array","isArray","i","splice","addEmptyToArray","addFilteredListItem","newObject","filterProperty","filterValue","emptyProperty","deleteFilteredListItem","deleteObject","allowEmptyFilteredList","originalFilterValue","cycleMod","max","index","date","isNullOrUndefined","nullDate","NullDate","getUTCFullYear","getFullYear","guidIsNullOrEmpty","guid","EmptyGuid","enumValue","object","stringIsNullOrEmpty","htmlEntities","str","String","htmlEntitiesToText","convertDateStringsToDates","input","hasOwnProperty","value","this","milliseconds","parse","isNaN","UTCDateAsLocal","convertDatesFlaggedAsLocal","localDateAsUTC","dataContainsAsLocals","Object","keys","k","includes","getDDMMYY","dateObject","inUTC","newDate","getUTCDate","slice","getUTCMonth","getDate","getMonth","getSafeDateString","getSafeDate","dateString","dateArray","datesAreSameDay","date1","date2","datesAreSameYear","isBetweenDates","dateToSearch","startDate","endDate","timesAreSame","datetime1","datetime2","getDaysInMonth","anyDateInMonth","year","setUTCFullYear","setUTCMonth","setUTCDate","addMonths","months","adjusted","addDays","days","addHours","hours","setUTCHours","getUTCHours","addMinutes","minutes","setUTCMinutes","getUTCMinutes","addSeconds","seconds","setUTCSeconds","getUTCSeconds","addMilliseconds","setUTCMilliseconds","getUTCMilliseconds","timesOverlap","range1Start","range1End","range2Start","range2End","durationAZeroLength","durationBZeroLength","range1EndTime","range2EndTime","DateStart","DateEnd","tmpDate","localMidnightOnUTCDate","setTimeOnDate","getDateOnly","getHoursMinutes","ticks","minutesRemainder","ceil","totalMinutes","getHHMMString","hoursminutes","getHMString","keyIsNumber","evt","charCode","event","which","keyCode","formatBytes","bytes","precision","parseFloat","isFinite","number","pow","toFixed","formatNumberWithCommas","num","leadingZeros","stripToInt","integervalue","parseInt","isHtml","text","newlineToBr","plainToHtml","document","createElement","innerText","innerHTML","stripHTML","formatMoney","prefix","suffix","newval","formatInt","sender","callback","getOrdinal","parseFixedFloat","parseValue","places","escapeRegex","htmlToElement","html","template","content","firstChild","htmlToElements","childNodes","objectToArray","srcObject","predicate","newArray","getQueryString","default_","qs","exec","location","href","parseQuery","preserveCase","search","part","first","second","s","s_length","query","decodeURIComponent","toLowerCase","objectToURI","obj","encodeURIComponent","buildParams","parameterObject","parameterString","pair","createCORSRequest","method","url","xhr","XMLHttpRequest","open","withCredentials","sendCookies","XDomainRequest","addListener","type","addEventListener","attachEvent","addListeners","elementCollection","len","_storageIsAvailable","selectStorage","useSession","getStorage","storageAvailable","storageType","storage","setItem","removeItem","e","saveToStorage","saveObject","getFromStorage","retVal","getItem","tmpRetVal","removeFromStorage","clearStorage","clear","hooksvg","elementID","svgdoc","svgwin","getElementById","contentDocument","getSVGDocument","exception","defaultView","getWindow","triggerSVG","targetDataSvgName","allowAnimation","noErrorOnUnnamed","data","svgname","specificfound","objectElements","querySelectorAll","el","injectSVG","inputData","objectElement","_this","enableAnimation","isVisible","svgElement","loadTriggered","loadCallback","setgauge","bindings","svgBindings","onload","svgElementtmp","hasrect","offsetWidth","offsetHeight","getClientRects","style","getComputedStyle","opacity","display","visibility","timers","TIOSTimeout","name","fn","interval","scope","args","self","id","setTimeout","apply","arguments","prototype","cleared","clearTimeout","TIOSInterval","setInterval","clearInterval","getGlyph","glyph","glyphs","getSymbol","symbol","getClientSize","w","documentElement","g","getElementsByTagName","width","innerWidth","clientWidth","height","innerHeight","clientHeight","addToTiosBar","$tiosbar","$content","append","arrayContainedBy","searchFor","inArray","every","arrayContentsMatch","array1","array2","equalsAny","equalsAll","arg","firstFreeIndex","oneBased","freeIndex","sort","y","currentValue","sortBy","arr","reverse","numeric","sort_by","field","rev","primer","a","b","toUpperCase","deepFreeze","getOwnPropertyNames","freeze","areSharedPropertiesEqual","isEqual","getPropertyByPath","defaultValue","setPropertyByPath","nestedRef","fileDialog","_changeEvent","multiple","setAttribute","undefined","accept","Promise","resolve","reject","inputEvent","files","lastArg","removeEventListener","click","getFileUrl","contentBytes","contentIsB64","btoa","fromCharCode","Uint8Array","windowUrl","URL","webkitURL","mozURL","msURL","openLink","hrefOrBlob","filename","fromFile","anchor","target","createObjectURL","download","fileDownload","contentLength","byteLength","useCreateObjectUrl","Blob","atob","revokeObjectURL","sleepUntil","f","checkInterval","timeoutMs","timeWas","wait","draw","running","queue","methodname","context","duration","methodimplementation","remove","tag","startTime","animStart","stop","startAll","stopAll","execute","count","contextcount","currentTime","requestAnimFrame","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","oRequestAnimationFrame","msRequestAnimationFrame","animateID","animLoop","animStop","cancelAnimationFrame","assign","defineProperty","enumerable","configurable","writable","TypeError","to","nextSource","keysArray","nextIndex","nextKey","desc","getOwnPropertyDescriptor","position","endsWith","subjectString","lastIndex","thisArg","call","angular","tiosModule","module","constant"],"sources":["jscript/tios.js"],"mappings":"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","sourcesContent":["var tios = tios || {};\r\n\r\n(function () {\r\n var _u = 'undefined';\r\n var _f = 'function';\r\n var _o = 'object';\r\n var _n = 'number';\r\n\r\n var _localStorage = 'localStorage';\r\n var _sessionStorage = 'sessionStorage';\r\n\r\n var jQ = jQ || false;\r\n if (typeof jQuery !== _u) {\r\n jQ = jQuery;\r\n }\r\n\r\n tios.vars = (function (vars, $) {\r\n vars.cdn = null; //global for clientside cdn\r\n vars.blob = null;// Blob storage for clientside reference\r\n vars.version = null; //global for clientside cdn version\r\n vars.isTouchScreen = function () { return false; }; //global for touchscreen status\r\n vars.isMobile = false; //global for whether we're on a mobile\r\n vars.isMac = false; //global for whether we're on a mac\r\n vars.debug = false;//Whether to show debug messages\r\n\r\n //Check if jquery exists, if so patch the jquery dependent functions\r\n if (typeof $ !== _u) {\r\n vars.isTouchScreen = function () { return $('html').is('.touch'); };\r\n }\r\n\r\n return vars;\r\n\r\n }(tios.vars || {}, jQ));\r\n\r\n tios.util = (function (utility, $, contextWindow) {\r\n\r\n // Bind console logging - disable this in the JS generated by c# if set to false by setting to function(){};\r\n utility.log = console.log.bind(window.console);\r\n utility.debug = console.debug.bind(window.console);\r\n utility.warn = console.warn.bind(window.console);\r\n\r\n // Return the value of tios.vars.isMobile and\r\n // tios.vars.isMac to the front end.\r\n utility.isMobile = function () { return tios.vars.isMobile };\r\n utility.isMac = function () { return tios.vars.isMac };\r\n\r\n //tios.util = (function (utility, $) {\r\n\r\n // Date validity regex\r\n utility.regexIso8601 = /^((\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z?))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z?))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z?)))$/;//Deane added optional Z and outer brackets to make sure only the whole string matches.\r\n\r\n // WARNING when using angular patterns, these must be passed as strings, otherwise they act as regex objects. (hence escaping slashes)\r\n // Email matching regex *string* \r\n // Remember that the string variants need \\ escaping to \\\\\r\n // This one doesn't work with single character subdomains\r\n //utility.regexEmail = \"[0-9a-zA-Z][a-zA-Z0-9_.'+-]+@([0-9a-zA-Z][-\\\\w]*[0-9a-zA-Z]\\\\.)+[a-zA-Z]{2,}$\"; // Commented as would not allow single character subdomain\r\n\r\n utility.regexEmail = '^[0-9a-zA-Z]+[a-zA-Z0-9_.\\'+\\\\-]*@([0-9a-zA-Z\\\\-\\\\w]*[0-9a-zA-Z]\\\\.)+[a-zA-Z]{2,}$';\r\n\r\n // Capture a semicolon delimited email address (group). Each email address comes back as a separate capture group\r\n utility.regexEmailDelimited = '^([0-9a-zA-Z]+[a-zA-Z0-9_.\\'+\\\\-]*@(?:[0-9a-zA-Z\\\\-\\\\w]*[0-9a-zA-Z]\\\\.)+[a-zA-Z]{2,})(?:\\\\s*[;.]\\\\s*([0-9a-zA-Z]+[a-zA-Z0-9_.\\'+\\\\-]*@(?:[0-9a-zA-Z\\\\-\\\\w]*[0-9a-zA-Z]\\\\.)+[a-zA-Z]{2,}))*$';\r\n\r\n utility.regexPhone = '^[+\\\\-()\\\\s0-9]+?$';\r\n\r\n utility.regexPostcode = '^(GIR 0AA|[a-pr-uwyzA-PR-UWYZ]([a-hk-yA-HK-Y]([0-9][a-zA-Z]?|[1-9][0-9])|[1-9]([0-9]|[a-hjkpstuwA-HJKPSTUW])?) ?[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2})$';\r\n\r\n // Password matching pattern (must contain 1 lowercase letter, 1 uppercase letter, 1 digit and be at least 6 characters long)\r\n utility.regexPassword = '^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,}$';\r\n\r\n utility.regexNonEmpty = '\\\\S+';// Any non-whitespace characters - use for required fields that shouldn't have spaces\r\n\r\n utility.regexSearchClean = /[^\\d\\w]+/gi; // Regex for cleaning input of list searches (removes non-digit/word characters)\r\n\r\n utility.titles = ['Mr', 'Mrs', 'Miss', 'Ms', 'Dr', 'Prof', 'Rev', 'Maj', 'Col', 'Sir', 'Dame', 'Lord', 'Lady'];\r\n\r\n utility.getGuid = function () {\r\n var d = new Date().getTime();\r\n var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\r\n var r = (d + Math.random() * 16) % 16 | 0;\r\n d = Math.floor(d / 16);\r\n return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);\r\n });\r\n return uuid;\r\n };\r\n\r\n utility.getRegexSearch = function (searchString) {\r\n // Generates a regex containing match groups for every separate segment (anything separated by\r\n // the characters removed by the cleaning regex\r\n // eg: /(a)(?:.*?)(b)/i \r\n // We don't use global, otherwise it will return only one search group rather than multiples\r\n var splitsearch = searchString.replace(utility.regexSearchClean, ' ').trim(' ').split(' ').map(x => '(' + x + ')').join('(?:.*?)');\r\n\r\n return new RegExp(splitsearch, 'i');\r\n };\r\n\r\n // Pass in the original search string, the x.match(regex) groups array, and the seach replacement eg $&\r\n // the $& is the current found item in the replacement string. If the matchgroup is null, replace the whole input\r\n utility.replaceRegexGroups = function (originalString, regexGroups, replacement) {\r\n\r\n var result = originalString;\r\n if (regexGroups != null) {\r\n regexGroups.forEach(function (item, idx) {\r\n // Don't process on the first item, as this will contain the entire matched group from start to end,\r\n // whereas we want to replace the individual groups\r\n if (idx > 0) {\r\n result = result.replace(new RegExp(item, 'gi'), function (match, offset, string) {\r\n // Replacer function to ignore tags.\r\n var opt = match;\r\n // If the current matched string is not enclosed in angle brackets\r\n // i.e. the position of the match (offset) within the string is not\r\n // immediately preceeded and followed by < and > run the replace\r\n // as normal, otherwise return the match without replacing.\r\n if (string.charAt(offset - 1) !== '<' &&\r\n string.charAt(offset + 1) !== '>') {\r\n opt = match.replace(match, replacement);\r\n }\r\n return opt;\r\n });\r\n }\r\n });\r\n } else {\r\n result = result.replace(new RegExp(originalString, 'gi'), replacement);\r\n }\r\n\r\n return result;\r\n };\r\n\r\n utility.getShortRandomString = function () {\r\n // based on https://gist.github.com/gordonbrander/2230317\r\n // Math.random should be unique because of its seeding algorithm.\r\n // Convert it to base 36 (numbers + letters), and grab the first 9 characters\r\n // after the decimal.\r\n return Math.random().toString(36).substr(2, 9);\r\n }\r\n\r\n utility.getApplicationWindow = function (currentWindow) {\r\n // NB if using plnkr, just return window here\r\n if (!currentWindow) {//first call will hae currentWindow undefined\r\n currentWindow = window;\r\n if (tios.vars.debug) utility.log('no window passed');\r\n }\r\n\r\n if (currentWindow.tiosName === 'application') {\r\n if (tios.vars.debug) { utility.log('found application window'); utility.log(currentWindow); }\r\n return currentWindow;\r\n } else {\r\n if (currentWindow.parent != currentWindow) {//has a parent window\r\n if (tios.vars.debug) utility.log('drilling into parent');\r\n return utility.getApplicationWindow(currentWindow.parent);\r\n } else {\r\n if (tios.vars.debug) utility.log('applcation window not found');\r\n return null;\r\n }\r\n }\r\n };;\r\n\r\n utility.appWindow = utility.getApplicationWindow() || window.top; //used to just refer to window.top\r\n\r\n // Return an absolute URL from a passed relative URL.\r\n utility.absUrl = (relative => vars.SiteUrl + relative);\r\n\r\n utility.cdnUrl = function (path, noversion) {//path must be without a leading slash\r\n\r\n if (!path) {\r\n //utility.log('path:', path);\r\n return null;\r\n } else if (path === '/') {\r\n return tios.vars.cdn;\r\n } else {\r\n return tios.vars.cdn + path + (noversion ? '' : \"?v=\" + tios.vars.version);\r\n }\r\n };\r\n\r\n utility.blobUrl = function (path, noversion) {//path must be without a leading slash\r\n\r\n if (!path) {\r\n //utility.log('path:', path);\r\n return null;\r\n } else {\r\n return tios.vars.blob + path;\r\n }\r\n };\r\n\r\n utility.versionUrl = function (path) {//path must be without a leading slash\r\n return path + (path.indexOf('?') > -1 ? 'v=' : \"?v=\") + tios.vars.version;\r\n };\r\n\r\n utility.goBack = function () {\r\n window.history.back();\r\n };\r\n\r\n utility.clientTimeInfo = function (overridedate) {\r\n var time = new Date();\r\n var adjustedTime = new Date(time);\r\n\r\n if (typeof overridedate !== _u && overridedate !== null) {\r\n adjustedTime = new Date(new Date(overridedate).setHours(time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()));\r\n }\r\n\r\n return {\r\n UTCString: JSON.stringify(adjustedTime),\r\n offset: adjustedTime.getTimezoneOffset(),\r\n dateOnly: new Date(new Date(adjustedTime).setHours(0, 0, 0, 0)),\r\n dateTime: adjustedTime\r\n };\r\n };\r\n\r\n // Retrieve the time and time offset as an object\r\n utility.timeParam = function (localDateTime) {\r\n if (!utility.dateIsNullOrMin(localDateTime)) {\r\n return {\r\n UTC: localDateTime,\r\n LocalOffset: localDateTime.getTimezoneOffset()\r\n };\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n utility.mimeIcon = function (contentType) {\r\n var xls = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.oasis.opendocument.spreadsheet'];\r\n var word = ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.oasis.opendocument.text']\r\n //utility.log('contentType', contentType);\r\n if (contentType.startsWith('image')) {\r\n return 'doc-image';\r\n } else if (contentType.startsWith('application/pdf')) {\r\n return 'doc-pdf';\r\n } else if (!!xls.find(function (item) { return item == contentType; })) {\r\n return 'doc-xls';\r\n } else if (!!word.find(function (item) { return item == contentType; })) {\r\n return 'doc-word'\r\n } else {\r\n return 'doc-other';\r\n }\r\n };\r\n\r\n //Check if jquery exists, if so patch the jquery dependent functions\r\n if (typeof $ !== _u) {\r\n\r\n /*Client side enable/disable code */\r\n utility.enableByCss = function (element) {\r\n var $CurrentElement = $(element);\r\n if ($CurrentElement.length) {\r\n $CurrentElement.removeAttr('disabled');\r\n $CurrentElement.removeAttr('data-disabled');\r\n $CurrentElement.removeClass('disabled');\r\n\r\n var OnClick = $CurrentElement.attr('data-onclientclick');\r\n if (OnClick) {\r\n $CurrentElement.attr('onclick', OnClick);\r\n $CurrentElement.removeAttr('data-onclientclick');\r\n }\r\n\r\n var Href = $CurrentElement.attr('data-href');\r\n if (Href) {\r\n $CurrentElement.attr('href', Href);\r\n $CurrentElement.removeAttr('data-href');\r\n }\r\n\r\n var $skin = $CurrentElement.parents('.rfdSkinnedButton');\r\n if ($skin.length) {\r\n $skin.removeAttr('disabled');\r\n }\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n\r\n };\r\n\r\n utility.disableByCss = function (element) {\r\n var $CurrentElement = $(element);\r\n if ($CurrentElement.length) {\r\n $CurrentElement.attr('disabled', 'disabled');\r\n $CurrentElement.attr('data-disabled', 'true');\r\n $CurrentElement.addClass('disabled');\r\n\r\n var OnClick = $CurrentElement.attr('onclick');\r\n if (OnClick) {\r\n $CurrentElement.attr('data-onclientclick', OnClick);\r\n $CurrentElement.removeAttr('onclick');\r\n }\r\n\r\n var Href = $CurrentElement.attr('href');\r\n if (Href) {\r\n $CurrentElement.attr('data-href', Href);\r\n $CurrentElement.removeAttr('href');\r\n }\r\n\r\n var $skin = $CurrentElement.parents('.rfdSkinnedButton');\r\n if ($skin.length) {\r\n $skin.attr('disabled', 'true');\r\n }\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n };\r\n /* end Client side enable/disable code */\r\n }\r\n\r\n utility.flagValuesString = function (val, enumerator, joinstring) {\r\n var proparray = [];\r\n for (var prop in enumerator) {\r\n if (!utility.enumIsNullOrNoValue(prop) && (enumerator[prop].Value == (val & enumerator[prop].Value))) {\r\n proparray.push(enumerator[prop].Description);\r\n }\r\n }\r\n return proparray.join(joinstring);\r\n };\r\n\r\n //#region Array functions\r\n utility.arrayContainsEmptyProperty = function (list, property) {\r\n return list.some(//Check whether any of the entries matches this criteria\r\n function (item) {\r\n return item[property].trim().length === 0;//is the trimmed string's length zero\r\n }\r\n );\r\n };\r\n\r\n utility.stringIsJSON = function (string) {\r\n if (string.length && /^[\\],:{}\\s]*$/.test(string.replace(/\\\\[\"\\\\\\/bfnrtu]/g, '@').replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']').replace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {\r\n //the json is ok\r\n return true;\r\n } else {\r\n //the json is not ok\r\n return false;\r\n }\r\n };\r\n\r\n /* //Future variation that uses arrow functions\r\n utility.arrayContainsEmptyProperty = function (list, property) {\r\n return list.some( item => item[property].trim().length === 0); //Check whether any of the entries matches string length zero\r\n };\r\n */\r\n\r\n utility.arrayGroupBy = function (list, groupValueProperty) {\r\n //Returns array of {key:obj, values:[]}\r\n if (list && groupValueProperty && list.length) {\r\n\r\n var groupIdentifiers = new Set();\r\n var tmpList = [];\r\n //create list of groups\r\n for (var listItem of list) {\r\n groupIdentifiers.add((listItem[groupValueProperty] instanceof Date ? listItem[groupValueProperty].getTime() : listItem[groupValueProperty]));//if it's a date, using getTime so that the identifier is an int rather than reference to date object (which would be unique)\r\n }\r\n\r\n groupIdentifiers.forEach(function (item) {\r\n //retrieve a list of prospect entries for each group\r\n var items = list.filter(function (p) {\r\n //Again, comparing getTime if this is a date\r\n return (p[groupValueProperty] instanceof Date ? p[groupValueProperty].getTime() : p[groupValueProperty]) === item;\r\n });\r\n //If there are entries found for the group (there should always be), add the list of items to the new group object\r\n //along with the labels\r\n tmpList.push({\r\n key: items[0][groupValueProperty],\r\n values: items\r\n });\r\n\r\n });\r\n\r\n return tmpList;\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n //Return a new array of numbers based on length, start, increment\r\n utility.fillArray = function (length, start, increment) {\r\n if (length < 1) return [];\r\n if (typeof increment === _u) increment = 1;\r\n var newarray = [];\r\n while (length--) {\r\n newarray[length] = start + (length * increment);\r\n }\r\n return newarray;\r\n };\r\n\r\n //Strip out empty strings from array\r\n utility.removeEmptyFromArray = function (arrayObject) { if (Array.isArray(arrayObject)) { for (var i = 0; i < arrayObject.length; i++) { if (arrayObject[i].length == 0) arrayObject.splice(i, 1); } } return arrayObject; };\r\n\r\n //Add an empty string if none exist in the array already\r\n utility.addEmptyToArray = function (arrayObject) {\r\n if (arrayObject && Array.isArray(arrayObject)) {\r\n if (arrayObject.length) { //if contains items\r\n for (var i of arrayObject) {//do not allow to continue if empty element present and return the original array\r\n if (i.length == 0) return arrayObject;\r\n }\r\n }\r\n arrayObject.push('');//adds an empty entry\r\n } else if (arrayObject == null) {//arrayobject null, so make an array from it\r\n arrayObject = [];\r\n arrayObject.push('');//adds an empty entry\r\n }\r\n\r\n return arrayObject;\r\n };\r\n\r\n //The two following functions operate on complex lists that can be filtered by a property, for example an enum that effectively separates a list into categories\r\n utility.addFilteredListItem = function (list, newObject, filterProperty, filterValue, emptyProperty) {\r\n //list - source array\r\n //newObject - object to add to array if empty one doesn't exist\r\n //filterProperty - property to filter by\r\n //filterValue - value for the filter property\r\n //emptyProperty - property to check against for emptiness\r\n\r\n newObject[filterProperty] = filterValue;//set the new Object's property to that which we wish to create\r\n if (!tios.util.arrayContainsEmptyProperty(list.filter(function (item) { return item[filterProperty] === filterValue }), emptyProperty)) list.push(newObject); //add if empty item not found\r\n };\r\n\r\n utility.deleteFilteredListItem = function (list, deleteObject, newObject, filterProperty, emptyProperty, allowEmptyFilteredList) {\r\n //the deleteObject's filterProperty is used to check the list for the existence of others with the deleted item's filterProperty value\r\n var originalFilterValue = deleteObject[filterProperty];\r\n\r\n //If there are there will be no [filterProperty: originalFilterValue] entries in this list after deletion, add one with the same filterProperty value in its place\r\n //placing in order prevents angular from believing the list to be different if an empty item is placed at the end after removing the last entry.\r\n if (!allowEmptyFilteredList && list.filter(function (item) { return item[filterProperty] == originalFilterValue }).length - 1 < 1) {\r\n newObject[filterProperty] = originalFilterValue;\r\n //replace deleteObject with the newObject\r\n list.splice(list.indexOf(deleteObject), 1, newObject);\r\n //addFilteredListItem(list, newObject, filterProperty, originalFilterValue, emptyProperty);\r\n } else {\r\n //There will be items left that match the filtered criteria, or we don't care about empty filtered lists, so just delete this row\r\n list.splice(list.indexOf(deleteObject), 1);\r\n }\r\n };\r\n\r\n //#endregion Array functions\r\n\r\n //Modulo operator that allows reversing direction (negatives will cycle back through from the maximum)\r\n utility.cycleMod = function (max, index, increment) {\r\n return ((index + increment) % max + max) % max;\r\n };\r\n\r\n //date is either null or set to vars.NulLDate\r\n utility.dateIsNullOrMin = function (date) {\r\n if (utility.isNullOrUndefined(date) || typeof (date) === 'string' && date.length === 0) return true;\r\n date = new Date(date);//just in case date is a string date\r\n var nullDate = vars.NullDate;\r\n return (date.getTime() - nullDate.getTime() === 0 || date.getUTCFullYear() <= nullDate.getUTCFullYear() || date.getFullYear() <= nullDate.getFullYear());\r\n };\r\n\r\n //guid is either null or empty guid\r\n utility.guidIsNullOrEmpty = function (guid) {\r\n return utility.isNullOrUndefined(guid) || guid.length === 0 || guid === vars.EmptyGuid;\r\n };\r\n\r\n utility.enumIsNullOrNoValue = function (enumValue) {\r\n return utility.isNullOrUndefined(enumValue) || !enumValue || enumValue === 'NoValue';\r\n };\r\n\r\n utility.isNullOrUndefined = function (object) {\r\n return (typeof (object) === _u || object === null);\r\n };\r\n\r\n utility.stringIsNullOrEmpty = function (string) {\r\n return utility.isNullOrUndefined(string) || string === false || string.length === 0 || !/\\S/.test(string);\r\n };\r\n\r\n //From: https://css-tricks.com/snippets/javascript/htmlentities-for-javascript/\r\n utility.htmlEntities = function (str) {\r\n return String(str).replace(/&/g, '&').replace(//g, '>').replace(/\"/g, '"');\r\n };\r\n\r\n utility.htmlEntitiesToText = function (str) {\r\n return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '\"');\r\n };\r\n\r\n //#region date manipulation\r\n\r\n //from: http://aboutcode.net/2013/07/27/json-date-parsing-angularjs.html\r\n //updated regex from: http://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime/3143231#3143231\r\n utility.convertDateStringsToDates = function (input) {\r\n //var regexIso8601 = /^(\\d{4}|\\+\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{1,})(Z|([\\-+])(\\d{2}):(\\d{2}))?)?)?)?$/;//incorrect original\r\n //reference: angular's date filter var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\r\n\r\n\r\n // Ignore things that aren't objects.\r\n if (typeof input !== \"object\") return input;\r\n\r\n for (var key in input) {\r\n // Skip if this property is not one set on the object (could be a prototype)\r\n if (!input.hasOwnProperty(key)) continue;\r\n\r\n var value = input[key];\r\n var match;\r\n // Check for string properties which look like dates.\r\n if (typeof value === \"string\" && (match = value.match(this.regexIso8601))) {\r\n var milliseconds = Date.parse(match[0]);\r\n if (!isNaN(milliseconds)) {\r\n input[key] = new Date(milliseconds);\r\n\r\n // Check whether the given property has an associated property _AsLocal\r\n // If so, cast this from utc to local (so the date, hours, minutes and seconds are the *same*, but local times)\r\n if (input.hasOwnProperty(key + '_AsLocal') && !!input[key + '_AsLocal']) {\r\n input[key] = utility.UTCDateAsLocal(input[key]);\r\n }\r\n\r\n }\r\n } else if (typeof value === \"object\") {\r\n // Recurse into object\r\n this.convertDateStringsToDates(value);\r\n }\r\n }\r\n };\r\n\r\n // In combination with the above, (for sending data) converts any dates\r\n // present in the data with an _AsLocal sibling into UTC equivalents\r\n // (local midnight = utc midnight etc.) and returns new output.\r\n // WARNING make sure to operate on a copy of the data, otherwise original\r\n // objects will be modified and could lead to dates creeping back and forth.\r\n utility.convertDatesFlaggedAsLocal = function (input) {\r\n\r\n // Ignore things that aren't objects.\r\n if (typeof input !== \"object\") return input;\r\n\r\n for (var key in input) {\r\n // Skip if this property is not one set on the object (could be a prototype)\r\n if (!input.hasOwnProperty(key)) continue;\r\n\r\n var value = input[key];\r\n //utility.log('value type', key, value, typeof value);\r\n\r\n // Check whether this object is a date\r\n if (value instanceof Date) {\r\n //utility.log('value is date', key, value);\r\n // Check whether the given property has an associated property _AsLocal\r\n // If so, cast this from local to UTC (so the date, hours, minutes and seconds are the *same*, but as UTC times)\r\n if (input.hasOwnProperty(key + '_AsLocal') && !!input[key + '_AsLocal']) {\r\n input[key] = utility.localDateAsUTC(input[key]);\r\n //utility.log('converting date local to utc', input[key]);\r\n }\r\n\r\n } else if (typeof value === \"object\") {\r\n // Recurse into object\r\n utility.convertDatesFlaggedAsLocal(value);\r\n }\r\n }\r\n };\r\n\r\n // Search through the object to find any properties ending with _AsLocal\r\n // if we find them, we should then process further (this stops other types of data getting munged)\r\n utility.dataContainsAsLocals = function (input) {\r\n var value;\r\n Object.keys(input).some(function (k) {\r\n if (k.includes('_AsLocal')) {\r\n value = true;\r\n return true;\r\n }\r\n if (input[k] && typeof input[k] === 'object') {\r\n value = utility.dataContainsAsLocals(input[k]);\r\n return value;\r\n }\r\n });\r\n return value;\r\n };\r\n\r\n //Return DD/MM/YY from date object\r\n utility.getDDMMYY = function (dateObject, inUTC) {\r\n var newDate = null;\r\n if (typeof dateObject == 'string') {\r\n newDate = new Date(dateObject);\r\n } else if (typeof dateObject == _o) {\r\n newDate = dateObject;\r\n }\r\n\r\n if (newDate) {\r\n if (inUTC) {\r\n return ('00' + newDate.getUTCDate()).slice(-2) + '/' + ('00' + (newDate.getUTCMonth() + 1)).slice(-2) + '/' + ('00' + newDate.getUTCFullYear()).slice(-2);\r\n } else {\r\n return ('00' + newDate.getDate()).slice(-2) + '/' + ('00' + (newDate.getMonth() + 1)).slice(-2) + '/' + ('00' + newDate.getFullYear()).slice(-2);\r\n }\r\n } else return null;\r\n };\r\n\r\n //These two prevent client-side date/timezone shifting\r\n utility.getSafeDateString = function (dateObject) {\r\n if (dateObject !== null) {\r\n return dateObject.getFullYear() + '-' + (dateObject.getMonth() + 1) + '-' + dateObject.getDate() + '-' + dateObject.getHours() + '-' + dateObject.getMinutes() + '-' + dateObject.getSeconds();/*JS month is zero indexed*/\r\n }\r\n else {\r\n return null;\r\n }\r\n };\r\n\r\n utility.getSafeDate = function (dateString) {\r\n if (dateString !== null) {\r\n var dateArray = dateString.split('-');\r\n return new Date(dateArray[0], dateArray[1] - 1, dateArray[2], dateArray[3], dateArray[4], dateArray[5]);\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n //are both dates on the same day (local dates)\r\n utility.datesAreSameDay = function (date1, date2) {\r\n // Do not use - if you have a midnight date in a timezone shifted region, it will set the time to midnight on the previous day.\r\n //var da = (date1 ? new Date(date1).setUTCHours(0, 0, 0, 0) : 0);\r\n //var db = (date2 ? new Date(date2).setUTCHours(0, 0, 0, 0) : 0);\r\n //return (da - db) === 0;\r\n \r\n //Compare the displayed dates' times - this will show different dates when comparing a midnight with a time in the day.\r\n if (!!date1 && !!date2) {\r\n return (date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear());\r\n } return false;\r\n\r\n };\r\n\r\n //are both dates in the same year\r\n utility.datesAreSameYear = function (date1, date2) {\r\n if (!!date1 && !!date2) {\r\n return (date1.getFullYear() === date2.getFullYear());\r\n } return false;\r\n };\r\n\r\n // Checks local dates\r\n utility.isBetweenDates = function (dateToSearch, startDate, endDate) {\r\n // If is either on start or end or between\r\n return utility.datesAreSameDay(dateToSearch, startDate) || utility.datesAreSameDay(dateToSearch, endDate) //Check whether the date falls on start or end of the range\r\n ||\r\n (dateToSearch > startDate && dateToSearch < endDate); //must be after start date and before end date \r\n };\r\n\r\n utility.timesAreSame = function (datetime1, datetime2) {\r\n return (datetime1.getTime() - datetime2.getTime()) === 0;\r\n };\r\n\r\n utility.getDaysInMonth = function (anyDateInMonth, year) {\r\n if (typeof anyDateInMonth === _o) {\r\n return new Date(anyDateInMonth.getUTCFullYear(),\r\n anyDateInMonth.getUTCMonth() + 1,// This will work for december +1 as javscript increments months/years if the units roll over\r\n 0).getUTCDate();\r\n } else { //anyDateInMonth is a month\r\n var d = new Date();\r\n d.setUTCFullYear(year);\r\n d.setUTCMonth(anyDateInMonth + 1);\r\n d.setUTCDate(0);\r\n return d.getUTCDate();\r\n }\r\n };\r\n\r\n utility.addMonths = function (date, months) {\r\n var adjusted = new Date(date);\r\n return new Date(adjusted.setUTCMonth(adjusted.getUTCMonth() + months));\r\n };\r\n\r\n utility.addDays = function (date, days) {\r\n var adjusted = new Date(date);\r\n return new Date(adjusted.setUTCDate(adjusted.getUTCDate() + days));\r\n };\r\n\r\n utility.addHours = function (date, hours) {\r\n var adjusted = new Date(date);\r\n return new Date(adjusted.setUTCHours(adjusted.getUTCHours() + hours));\r\n };\r\n\r\n utility.addMinutes = function (date, minutes) {\r\n var adjusted = new Date(date);\r\n return new Date(adjusted.setUTCMinutes(adjusted.getUTCMinutes() + minutes));\r\n };\r\n\r\n utility.addSeconds = function (date, seconds) {\r\n var adjusted = new Date(date);\r\n return new Date(adjusted.setUTCSeconds(adjusted.getUTCSeconds() + seconds));\r\n };\r\n\r\n utility.addMilliseconds = function (date, milliseconds) {\r\n var adjusted = new Date(date);\r\n return new Date(adjusted.setUTCMilliseconds(adjusted.getUTCMilliseconds() + milliseconds));\r\n };\r\n\r\n utility.timesOverlap = function (range1Start, range1End, range2Start, range2End) {\r\n // If either of the ranges end times is null or min, or the range is zero length, set the end to that range's start plus one tick\r\n // this allows zero length ranges to overlap correctly, for example checking whether the current time\r\n // enters a range will match if now falls on the start of the range, but not on the end of the range.\r\n\r\n // We keep the result of the duration length checks so we can return the start time only in the overlap (rather than the 1-tick duration we use\r\n // for the overlap check.)\r\n var durationAZeroLength = utility.dateIsNullOrMin(range1End) || range1End - range1Start == 0;\r\n var durationBZeroLength = utility.dateIsNullOrMin(range2End) || range2End - range2Start == 0;\r\n\r\n // If either of the end times is the same as the start or not defined, add one tick\r\n var range1EndTime = (!durationAZeroLength ? range1End : new Date(range1Start.getTime() + 1));\r\n var range2EndTime = (!durationBZeroLength ? range2End : new Date(range2Start.getTime() + 1));\r\n\r\n // Now check our adjusted times for whether there's an overlap\r\n // They will not overlap if they end at the start time or start at the end time\r\n // The only case that would not be caught by this logic would be the zero length times, hence adjusting them above\r\n if (range1EndTime > range2Start && range1Start < range2EndTime) {\r\n // If either of the ranges was zero length (or had no end)\r\n // Return just the start time of that range\r\n if (durationAZeroLength || durationBZeroLength) {\r\n return {\r\n DateStart: new Date((durationAZeroLength ? range1Start : range2Start)),\r\n DateEnd: new Date((durationAZeroLength ? range1Start : range2Start))\r\n };\r\n } else {\r\n // Neither was zero duration, so we can return the time range of the overlap\r\n // This entails returning the latest start and the earliest end\r\n return {\r\n DateStart: new Date(range1Start > range2Start ? range1Start : range2Start),\r\n DateEnd: new Date(range1EndTime < range2EndTime ? range1EndTime : range2EndTime)\r\n };\r\n }\r\n } else {\r\n // No overlap, return a null overlap range\r\n return null;\r\n }\r\n };\r\n\r\n //Use to create new date without time offset to send to server (toString will display *with* time offset taken into account eg 00:00 UTC shows as 01:00 GMT+1)\r\n //Current hours become the UTC hours without being adjusted by time offset\r\n //sending midnight local time will set the utc to midnight\r\n utility.localDateAsUTC = function (date) {\r\n if (typeof date != _u && date != null) {\r\n var tmpDate = date;\r\n if (typeof (date) == 'string') {\r\n tmpDate = new Date(date);\r\n }\r\n return new Date(Date.UTC(tmpDate.getFullYear(), tmpDate.getMonth(), tmpDate.getDate(), tmpDate.getHours(), tmpDate.getMinutes(), tmpDate.getSeconds(), tmpDate.getMilliseconds()));\r\n } else { return null; }\r\n };\r\n\r\n //When returning a utc date (especially midnight), convert this so it is a local date, rather than being the equivalent time.\r\n utility.UTCDateAsLocal = function (date) {\r\n if (typeof date != _u && date != null) {\r\n var tmpDate = date;\r\n if (typeof (date) == 'string') {\r\n tmpDate = new Date(date);\r\n }\r\n return new Date(tmpDate.getUTCFullYear(), tmpDate.getUTCMonth(), tmpDate.getUTCDate(), tmpDate.getUTCHours(), tmpDate.getUTCMinutes(), tmpDate.getUTCSeconds(), tmpDate.getUTCMilliseconds());\r\n } else { return null; }\r\n };\r\n \r\n // Creates a local midnight time on the utc date passed\r\n utility.localMidnightOnUTCDate = function (date) {\r\n if (typeof date != _u && date != null) {\r\n var tmpDate = date;\r\n if (typeof (date) == 'string') {\r\n tmpDate = new Date(date);\r\n }\r\n return new Date(tmpDate.getUTCFullYear(), tmpDate.getUTCMonth(), tmpDate.getUTCDate(), 0, 0, 0);\r\n } else { return null; }\r\n };\r\n\r\n utility.setTimeOnDate = function (date, hours, minutes, seconds) {\r\n return new Date(new Date(date).setHours(hours, minutes, seconds, 0));\r\n };\r\n\r\n utility.getDateOnly = function (date) {\r\n return utility.dateIsNullOrMin(date) ? null : utility.setTimeOnDate(date, 0, 0, 0);\r\n };\r\n\r\n utility.getHoursMinutes = function (dateTime) {\r\n\r\n var ticks;\r\n\r\n if (typeof dateTime === _o) {\r\n ticks = dateTime.getTime();\r\n } else if (typeof dateTime === _n){\r\n ticks = dateTime;\r\n } else {\r\n return null;\r\n }\r\n\r\n var minutesRemainder = Math.ceil((ticks / 60000) % 60); // Round up to the nearest whole minute\r\n var hours = Math.floor((ticks / 60000) / 60); // Round down to the nearest whole hour\r\n return { minutes: minutesRemainder, hours: hours, totalMinutes: minutesRemainder + (hours * 60) };\r\n };\r\n\r\n utility.getHHMMString = function (time) {\r\n var hoursminutes = utility.getHoursMinutes(time);\r\n return (hoursminutes.hours > 0 ? hoursminutes.hours + ':' : '') + (hoursminutes.minutes > 0 ? (hoursminutes.hours > 0 ? ('00' + hoursminutes.minutes).slice(-2) : hoursminutes.minutes) : '');\r\n };\r\n\r\n utility.getHMString = function (time) {\r\n var hoursminutes = utility.getHoursMinutes(time);\r\n\r\n return (hoursminutes.hours > 0 ? hoursminutes.hours + 'h ' : '') + (hoursminutes.minutes > 0 ? hoursminutes.minutes + 'm' : '');\r\n };\r\n //#endregion\r\n\r\n utility.keyIsNumber = function (evt) {\r\n evt = (evt) ? evt : contextWindow.event;\r\n var charCode = (evt.which) ? evt.which : evt.keyCode;\r\n if (charCode > 31 && (charCode < 48 || charCode > 57)) {\r\n return false;\r\n }\r\n return true;\r\n\r\n /* evt = (evt) ? evt : contextWindow.event;\r\n var key = (evt.which) ? evt.which : evt.keyCode;//Which is deprecated and should be replaced with key (chrome/ff/ie) or keyIdentifier (safari)\r\n if (!evt.shiftKey && !evt.altKey && !evt.ctrlKey &&\r\n // numbers \r\n key >= 48 && key <= 57 ||\r\n // Numeric keypad\r\n key >= 96 && key <= 105 ||\r\n // comma, period and minus, . on keypad\r\n key == 190 || key == 188 || key == 109 || key == 110 ||\r\n // Backspace and Tab and Enter\r\n key == 8 || key == 9 || key == 13 ||\r\n // Home and End\r\n key == 35 || key == 36 ||\r\n // left and right arrows\r\n key == 37 || key == 39 ||\r\n // Del and Ins\r\n key == 46 || key == 45) return true;\r\n return false;*/\r\n };\r\n\r\n //Convert byte values from: https://gist.github.com/thomseddon/3511330\r\n utility.formatBytes = function (bytes, precision) {\r\n if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return '-';\r\n if (typeof precision === _u) precision = 1;\r\n var units = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'],\r\n number = Math.floor(Math.log(bytes) / Math.log(1024));\r\n return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];\r\n };\r\n\r\n utility.formatNumberWithCommas = function (num) {\r\n return num.toString().replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, \"$1,\");\r\n };\r\n\r\n utility.leadingZeros = function (value, length) {\r\n // Create an array of length, joining with zeros\r\n // Add the value to the end, then slice it down to the length\r\n return (new Array(length + 1).join('0') + value).slice(-length)\r\n };\r\n\r\n utility.stripToInt = function (str) {\r\n if (typeof (str) === _u) {\r\n str = '';\r\n }\r\n var integervalue = parseInt(str.replace(/(\\.[0-9]*)/g, '').replace(/[^0-9]/g, ''), 10);//strip out trailing dot and numbers, then strip out any non-numerics\r\n if (!isNaN(integervalue)) {\r\n return integervalue;\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n utility.isHtml = function (text) {\r\n return /<[^>]+>/igm.test(text);\r\n };\r\n\r\n utility.newlineToBr = function (text) {\r\n return text.replace(/\\n/g, '
');\r\n //content.replace(/(?:\\r\\n|\\r|\\n)/g, '
');\r\n };\r\n\r\n // Convert plaintext to encoded (safe) html - unfortunately cannot encode multiple spaces\r\n utility.plainToHtml = function (text) {\r\n if (typeof text == _u) {\r\n return null;\r\n } else {\r\n var p = document.createElement('p');\r\n p.innerText = text;\r\n return p.innerHTML;\r\n }\r\n };\r\n\r\n utility.stripHTML = function (text) {\r\n if (typeof (text) !== _u) {\r\n //Does the string contain html already?\r\n if (utility.isHtml(text)) {\r\n //If so, get rid of newlines in the source\r\n text = text.replace(/[\\r\\n]/igm, '');\r\n }\r\n\r\n text = text.replace(' ', ' ');\r\n text = text.replace(/\\s{2,}/igm, ' ');//Multiple spaces\r\n text = text.replace(/<(br|p)\\s?\\/?>/igm, '\\r\\n');\r\n text = text.replace(/<\\/+(div|hr|p|section|footer|header|article|title)>/igm, '\\r\\n');\r\n text = text.replace(/<[^>]*>/igm, '');//Strip remaining tags \r\n text = text.replace(/[\\r\\n\\s]{2,}/igm, '\\r\\n\\r\\n');//Multiple newlines to two\r\n text = text.replace(/[\\r\\n\\s]+$/ig, '');//trailing newline characters (on the whole block)\r\n text = text.replace(/^[\\r\\n\\s]+/ig, '');//leading newline characters (on the whole block)\r\n return text;\r\n } else {\r\n return '';\r\n }\r\n };\r\n\r\n utility.formatMoney = function (value, prefix, suffix) {\r\n var newval = (typeof value === 'string' ? utility.stripToInt(value) : value);\r\n if (newval != 0) {\r\n return prefix + utility.formatNumberWithCommas(newval) + suffix;\r\n } else {\r\n return '';\r\n }\r\n };\r\n\r\n utility.formatInt = function (sender, callback) {\r\n var newval = utility.stripToInt(sender.value);\r\n sender.value = newval;\r\n if (typeof (callback) === _f) {\r\n callback(sender);\r\n }\r\n };\r\n\r\n utility.getOrdinal = function (num) {\r\n if (num <= 0) return \"\";\r\n switch (num % 100) {\r\n case 11:\r\n case 12:\r\n case 13:\r\n return \"th\";//14-20 covered by default below\r\n }\r\n\r\n switch (num % 10) {\r\n case 1:\r\n return \"st\";\r\n case 2:\r\n return \"nd\";\r\n case 3:\r\n return \"rd\";\r\n default:\r\n return \"th\";\r\n }\r\n };\r\n\r\n utility.parseFixedFloat = function (parseValue, places) {\r\n //Convert the incoming value to a floating point number, limit the decimal places to the passed number or 10 and return the resultant string as a parsed floating point number.\r\n var places = places || 10;\r\n\r\n return parseFloat(parseFloat(parseValue).toFixed(places));\r\n };\r\n\r\n utility.escapeRegex = function (string) {\r\n //From: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions\r\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // $& means the whole matched string\r\n };\r\n\r\n //Return a single node (ensuring that the string consists of a single outer node) as a document fragment\r\n utility.htmlToElement = function (html) {\r\n var template = document.createElement('template');\r\n template.innerHTML = html;\r\n return template.content.firstChild;\r\n };\r\n\r\n //Return a set of document nodes, formed from the html provided (does not need to be one enclosed node)\r\n utility.htmlToElements = function (html) {\r\n var template = document.createElement('template');\r\n template.innerHTML = html;\r\n return template.content.childNodes;\r\n };\r\n\r\n //Convert object properties to entries in an array with their values as elements\r\n //TODO potential optimisation: Object.values(enums.NoFutureManagement).filter(function (i) { return i !== enums.NoFutureManagement.NoValue; });\r\n //becomes internally: Object.values(srcObject).filter(predicate);\r\n utility.objectToArray = function (srcObject, predicate) {\r\n var newArray = [];\r\n if (typeof (srcObject) == 'object') {\r\n for (var prop in srcObject) {\r\n if (predicate\r\n && (\r\n (typeof predicate == _f && !predicate(srcObject[prop])) //exclude things that return false for predicate function\r\n ||\r\n (srcObject[prop] == predicate) //exclude exact matches to predicate string\r\n )\r\n || !srcObject[prop]) {\r\n // do not add novalue or nulls\r\n } else {\r\n newArray.push(srcObject[prop]);\r\n }\r\n }\r\n }\r\n return newArray;\r\n };\r\n\r\n //check querystring for given key, returning a default\r\n utility.getQueryString = function (key, default_) {\r\n key = key.replace(/[\\[]/, \"\\\\\\[\").replace(/[\\]]/, \"\\\\\\]\");\r\n var regex = new RegExp(\"[\\\\?&]\" + key + \"=([^]*)\");\r\n var qs = regex.exec(contextWindow.location.href);\r\n if (qs == null)\r\n return default_;\r\n else\r\n return qs[1];\r\n };\r\n\r\n //Split the querystring out into object properties\r\n utility.parseQuery = function (str, preserveCase) {\r\n if (typeof str != \"string\") {\r\n //use window querystring \r\n str = contextWindow.location.search;//url from ? inclusive \r\n }\r\n\r\n if (str.startsWith('?')) {\r\n str = str.slice(1);//remove ?\r\n } else if (str.indexOf('?') > 0){ // otherwise if it contains a questionmark, get everything after it\r\n str = str.split(\"?\")[1];\r\n }\r\n\r\n if (str.length == 0) return {};\r\n\r\n var s = str.split(\"&\");\r\n var s_length = s.length;\r\n var part, query = {}, first, second;\r\n for (var i = 0; i < s_length; i++) {\r\n part = s[i].split(\"=\");\r\n first = decodeURIComponent(part[0]);//Parameters are lowercase\r\n if (!preserveCase) first.toLowerCase();\r\n if (first.length == 0) continue;//This parameter name is zero length, skip\r\n second = decodeURIComponent(part[1]);\r\n if (second.length == 0) second = null;\r\n if (typeof query[first] === \"undefined\") query[first] = second;\r\n else if (query[first] instanceof Array) query[first].push(second);\r\n else query[first] = [query[first], second];\r\n }\r\n return query;\r\n };\r\n\r\n utility.objectToURI = function (obj) {\r\n return encodeURIComponent(JSON.stringify(obj));\r\n };\r\n\r\n //Build up a querystring from properties of an object. All parameters are returned lowercase\r\n utility.buildParams = function (parameterObject) {\r\n var parameterString = '';\r\n if (typeof (parameterObject) !== _u) {\r\n for (var pair in parameterObject) {\r\n if (typeof parameterObject[pair] !== _f && parameterObject.hasOwnProperty(pair)) {\r\n //use empty string after param if null or undefined\r\n parameterString += (parameterString.length > 0 ? '&' : '') + pair.toLowerCase() + '='\r\n + (typeof (parameterObject[pair]) === _u || parameterObject[pair] == null ? '' : encodeURIComponent(parameterObject[pair]));\r\n\r\n }\r\n }\r\n }\r\n return parameterString;\r\n };\r\n\r\n //Create a crossdomain request\r\n utility.createCORSRequest = function (method, url) {\r\n //from http://www.html5rocks.com/en/tutorials/cors/\r\n var xhr = new XMLHttpRequest();\r\n if (\"withCredentials\" in xhr) {\r\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\r\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\r\n xhr.open(method, url, true);\r\n xhr.withCredentials = true;\r\n xhr.sendCookies = true;//custom property so the page can determine if cookies are going or not\r\n } else if (typeof XDomainRequest != \"undefined\") {\r\n // Otherwise, check if XDomainRequest.\r\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\r\n xhr = new XDomainRequest();\r\n xhr.sendCookies = false;\r\n xhr.open(method, url);\r\n } else {\r\n // Otherwise, CORS is not supported by the browser.\r\n xhr = null;\r\n }\r\n return xhr;\r\n\r\n /*\r\n //Use the following to trigger reactions in your pages\r\n var xhr = tios.util.createCORSRequest('GET', issuer);\r\n if (!xhr) {\r\n throw new Error('CORS not supported');\r\n } else {\r\n xhr.onload = function () {\r\n var responseText = xhr.responseText;\r\n alert('CORS response: ' + responseText);\r\n };\r\n \r\n xhr.onerror = function () {\r\n alert('CORS error');\r\n };\r\n \r\n xhr.send();\r\n \r\n }\r\n */\r\n };\r\n\r\n\r\n // Cross browser way to listen for events.\r\n utility.addListener = function (element, type, callback) {\r\n if (element.addEventListener) element.addEventListener(type, callback, true);\r\n else if (element.attachEvent) element.attachEvent('on' + type, callback);\r\n };\r\n\r\n utility.addListeners = function (elementCollection, type, callback) {\r\n var i, len = elementCollection.length;\r\n if (len > 0) {\r\n for (i = 0; i < len; i++) {\r\n if (elementCollection[i].addEventListener) {\r\n elementCollection[i].addEventListener(type, callback);\r\n }\r\n else if (elementCollection[i].attachEvent) {\r\n elementCollection[i].attachEvent('on' + type, callback);\r\n }\r\n }\r\n }\r\n };\r\n\r\n \r\n\r\n //#region Storage methods\r\n\r\n // Variable to save whether storage exists (prevents multiple additions of storage test)\r\n var _storageIsAvailable = {\r\n [_localStorage]: null,\r\n [_sessionStorage]: null\r\n };\r\n\r\n function selectStorage(useSession) {\r\n return useSession ? _sessionStorage : _localStorage;\r\n }\r\n\r\n function getStorage(useSession) {\r\n return window[selectStorage(useSession)];\r\n }\r\n\r\n utility.storageAvailable = function (useSession) {\r\n var storageType = selectStorage(useSession);\r\n // If availability for this storage type has not yet been checked, do so now\r\n if (_storageIsAvailable[storageType] == null) {\r\n //based on: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\r\n try {\r\n var storage = getStorage(useSession),\r\n x = '__storage_test__';\r\n storage.setItem(x, x);\r\n storage.removeItem(x);\r\n _storageIsAvailable[storageType] = true;\r\n }\r\n catch (e) {\r\n _storageIsAvailable[storageType] = false;\r\n }\r\n }\r\n return _storageIsAvailable[storageType];\r\n };\r\n\r\n utility.saveToStorage = function (key, obj, useSession) {\r\n if (this.storageAvailable(useSession)) {\r\n var saveObject = obj;\r\n if (typeof obj == _o) {\r\n saveObject = JSON.stringify(obj);\r\n }\r\n getStorage(useSession).setItem(key, saveObject);\r\n return (obj);\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n utility.getFromStorage = function (key, useSession) {//TODO find an alternative to trying and parsing\r\n if (this.storageAvailable(useSession)) {\r\n var retVal = getStorage(useSession).getItem(key);\r\n if (typeof retVal !== _u && retVal !== null) {\r\n if (utility.stringIsJSON(retVal)) {//is the string a json object?\r\n var tmpRetVal = JSON.parse(retVal);//parse the JSON into temporary object\r\n return (typeof tmpRetVal === 'string' ? retVal : tmpRetVal); //return either object (if json parsed it as such) or the raw string (so no extra quotes)\r\n } else {\r\n return retVal;//Not JSON so just return it as-is\r\n }\r\n } else return null;\r\n } else return null;\r\n };\r\n\r\n utility.removeFromStorage = function (key, useSession) {\r\n if (this.storageAvailable(useSession)) {\r\n getStorage(useSession).removeItem(key);\r\n }\r\n };\r\n\r\n utility.clearStorage = function (useSession) {\r\n if (this.storageAvailable(useSession)) {\r\n getStorage(useSession).clear();\r\n }\r\n };\r\n //#endregion\r\n\r\n //#region SVG interaction\r\n utility.hooksvg = function (elementID) { //Hook in the contentDocument of the svg so we can fire its internal scripts\r\n var svgdoc, svgwin, returnvalue = false;\r\n var object = (typeof (elementID) === 'string' ? document.getElementById(elementID) : elementID);\r\n if (object && object.contentDocument) {\r\n svgdoc = object.contentDocument;\r\n }\r\n else {\r\n if (typeof (object.getSVGDocument) == _f) {\r\n try {\r\n svgdoc = object.getSVGDocument();\r\n } catch (exception) {\r\n //utility.log('Neither the HTMLObjectElement nor the GetSVGDocument interface are implemented');\r\n }\r\n }\r\n }\r\n if (svgdoc && svgdoc.defaultView) {\r\n svgwin = svgdoc.defaultView;\r\n }\r\n else if (object.window) {\r\n svgwin = object.window;\r\n }\r\n else {\r\n if (typeof (object.getWindow) == _f) {\r\n try {\r\n svgwin = object.getWindow();//TODO look at fixing this \r\n }\r\n catch (exception) {\r\n // utility.log('The DocumentView interface is not supported\\r\\n Non-W3C methods of obtaining \"window\" also failed');\r\n }\r\n }\r\n }\r\n\r\n //utility.log('svgdoc is ' + svgdoc + ' and svgwin is ' + svgwin);\r\n if (typeof (svgwin) === _u || typeof (svgwin) === null) {\r\n returnvalue = null;\r\n } else {\r\n returnvalue = svgwin;\r\n }\r\n return returnvalue;\r\n };\r\n\r\n //TODO: throw an alert if an svg isn't found in the document with the correct attributes\r\n //NOTE: If replacing this in older projects, the SVGs need to have data-svgname set to the same name as their id/name\r\n //data-svgname must only be placed on svgs that require data injection. Make sure that name is changed to svgname where referred in svg's .js files\r\n utility.triggerSVG = function (d, targetDataSvgName, allowAnimation, noErrorOnUnnamed) {\r\n if (typeof allowAnimation === _u) {\r\n allowAnimation = true;\r\n }\r\n\r\n for (var data in d) {\r\n var svgname = d[data].svgname;\r\n if (svgname) {//only process if this data has svgname (could be a config property rather than svg data)\r\n\r\n var specificfound = false;\r\n if (targetDataSvgName) {\r\n if (svgname === targetDataSvgName) {\r\n specificfound = true;\r\n } else {\r\n continue; //if targetDataSvgName specified and the current element is not the target, skip this loop iteration.\r\n }\r\n }\r\n\r\n //Run the injectSVG on each object with the correct data-svgname attribute\r\n var objectElements = document.querySelectorAll('[data-svgname=\"' + svgname + '\"]');//Find the object in the page based on the data-svgname\r\n if (objectElements.length) {\r\n for (var el of objectElements) {\r\n this.injectSVG(d[data], el, allowAnimation);\r\n }\r\n } else {\r\n // If we're looking for a specific svg or we haven't been told to\r\n // ignore errors when adding names from data, log an error\r\n if (targetDataSvgName || !noErrorOnUnnamed) {\r\n utility.log('data-svgname:' + svgname + ' not found. Please check the html.');\r\n }\r\n specificfound = false;\r\n }\r\n\r\n if (specificfound) {\r\n //if targetDataSvgName was specified and the current element is found (and triggered above) skip the remainder of the loop\r\n break;\r\n }\r\n\r\n }\r\n }\r\n\r\n //utility.log('trigger firing event');\r\n //window.top.dispatchEvent(new CustomEvent(\"TIOSAnimation\", { detail: {run:true}}));\r\n //utility.draw.startAll();\r\n //window.animStart();//launch the animation cycle\r\n };\r\n\r\n //Attach data for an svg injection to the specified svg element\r\n utility.injectSVG = function (inputData, objectElement, allowAnimation) {\r\n //Chrome has difficulty with SVG and resets the display if modified via javascript and changing from display:none - use visibility:hidden instead.\r\n if (typeof allowAnimation === _u) {\r\n allowAnimation = true;\r\n }\r\n var _this = this;\r\n if (objectElement) {\r\n var enableAnimation = _this.isVisible(objectElement) && allowAnimation;//pass in whether object is visible and animation allowed (SVGs should not animate in this case.)\r\n var svgElement = _this.hooksvg(objectElement);\r\n if (svgElement !== null && typeof (svgElement.setgauge) === _f) {//if svg element can be hooked, fire its setgauge method\r\n //utility.log('svg hooked:'+ currentElementID);\r\n\r\n if (!inputData.loadTriggered) {\r\n //Add an optional callback to be triggered on load.\r\n if (typeof inputData.loadCallback === _f) inputData.loadCallback();\r\n inputData.loadTriggered = true;\r\n }\r\n\r\n svgElement.setgauge(inputData, enableAnimation);\r\n\r\n // If there are any event bindings (onunbind etc), set those on the parent object element.\r\n if (svgElement.bindings) {\r\n objectElement.svgBindings = svgElement.bindings;\r\n }\r\n\r\n } else {//cannot find svg or its function, so set the onload instead\r\n objectElement.onload = function () {\r\n //utility.log('fired onload for:' + this.getAttribute('id'));\r\n var svgThis = this;\r\n var svgElementtmp = _this.hooksvg(svgThis);\r\n if (typeof (svgElementtmp.setgauge) === _f) {\r\n svgElementtmp.setgauge(inputData, enableAnimation);//trigger the setgauge function using current passed data (prevents scoping errors)\r\n\r\n // Set the svg event bindings as above\r\n if (svgElementtmp.bindings) {\r\n //utility.log('binding svgBindings');\r\n objectElement.svgBindings = svgElementtmp.bindings;\r\n }\r\n\r\n }\r\n\r\n if (!inputData.loadTriggered) {\r\n //Add an optional callback to be triggered on load.\r\n if (typeof inputData.loadCallback === _f) inputData.loadCallback();\r\n inputData.loadTriggered = true;\r\n }\r\n\r\n svgThis.onload = null; //Erase the onload once fired - so it doesn't reload while dragging a drag and drop svg\r\n };\r\n }\r\n }\r\n };\r\n\r\n //#endregion\r\n\r\n //Non jquery isvisible function\r\n utility.isVisible = function (element) {\r\n var hasrect = !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length); // !! casts to a true bool\r\n var style = utility.appWindow.getComputedStyle(element);\r\n return hasrect &&\r\n style.opacity !== 0 &&\r\n style.display !== 'none' &&\r\n style.visibility !== 'hidden';\r\n };\r\n\r\n //#region animation methods\r\n\r\n utility.timers = utility.appWindow && utility.appWindow.tios && utility.appWindow.tios.util && utility.appWindow.tios.util.timers ? utility.appWindow.tios.util.timers : [];//Use global appwindow timer reference\r\n\r\n //Timeout hints from http://stackoverflow.com/questions/5226578/check-if-a-timeout-has-been-cleared\r\n\r\n utility.TIOSTimeout = function (name, fn, interval, scope, args) {\r\n scope = scope || utility.appWindow;\r\n var self = this;\r\n var wrap = function () {\r\n self.clear();\r\n fn.apply(scope, args || arguments);\r\n }\r\n this.id = setTimeout(wrap, interval);\r\n this.name = name;\r\n utility.timers.push(self);//add to timers array\r\n }\r\n utility.TIOSTimeout.prototype.name = null;\r\n utility.TIOSTimeout.prototype.type = 'timeout';\r\n utility.TIOSTimeout.prototype.id = null;\r\n utility.TIOSTimeout.prototype.cleared = false;\r\n utility.TIOSTimeout.prototype.clear = function () {\r\n utility.timers.splice(utility.timers.indexOf(this), 1);//Remove from timers array\r\n clearTimeout(this.id);\r\n this.cleared = true;\r\n this.id = null;\r\n };\r\n\r\n utility.TIOSInterval = function (name, fn, interval, scope, args) {\r\n scope = scope || utility.appWindow;\r\n var self = this;\r\n var wrap = function () {\r\n fn.apply(scope, args || arguments);\r\n }\r\n this.id = setInterval(wrap, interval);\r\n this.name = name;\r\n utility.timers.push(self);//add to timers array\r\n }\r\n utility.TIOSInterval.prototype.name = null;\r\n utility.TIOSInterval.prototype.type = 'interval';\r\n utility.TIOSInterval.prototype.id = null\r\n utility.TIOSInterval.prototype.cleared = false;\r\n utility.TIOSInterval.prototype.clear = function () {\r\n utility.timers.splice(utility.timers.indexOf(this), 1);//Remove from timers array\r\n clearInterval(this.id);\r\n this.cleared = true;\r\n this.id = null;\r\n };\r\n\r\n //#endregion\r\n\r\n utility.getGlyph = function (glyph) {\r\n // Retrieve the glyph path from the enum, returning false if it's NoValue or not declared\r\n if (!!glyphs[glyph]) {\r\n return utility.getSymbol(glyphs[glyph]);\r\n } else return false;\r\n };\r\n\r\n utility.getSymbol = function (symbol) {\r\n // Generate the symbol path \r\n if (!!symbol) {\r\n return utility.cdnUrl('images-svg/icon-symbols.svg') + '#' + symbol;\r\n } else return false;\r\n };\r\n\r\n utility.getClientSize = function () {\r\n var w = contextWindow,\r\n d = document,\r\n e = d.documentElement,\r\n g = d.getElementsByTagName('body')[0];\r\n return { width: w.innerWidth || e.clientWidth || g.clientWidth, height: w.innerHeight || e.clientHeight || g.clientHeight };\r\n };\r\n\r\n utility.addToTiosBar = function (content) {\r\n if (contextWindow == utility.appWindow) {\r\n var $tiosbar;\r\n var $content = $(content);\r\n $content.addClass('icon');\r\n if ($('#tiosbar').length == 0) {\r\n $tiosbar = $('');\r\n $('body').append($tiosbar);\r\n /*\r\n $tiosbar.on({\r\n mouseenter: function () { if (!tios.vars.isMobile) $(this).animate({ opacity: '1' }, 500); },\r\n mouseleave: function () { if (!tios.vars.isMobile) $(this).animate({ opacity: '0' }, 500); }\r\n });\r\n */\r\n } else {\r\n $tiosbar = $('#tiosbar');\r\n }\r\n $tiosbar.append($content);\r\n return $content;\r\n } else {\r\n return null;\r\n }\r\n };\r\n\r\n //Determines whether every element in searchFor exists in inArray\r\n utility.arrayContainedBy = function (searchFor, inArray) {\r\n return searchFor.every(function (val) { return inArray.indexOf(val) >= 0; });\r\n };\r\n\r\n // Check whether the contents of two arrays match, even if there are duplicates or the data is unsorted\r\n utility.arrayContentsMatch = function (array1, array2) {\r\n return utility.arrayContainedBy(array1, array2) && utility.arrayContainedBy(array2, array1);\r\n };\r\n\r\n // Return true if the first argument matches any of the subsequent arguments in an === fashion\r\n utility.equalsAny = function (...args) {\r\n // Start at index 1 because we don't want to compare the first argument and get a false (and by false, we mean unintentional) true\r\n for (var i = 1; i < args.length; i++) {\r\n if (args[0] === args[i]) return true;\r\n }\r\n return false;\r\n };\r\n\r\n // Return true if all arguments are equal to the first\r\n utility.equalsAll = function (...args) {\r\n for(var arg of args) {\r\n if (args[0] !== arg) return false;\r\n }\r\n return true;\r\n };\r\n\r\n \r\n // Find the first free number in an unsorted list of numbers\r\n utility.firstFreeIndex = function (items, oneBased) {\r\n var freeIndex = !!oneBased ? 1 : 0;\r\n // If there are no items, return 0\r\n if (!items || !items.length) return freeIndex;\r\n\r\n // Spread copy the array as a set, so we don't sort the original in place\r\n // and we don't get duplicates\r\n var newArray = [...new Set(items)];\r\n\r\n // Sort numerically (if we don't use a custom sort function,\r\n // it will convert values to strings, bringing 10 before 2, 20 before 3 etc.)\r\n newArray.sort(function (x, y) {\r\n return x > y;\r\n });\r\n\r\n // now find the first gap in the numbers\r\n for (var i = 0; i < newArray.length; i++) {\r\n var currentValue = newArray[i];\r\n\r\n // Check the current value against the first free index\r\n if (freeIndex != currentValue) {\r\n // If the value is different, there's a gap, so return the freeIndex.\r\n return freeIndex;\r\n } else {\r\n // Otherwise, there is no gap, so increment the freeIndex and check the next\r\n freeIndex = currentValue + 1;\r\n }\r\n }\r\n // If we've gone past the end of the array,\r\n // return the next free number.\r\n return freeIndex;\r\n }\r\n\r\n //Depracated\r\n //http://stackoverflow.com/questions/979256/sorting-an-array-of-javascript-objects\r\n utility.sortBy = function (arr, prop, reverse, numeric) {\r\n // Ensure there's a property\r\n if (!prop || !arr) {\r\n return arr;\r\n }\r\n // Set up sort function\r\n var sort_by = function (field, rev, primer) {\r\n // Return the required a,b function\r\n return function (a, b) {\r\n // Reset a, b to the field\r\n a = primer(a[field]), b = primer(b[field]);\r\n // Do actual sorting, reverse as needed\r\n return ((a < b) ? -1 : ((a > b) ? 1 : 0)) * (rev ? -1 : 1);\r\n };\r\n };\r\n\r\n // Distinguish between numeric and string to prevent 100's from coming before smaller\r\n // e.g.\r\n // 1\r\n // 20\r\n // 3\r\n // 4000\r\n // 50\r\n\r\n if (numeric) {\r\n // Do sort \"in place\" with sort_by function\r\n arr.sort(sort_by(prop, reverse, function (a) {\r\n\r\n // - Force value to a string.\r\n // - Replace any non numeric characters.\r\n // - Parse as float to allow 0.02 values.\r\n return parseFloat(String(a).replace(/[^0-9.-]+/g, ''));\r\n }));\r\n } else {\r\n // Do sort \"in place\" with sort_by function\r\n arr.sort(sort_by(prop, reverse, function (a) {\r\n\r\n // - Force value to string.\r\n return String(a).toUpperCase();\r\n\r\n }));\r\n }\r\n };\r\n\r\n //Freeze all properties of an object recursively.\r\n utility.deepFreeze = function (obj) {\r\n\r\n // Retrieve the property names defined on obj\r\n var propNames = Object.getOwnPropertyNames(obj);\r\n\r\n // Freeze properties before freezing self\r\n propNames.forEach(function (name) {\r\n var prop = obj[name];\r\n\r\n // Freeze prop if it is an object\r\n if (typeof prop == 'object' && prop !== null)\r\n utility.deepFreeze(prop);\r\n });\r\n\r\n // Freeze self (no-op if already frozen)\r\n return Object.freeze(obj);\r\n };\r\n\r\n //Depracated\r\n utility.areSharedPropertiesEqual = function (first, second) {\r\n var isEqual = true;\r\n //if they are objects, iterate properties, otherwise...\r\n if (typeof first === _o && typeof second === _o) {\r\n if (Array.isArray(first)) {\r\n if (Array.isArray(second)) {//both arrays\r\n if (first.length == second.length) {//same length\r\n for (var i = 0; i < first.length; i++) {\r\n if (!utility.areSharedPropertiesEqual(first[i], second[i])) {\r\n isEqual = false;\r\n break;\r\n }\r\n }\r\n }\r\n else {\r\n isEqual = false;\r\n }\r\n } else {\r\n isEqual = false;\r\n }\r\n } else {\r\n if (Array.isArray(second)) {\r\n isEqual = false;\r\n } else {//both are objects (not arrays)\r\n for (var prop in first) {\r\n if (first.hasOwnProperty(prop) && second.hasOwnProperty(prop)) {\r\n if (!utility.areSharedPropertiesEqual(first[prop], second[prop])) {\r\n isEqual = false;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } else { //...compare the two directly if they are not functions\r\n if ((typeof (first) !== _f && typeof (second) !== _f) && first !== second) {\r\n isEqual = false;\r\n }\r\n }\r\n return isEqual;\r\n };\r\n\r\n //Depracated\r\n /**\r\n * Retrieve nested item from object/array\r\n * @param {Object|Array} obj\r\n * @param {String} path dot separated\r\n * @param {*} def default value ( if result undefined )\r\n * @returns {*}\r\n */\r\n // from http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key\r\n utility.getPropertyByPath = function (obj, path, defaultValue) {\r\n if (typeof (obj) === _u) return defaultValue;\r\n\r\n path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\r\n path = path.replace(/^\\./, ''); // strip a leading dot\r\n var a = path.split('.');\r\n\r\n for (var i = 0; i < a.length; i++) { //This loop iterates properties\r\n var k = a[i];\r\n if (k in obj) { //property exists\r\n obj = obj[k]; //drill down through object\r\n } else { //doesn't exist, return default\r\n return defaultValue;\r\n }\r\n }\r\n return obj;\r\n }\r\n\r\n //Depracated\r\n //sort-of based on this: set function https://github.com/lodash/lodash/blob/3.10.1/lodash.src.js#L10155\r\n //Set or create properties by the path passed.\r\n utility.setPropertyByPath = function (obj, path, value) {\r\n if (typeof (obj) === _u) return false;\r\n\r\n var nestedRef = obj;//grab reference to original so that when nestedRef changes it modifies the properties of obj rather than detaching\r\n\r\n path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\r\n path = path.replace(/^\\./, ''); // strip a leading dot\r\n var a = path.split('.');\r\n for (var i = 0; i < a.length; i++) {\r\n var k = a[i];\r\n\r\n if (i == a.length - 1) { //final property, Set the value\r\n nestedRef[k] = value;\r\n } else if (typeof (nestedRef[k]) === _u) { //not final and property doesn't exist - create it\r\n nestedRef[k] = (typeof (a[i + 1]) == 'number' ? [] : {}); //create as array or object depending on whether next index is a number or not\r\n }\r\n\r\n // not final but does exist (or does now), step into property and continue\r\n nestedRef = nestedRef[k];\r\n }\r\n\r\n return obj;\r\n };\r\n\r\n //From https://github.com/alnorris/file-dialog (snapshot 08-03-2017)\r\n //Adds a file dialog command (last argument is the callback which accepts a list of files)\r\n /*\r\n *Get a File via a promise and POST to server via Fetch\r\n \r\n fileDialog()\r\n .then(file => {\r\n const data = new FormData()\r\n data.append('file', file[0])\r\n data.append('imageName', 'flower')\r\n \r\n // Post to server\r\n fetch('/uploadImage', {\r\n method: 'POST',\r\n body: data\r\n })\r\n })\r\n \r\n Allow user to select multiple image files at once\r\n \r\n fileDialog({ multiple: true, accept: 'image/*' })\r\n .then(files => {\r\n // files contains an array of FileList\r\n })\r\n \r\n Classic callback version of the above\r\n \r\n fileDialog({ multiple: true, accept: 'image/*' }, files => {\r\n // files contains an array of FileList\r\n })\r\n */\r\n utility.fileDialog = function (...args) { // Must be triggered by an event initated by a user click\r\n var _changeEvent = 'change';\r\n var input = document.createElement('input')\r\n\r\n // Set config\r\n if (typeof args[0] === _o) {\r\n if (args[0].multiple === true) input.setAttribute('multiple', '')\r\n if (args[0].accept !== undefined) input.setAttribute('accept', args[0].accept)\r\n }\r\n input.setAttribute('type', 'file')\r\n\r\n // Return promise/callback\r\n return new Promise((resolve, reject) => {\r\n\r\n // Create an event to trigger (which deletes itself)\r\n var inputEvent = function () {\r\n resolve(input.files);\r\n var lastArg = args[args.length - 1]\r\n if (typeof lastArg === _f) lastArg(input.files);\r\n input.removeEventListener(_changeEvent, inputEvent);\r\n input = null;\r\n };\r\n\r\n input.addEventListener(_changeEvent, inputEvent);\r\n\r\n // Simulate click event\r\n //var evt = document.createEvent('MouseEvents')\r\n //evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null)\r\n //input.dispatchEvent(evt);\r\n input.click();\r\n //evt = null;\r\n });\r\n };\r\n\r\n utility.getFileUrl = function (contentBytes, contentType, contentIsB64) {\r\n var contentData = null;\r\n if (contentIsB64) {\r\n contentData = contentBytes;\r\n } else {\r\n contentData = btoa(String.fromCharCode.apply(null, new Uint8Array(contentBytes)));\r\n }\r\n return 'data:' + contentType + ';base64,' + contentData;\r\n };\r\n\r\n var windowUrl = window.URL || window.webkitURL || window.mozURL || window.msURL;\r\n\r\n // This method presumes the blob is a bloburl or regular url object. If it's a real file blob, use createobject\r\n utility.openLink = function (hrefOrBlob, filename, fromFile) {\r\n var anchor = document.createElement('a');// Create a fake event for link click\r\n //var event = document.createEvent('MouseEvents');\r\n //event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);\r\n anchor.target = '_blank';\r\n\r\n if (fromFile) {\r\n anchor.href = windowUrl.createObjectURL(hrefOrBlob);\r\n } else {\r\n anchor.href = hrefOrBlob;\r\n }\r\n\r\n if (filename) {\r\n anchor.download = filename;\r\n }\r\n\r\n anchor.click();\r\n //anchor.dispatchEvent(event);// Simulate clicking the download link\r\n };\r\n\r\n\r\n // This converts content passed into a fake download event so the user is prompted to save\r\n utility.fileDownload = function (filename, contentType, contentBytes, contentIsB64) {\r\n\r\n // Pass ContentIsB64 if using a string for data\r\n var contentLength = typeof contentBytes.length != _u ? contentBytes.length : contentBytes.byteLength;\r\n\r\n var _maxSizeForBase64 = 32766; // More than max number of arguments for getfileURL's btoa call \r\n\r\n var useCreateObjectUrl = typeof windowUrl.createObjectURL === _f;\r\n var url = null;\r\n\r\n // If too large for base64 method, use blobs instead\r\n if (contentLength > _maxSizeForBase64 && useCreateObjectUrl) {\r\n // atob converts base64 encoded string into raw data if the passed data is a base64 string\r\n url = windowUrl.createObjectURL(new Blob([(contentIsB64 ? window.atob(contentBytes) : contentBytes)], { type: contentType }));\r\n }\r\n else {\r\n //use base64 encoding when less than set limit or file API is not available\r\n // btoa converts raw data into base64 encoded string\r\n url = utility.getFileUrl(contentBytes, contentType, contentIsB64); // 'data:' + contentType + ';base64,' + (contentIsB64 ? contentBytes : btoa(String.fromCharCode.apply(null, new Uint8Array(contentBytes))))\r\n }\r\n\r\n utility.openLink(url, filename);\r\n\r\n if (useCreateObjectUrl) windowUrl.revokeObjectURL(url);\r\n\r\n };\r\n\r\n // Waits until the timeout, testing every few ms until the condition is resolved\r\n // If the timeout is hit, returns the rejection. It checks every checkInterval.\r\n // From: https://stackoverflow.com/questions/49054748/wait-until-condition-is-met-or-timeout-is-passed-in-javascript\r\n utility.sleepUntil = function (f, checkInterval, timeoutMs) {\r\n return new Promise((resolve, reject) => {\r\n let timeWas = new Date();\r\n let wait = setInterval(function () {\r\n if (f()) {\r\n clearInterval(wait);\r\n resolve();\r\n } else if (new Date() - timeWas > timeoutMs) { // Timeout\r\n clearInterval(wait);\r\n reject();\r\n }\r\n }, checkInterval);\r\n });\r\n };\r\n\r\n return utility;\r\n }(tios.util || {}, jQ, window));\r\n\r\n\r\n window.draw = tios.util.appWindow.draw || { //draw handler by Deane Saunders-Stowe - using centralised appwindow draw reference\r\n running: true,\r\n queue: [],\r\n add: function (methodname, context, duration, methodimplementation) {\r\n this.remove(methodname);\r\n if (typeof (methodimplementation) === _f) {\r\n this.queue.push({ tag: methodname, method: methodimplementation, context: context, running: false, startTime: null, duration: duration });\r\n }\r\n },\r\n clear: function () {\r\n this.queue.length = 0;\r\n },\r\n remove: function (methodname) {\r\n for (var item of this.queue) {\r\n if (item.tag == methodname) {\r\n item.running = false;\r\n this.queue.splice(this.queue.indexOf(item), 1);//if method name matches, remove it from queue.\r\n break;\r\n }\r\n }\r\n },\r\n start: function (methodname, duration) {\r\n this.running = true;\r\n for (var item of this.queue) {\r\n if (item.tag == methodname) {\r\n item.running = true;\r\n item.startTime = new Date().getTime();\r\n item.duration = duration;\r\n item.context.animStart();\r\n break;\r\n }\r\n }\r\n },\r\n stop: function (methodname) {\r\n for (var item of this.queue) {\r\n if (item.tag == methodname) {\r\n item.running = false;\r\n break;\r\n }\r\n }\r\n },\r\n startAll: function (context) {\r\n this.running = true;\r\n for (var item of this.queue.filter(function (i) { return i.context === context; })) {\r\n item.running = true;\r\n item.startTime = new Date().getTime();\r\n item.context.animStart();\r\n }\r\n },\r\n stopAll: function () { this.running = false; },\r\n execute: function (context) {\r\n if (this.running) {\r\n var count = 0;\r\n var contextcount = 0;\r\n var currentTime = new Date().getTime();\r\n //Iterate all animations in the queue for the current context\r\n for (var item of this.queue) {\r\n if (item.running) {\r\n if (item.context === context) {\r\n contextcount++;\r\n item.method(currentTime - item.startTime, item.duration); //pass in the phase and duration\r\n }\r\n count++;\r\n }\r\n }\r\n if (count === 0) {\r\n this.running = false;//stop all animations if none left running\r\n return false;\r\n }\r\n if (contextcount === 0) {\r\n return false;//context not running animations as they have all finished.\r\n }\r\n return true;\r\n } else return false;//No animations running at all, stop this context\r\n }\r\n };\r\n\r\n /*\r\n window.top.addEventListener('TIOSAnimation', function (e) {\r\n utility.log('tios recieved TIOSAnimation event');\r\n if (e.run) {\r\n window.animStart();\r\n } else {\r\n utility.draw.stopAll();//animStop fires automatically when draw.execute returns as non-running\r\n }\r\n }, false);\r\n */\r\n // requestAnim shim layer by Paul Irish see:http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\r\n window.requestAnimFrame = (function () {\r\n return window.requestAnimationFrame ||\r\n window.webkitRequestAnimationFrame ||\r\n window.mozRequestAnimationFrame ||\r\n window.oRequestAnimationFrame ||\r\n window.msRequestAnimationFrame ||\r\n function (/* function */ callback, /* DOMElement */ element) {\r\n new tios.util.TIOSTimeout('tios.requestAnimFrame', callback, 1000 / 60);\r\n };\r\n })();\r\n\r\n window.animateID = null;\r\n\r\n window.animLoop = function () {\r\n //if currently running, execute call again on next frame\r\n window.animateID = window.requestAnimFrame(window.animLoop);\r\n if (!tios.util.draw.execute(window)) window.animStop();//if execute returns false, stop the animation\r\n };\r\n\r\n window.animStart = function () {\r\n if (!window.animateID) {\r\n window.animLoop();\r\n }\r\n };\r\n\r\n window.animStop = function () {\r\n if (window.animateID) {\r\n window.cancelAnimationFrame(window.animateID);\r\n window.animateID = null;\r\n }\r\n };\r\n\r\n //Function polyfills - this one creates object.assign if not present in the javascript implementation of the browser.\r\n //Use Object.assign(targetobject, sourceobjects ...) // copies properties into target object.\r\n if (!Object.assign) {\r\n Object.defineProperty(Object, 'assign', {\r\n enumerable: false,\r\n configurable: true,\r\n writable: true,\r\n value: function (target) {\r\n 'use strict';\r\n if (target === undefined || target === null) {\r\n throw new TypeError('Cannot convert first argument to object');\r\n }\r\n\r\n var to = Object(target);\r\n for (var i = 1; i < arguments.length; i++) {\r\n var nextSource = arguments[i];\r\n if (nextSource === undefined || nextSource === null) {\r\n continue;\r\n }\r\n nextSource = Object(nextSource);\r\n\r\n var keysArray = Object.keys(nextSource);\r\n for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {\r\n var nextKey = keysArray[nextIndex];\r\n var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);\r\n if (desc !== undefined && desc.enumerable) {\r\n to[nextKey] = nextSource[nextKey];\r\n }\r\n }\r\n }\r\n return to;\r\n }\r\n });\r\n }\r\n\r\n //recreate the string's startsWith and endsWith functions\r\n if (!String.prototype.startsWith) {\r\n String.prototype.startsWith = function (searchString, position) {\r\n position = position || 0;\r\n return this.substr(position, searchString.length) === searchString;\r\n };\r\n }\r\n\r\n if (!String.prototype.endsWith) {\r\n String.prototype.endsWith = function (searchString, position) {\r\n var subjectString = this.toString();\r\n if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {\r\n position = subjectString.length;\r\n }\r\n position -= searchString.length;\r\n var lastIndex = subjectString.indexOf(searchString, position);\r\n return lastIndex !== -1 && lastIndex === position;\r\n };\r\n }\r\n\r\n //Find item in array by function\r\n if (!Array.prototype.find) {\r\n Array.prototype.find = function (predicate) {\r\n if (this === null) {\r\n throw new TypeError('Array.prototype.find called on null or undefined');\r\n }\r\n if (typeof predicate !== _f) {\r\n throw new TypeError('predicate must be a function');\r\n }\r\n var list = Object(this);\r\n var length = list.length >>> 0;\r\n var thisArg = arguments[1];\r\n var value;\r\n\r\n for (var i = 0; i < length; i++) {\r\n value = list[i];\r\n if (predicate.call(thisArg, value, i, list)) {\r\n return value;\r\n }\r\n }\r\n return undefined;\r\n };\r\n }\r\n\r\n // Creating angular factories for dependency injection\r\n if (!!angular) {\r\n var tiosModule = angular.module('tios', []);\r\n tiosModule.constant('tiosUtil', tios.util);// Using constants so they can be referenced in config blocks\r\n tiosModule.constant('tiosVars', tios.vars);\r\n }\r\n\r\n})();"]}