798 lines · 25.6 KB · JavaScript
RawDownload
//******************************************************************************************************//  gsf.web.client.js - Gbtc////  Copyright © 2016, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  01/26/2016 - J. Ritchie Carroll//       Generated original version of source code.////******************************************************************************************************// ReSharper disable NativeTypePrototypeExtending// ReSharper disable UndeclaredGlobalVariableUsing // Grid Solutions Framework Core Web Client Script Functions"use strict"; const isIE = detectIE();var textMetrics; $(function() {    // Create a canvas object that will be used for text metrics calculations    $("<canvas id=\"textMetricsCanvas\" height=\"1px\" width=\"1px\" style=\"visibility: hidden\"></canvas>").appendTo("body");     // Get text metrics canvas context    textMetrics = document.getElementById("textMetricsCanvas").getContext("2d");}); // Miscellaneous functionsfunction notNull(value, nonNullValue) {    return value || (nonNullValue || "");} function detectIE() {    const ua = window.navigator.userAgent;    const msie = ua.indexOf("MSIE ");     if (msie > 0) {        // IE 10 or older => return version number        return parseInt(ua.substring(msie + 5, ua.indexOf(".", msie)), 10);    }     const trident = ua.indexOf("Trident/");     if (trident > 0) {        // IE 11 => return version number        const rv = ua.indexOf("rv:");        return parseInt(ua.substring(rv + 3, ua.indexOf(".", rv)), 10);    }     const edge = ua.indexOf("Edge/");     if (edge > 0) {        // Edge (IE 12+) => return version number        return parseInt(ua.substring(edge + 5, ua.indexOf(".", edge)), 10);    }     // Other browser    return false;} function isNumber(val) {    return !isNaN(parseFloat(val)) && isFinite(val);} function toHex(val, leftPadding) {    if (leftPadding === undefined)        leftPadding = 4;     const isNegative = val < 0;    return (isNegative ? "-" : "") + "0x" + Math.abs(val).toString(16).padLeft(leftPadding, "0").toUpperCase();} function isBool(val) {    if (typeof value === "boolean")        return true;     const lval = val.toString().toLowerCase();    return lval === "true" || lval === "false";} function getBool(val) {    const num = +val;    return !isNaN(num) ? !!num : !!String(val).toLowerCase().replace(false, "");} // Number functionsNumber.prototype.truncate = function() {    if (typeof Math.trunc != "function")        return parseInt(this.toString());     return Math.trunc(this);} Number.prototype.padLeft = function(totalWidth, paddingChar) {    return this.truncate().toString().padLeft(totalWidth, paddingChar || "0");} Number.prototype.padRight = function(totalWidth, paddingChar) {    return this.truncate().toString().padRight(totalWidth, paddingChar || "0");} // Array functions // Combines a dictionary of key-value pairs into a string. Values will be escaped within startValueDelimiter and endValueDelimiter// to contain nested key/value pair expressions like the following: "normalKVP=-1; nestedKVP={p1=true; p2=0.001}" when either the// parameterDelimiter or the keyValueDelimiter are detected in the value of the key/value pair.function joinKeyValuePairs (source, parameterDelimiter, keyValueDelimiter, startValueDelimiter, endValueDelimiter) {    if (!parameterDelimiter)        parameterDelimiter = ";";     if (!keyValueDelimiter)        keyValueDelimiter = "=";     if (!startValueDelimiter)        startValueDelimiter = "{";     if (!endValueDelimiter)        endValueDelimiter = "}";     const values = [];     for (let key in source) {        if (source.hasOwnProperty(key)) {            let value = source[key];             if (isBool(value))                value = value.toString().toLowerCase();            else                value = value ? value.toString() : "";             if (value.indexOf(parameterDelimiter) >= 0 || value.indexOf(keyValueDelimiter) >= 0)                value = startValueDelimiter + value + endValueDelimiter;             values.push(key + keyValueDelimiter + value);        }    }     return values.join(parameterDelimiter + " ");} Array.prototype.joinKeyValuePairs = function(parameterDelimiter, keyValueDelimiter, startValueDelimiter, endValueDelimiter) {    return joinKeyValuePairs(this, parameterDelimiter, keyValueDelimiter, startValueDelimiter, endValueDelimiter);}; Array.prototype.forEachWithDelay = function(iterationCallback, timeout, completedCallback, thisArg) {    var index = 0,    count = this.length,    self = this,    next = function() {        if (self[index])            iterationCallback.call(thisArg || self, self[index], index, self);                index++;         if (index < count)            setTimeout(next, timeout);        else            completedCallback.call(thisArg || self, self);    };     next();}; if (!Array.prototype.any) {     if (Array.prototype.some) {        Array.prototype.any = Array.prototype.some;    }    else {        Array.prototype.any = function(callback, thisArg) {            var args;             if (this == null)                throw new TypeError("this is null or not defined");             const array = Object(this);            const length = array.length >>> 0; // Convert array length to positive integer             if (typeof callback !== "function")                throw new TypeError();             if (arguments.length > 1)                args = thisArg;            else                args = undefined;             var index = 0;             while (index < length) {                if (index in array) {                    const element = array[index];                     if (callback.call(args, element, index, array))                        return true;                }                 index++;            }             return false;        }    }} // Represents a dictionary style class with case-insensitive keysfunction Dictionary(source) {    const self = this;     if (!source)        source = [];     self._keys = [];    self._values = [];     self.count = function() {        var size = 0;         for (let property in self._values) {            if (self._values.hasOwnProperty(property))                size++;        }         return size;    }     self.keys = function() {        const keys = [];         for (let property in self._keys) {            if (self._keys.hasOwnProperty(property))                keys.push(self._keys[property]);        }         return keys;    }     self.values = function() {        const values = [];         for (let property in self._values) {            if (self._keys.hasOwnProperty(property))                values.push(self._values[property]);        }         return values;    }     self.get = function(key) {        return self._values[String(key).toLowerCase()];    }     self.set = function(key, value) {        const lkey = String(key).toLowerCase();         if (!self._keys[lkey] || self._keys[lkey].toLowerCase() !== key)            self._keys[lkey] = key;         if (isBool(value))            self._values[lkey] = getBool(value);        else            self._values[lkey] = value;    }     self.remove = function(key) {        const lkey = String(key).toLowerCase();        delete self._keys[lkey];        delete self._values[lkey];    }     self.containsKey = function(key) {        const lkey = String(key).toLowerCase();         for (let property in self._values) {            if (self._values.hasOwnProperty(property) && property === lkey)                return true;        }         return false;    }     self.containsValue = function(value) {        for (let property in self._values) {            if (self._values.hasOwnProperty(property) && self._values[property] === value)                return true;        }         return false;    }     self.clear = function() {        self._keys = [];        self._values = [];    }     self.joinKeyValuePairs = function(parameterDelimiter, keyValueDelimiter, startValueDelimiter, endValueDelimiter) {        const keyValuePairs = [];         for (let property in self._values) {            if (self._values.hasOwnProperty(property))                keyValuePairs[self._keys[property]] = self._values[property];        }         return keyValuePairs.joinKeyValuePairs(parameterDelimiter, keyValueDelimiter, startValueDelimiter, endValueDelimiter);    }     self.pushAll = function(source) {        for (let property in source)            if (source.hasOwnProperty(property))                self.set(property, source[property]);    }     self.toObservableDictionary = function(useLowerKeys) {        // See ko.observableDictionary.js        const observableDictionary = new ko.observableDictionary();         for (let property in self._values) {            if (self._values.hasOwnProperty(property))                observableDictionary.push(useLowerKeys ? property : self._keys[property], self._values[property]);        }         return observableDictionary;    }     self.updateObservableDictionary = function(observableDictionary, useLowerKeys) {        for (let property in self._values) {            if (self._values.hasOwnProperty(property))                observableDictionary.set(useLowerKeys ? property : self._keys[property], self._values[property]);        }    }     // Construction    if (source instanceof Dictionary) {        for (let property in source._values)            if (source._values.hasOwnProperty(property))                self.set(source._keys[property], source._values[property]);    }    else {        for (let property in source) {            if (source.hasOwnProperty(property))                self.set(property, source[property]);        }    }} Dictionary.fromObservableDictionary = function(observableDictionary) {    const dictionary = new Dictionary();    dictionary.pushAll(observableDictionary.toJSON());    return dictionary;} // String functionsfunction isEmpty(str) {    return !str || String(str).length === 0;} String.prototype.truncate = function(limit) {    const text = this.trim();     if (text.length > limit)        return text.substr(0, limit - 3) + "...";     return text;} String.prototype.replaceAll = function(findText, replaceWith, ignoreCase) {    return this.replace(        new RegExp(findText.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g, "\\$&"), (ignoreCase ? "gi" : "g")),        (typeof replaceWith == "string") ? replaceWith.replace(/\$/g, "$$$$") : replaceWith);} if (!String.format) {    String.format = function(format) {        var text = format;         for (let i = 1; i < arguments.length; i++)            text = text.replaceAll("{" + (i - 1) + "}", arguments[i]);         return text;    };} String.prototype.padLeft = function(totalWidth, paddingChar) {    if (totalWidth > this.length)        return Array(totalWidth - this.length + 1).join(paddingChar || " ") + this;     return this;} String.prototype.padRight = function(totalWidth, paddingChar) {    if (totalWidth > this.length)        return this + Array(totalWidth - this.length + 1).join(paddingChar || " ");     return this;} String.prototype.countOccurrences = function(searchString) {    return (this.split(searchString).length - 1);} if (!String.prototype.startsWith) {    String.prototype.startsWith = function(searchString, position) {        position = position || 0;        return this.substr(position, searchString.length) === searchString;    }} String.prototype.regexEncode = function() {    return "\\u" + this.charCodeAt(0).toString(16).padLeft(4, "0");} // Returns a Dictionary of the parsed key/value pair expressions from a string. Parameter pairs are delimited by keyValueDelimiter// and multiple pairs separated by parameterDelimiter. Supports encapsulated nested expressions.String.prototype.parseKeyValuePairs = function(parameterDelimiter, keyValueDelimiter, startValueDelimiter, endValueDelimiter, ignoreDuplicateKeys) {    if (!parameterDelimiter)        parameterDelimiter = ";";     if (!keyValueDelimiter)        keyValueDelimiter = "=";     if (!startValueDelimiter)        startValueDelimiter = "{";     if (!endValueDelimiter)        endValueDelimiter = "}";     if (ignoreDuplicateKeys === undefined)        ignoreDuplicateKeys = true;     if (parameterDelimiter === keyValueDelimiter ||        parameterDelimiter === startValueDelimiter ||        parameterDelimiter === endValueDelimiter ||        keyValueDelimiter === startValueDelimiter ||        keyValueDelimiter === endValueDelimiter ||        startValueDelimiter === endValueDelimiter)            throw "All delimiters must be unique";     const escapedParameterDelimiter = parameterDelimiter.regexEncode();    const escapedKeyValueDelimiter = keyValueDelimiter.regexEncode();    const escapedStartValueDelimiter = startValueDelimiter.regexEncode();    const escapedEndValueDelimiter = endValueDelimiter.regexEncode();    const backslashDelimiter = "\\".regexEncode();     var keyValuePairs = new Dictionary();    var escapedValue = [];    var valueEscaped = false;    var delimiterDepth = 0;     // Escape any parameter or key/value delimiters within tagged value sequences    //      For example, the following string:    //          "normalKVP=-1; nestedKVP={p1=true; p2=false}")    //      would be encoded as:    //          "normalKVP=-1; nestedKVP=p1\\u003dtrue\\u003b p2\\u003dfalse")    for (let i = 0; i < this.length; i++) {        var character = this[i];         if (character === startValueDelimiter) {            if (!valueEscaped) {                valueEscaped = true;                continue;   // Don't add tag start delimiter to final value            }             // Handle nested delimiters            delimiterDepth++;        }         if (character === endValueDelimiter) {            if (valueEscaped) {                if (delimiterDepth > 0) {                    // Handle nested delimiters                    delimiterDepth--;                }                else {                    valueEscaped = false;                    continue;   // Don't add tag stop delimiter to final value                }            }            else {                throw "Failed to parse key/value pairs: invalid delimiter mismatch. Encountered end value delimiter \"" + endValueDelimiter + "\" before start value delimiter \"" + startValueDelimiter + "\".";            }        }         if (valueEscaped) {            // Escape any delimiter characters inside nested key/value pair            if (character === parameterDelimiter)                escapedValue.push(escapedParameterDelimiter);            else if (character === keyValueDelimiter)                escapedValue.push(escapedKeyValueDelimiter);            else if (character === startValueDelimiter)

Lines 1–500 of 798.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t