{"version":3,"file":"sidekick.js","sources":["../node_modules/crypto-js/core.js","../src/util/polyfill.js","../src/cmpt/sidekick-session-timeout/session-timeout.js","../src/cmpt/sidekick-nav-item/nav-item.js","../src/util/object-helpers.js","../src/util/asset-loader.js","../src/util/string-helpers.js","../src/util/easy-dom.js","../src/util/deprecated.js","../src/util/type-checkers.js","../src/util/event-bus.js","../src/util/store.js","../src/util/translations.js","../src/util/env.js","../src/util/persistence.js","../src/util/ajax.js","../src/util/idm-helpers.js","../src/cmpt/sidekick-nav/nav-platform.js","../src/util/key-press-helpers.js","../src/util/cmpt-common-features.js","../src/cmpt/sidekick-help/help.js","../src/cmpt/sidekick-search/search.js","../src/cmpt/sidekick-loader/loader.js","../node_modules/debounce/index.js","../src/cmpt/sidekick-app-switcher/app-switcher.js","../src/cmpt/sidekick-tooltip/tooltip.js","../src/cmpt/sidekick-impersonated-user/impersonated-user.js","../node_modules/detect-browser/index.js","../src/util/audioeye-helpers.js","../src/cmpt/index.js","../src/util/dom-scanner.js","../src/util/passport-helpers.js","../src/util/feature-flags-cc.js","../src/util/view-permissions.js","../node_modules/es6-promise/auto.js","../src/ambient/ambient.js","../src/ambient/ambient-height.js","../src/ambient/ambient-width.js","../src/ambient/ambient-config-states.js","../.💩/sidekick-templates.js","../src/util/store-validate.js","../src/util/vendorSSO-helpers.js","../src/cmpt/sidekick-nav/nav.js","../src/util/route-helpers.js","../src/cmpt/sidekick-unsupported-browser-alert/unsupported-browser-alert.js","../src/cmpt/sidekick-header/header.js","../src/cmpt/sidekick-notifications/notifications.js","../src/cmpt/sidekick-nav-item-submenu/nav-item-submenu.js","../src/cmpt/sidekick-user-info/user-info.js","../src/cmpt/sidekick-org-switcher/org-switcher.js","../src/cmpt/sidekick-footer/footer.js","../src/cmpt/sidekick-contact-org/contact-org.js","../src/cmpt/sidekick-pick-org-app/pick-org-app.js","../src/cmpt/sidekick-pick-org/pick-org.js","../src/cmpt/sidekick-pick-app/pick-app.js","../src/cmpt/sidekick-activity-indicator/activity-indicator.js","../src/cmpt/sidekick-nav-item-mega-menu/nav-item-mega-menu.js","../src/cmpt/sidekick-site-errors/site-errors.js","../src/cmpt/sidekick-skip-nav/skip-nav.js","../src/cmpt/sidekick-audioeye/audioeye.js","../src/util/idm.js","../src/util/passport.js","../node_modules/crypto-js/x64-core.js","../node_modules/crypto-js/lib-typedarrays.js","../node_modules/crypto-js/enc-utf16.js","../node_modules/crypto-js/enc-base64.js","../node_modules/crypto-js/enc-base64url.js","../node_modules/crypto-js/md5.js","../node_modules/crypto-js/sha1.js","../node_modules/crypto-js/sha256.js","../node_modules/crypto-js/sha224.js","../node_modules/crypto-js/sha512.js","../node_modules/crypto-js/sha384.js","../node_modules/crypto-js/sha3.js","../node_modules/crypto-js/ripemd160.js","../node_modules/crypto-js/hmac.js","../node_modules/crypto-js/pbkdf2.js","../node_modules/crypto-js/evpkdf.js","../node_modules/crypto-js/cipher-core.js","../node_modules/crypto-js/mode-cfb.js","../node_modules/crypto-js/mode-ctr.js","../node_modules/crypto-js/mode-ctr-gladman.js","../node_modules/crypto-js/mode-ofb.js","../node_modules/crypto-js/mode-ecb.js","../node_modules/crypto-js/pad-ansix923.js","../node_modules/crypto-js/pad-iso10126.js","../node_modules/crypto-js/pad-iso97971.js","../node_modules/crypto-js/pad-zeropadding.js","../node_modules/crypto-js/pad-nopadding.js","../node_modules/crypto-js/format-hex.js","../node_modules/crypto-js/aes.js","../node_modules/crypto-js/tripledes.js","../node_modules/crypto-js/rc4.js","../node_modules/crypto-js/rabbit.js","../node_modules/crypto-js/rabbit-legacy.js","../node_modules/crypto-js/blowfish.js","../node_modules/crypto-js/index.js","../src/index.js","../src/init.js","../src/audioeye.js"],"sourcesContent":[";(function (root, factory) {\n\tif (typeof exports === \"object\") {\n\t\t// CommonJS\n\t\tmodule.exports = exports = factory();\n\t}\n\telse if (typeof define === \"function\" && define.amd) {\n\t\t// AMD\n\t\tdefine([], factory);\n\t}\n\telse {\n\t\t// Global (browser)\n\t\troot.CryptoJS = factory();\n\t}\n}(this, function () {\n\n\t/*globals window, global, require*/\n\n\t/**\n\t * CryptoJS core components.\n\t */\n\tvar CryptoJS = CryptoJS || (function (Math, undefined) {\n\n\t var crypto;\n\n\t // Native crypto from window (Browser)\n\t if (typeof window !== 'undefined' && window.crypto) {\n\t crypto = window.crypto;\n\t }\n\n\t // Native crypto in web worker (Browser)\n\t if (typeof self !== 'undefined' && self.crypto) {\n\t crypto = self.crypto;\n\t }\n\n\t // Native crypto from worker\n\t if (typeof globalThis !== 'undefined' && globalThis.crypto) {\n\t crypto = globalThis.crypto;\n\t }\n\n\t // Native (experimental IE 11) crypto from window (Browser)\n\t if (!crypto && typeof window !== 'undefined' && window.msCrypto) {\n\t crypto = window.msCrypto;\n\t }\n\n\t // Native crypto from global (NodeJS)\n\t if (!crypto && typeof global !== 'undefined' && global.crypto) {\n\t crypto = global.crypto;\n\t }\n\n\t // Native crypto import via require (NodeJS)\n\t if (!crypto && typeof require === 'function') {\n\t try {\n\t crypto = require('crypto');\n\t } catch (err) {}\n\t }\n\n\t /*\n\t * Cryptographically secure pseudorandom number generator\n\t *\n\t * As Math.random() is cryptographically not safe to use\n\t */\n\t var cryptoSecureRandomInt = function () {\n\t if (crypto) {\n\t // Use getRandomValues method (Browser)\n\t if (typeof crypto.getRandomValues === 'function') {\n\t try {\n\t return crypto.getRandomValues(new Uint32Array(1))[0];\n\t } catch (err) {}\n\t }\n\n\t // Use randomBytes method (NodeJS)\n\t if (typeof crypto.randomBytes === 'function') {\n\t try {\n\t return crypto.randomBytes(4).readInt32LE();\n\t } catch (err) {}\n\t }\n\t }\n\n\t throw new Error('Native crypto module could not be used to get secure random number.');\n\t };\n\n\t /*\n\t * Local polyfill of Object.create\n\n\t */\n\t var create = Object.create || (function () {\n\t function F() {}\n\n\t return function (obj) {\n\t var subtype;\n\n\t F.prototype = obj;\n\n\t subtype = new F();\n\n\t F.prototype = null;\n\n\t return subtype;\n\t };\n\t }());\n\n\t /**\n\t * CryptoJS namespace.\n\t */\n\t var C = {};\n\n\t /**\n\t * Library namespace.\n\t */\n\t var C_lib = C.lib = {};\n\n\t /**\n\t * Base object for prototypal inheritance.\n\t */\n\t var Base = C_lib.Base = (function () {\n\n\n\t return {\n\t /**\n\t * Creates a new object that inherits from this object.\n\t *\n\t * @param {Object} overrides Properties to copy into the new object.\n\t *\n\t * @return {Object} The new object.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var MyType = CryptoJS.lib.Base.extend({\n\t * field: 'value',\n\t *\n\t * method: function () {\n\t * }\n\t * });\n\t */\n\t extend: function (overrides) {\n\t // Spawn\n\t var subtype = create(this);\n\n\t // Augment\n\t if (overrides) {\n\t subtype.mixIn(overrides);\n\t }\n\n\t // Create default initializer\n\t if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {\n\t subtype.init = function () {\n\t subtype.$super.init.apply(this, arguments);\n\t };\n\t }\n\n\t // Initializer's prototype is the subtype object\n\t subtype.init.prototype = subtype;\n\n\t // Reference supertype\n\t subtype.$super = this;\n\n\t return subtype;\n\t },\n\n\t /**\n\t * Extends this object and runs the init method.\n\t * Arguments to create() will be passed to init().\n\t *\n\t * @return {Object} The new object.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var instance = MyType.create();\n\t */\n\t create: function () {\n\t var instance = this.extend();\n\t instance.init.apply(instance, arguments);\n\n\t return instance;\n\t },\n\n\t /**\n\t * Initializes a newly created object.\n\t * Override this method to add some logic when your objects are created.\n\t *\n\t * @example\n\t *\n\t * var MyType = CryptoJS.lib.Base.extend({\n\t * init: function () {\n\t * // ...\n\t * }\n\t * });\n\t */\n\t init: function () {\n\t },\n\n\t /**\n\t * Copies properties into this object.\n\t *\n\t * @param {Object} properties The properties to mix in.\n\t *\n\t * @example\n\t *\n\t * MyType.mixIn({\n\t * field: 'value'\n\t * });\n\t */\n\t mixIn: function (properties) {\n\t for (var propertyName in properties) {\n\t if (properties.hasOwnProperty(propertyName)) {\n\t this[propertyName] = properties[propertyName];\n\t }\n\t }\n\n\t // IE won't copy toString using the loop above\n\t if (properties.hasOwnProperty('toString')) {\n\t this.toString = properties.toString;\n\t }\n\t },\n\n\t /**\n\t * Creates a copy of this object.\n\t *\n\t * @return {Object} The clone.\n\t *\n\t * @example\n\t *\n\t * var clone = instance.clone();\n\t */\n\t clone: function () {\n\t return this.init.prototype.extend(this);\n\t }\n\t };\n\t }());\n\n\t /**\n\t * An array of 32-bit words.\n\t *\n\t * @property {Array} words The array of 32-bit words.\n\t * @property {number} sigBytes The number of significant bytes in this word array.\n\t */\n\t var WordArray = C_lib.WordArray = Base.extend({\n\t /**\n\t * Initializes a newly created word array.\n\t *\n\t * @param {Array} words (Optional) An array of 32-bit words.\n\t * @param {number} sigBytes (Optional) The number of significant bytes in the words.\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.lib.WordArray.create();\n\t * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);\n\t * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);\n\t */\n\t init: function (words, sigBytes) {\n\t words = this.words = words || [];\n\n\t if (sigBytes != undefined) {\n\t this.sigBytes = sigBytes;\n\t } else {\n\t this.sigBytes = words.length * 4;\n\t }\n\t },\n\n\t /**\n\t * Converts this word array to a string.\n\t *\n\t * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex\n\t *\n\t * @return {string} The stringified word array.\n\t *\n\t * @example\n\t *\n\t * var string = wordArray + '';\n\t * var string = wordArray.toString();\n\t * var string = wordArray.toString(CryptoJS.enc.Utf8);\n\t */\n\t toString: function (encoder) {\n\t return (encoder || Hex).stringify(this);\n\t },\n\n\t /**\n\t * Concatenates a word array to this word array.\n\t *\n\t * @param {WordArray} wordArray The word array to append.\n\t *\n\t * @return {WordArray} This word array.\n\t *\n\t * @example\n\t *\n\t * wordArray1.concat(wordArray2);\n\t */\n\t concat: function (wordArray) {\n\t // Shortcuts\n\t var thisWords = this.words;\n\t var thatWords = wordArray.words;\n\t var thisSigBytes = this.sigBytes;\n\t var thatSigBytes = wordArray.sigBytes;\n\n\t // Clamp excess bits\n\t this.clamp();\n\n\t // Concat\n\t if (thisSigBytes % 4) {\n\t // Copy one byte at a time\n\t for (var i = 0; i < thatSigBytes; i++) {\n\t var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;\n\t thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);\n\t }\n\t } else {\n\t // Copy one word at a time\n\t for (var j = 0; j < thatSigBytes; j += 4) {\n\t thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];\n\t }\n\t }\n\t this.sigBytes += thatSigBytes;\n\n\t // Chainable\n\t return this;\n\t },\n\n\t /**\n\t * Removes insignificant bits.\n\t *\n\t * @example\n\t *\n\t * wordArray.clamp();\n\t */\n\t clamp: function () {\n\t // Shortcuts\n\t var words = this.words;\n\t var sigBytes = this.sigBytes;\n\n\t // Clamp\n\t words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);\n\t words.length = Math.ceil(sigBytes / 4);\n\t },\n\n\t /**\n\t * Creates a copy of this word array.\n\t *\n\t * @return {WordArray} The clone.\n\t *\n\t * @example\n\t *\n\t * var clone = wordArray.clone();\n\t */\n\t clone: function () {\n\t var clone = Base.clone.call(this);\n\t clone.words = this.words.slice(0);\n\n\t return clone;\n\t },\n\n\t /**\n\t * Creates a word array filled with random bytes.\n\t *\n\t * @param {number} nBytes The number of random bytes to generate.\n\t *\n\t * @return {WordArray} The random word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.lib.WordArray.random(16);\n\t */\n\t random: function (nBytes) {\n\t var words = [];\n\n\t for (var i = 0; i < nBytes; i += 4) {\n\t words.push(cryptoSecureRandomInt());\n\t }\n\n\t return new WordArray.init(words, nBytes);\n\t }\n\t });\n\n\t /**\n\t * Encoder namespace.\n\t */\n\t var C_enc = C.enc = {};\n\n\t /**\n\t * Hex encoding strategy.\n\t */\n\t var Hex = C_enc.Hex = {\n\t /**\n\t * Converts a word array to a hex string.\n\t *\n\t * @param {WordArray} wordArray The word array.\n\t *\n\t * @return {string} The hex string.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var hexString = CryptoJS.enc.Hex.stringify(wordArray);\n\t */\n\t stringify: function (wordArray) {\n\t // Shortcuts\n\t var words = wordArray.words;\n\t var sigBytes = wordArray.sigBytes;\n\n\t // Convert\n\t var hexChars = [];\n\t for (var i = 0; i < sigBytes; i++) {\n\t var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;\n\t hexChars.push((bite >>> 4).toString(16));\n\t hexChars.push((bite & 0x0f).toString(16));\n\t }\n\n\t return hexChars.join('');\n\t },\n\n\t /**\n\t * Converts a hex string to a word array.\n\t *\n\t * @param {string} hexStr The hex string.\n\t *\n\t * @return {WordArray} The word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.enc.Hex.parse(hexString);\n\t */\n\t parse: function (hexStr) {\n\t // Shortcut\n\t var hexStrLength = hexStr.length;\n\n\t // Convert\n\t var words = [];\n\t for (var i = 0; i < hexStrLength; i += 2) {\n\t words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);\n\t }\n\n\t return new WordArray.init(words, hexStrLength / 2);\n\t }\n\t };\n\n\t /**\n\t * Latin1 encoding strategy.\n\t */\n\t var Latin1 = C_enc.Latin1 = {\n\t /**\n\t * Converts a word array to a Latin1 string.\n\t *\n\t * @param {WordArray} wordArray The word array.\n\t *\n\t * @return {string} The Latin1 string.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);\n\t */\n\t stringify: function (wordArray) {\n\t // Shortcuts\n\t var words = wordArray.words;\n\t var sigBytes = wordArray.sigBytes;\n\n\t // Convert\n\t var latin1Chars = [];\n\t for (var i = 0; i < sigBytes; i++) {\n\t var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;\n\t latin1Chars.push(String.fromCharCode(bite));\n\t }\n\n\t return latin1Chars.join('');\n\t },\n\n\t /**\n\t * Converts a Latin1 string to a word array.\n\t *\n\t * @param {string} latin1Str The Latin1 string.\n\t *\n\t * @return {WordArray} The word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.enc.Latin1.parse(latin1String);\n\t */\n\t parse: function (latin1Str) {\n\t // Shortcut\n\t var latin1StrLength = latin1Str.length;\n\n\t // Convert\n\t var words = [];\n\t for (var i = 0; i < latin1StrLength; i++) {\n\t words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);\n\t }\n\n\t return new WordArray.init(words, latin1StrLength);\n\t }\n\t };\n\n\t /**\n\t * UTF-8 encoding strategy.\n\t */\n\t var Utf8 = C_enc.Utf8 = {\n\t /**\n\t * Converts a word array to a UTF-8 string.\n\t *\n\t * @param {WordArray} wordArray The word array.\n\t *\n\t * @return {string} The UTF-8 string.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);\n\t */\n\t stringify: function (wordArray) {\n\t try {\n\t return decodeURIComponent(escape(Latin1.stringify(wordArray)));\n\t } catch (e) {\n\t throw new Error('Malformed UTF-8 data');\n\t }\n\t },\n\n\t /**\n\t * Converts a UTF-8 string to a word array.\n\t *\n\t * @param {string} utf8Str The UTF-8 string.\n\t *\n\t * @return {WordArray} The word array.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var wordArray = CryptoJS.enc.Utf8.parse(utf8String);\n\t */\n\t parse: function (utf8Str) {\n\t return Latin1.parse(unescape(encodeURIComponent(utf8Str)));\n\t }\n\t };\n\n\t /**\n\t * Abstract buffered block algorithm template.\n\t *\n\t * The property blockSize must be implemented in a concrete subtype.\n\t *\n\t * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0\n\t */\n\t var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({\n\t /**\n\t * Resets this block algorithm's data buffer to its initial state.\n\t *\n\t * @example\n\t *\n\t * bufferedBlockAlgorithm.reset();\n\t */\n\t reset: function () {\n\t // Initial values\n\t this._data = new WordArray.init();\n\t this._nDataBytes = 0;\n\t },\n\n\t /**\n\t * Adds new data to this block algorithm's buffer.\n\t *\n\t * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.\n\t *\n\t * @example\n\t *\n\t * bufferedBlockAlgorithm._append('data');\n\t * bufferedBlockAlgorithm._append(wordArray);\n\t */\n\t _append: function (data) {\n\t // Convert string to WordArray, else assume WordArray already\n\t if (typeof data == 'string') {\n\t data = Utf8.parse(data);\n\t }\n\n\t // Append\n\t this._data.concat(data);\n\t this._nDataBytes += data.sigBytes;\n\t },\n\n\t /**\n\t * Processes available data blocks.\n\t *\n\t * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.\n\t *\n\t * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.\n\t *\n\t * @return {WordArray} The processed data.\n\t *\n\t * @example\n\t *\n\t * var processedData = bufferedBlockAlgorithm._process();\n\t * var processedData = bufferedBlockAlgorithm._process(!!'flush');\n\t */\n\t _process: function (doFlush) {\n\t var processedWords;\n\n\t // Shortcuts\n\t var data = this._data;\n\t var dataWords = data.words;\n\t var dataSigBytes = data.sigBytes;\n\t var blockSize = this.blockSize;\n\t var blockSizeBytes = blockSize * 4;\n\n\t // Count blocks ready\n\t var nBlocksReady = dataSigBytes / blockSizeBytes;\n\t if (doFlush) {\n\t // Round up to include partial blocks\n\t nBlocksReady = Math.ceil(nBlocksReady);\n\t } else {\n\t // Round down to include only full blocks,\n\t // less the number of blocks that must remain in the buffer\n\t nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);\n\t }\n\n\t // Count words ready\n\t var nWordsReady = nBlocksReady * blockSize;\n\n\t // Count bytes ready\n\t var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);\n\n\t // Process blocks\n\t if (nWordsReady) {\n\t for (var offset = 0; offset < nWordsReady; offset += blockSize) {\n\t // Perform concrete-algorithm logic\n\t this._doProcessBlock(dataWords, offset);\n\t }\n\n\t // Remove processed words\n\t processedWords = dataWords.splice(0, nWordsReady);\n\t data.sigBytes -= nBytesReady;\n\t }\n\n\t // Return processed words\n\t return new WordArray.init(processedWords, nBytesReady);\n\t },\n\n\t /**\n\t * Creates a copy of this object.\n\t *\n\t * @return {Object} The clone.\n\t *\n\t * @example\n\t *\n\t * var clone = bufferedBlockAlgorithm.clone();\n\t */\n\t clone: function () {\n\t var clone = Base.clone.call(this);\n\t clone._data = this._data.clone();\n\n\t return clone;\n\t },\n\n\t _minBufferSize: 0\n\t });\n\n\t /**\n\t * Abstract hasher template.\n\t *\n\t * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)\n\t */\n\t var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({\n\t /**\n\t * Configuration options.\n\t */\n\t cfg: Base.extend(),\n\n\t /**\n\t * Initializes a newly created hasher.\n\t *\n\t * @param {Object} cfg (Optional) The configuration options to use for this hash computation.\n\t *\n\t * @example\n\t *\n\t * var hasher = CryptoJS.algo.SHA256.create();\n\t */\n\t init: function (cfg) {\n\t // Apply config defaults\n\t this.cfg = this.cfg.extend(cfg);\n\n\t // Set initial values\n\t this.reset();\n\t },\n\n\t /**\n\t * Resets this hasher to its initial state.\n\t *\n\t * @example\n\t *\n\t * hasher.reset();\n\t */\n\t reset: function () {\n\t // Reset data buffer\n\t BufferedBlockAlgorithm.reset.call(this);\n\n\t // Perform concrete-hasher logic\n\t this._doReset();\n\t },\n\n\t /**\n\t * Updates this hasher with a message.\n\t *\n\t * @param {WordArray|string} messageUpdate The message to append.\n\t *\n\t * @return {Hasher} This hasher.\n\t *\n\t * @example\n\t *\n\t * hasher.update('message');\n\t * hasher.update(wordArray);\n\t */\n\t update: function (messageUpdate) {\n\t // Append\n\t this._append(messageUpdate);\n\n\t // Update the hash\n\t this._process();\n\n\t // Chainable\n\t return this;\n\t },\n\n\t /**\n\t * Finalizes the hash computation.\n\t * Note that the finalize operation is effectively a destructive, read-once operation.\n\t *\n\t * @param {WordArray|string} messageUpdate (Optional) A final message update.\n\t *\n\t * @return {WordArray} The hash.\n\t *\n\t * @example\n\t *\n\t * var hash = hasher.finalize();\n\t * var hash = hasher.finalize('message');\n\t * var hash = hasher.finalize(wordArray);\n\t */\n\t finalize: function (messageUpdate) {\n\t // Final message update\n\t if (messageUpdate) {\n\t this._append(messageUpdate);\n\t }\n\n\t // Perform concrete-hasher logic\n\t var hash = this._doFinalize();\n\n\t return hash;\n\t },\n\n\t blockSize: 512/32,\n\n\t /**\n\t * Creates a shortcut function to a hasher's object interface.\n\t *\n\t * @param {Hasher} hasher The hasher to create a helper for.\n\t *\n\t * @return {Function} The shortcut function.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);\n\t */\n\t _createHelper: function (hasher) {\n\t return function (message, cfg) {\n\t return new hasher.init(cfg).finalize(message);\n\t };\n\t },\n\n\t /**\n\t * Creates a shortcut function to the HMAC's object interface.\n\t *\n\t * @param {Hasher} hasher The hasher to use in this HMAC helper.\n\t *\n\t * @return {Function} The shortcut function.\n\t *\n\t * @static\n\t *\n\t * @example\n\t *\n\t * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);\n\t */\n\t _createHmacHelper: function (hasher) {\n\t return function (message, key) {\n\t return new C_algo.HMAC.init(hasher, key).finalize(message);\n\t };\n\t }\n\t });\n\n\t /**\n\t * Algorithm namespace.\n\t */\n\t var C_algo = C.algo = {};\n\n\t return C;\n\t}(Math));\n\n\n\treturn CryptoJS;\n\n}));","'use strict';\r\nimport 'es6-promise/auto';\r\n\r\n// Object.assign\r\nfunction objectAssign(target, varArgs) { // .length of function is 2\r\n\t'use strict';\r\n\tif (target == null) { // TypeError if undefined or null\r\n\t\tthrow new TypeError('Cannot convert undefined or null to object');\r\n\t}\r\n\r\n\tvar to = Object(target);\r\n\r\n\tfor (var index = 1; index < arguments.length; index++) {\r\n\t\tvar nextSource = arguments[index];\r\n\r\n\t\tif (nextSource != null) { // Skip over if undefined or null\r\n\t\t\tfor (var nextKey in nextSource) {\r\n\t\t\t\t// Avoid bugs when hasOwnProperty is shadowed\r\n\t\t\t\tif (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\r\n\t\t\t\t\tto[nextKey] = nextSource[nextKey];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn to;\r\n}\r\n\r\n// Array.includes\r\nfunction arrayIncludes(searchElement /*, fromIndex*/ ) {\r\n\tvar O = Object(this);\r\n\tvar len = parseInt(O.length, 10) || 0;\r\n\tif (len === 0) {\r\n\t\treturn false;\r\n\t}\r\n\tvar n = parseInt(arguments[1], 10) || 0;\r\n\tvar k;\r\n\tif (n >= 0) {\r\n\t\tk = n;\r\n\t} else {\r\n\t\tk = len + n;\r\n\t\tif (k < 0) {k = 0;}\r\n\t}\r\n\tvar currentElement;\r\n\twhile (k < len) {\r\n\t\tcurrentElement = O[k];\r\n\t\tif (searchElement === currentElement ||\r\n\t\t\t(searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t\tk++;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// String.endsWidth\r\nfunction stringEndsWith(searchString, position) {\r\n\tvar subjectString = this.toString();\r\n\tif (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {\r\n\t\tposition = subjectString.length;\r\n\t}\r\n\tposition -= searchString.length;\r\n\tvar lastIndex = subjectString.indexOf(searchString, position);\r\n\treturn lastIndex !== -1 && lastIndex === position;\r\n}\r\n\r\n// String.startsWith\r\nfunction stringStartsWith(searchString, position){\r\n\tposition = position || 0;\r\n\treturn this.substr(position, searchString.length) === searchString;\r\n}\r\n\r\n\r\nfunction arrayFind(predicate) {\r\n\tif (this == null) {\r\n\t\tthrow new TypeError('Array.prototype.find called on null or undefined');\r\n\t}\r\n\tif (typeof predicate !== 'function') {\r\n\t\tthrow new TypeError('predicate must be a function');\r\n\t}\r\n\tvar list = Object(this);\r\n\tvar len = list.length >>> 0; // eslint-disable-line no-bitwise\r\n\tvar thisArg = arguments[1];\r\n\tvar value;\r\n\r\n\tfor (var i = 0; i < len; i++) {\r\n\t\tvalue = list[i];\r\n\t\tif (predicate.call(thisArg, value, i, list)) {\r\n\t\t\treturn value;\r\n\t\t}\r\n\t}\r\n\treturn undefined;\r\n}\r\n\r\nfunction arrayFindIndex(predicate) {\r\n\tif (this == null) {\r\n\t\tthrow new TypeError('Array.prototype.findIndex called on null or undefined');\r\n\t}\r\n\tif (typeof predicate !== 'function') {\r\n\t\tthrow new TypeError('predicate must be a function');\r\n\t}\r\n\tvar list = Object(this);\r\n\tvar len = list.length >>> 0; // eslint-disable-line no-bitwise\r\n\tvar thisArg = arguments[1];\r\n\tvar value;\r\n\r\n\tfor (var i = 0; i < len; i++) {\r\n\t\tvalue = list[i];\r\n\t\tif (predicate.call(thisArg, value, i, list)) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n// Production steps of ECMA-262, Edition 6, 22.1.2.1\r\nfunction arrayFrom() {\r\n\tvar toStr = Object.prototype.toString;\r\n\tvar isCallable = function (fn) {\r\n\t\treturn typeof fn === 'function' || toStr.call(fn) === '[object Function]';\r\n\t};\r\n\tvar toInteger = function (value) {\r\n\t\tvar number = Number(value);\r\n\t\tif (isNaN(number)) { return 0; }\r\n\t\tif (number === 0 || !isFinite(number)) { return number; }\r\n\t\treturn (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\r\n\t};\r\n\tvar maxSafeInteger = Math.pow(2, 53) - 1;\r\n\tvar toLength = function (value) {\r\n\t\tvar len = toInteger(value);\r\n\t\treturn Math.min(Math.max(len, 0), maxSafeInteger);\r\n\t};\r\n\r\n\t// The length property of the from method is 1.\r\n\treturn function from(arrayLike/*, mapFn, thisArg */) {\r\n\t\t// 1. Let C be the this value.\r\n\t\tvar C = this;\r\n\r\n\t\t// 2. Let items be ToObject(arrayLike).\r\n\t\tvar items = Object(arrayLike);\r\n\r\n\t\t// 3. ReturnIfAbrupt(items).\r\n\t\tif (arrayLike == null) {\r\n\t\t\tthrow new TypeError('Array.from requires an array-like object - not null or undefined');\r\n\t\t}\r\n\r\n\t\t// 4. If mapfn is undefined, then let mapping be false.\r\n\t\tvar mapFn = arguments.length > 1 ? arguments[1] : void undefined;\r\n\t\tvar T;\r\n\t\tif (typeof mapFn !== 'undefined') {\r\n\t\t\t// 5. else\r\n\t\t\t// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\r\n\t\t\tif (!isCallable(mapFn)) {\r\n\t\t\t\tthrow new TypeError('Array.from: when provided, the second argument must be a function');\r\n\t\t\t}\r\n\r\n\t\t\t// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\r\n\t\t\tif (arguments.length > 2) {\r\n\t\t\t\tT = arguments[2];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// 10. Let lenValue be Get(items, \"length\").\r\n\t\t// 11. Let len be ToLength(lenValue).\r\n\t\tvar len = toLength(items.length);\r\n\r\n\t\t// 13. If IsConstructor(C) is true, then\r\n\t\t// 13. a. Let A be the result of calling the [[Construct]] internal method\r\n\t\t// of C with an argument list containing the single item len.\r\n\t\t// 14. a. Else, Let A be ArrayCreate(len).\r\n\t\tvar A = isCallable(C) ? Object(new C(len)) : new Array(len);\r\n\r\n\t\t// 16. Let k be 0.\r\n\t\tvar k = 0;\r\n\t\t// 17. Repeat, while k < len… (also steps a - h)\r\n\t\tvar kValue;\r\n\t\twhile (k < len) {\r\n\t\t\tkValue = items[k];\r\n\t\t\tif (mapFn) {\r\n\t\t\t\tA[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\r\n\t\t\t} else {\r\n\t\t\t\tA[k] = kValue;\r\n\t\t\t}\r\n\t\t\tk += 1;\r\n\t\t}\r\n\t\t// 18. Let putStatus be Put(A, \"length\", len, true).\r\n\t\tA.length = len;\r\n\t\t// 20. Return A.\r\n\t\treturn A;\r\n\t};\r\n}\r\n\r\n// Number.isInteger polyfill\r\nfunction numberIsInteger(value) {\r\n\treturn typeof value === 'number' && isFinite(value) && Math.floor(value) === value;\r\n}\r\n\r\n/////\r\n// Run the polyfills\r\n//\r\nif (typeof Object.assign !== 'function') {\r\n\tObject.defineProperty(Object, 'assign', {\r\n\t\tconfigurable: true,\r\n\t\twritable: true,\r\n\t\tvalue: objectAssign\r\n\t});\r\n}\r\nif (!Array.prototype.includes) { Array.prototype.includes = arrayIncludes; }\r\nif (!String.prototype.endsWith) { String.prototype.endsWith = stringEndsWith; }\r\nif (!String.prototype.startsWith) { String.prototype.startsWith = stringStartsWith; }\r\nif (!Array.prototype.find) { Array.prototype.find = arrayFind; }\r\nif (!Array.prototype.findIndex) { Array.prototype.findIndex = arrayFindIndex; }\r\nif (!Number.isInteger) { Number.isInteger = numberIsInteger; }\r\nif (!Array.from) { Array.from = arrayFrom(); }\r\n","import * as store from '../../util/store';\r\nimport * as events from '../../util/event-bus';\r\n\r\n/**\r\n * Launches a modal window with a countdown until sessions times out.\r\n * @class Sidekick.SessionTimeout\r\n * @memberOf Sidekick\r\n * @param {EasyDom} elem - Container {@link EasyDom} element\r\n * @param {Object} attrs\r\n * @param {Object} ctx\r\n * @param {Function} i18n - translation function\r\n * @emits session.logout - Thrown when the logout button is clicked\r\n * @emits session.extend - Thrown when the stay signed in button is clicked\r\n * @listens session-timeout.clear - Clears the countdown and hides the modal\r\n * @example\r\n * timer: seconds to countdown\r\n * {\r\n\t'timer': 180\r\n}\r\n */\r\n\r\n\r\nclass Countdown {\r\n\tconstructor() {\r\n this.duration = 0;\r\n this.elapsed = 0;\r\n this.isActive = false;\r\n this.lastFrameTime = Date.now();\r\n this.onTick = () => {};\r\n this.onCompleted = () => {};\r\n\r\n this.tick();\r\n }\r\n\r\n getTimeLeft() {\r\n const t = this.duration - this.elapsed;\r\n\r\n return Math.max(0, t);\r\n }\r\n\r\n pause() {\r\n\tthis.isActive = false;\r\n return this;\r\n }\r\n\r\n reset() {\r\n\tthis.isActive = false;\r\n this.elapsed = 0;\r\n }\r\n\r\n setDuration(seconds) {\r\n this.lastFrameTime = Date.now();\r\n this.duration = seconds;\r\n\r\n return this;\r\n }\r\n\r\n start() {\r\n\tthis.isActive = true;\r\n\r\n return this;\r\n }\r\n\r\n tick() {\r\n\tconst currentFrameTime = Date.now();\r\n const deltaTime = currentFrameTime - this.lastFrameTime;\r\n this.lastFrameTime = currentFrameTime;\r\n\r\n if (this.isActive) {\r\n this.elapsed += deltaTime / 1000;\r\n this.onTick(this.getTimeLeft());\r\n\r\n if(this.getTimeLeft() <= 0) {\r\n this.pause();\r\n this.onCompleted();\r\n }\r\n }\r\n\r\n window.requestAnimationFrame(this.tick.bind(this));\r\n }\r\n}\r\n\r\nexport default function(elem, attrs, ctx, i18n) {\r\n\r\n\tlet timerInterval;\r\n\r\n\t/////\r\n\t// find dom elements that we care about\r\n\t//\r\n\tconst domLogout = elem.find('.sk--logout')[0];\r\n\tconst domExtendBtn = elem.find('.sk--extend')[0];\r\n\tconst domTimer = elem.find('.sk--timer')[0];\r\n\tconst domSignedOut = elem.find('.sk--signed-out')[0];\r\n\tconst domSignInLink = elem.find('.sk--sign-in-link')[0];\r\n\r\n\t/////\r\n\t// handle initial state and data changes\r\n\t//\r\n\tstore.onValue('session-timeout', load);\r\n\tevents.on('session-timeout.clear', clear);\r\n\r\n\t/////\r\n\t// listen for events and take action\r\n\t//\r\n\tdomSignInLink.on('click', evt => {\r\n\t\tevt.stopPropagation();\r\n\t\tevt.preventDefault();\r\n\r\n\t\t// reload the page on the current url so we come back to what we were doing.\r\n\t\twindow.location.reload();\r\n\t});\r\n\r\n\tdomLogout.on('click', evt => {\r\n\t\tevt.stopPropagation();\r\n\t\tevt.preventDefault();\r\n\r\n\t\tclearInterval(timerInterval);\r\n\r\n\t\tevents.emit('session.logout');\r\n\t\tevents.emit('sk-menu-close', elem);\r\n\t});\r\n\r\n\tdomExtendBtn.on('click', evt => {\r\n\t\tevt.stopPropagation();\r\n\t\tevt.preventDefault();\r\n\r\n\t\tclear();\r\n\r\n\t\tevents.emit('session.extend');\r\n\t\tevents.emit('sk-menu-close', elem);\r\n\t});\r\n\r\n\t/////\r\n\t// helper functions\r\n\t//\r\n\r\n\t// timer defaults to 3 minutes\r\n\tlet countdown;\r\n\tfunction load({timer = 180} = {}) {\r\n\t\tcountdown = new Countdown().setDuration(timer);\r\n\r\n\t\t// show the main component (which starts out hidden)\r\n\t\telem.addClass('show');\r\n\r\n\t\tif (timer <= 0) {\r\n\t\t\tevents.emit('session-timeout.timer-end');\r\n\t\t\tshowSignedOutScreen();\r\n\t\t\treturn; // they are already signed out... we be done\r\n\t\t}\r\n\r\n\t\t// fill the countdown timer and show it\r\n\r\n\t\tcountdown.onTick = (time) => {\r\n\t\t\tdomTimer._.innerHTML = format(Math.round(time));\r\n\t\t};\r\n\t\tcountdown.start();\r\n\t}\r\n\r\n\tcountdown.onCompleted = () => {\r\n\t\tevents.emit('session-timeout.timer-end');\r\n\t\tshowSignedOutScreen();\r\n\t};\r\n\r\n\tfunction showSignedOutScreen() {\r\n\t\tdomSignedOut.addClass('show');\r\n\t\tevents.emit('sk-menu-close', elem);\r\n\t}\r\n\r\n\tfunction format(val) {\r\n\t\tvar seconds = val;\r\n\t\tvar minutes = Math.floor(seconds / 60);\r\n\t\tseconds -= minutes * 60;\r\n\r\n\t\tif (seconds < 10) {\r\n\t\t\tseconds = '0' + seconds;\r\n\t\t}\r\n\t\treturn minutes + ':' + seconds;\r\n\t}\r\n\r\n\tfunction clear() {\r\n\t\tcountdown.reset();\r\n\t\tdomTimer._.innerHTML = Math.ceil(countdown.getTimeLeft());\r\n\t\tdomSignedOut.removeClass('show');\r\n\t\telem.removeClass('show');\r\n\t}\r\n};\r\n","import * as dom from '../../util/easy-dom';\r\nimport * as events from '../../util/event-bus';\r\nimport {pathMatchesRoute} from '../../util/route-helpers';\r\nimport {isArray} from '../../util/type-checkers';\r\n\r\nexport default function(elem, attrs, ctx, i18n) {\r\n\r\n\t// backward compatability with item.route value\r\n\tctx.url = ctx.url || ctx.route || null;\r\n\tif (ctx.isPlatformMenu) { elem.addClass('sk--platform-menu'); }\r\n\r\n\tlet subMenu = null;\r\n\tif (ctx.children && ctx.children.length) {\r\n\t\tconst subMenuType = (shouldWeMega(ctx.children) ? 'mega-menu' : 'submenu');\r\n\t\tsubMenu = dom.parse(`
`);\r\n\t\tsubMenu._.context = ctx.children;\r\n\t\telem.append(subMenu);\r\n\t\telem.addClass('sk--has-children');\r\n\t} else {\r\n\t\tvar a = elem.find('.sk--main-menu-item-container')[0];\r\n\t\tif (ctx.target) {\r\n\t\t\ta.attr('target', ctx.target);\r\n\t\t}\r\n\t\telem.addClass('sk--menu-action');\r\n\t\tconst menuType = (ctx.isPlatformMenu ? 'plat-menu-item' : 'menu-item');\r\n\t\telem.on('click', evt => events.emit(`nav.${menuType}-clicked`, ctx, evt));\r\n\t}\r\n\r\n\tif (ctx.badgeEvent != null) {\r\n\t\tconst domBadge = elem.find('.sk--badge')[0];\r\n\r\n\t\tevents.on(ctx.badgeEvent, data => {\r\n\t\t\tdomBadge.css('display', 'none');\r\n\t\t\tdomBadge.removeClass('sk--max');\r\n\r\n\t\t\tif (data === true) {\r\n\t\t\t\tdomBadge.css('display', 'block');\r\n\t\t\t\tdomBadge.addClass('sk--empty');\r\n\t\t\t} else if (Number.isInteger(data)) {\r\n\t\t\t\tif (data < 1) { return; }\r\n\r\n\t\t\t\tdomBadge.css('display', 'block');\r\n\r\n\t\t\t\tdomBadge.css('display', 'block');\r\n\t\t\t\tdomBadge._.innerHTML = Math.min(data, 99);\r\n\r\n\t\t\t\tif (data > 99) {\r\n\t\t\t\t\tdomBadge.addClass('sk--max');\r\n\t\t\t\t\tdomBadge._.innerHTML += '+';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}, true);\r\n\t}\r\n\r\n\tevents.on('_location.path-change', highlightRoute);\r\n\r\n\tfunction highlightRoute(path) {\r\n\t\tconst highlighted = pathMatchesRoute(path, ctx.url, ctx.routeMatcher, ctx.baseUrl);\r\n\t\telem.toggleClass('highlight', highlighted);\r\n\t}\r\n\r\n\tfunction shouldWeMega(children) {\r\n\t\tconst noOrphanNodes = children.every(n => isArray(n.children));\r\n\t\tconst totalNodes = countNodes(children);\r\n\t\treturn noOrphanNodes && totalNodes <= 30;\r\n\t}\r\n\r\n\tfunction countNodes(children) {\r\n\t\t// children must be an array\r\n\t\tif (!isArray(children)) { return 0; }\r\n\t\treturn children.reduce(function (total, child) {\r\n\t\t\t++total;\r\n\t\t\tif (isArray(child.children)) { total += child.children.length; }\r\n\t\t\treturn total;\r\n\t\t}, 0);\r\n\t}\r\n};\r\n","export function glean(source, accessor, defaultValue = null) {\r\n try {\r\n const val = accessor(source);\r\n if (typeof val === 'undefined') { return defaultValue; }\r\n return val;\r\n } catch (err) {\r\n return defaultValue;\r\n }\r\n}\r\n","import { glean } from './object-helpers';\r\n\r\n/**\r\n * @module Sidekick.AssetLoader\r\n * @memberOf Sidekick\r\n */\r\n\r\n/**\r\n * Returns the base path, respecting Storm's overridden value if it is set\r\n * @function baseAssetPath\r\n * @instance\r\n */\r\nexport function getBaseAssetPath() {\r\n\tconst currentSidekickSrc = document.currentScript && document.currentScript.src ? document.currentScript.src : 'https://sidekick.uitools.frontlineeducation.com';\r\n\tconst sidekickUrl = new URL(currentSidekickSrc);\r\n\tconst defaultUrl = sidekickUrl.origin;\r\n\treturn glean(window, (w) => w.ss.env.tools.sidekick, defaultUrl);\r\n}\r\n\r\nconst baseAssetPath = getBaseAssetPath();\r\n\r\nexport function isUrlUiModule(url) {\r\n\tconst urlPattern = /^https:\\/\\/(supersuitaws(.*?)\\.flqa\\.net|(app|zeit)\\.frontlineeducation\\.com)\\//;\r\n\treturn urlPattern.test(url);\r\n}\r\n\r\n/**\r\n * Loads a script\r\n * @function script\r\n * @instance\r\n * @param {String} fileName\r\n */\r\nexport const script = loadScript;\r\n\r\n/**\r\n * Loads a style sheet\r\n * @function stylesheet\r\n * @instance\r\n * @param {String} fileName\r\n * @param {Function} success\r\n * @param {Function} failure\r\n */\r\nexport const stylesheet = loadStylesheet;\r\n\r\n/**\r\n * Loads the sidekick print styles (hides sidekick for print)\r\n * @function printStyles\r\n * @instance\r\n */\r\nexport const printStyles = function() {\r\n\tconst el = document.createElement('style');\r\n\tel.setAttribute('type', 'text/css');\r\n\tel.setAttribute('media', 'print');\r\n\tel.innerHTML = '.sidekick { display: none !important; } .sidekick-wrapped-application {\tmargin: 0 !important } ';\r\n\tdocument.head.appendChild(el);\r\n};\r\n\r\n\r\n/**\r\n * Loads a font\r\n * @function fontFace\r\n * @instance\r\n * @param {String} fontName\r\n */\r\nexport const fontFace = loadFont;\r\n\r\n/////\r\n// helper functions\r\n//\r\n\r\nfunction loadStylesheet(fileName, success, basePath = baseAssetPath) {\r\n\tconst fileLoc = `${basePath}/${fileName}`;\r\n\tconst linkAttrs = {\r\n\t\t'rel': 'stylesheet',\r\n\t\t'media': 'screen',\r\n\t\t'charset': 'utf-8',\r\n\t\t'href': fileLoc,\r\n\t};\r\n\tconst styleTestAttrs = {\r\n\t\tstyle: 'display: none;',\r\n\t\t'class': 'sidekick-stylesheet-test',\r\n\t};\r\n\r\n\tconst linkEl = injectTag('link', linkAttrs, document.head);\r\n\t// watch hidden element for style update from sidekick.css\r\n\tconst styleTestEl = injectTag('div', styleTestAttrs, document.body);\r\n\r\n\tconst checkStyles = setInterval( function() {\r\n\t\ttry {\r\n\t\t\tif (window.getComputedStyle(styleTestEl).visibility === 'hidden') {\r\n\t\t\t\tclearInterval(checkStyles);\r\n\t\t\t\tsuccess(linkEl);\r\n\t\t\t\tdocument.body.removeChild(styleTestEl);\r\n\t\t\t}\r\n\t\t} catch(e) {}\r\n\t}, 50);\r\n}\r\n\r\nfunction loadScript(fileName, basePath = baseAssetPath) {\r\n\tconst fileLoc = `${basePath}/${fileName}`;\r\n\tconst attrs = {'type':'text/javascript', 'charset':'utf-8', 'src':fileLoc};\r\n\treturn injectTag('script', attrs, document.body);\r\n}\r\n\r\nfunction injectTag(tagName, attrs, target) {\r\n\tconst el = document.createElement(tagName);\r\n\tObject.keys(attrs).sort().forEach(attr => el.setAttribute(attr, attrs[attr]));\r\n\ttarget.appendChild(el);\r\n\treturn el;\r\n}\r\n\r\nconst fontCode = {\r\n\t'fl-icons': fontFaceCss('FL-Icons', 'FL-Icons', 'FL-Icons', 'normal', 'normal'),\r\n\t'open-sans': (\r\n\t\t// Open Sans: regular\r\n\t\tfontFaceCss('Open Sans', 'opensans-regular-webfont', 'open_sansregular', 400, 'normal') +\r\n\t\t// Open Sans: semi-bold\r\n\t\tfontFaceCss('Open Sans', 'opensans-semibold-webfont', 'open_sanssemibold', 600, 'normal') +\r\n\t\t// Open Sans: bold\r\n\t\tfontFaceCss('Open Sans', 'opensans-bold-webfont', 'open_sansbold', 700, 'normal')\r\n\t)\r\n};\r\nfunction loadFont(fontName) {\r\n\tconst el = document.createElement('style');\r\n\tel.setAttribute('type', 'text/css');\r\n\tel.innerHTML = fontCode[fontName.toLowerCase()];\r\n\tdocument.head.appendChild(el);\r\n}\r\n\r\nfunction fontFaceCss(fontName, fileName, svgType, fontWeight, fontStyle) {\r\n\treturn (`\r\n\t\t@font-face {\r\n\t\t\tfont-family: '${fontName}';\r\n\t\t\tsrc: url('${baseAssetPath}/font/${fileName}.eot?#iefix') format('embedded-opentype'),\r\n\t\t\t\turl('${baseAssetPath}/font/${fileName}.woff') format('woff'),\r\n\t\t\t\turl('${baseAssetPath}/font/${fileName}.ttf') format('truetype'),\r\n\t\t\t\turl('${baseAssetPath}/font/${fileName}.svg#${svgType}') format('svg');\r\n\t\t\tfont-weight: ${fontWeight};\r\n\t\t\tfont-style: ${fontStyle};\r\n\t\t}\r\n\t`).replace(/[\\t\\n]+/g, ' ').replace(/^\\s+|\\s+$/g, '');\r\n}\r\n","\r\n/**\r\n * Common string helper functions\r\n * @module Sidekick.StringHelpers\r\n * @memberOf Sidekick\r\n */\r\n\r\n/**\r\n * Turns a space delimited string to dash delimited.\r\n * @function toDashCase\r\n * @instance\r\n * @param {String} txt - String to transform\r\n */\r\nexport function toDashCase(txt) {\r\n\treturn splitWords(txt).join('-');\r\n}\r\n\r\n/**\r\n * Turns a space delimited string to camel case.\r\n * @function toDashCase\r\n * @instance\r\n * @param {String} txt - String to transform\r\n */\r\nexport function toCamelCase(txt) {\r\n\treturn splitWords(txt)\r\n\t\t.map(function (v,i) {\r\n\t\t\tif (i === 0) { return v; }\r\n\t\t\treturn v.charAt(0).toUpperCase() + v.substr(1);\r\n\t\t})\r\n\t\t.join('');\r\n}\r\n\r\nfunction splitWords(txt) {\r\n\treturn txt.toString()\r\n\t\t.replace(/[\\s_-]/g, '{!}')\r\n\t\t.replace(/([A-Z])/g, '{!}$1')\r\n\t\t.toLowerCase()\r\n\t\t.split('{!}')\r\n\t\t.filter(function (v) { return !!v.length; });\r\n}\r\n","import {toDashCase, toCamelCase} from './string-helpers';\r\n\r\n/**\r\n * @module Sidekick.EasyDom\r\n * @memberOf Sidekick\r\n */\r\n\r\n/**\r\n * Creates a new {@link EasyDom} element from the Element.\r\n * @function element\r\n * @instance\r\n * @param {Element} el - Element from which to wrap in {@link EasyDom}\r\n * @return {EasyDom} the new {@link EasyDom} element\r\n */\r\nexport const element = el => new EasyDom(el);\r\n\r\n/**\r\n * Finds an {@link EasyDom} element based on the selector.\r\n * @function find\r\n * @instance\r\n * @param {String} selector - Selector to look for elements from\r\n * @param {EasyDom} [parent=false] - Parent element to start the search in\r\n * @return {Array}\r\n */\r\nexport const find = elSelector;\r\n\r\n/**\r\n * Parses an HTML string, creates an Element, then returns it as an {@link EasyDom} element.\r\n * @function parse\r\n * @instance\r\n * @param {Element} el - Element from which to wrap in {@link EasyDom}\r\n * @return {EasyDom} the new {@link EasyDom} element\r\n */\r\nexport const parse = function (html) {\r\n\tconst el = document.createElement('span');\r\n\tel.innerHTML = html;\r\n\tif (el.children.length === 1) { return element(el.children[0]); }\r\n\treturn element(el);\r\n};\r\n\r\n/**\r\n * Runs a function on a timer (requestAnimationFrame)\r\n * @function rAF\r\n * @instance\r\n * @param {Function} callback - Callback when the timer runs\r\n */\r\nexport const rAF = (\r\n\t(window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) ||\r\n\t(window.webkitRequestAnimationFrame && window.webkitRequestAnimationFrame.bind(window)) ||\r\n\t(window.mozRequestAnimationFrame && window.mozRequestAnimationFrame.bind(window)) ||\r\n\t(window.oRequestAnimationFrame && window.oRequestAnimationFrame.bind(window)) ||\r\n\t(window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) ||\r\n\tfunction (callback) { window.setTimeout( callback, 1000 / 60 ); }\r\n);\r\n\r\nconst domCache = [];\r\n\r\n/**\r\n * EasyDom wrapper around HTML elements.\r\n * @class\r\n */\r\nclass EasyDom {\r\n\t/**\r\n\t * @param {Element} domNode\r\n\t */\r\n\tconstructor(domNode) {\r\n\t\t// if we have already built an EasyDom object for this domNode, pull it from cache\r\n\t\tif (domNode._easyDomID != null) { return domCache[domNode._easyDomID]; }\r\n\t\tthis._ = domNode;\r\n\t\tdomNode._easyDomID = domCache.length;\r\n\t\tdomCache.push(this);\r\n\t}\r\n\r\n\t/**\r\n\t * @inner\r\n\t * @param {String} selector - Selector for finding an element\r\n\t * @return {EasyDom}\r\n\t */\r\n\tfind(selector) { return elSelector(selector, this._); }\r\n\r\n\t/**\r\n\t * @param {String} cls - Classname to add\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\taddClass(cls) {\r\n\t\tconst prefix = (this._.className.length ? ' ' : '');\r\n\t\tif (!this.hasClass(cls)) { this._.className += `${prefix}${cls}`; }\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * @param {String} cls - Classname to remove\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tremoveClass(cls) {\r\n\t\tthis._.className = this._.className\r\n\t\t\t.split(' ')\r\n\t\t\t.filter(c => c !== cls && c.length > 0)\r\n\t\t\t.join(' ');\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * @param {String} cls - Classname to test if this element has.\r\n\t * @return {Boolean} Whether or not this element has the classname specified.\r\n\t */\r\n\thasClass(cls) { return this._.className.split(' ').includes(cls); }\r\n\r\n\t/**\r\n\t * @param {String} cls - Classname to toggle\r\n\t * @param {String} [state] - current state\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\ttoggleClass(cls, state) {\r\n\t\tif (state == null) { state = !this._.className.split(' ').includes(cls); }\r\n\t\treturn this[`${state ? 'add' : 'remove'}Class`](cls);\r\n\t}\r\n\r\n\t/**\r\n\t * @param {EasyDom|EasyDom[]} elem - Element to append to this element's children\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tappend(elem) {\r\n\t\tif (elem == null) { return; }\r\n\t\tconst elCount = elem.length;\r\n\t\tif (elCount == null) {\r\n\t\t\tthis._.appendChild(elem instanceof EasyDom ? elem._ : elem);\r\n\t\t} else {\r\n\t\t\t// we have an array of elements, recurse over the elements\r\n\t\t\tfor (let i = 0; i < elCount; i++) { this.append(elem[i]); }\r\n\t\t}\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * @param {String} name - Attribute name to get/set value for\r\n\t * @param {*} [value] - Value to set the attribute to\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tattr(name, value) {\r\n\t\tif (value === undefined) { return this._.getAttribute(name); }\r\n\t\tif (value === null) { this._.removeAttribute(name); return this; }\r\n\r\n\t\tthis._.setAttribute(toDashCase(name), value);\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * @param {String} name - Data attribute name to get/set value for\r\n\t * @param {*} [value] - Value to set the attribute to\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tdata(name, value) {\r\n\t\treturn this.attr(`data-${toDashCase(name)}`, value);\r\n\t}\r\n\r\n\t/**\r\n\t * Empties this element of any children\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tempty() {\r\n\t\twhile (this._.firstChild) {\r\n\t\t\tthis._.removeChild(this._.firstChild);\r\n\t\t}\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the children to be the content being passed in.\r\n\t * @param {EasyDom|EasyDom[]} content\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tchildren(content) {\r\n\t\treturn this.empty().append(content);\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the {@link EasyDom} parent for this element\r\n\t * @return {EasyDom}\r\n\t */\r\n\tparent() {\r\n\t\treturn new EasyDom(this._.parentNode);\r\n\t}\r\n\r\n\t/**\r\n\t * Registers an event handler to an event.\r\n\t * @param {String} evt - Event to react to\r\n\t * @param {Function} handler - Function to handle the event\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\ton(evt, handler) {\r\n\t\tthis._listeners = this._listeners || [];\r\n\t\tthis._listeners.push({evt, handler});\r\n\t\tthis._.addEventListener(evt, handler);\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * Deregisters an event handler to an event.\r\n\t * @param {String} evt - Event to react to\r\n\t * @param {Function} handler - Function to handle the event\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\toff(evt, handler) {\r\n\t\tvar toRemove = [];\r\n\t\tif (evt == null && handler == null) {\r\n\t\t\t// remove all listeners\r\n\t\t\ttoRemove = this._listeners || [];\r\n\t\t} else if (handler == null) {\r\n\t\t\t// remove all listeners of this type\r\n\t\t\ttoRemove = this._listeners.filter(h => h.evt === evt);\r\n\t\t} else {\r\n\t\t\t// remove just one specific listener\r\n\t\t\ttoRemove = [this._listeners.find(h => h.evt === evt && h.handler === handler)].filter(Boolean);\r\n\t\t}\r\n\t\t// if we couldn't find the listener, bail out\r\n\t\tif (toRemove.length === 0) { return this; }\r\n\t\t// remove the dom listeners\r\n\t\ttoRemove.forEach(h => this._.removeEventListener(h.evt, h.handler));\r\n\t\t// clean out the listeners log\r\n\t\tthis._listeners = this._listeners.filter(l => !toRemove.includes(l));\r\n\t\treturn this; // for chaining\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the css property(ies) to the values\r\n\t * @param {Object|String} target\r\n\t * @param {String|Number} [value] - Only used if the target is a String\r\n\t * @return {EasyDom} Reference to the current {@link EasyDom} element.\r\n\t */\r\n\tcss(target, value) {\r\n\t\tif (target instanceof Array) { return; }\r\n\t\tif (target instanceof Object) {\r\n\t\t\tconst keys = Object.keys(target);\r\n\t\t\tfor (let i=keys.length; i-- ;) {\r\n\t\t\t\tconst k = keys[i];\r\n\t\t\t\tthis.css(k, target[k]);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (typeof target === 'string') {\r\n\t\t\tif (value === undefined) {\r\n\t\t\t\treturn window.getComputedStyle(this._)[target];\r\n\t\t\t}\r\n\t\t\tthis._.style[toCamelCase(target)] = value;\r\n\t\t}\r\n\t\treturn this;\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if this element currently has focus\r\n\t * @returns {Boolean}\r\n\t */\r\n\thasFocus() {\r\n\t\treturn window.document.activeElement === this._;\r\n\t}\r\n}\r\n\r\nfunction elSelector(selector, parent = false) {\r\n\tconst context = parent || document;\r\n\tconst isComplex = /^..*[\\.\\# ]+.+$/;\r\n\tconst useQSA = isComplex.test(selector);\r\n\tconst qsa = 'querySelectorAll';\r\n\tvar method = {\r\n\t\t'#': 'ById',\r\n\t\t'.': 'sByClassName',\r\n\t\t'@': 'sByName',\r\n\t\t'=': 'sByTagName'\r\n\t}[selector[0]];\r\n\r\n\tmethod = (method == null || useQSA ? qsa : `getElement${method}`);\r\n\tif (method !== qsa) { selector = selector.slice(1); }\r\n\treturn map(context[method](selector), el => new EasyDom(el));\r\n}\r\n\r\nfunction map(collection, func) {\r\n\treturn Array.prototype.map.call(collection, func);\r\n}\r\n","export function deprecatedMsg(\r\n\toldInterface, newInterface,\r\n\ttmpl = `DEPRECATED => ${oldInterface} is being removed! Use ${newInterface} instead.`\r\n) {\r\n\tconsole && console.error && console.error(tmpl); // eslint-disable-line\r\n};\r\n\r\nexport function removedMsg(\r\n\toldInterface,\r\n\ttmpl = `REMOVED => ${oldInterface} is being removed! Do not use it!`\r\n) {\r\n\tconsole && console.error && console.error(tmpl); // eslint-disable-line\r\n};\r\n\r\nexport function deprecatedAttr({obj, attr, objLoc = '', newLoc = null} = {}, getterOrDefault) {\r\n\tconst getterFunc = (\r\n\t\ttypeof getterOrDefault === 'function'\r\n\t\t\t? getterOrDefault\r\n\t\t\t: () => getterOrDefault\r\n\t);\r\n\r\n\t// clear out the attr if it was previously defined\r\n\tif (obj.hasOwnProperty(attr)) { delete obj[attr]; }\r\n\r\n\t// define the getter function\r\n\tObject.defineProperty(obj, attr, {get() {\r\n\t\tconst dot = (objLoc ? '.' : '');\r\n\t\tconst oldLoc = `${objLoc}${dot}${attr}`;\r\n\r\n\t\tif (newLoc == null) {\r\n\t\t\tremovedMsg(oldLoc);\r\n\t\t} else {\r\n\t\t\tdeprecatedMsg(oldLoc, newLoc);\r\n\t\t}\r\n\t\treturn getterFunc();\r\n\t}});\r\n};\r\n","export const isArray = (input) => isOfType(input, 'array');\r\nexport const isNumber = (input) => isOfType(input, 'number');\r\nexport const isObject = (input) => isOfType(input, 'object');\r\nexport const isString = (input) => isOfType(input, 'string');\r\nexport const isDate = (input) => isOfType(input, 'date');\r\nexport const isNull = (input) => isOfType(input, 'null');\r\nexport const isUndefined = (input) => isOfType(input, 'undefined');\r\nexport const isBoolean = (input) => isOfType(input, 'boolean');\r\n\r\nexport function isOfType(input, type) {\r\n\treturn Object.prototype.toString\r\n\t\t.call(input) // => \"[object Type]\"\r\n\t\t.split(' ')[1] // => \"Type]\"\r\n\t\t.slice(0, -1) // => \"Type\"\r\n\t\t.toLowerCase() === type.toLowerCase(); // => \"type === type\"\r\n}\r\n","import {deprecatedMsg} from './deprecated';\r\nimport {isObject, isBoolean} from './type-checkers';\r\n\r\nconst handlerMap = {}; // map of all handlers for all events\r\nconst terminalEvents = []; // events that are handled by terminal handlers (only 1 allowed)\r\nconst lastEventCache = {}; // map of last data emitted for each event (for greedy event handlers)\r\nconst backwardCompatEvents = {\r\n\t'session.logout': 'header.user-info.logout'\r\n};\r\nconst deprecatedEvents = Object.keys(backwardCompatEvents).reduce(function (acc, key) {\r\n\tacc[backwardCompatEvents[key]] = key;\r\n\treturn acc;\r\n}, {});\r\nexport const logErr = msg => console && console.error && console.error(`SIDEKICK => ${msg}`); // eslint-disable-line\r\n\r\n/**\r\n * Event Bus Module\r\n * @module Sidekick.EventBus\r\n * @memberOf Sidekick\r\n */\r\n\r\n/**\r\n * Registers an event listener.\r\n * @function on\r\n * @instance\r\n * @param {String} evt - Event to respond to\r\n * @param {Function} handler - function to handle the event\r\n * @param {Object} [config] - the event handler config\r\n * @param {Boolean} [config.greedy=false] - execute immediately with last emitted data if possible\r\n * @param {Boolean} [config.once=false] - Run once?\r\n * @param {Boolean} [config.terminal=false] - Do not allow other handlers to listen to this event?\r\n * @return {Function} - Deregister function\r\n */\r\nexport const on = function(evt, handler, configOrGreedy = false, once = false) {\r\n\tlet terminal = false;\r\n\tlet greedy = false;\r\n\tif (isObject(configOrGreedy)) {\r\n\t\tconst cfg = configOrGreedy;\r\n\t\tif (cfg.greedy != null) { greedy = cfg.greedy; }\r\n\t\tif (cfg.once != null) { once = cfg.once; }\r\n\t\tif (cfg.terminal != null) { terminal = cfg.terminal; }\r\n\t} else if (isBoolean(configOrGreedy)) {\r\n\t\tgreedy = configOrGreedy;\r\n\t}\r\n\r\n\tconst handlerList = handlerMap[evt] = (handlerMap[evt] || []);\r\n\tif (terminalEvents.includes(evt)) {\r\n\t\tlogErr(`the event \"${evt}\" is already handled by a terminal event. No additional handlers can be registered.`);\r\n\t\treturn;\r\n\t}\r\n\tif (terminal === true) {\r\n\t\t// clear other handlers if this one is terminal\r\n\t\tconst hCount = handlerList.length;\r\n\t\tif (hCount > 0) {\r\n\t\t\thandlerList.length = 0;\r\n\t\t\tlogErr(`${hCount} \"${evt}\" event handler(s) have been removed due to a terminal handler registration.`);\r\n\t\t}\r\n\t\t// add it to the terminal events listen\r\n\t\tterminalEvents.push(evt);\r\n\t}\r\n\r\n\t// check if this handler is already registered with this event\r\n\tif (handlerList.includes(handler)) {\r\n\t\tlogErr(`the event \"${evt}\" is already handled by ${handler}`);\r\n\t\treturn;\r\n\t}\r\n\r\n\thandler.$once = once;\r\n\thandlerList.push(handler);\r\n\r\n\tif (greedy && lastEventCache[evt]) {\r\n\t\thandler.apply(null, lastEventCache[evt]);\r\n\t}\r\n\r\n\t// return a teardown function\r\n\treturn () => off(evt, handler);\r\n};\r\n\r\n\r\n/**\r\n * Registers an event listener to run once.\r\n * @function once\r\n * @instance\r\n * @param {String} evt - Event to respond to\r\n * @param {Function} handler - function to handle the event\r\n * @param {Boolean} [greedy=false] -\r\n * @return {Function}\r\n */\r\nexport const once = function(evt, handler, greedy = false) {\r\n\treturn on(evt, handler, {greedy, once: true});\r\n};\r\n\r\n\r\n/**\r\n * Deregisters an event listener.\r\n * @function off\r\n * @instance\r\n * @param {String} evt - Event to respond to\r\n * @param {Function} handler - function to handle the event\r\n */\r\nexport const off = function(evt, handler) {\r\n\t// we have no handlers for this event, get out\r\n\tif (handlerMap[evt] == null) { return; }\r\n\t// we are not removing a specific handler, remove all\r\n\tif (handler == null) { handlerMap[evt].length = 0; }\r\n\r\n\t// remove just the one handler\r\n\tconst handlerList = handlerMap[evt];\r\n\tconst idx = handlerList.lastIndexOf(handler);\r\n\tif (idx === -1) { return; }\r\n\thandlerList.splice(idx, 1);\r\n};\r\n\r\n\r\n/**\r\n * Emits an event.\r\n * @function emit\r\n * @instance\r\n * @param {String} evt - Event to respond to\r\n * @param {...*} args - Parameters to pass to the handler function for this event\r\n */\r\nexport const emit = function(evt, ...args) {\r\n\t// fire deprecated events for backward compatibility\r\n\tif (backwardCompatEvents.hasOwnProperty(evt)) {\r\n\t\temit.apply(null, [backwardCompatEvents[evt], ...args]); // re-emit\r\n\t}\r\n\r\n\tlastEventCache[evt] = args;\r\n\tif (!handlerMap[evt]) { return; }\r\n\tconst handlerList = handlerMap[evt];\r\n\tfor (let i = handlerList.length; i-- ;) {\r\n\t\thandlerList[i].apply(null, args);\r\n\t\tif (handlerList[i].$once === true) {\r\n\t\t\toff(evt, handlerList[i]);\r\n\t\t}\r\n\t}\r\n};\r\n\r\n/**\r\n * Deregisters all event listeners.\r\n * @function clear\r\n * @instance\r\n */\r\nexport const clear = function() {\r\n\tterminalEvents.length = 0;\r\n\tObject.keys(handlerMap).forEach(k => delete handlerMap[k]);\r\n\tObject.keys(lastEventCache).forEach(k => delete lastEventCache[k]);\r\n};\r\n\r\n/**\r\n * The object that exposes the events public api and logs warnings when internal\r\n * events are emitted or listened to\r\n */\r\nexport const publicApi = {\r\n\ton: warnForInternalEvents(on),\r\n\tonce: warnForInternalEvents(once),\r\n\temit: warnForInternalEvents(emit),\r\n\tclear\r\n};\r\n\r\nfunction warnForInternalEvents(func) {\r\n\treturn function (...args) {\r\n\t\tconst evt = args[0];\r\n\t\t/* eslint-disable no-console */\r\n\t\tif (evt.startsWith('_') && console && console.error) {\r\n\t\t\tlogErr(`the event \"${evt}\" is internal and not to be used`);\r\n\t\t}\r\n\r\n\t\t// warn about deprecated events\r\n\t\tif (deprecatedEvents.hasOwnProperty(evt)) {\r\n\t\t\tdeprecatedMsg(`The \"${evt}\" event`, `\"${deprecatedEvents[evt]}\"`);\r\n\t\t}\r\n\r\n\t\tfunc.apply(null, args);\r\n\t};\r\n}\r\n","import * as events from './event-bus';\r\nimport { isStoreSet } from './store-validate';\r\n\r\nconst store = {};\r\nconst eventPrefix = '_store.set';\r\nconst publicReadOnly = [\r\n\t'idm-data',\r\n\t'sk-config',\r\n\t'fl-internal-product-ids'\r\n];\r\nconst mutuallyExclusiveKeys = {\r\n 'idm': 'passport',\r\n 'passport': 'idm'\r\n};\r\n\r\n/**\r\n * @module Sidekick.Store\r\n * @memberOf Sidekick\r\n */\r\n\r\n/**\r\n * Sets a value to the store.\r\n * @function set\r\n * @instance\r\n * @param {String} key - Key for the value\r\n * @param {Function} value - value stored under the key\r\n * @emits ${eventPrefix}-$key\r\n */\r\nexport const set = (key, value) => {\r\n\tconst flag = isStoreSet(store, key, mutuallyExclusiveKeys);\r\n\tif(flag) {\r\n\t\tthrow new Error(`SIDEKICK.STORE: Please clear '${mutuallyExclusiveKeys[key]}' before setting '${key}'`);\r\n\t}\r\n\tstore[key] = value;\r\n\tevents.emit(`${eventPrefix}-${key}`, value);\r\n};\r\n\r\n\r\n/**\r\n * Returns the value stored at the key or null.\r\n * @function get\r\n * @instance\r\n * @param {String} key\r\n * @return {*} value - Value (or null) found (or not) at the key.\r\n */\r\nexport const get = (key) => store[key] || null;\r\n\r\n\r\n/**\r\n * Creates a listener for this key.\r\n * @function onValue\r\n * @instance\r\n * @param {String} key - key for the handler\r\n * @param {Function} handler - function to handle the event\r\n */\r\nexport const onValue = (key, handler) => events.on(`${eventPrefix}-${key}`, handler, true);\r\n\r\n\r\n/**\r\n * Creates a listener for this key that runs once.\r\n * @function onValueOnce\r\n * @instance\r\n * @param {String} key - key for the handler\r\n * @param {Function} handler - function to handle the event\r\n */\r\nexport const onValueOnce = (key, handler) => events.once(`${eventPrefix}-${key}`, handler, true);\r\n\r\n\r\n/**\r\n * Returns the value stored at the key or null.\r\n * @function clear\r\n * @instance\r\n */\r\nexport const clear = () => Object.keys(store).forEach(k => delete store[k]);\r\n\r\n/**\r\n * The object that exposes the events public api and logs warnings when internal\r\n * events are emitted or listened to\r\n */\r\nexport const publicApi = {\r\n\tset: warnForInternalStore(publicSet),\r\n\tget: warnForInternalStore(get),\r\n\tonValue: warnForInternalStore(onValue),\r\n\tonValueOnce: warnForInternalStore(onValueOnce),\r\n\tclear\r\n};\r\n\r\nfunction publicSet(...args) {\r\n\tconst key = args[0];\r\n\tif (key == null) {\r\n\t\t/* eslint-disable no-console */\r\n\t\tif (console && console.error) {\r\n\t\t\tconsole.error('SIDEKICK.STORE: the first parameter %ckeyon
handlers for a menu item\r\n * @function cmptMenuItem\r\n * @instance\r\n * @param {Element} domCmpt\r\n * @param {Element} domHandle\r\n * @param {Element} mItem\r\n */\r\nexport function cmptMenuItem(domCmpt, domHandle, domMenuList, domMenuItem) {\r\n\tdomMenuItem.find('[role=menuitem]').forEach(domMenuItemLink => {\r\n\t\tdomMenuItemLink.on('focus', evt => {\r\n\t\t\tdomMenuItemLink.attr('aria-selected', true);\r\n\t\t});\r\n\r\n\t\tdomMenuItemLink.on('blur', evt => {\r\n\t\t\tdomMenuItemLink.attr('aria-selected', false);\r\n\t\t});\r\n\t});\r\n\r\n\tdomMenuItem.on('keydown', evt => {\r\n\t\tlet prevDef = false;\r\n\r\n\t\tswitch(true) {\r\n\t\t\tcase keyPress.isTab(evt):\r\n\t\t\t\tbreak;\r\n\t\t\tcase keyPress.isLeft(evt):\r\n\t\t\tcase keyPress.isRight(evt):\r\n\t\t\t\tbreak;\r\n\t\t\tcase keyPress.isUp(evt):\r\n\t\t\tcase keyPress.isDown(evt):\r\n\t\t\t\tconst menuItemElems = Array.prototype.slice.call(domMenuList._.children);\r\n\t\t\t\tconst menuItemIdx = menuItemElems.indexOf(domMenuItem._);\r\n\t\t\t\tif (menuItemIdx === (keyPress.isUp(evt) ? 0 : menuItemElems.length - 1)) {\r\n\t\t\t\t\tprevDef = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tconst nextIdx = menuItemIdx + (keyPress.isUp(evt) ? -1 : 1);\r\n\t\t\t\tconst nextElem = menuItemElems[nextIdx].querySelector('[role=menuitem]');\r\n\t\t\t\tnextElem.focus();\r\n\t\t\t\tevt.stopPropagation(); // override up/down handling at the menu level\r\n\t\t\t\tprevDef = true;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tif (prevDef) {\r\n\t\t\tevt.preventDefault();\r\n\t\t}\r\n\t});\r\n}\r\n\r\n/**\r\n * Sets up common on
handlers for a menu\r\n * @function cmptMenu\r\n * @instance\r\n * @param {Element} domCmpt\r\n * @param {Element} domHandle\r\n * @param {Element} domMenu\r\n */\r\nexport function cmptMenu(domCmpt, domHandle, domMenu) {\r\n\tfunction onClick(evt) {\r\n\t\tconst isOpen = domHandle.hasClass('ss-menu-open');\r\n\t\tevents.emit(`sk-menu-${isOpen ? 'close' : 'open'}`, domCmpt, evt);\r\n\t}\r\n\r\n\tdomCmpt.on('click', function (evt) {\r\n\t\tif (!domCmpt.hasClass('sk-no-click')) { evt.stopPropagation(); }\r\n\t});\r\n\tdomHandle.on('click', onClick);\r\n\tdomHandle.on('keydown', (evt) => {\r\n\t\tlet prevDef = false;\r\n\t\tswitch (true) {\r\n\t\t\tcase keyPress.isEnter(evt):\r\n\t\t\tcase keyPress.isSpace(evt):\r\n\t\t\tcase keyPress.isDown(evt):\r\n\t\t\tcase keyPress.isUp(evt):\r\n\t\t\t\tonClick(evt);\r\n\t\t\t\tprevDef = true;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tif (prevDef) {\r\n\t\t\tevt.preventDefault();\r\n\t\t}\r\n\t});\r\n\tdomMenu.attr('tabindex', '-1');\r\n\tdomMenu.on('keydown', (evt) => {\r\n\t\tlet prevDef = false;\r\n\t\tswitch (true) {\r\n\t\t\tcase keyPress.isDown(evt):\r\n\t\t\tcase keyPress.isUp(evt):\r\n\t\t\t\tdomMenu\r\n\t\t\t\t\t.find('[role=menuitem]')\r\n\t\t\t\t\t.forEach((mItem, idx, menuItems) => {\r\n\t\t\t\t\t\tconst focusIdx = keyPress.isUp(evt) ? menuItems.length - 1 : 0;\r\n\t\t\t\t\t\tconst focusOrBlur = idx === focusIdx ? 'focus' : 'blur';\r\n\t\t\t\t\t\tmItem._[focusOrBlur]();\r\n\t\t\t\t\t});\r\n\t\t\t\tbreak;\r\n\t\t\tcase keyPress.isEscape(evt):\r\n\t\t\t\tevents.emit('sk-menu-close', domCmpt);\r\n\t\t\t\tdomHandle._.focus();\r\n\t\t\t\tprevDef = true;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tif (prevDef) {\r\n\t\t\tevt.preventDefault();\r\n\t\t}\r\n\t});\r\n\tdom.element(window).on('blur', function () {\r\n\t\tif (document.activeElement != null && document.activeElement.tagName === 'IFRAME') {\r\n\t\t\tevents.emit('sk-menu-close', domCmpt);\r\n\t\t}\r\n\t});\r\n\tdom.element(document).on('click', () => events.emit('sk-menu-close', domCmpt));\r\n\r\n\t// handle open events\r\n\tevents.on('sk-menu-open', function (cmpt, evt) {\r\n\t\tif (cmpt !== domCmpt) {\r\n\t\t\t// if this was an open event for another menu, close me\r\n\t\t\tevents.emit('sk-menu-close', domCmpt);\r\n\t\t} else {\r\n\t\t\t// this was an open event for me, open me\r\n\t\t\tdomHandle.addClass('ss-menu-open');\r\n\t\t\tdomHandle.attr('aria-pressed', 'true');\r\n\t\t\tdomMenu.addClass('ss-menu-open');\r\n\t\t\tdomMenu.attr('aria-hidden', 'false');\r\n\r\n\t\t\tif (keyPress.isDown(evt) || keyPress.isUp(evt)) {\r\n\t\t\t\t// focus the appropriate menu item (the first item by default, or the\r\n\t\t\t\t// last item if the 'up' keyCode was emitted)\r\n\t\t\t\tdomMenu\r\n\t\t\t\t\t.find('[role=menuitem]')\r\n\t\t\t\t\t.forEach((mItem, idx, menuItems) => {\r\n\t\t\t\t\t\tconst focusIdx = keyPress.isUp(evt) ? menuItems.length - 1 : 0;\r\n\t\t\t\t\t\tconst willFocus = idx === focusIdx;\r\n\t\t\t\t\t\tmItem._[willFocus ? 'focus' : 'blur']();\r\n\t\t\t\t\t});\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tdomMenu._.focus();\r\n\t\t}\r\n\t});\r\n\r\n\t// handle close events\r\n\tevents.on('sk-menu-close', function (cmpt, external = true) {\r\n\t\t// if this close event was for another menu, ignore\r\n\t\tif (cmpt !== domCmpt) { return; }\r\n\t\t// close the menu\r\n\t\tdomHandle.removeClass('ss-menu-open');\r\n\t\tdomHandle.attr('aria-pressed', 'false');\r\n\t\tdomMenu.removeClass('ss-menu-open');\r\n\t\tdomMenu.attr('aria-hidden', 'true');\r\n\r\n\t\tconst menuItems = domMenu.find('[role=menuitem]');\r\n\t\tmenuItems.map(mItem => mItem.attr('aria-selected', false));\r\n\t});\r\n}\r\n\r\n/**\r\n * handle the clear button functionality for an sk-input element\r\n * @function cmptInputClear\r\n * @instance\r\n * @param {Element} domInput\r\n * @param {Element} domClearBtn\r\n * @param {Boolean} clearOnEscape - Adds an event handler to run when you press escape\r\n */\r\nexport function cmptInputClear(domInput, domClearBtn, clearOnEscape) {\r\n\t// toggle sk-hidden based on the content\r\n\tconst toggleClear = () => {\r\n\t\tdomClearBtn.toggleClass('sk-hidden', !domInput._.value.length);\r\n\t};\r\n\r\n\tdomInput.on('input', toggleClear);\r\n\tdomClearBtn.on('click', clear);\r\n\tif (clearOnEscape) {\r\n\t\tdomInput.on('keydown', clearOnEscapeCall);\r\n\t}\r\n\r\n\ttoggleClear();\r\n\r\n\tfunction clear() {\r\n\t\tdomInput._.value = '';\r\n\t\tdomInput._.focus();\r\n\t\ttoggleClear();\r\n\t}\r\n\r\n\tfunction clearOnEscapeCall(evt) {\r\n\t\t// bail out if this was not the ESCAPE key\r\n\t\tif (!keyPress.isEscape(evt)) { return; }\r\n\r\n\t\tclear();\r\n\t}\r\n}\r\n\r\nexport const queryStringObject = function () {\r\n\tconst raw = window.location.search;\r\n\tif (raw.length === 0) { return {}; }\r\n\tconst rawArr = raw.slice(1).split('&');\r\n\treturn rawArr.reduce(function (o, qs) {\r\n\t\tconst [key, value] = qs.split('=');\r\n\t\to[decodeURIComponent(key)] = decodeURIComponent(value);\r\n\t\treturn o;\r\n\t}, {});\r\n};\r\n\r\n///////\r\n// calculating and distribute the top bar extra width\r\n// to dynamic width elements\r\n//\r\nvar activityIndicatorWidth = 0;\r\nvar impersonationMode = false;\r\nconst staticElems = {};\r\nconst dynamicElems = {};\r\nconst staticWidthElemNames = ['app-switcher', 'search', 'help', 'notifications'];\r\nconst impStaticWidthElemNames = ['app-switcher', 'search'];\r\nconst dynamicWidthElemNames = ['user-info', 'org-switcher'];\r\nconst impDynamicWidthElemNames = ['impersonated-user', 'org-switcher'];\r\n\r\n/**\r\n * cmptDynamicWidth - registers a header component that should be dynamic\r\n * width and occupy as much space (max-width) as possible\r\n *\r\n * @param {EasyDomElement} elem - the element that should be dynamic\r\n * @param {String} text - the dynamic text content to use for measurements\r\n * @param {Number} adjustment - the px amount to add to measurement to compensate for padding\r\n */\r\nexport const cmptDynamicWidth = function (name, elem, text, adjustment = 0, font = 'normal 15px') {\r\n\tconst firstRegistration = dynamicElems[name] == null;\r\n\tdynamicElems[name] = {elem, text, adjustment, font};\r\n\r\n\t// if this elem is the user-info component and this is the first\r\n\t// time we see it being registered. start watching for role data\r\n\tif (name === 'user-info' && firstRegistration) { watchForRoles(); }\r\n\r\n\t// update our size calculations\r\n\tadjustDynamicWidthElements();\r\n};\r\n\r\n// re-calculate the measurements because adjustments have been made\r\nfunction adjustDynamicWidthElements() {\r\n\t// decide what elements could be on the screen based on if we are impersonating\r\n\tconst _staticWidthElemNames = (impersonationMode ? impStaticWidthElemNames : staticWidthElemNames);\r\n\tconst _dynamicWidthElemNames = (impersonationMode ? impDynamicWidthElemNames : dynamicWidthElemNames);\r\n\r\n\t// calculate the total width of all static elements on the screen\r\n\t// give the header an extra 43 pixels for impersonation mode to accommodate the X\r\n\tconst _totalStaticWidth = _staticWidthElemNames.reduce(function (total, elName) {\r\n\t\tconst elWidth = staticElems[elName] && parseFloat(staticElems[elName].css('width'));\r\n\t\treturn total + (elWidth || 0);\r\n\t}, (impersonationMode ? 48 : 5));\r\n\r\n\t// figure out what dyamic elements are on screen currently\r\n\tconst _dynamicWidthElems = _dynamicWidthElemNames\r\n\t\t.filter(elName => dynamicElems[elName] != null)\r\n\t\t.map(elName => dynamicElems[elName])\r\n\t\t.map(e => Object.assign({}, e, {width: measureText(e.text, e.font)}));\r\n\r\n\t// calculate the total width of all dymanic elements based on their text width\r\n\tconst _totalDynamicWidth = _dynamicWidthElems.reduce((t, e) => t + (e.width + e.adjustment), 0);\r\n\r\n\t// apply the corrent percent width calculation for each dynamic element\r\n\t_dynamicWidthElems.forEach(function (e) {\r\n\t\tconst _staticWidth = _totalStaticWidth + activityIndicatorWidth;\r\n\t\tconst widthPercent = Math.floor(((e.width + e.adjustment)/_totalDynamicWidth) * 100);\r\n\t\tconst itemPxReductionAmt = _staticWidth * (widthPercent / 100);\r\n\t\te.elem.css('max-width', `calc(${widthPercent}% - ${itemPxReductionAmt}px)`);\r\n\t});\r\n}\r\n\r\nconst drawCtx = document.createElement('canvas').getContext('2d');\r\n// measure how many px this text will take up\r\nfunction measureText(text, font = 'normal 15px') {\r\n\tconst fontFamily = `'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif`;\r\n\tdrawCtx.font = `${font} ${fontFamily}`;\r\n\treturn drawCtx.measureText(text).width;\r\n}\r\n\r\n// if we switch to or from impersonation mode, we should recalculate header space\r\nevents.on('_header.impersonation', function (impMode) {\r\n\timpersonationMode = impMode;\r\n\tadjustDynamicWidthElements();\r\n});\r\n\r\n// the activity-indicator doesn't initially take up space, but it requires\r\n// space when it is shown. hook into the visible events and re-adjust if\r\n// if shows up on the scene.\r\nevents.on(`_activity-indicator-initialized`, function (elem) {\r\n\tevents.on(`activity-indicator.visible`, function (visible) {\r\n\t\tif (visible) {\r\n\t\t\tactivityIndicatorWidth = parseFloat(elem.css('width')) + parseFloat(elem.css('margin-right'));\r\n\t\t} else {\r\n\t\t\tactivityIndicatorWidth = 0;\r\n\t\t}\r\n\t\tadjustDynamicWidthElements();\r\n\t}, true);\r\n}, true);\r\n\r\n// if roles are filled, we need to make sure the role name is not longer\r\n// than the user's name, if it is, we need to use it for calculations instead\r\nfunction watchForRoles() {\r\n\tstore.onValue('roles', function (data) {\r\n\t\tconst roleName = data.roles.find(r => r.id === data.currentRole).name;\r\n\t\tconst userInfo = dynamicElems['user-info'];\r\n\t\tconst userNameWidth = measureText(userInfo.text, userInfo.font);\r\n\t\tconst roleFont = '600 13px';\r\n\t\tconst roleWidth = measureText(roleName, roleFont);\r\n\r\n\t\tif (roleWidth > userNameWidth) {\r\n\t\t\tuserInfo.text = roleName;\r\n\t\t\tuserInfo.font = roleFont;\r\n\t\t}\r\n\r\n\t\tadjustDynamicWidthElements();\r\n\t});\r\n}\r\n\r\n// listen to other header elements and readjust when they show up\r\nstaticWidthElemNames.forEach(function (name) {\r\n\tevents.on(`_${name}-initialized`, elem => addStaticWidthElem(name, elem), true);\r\n});\r\n\r\nfunction addStaticWidthElem(name, elem) {\r\n\tstaticElems[name] = elem;\r\n\tadjustDynamicWidthElements();\r\n}\r\n","import * as dom from '../../util/easy-dom';\r\nimport * as store from '../../util/store';\r\nimport { cmptMenu, cmptMenuItem } from '../../util/cmpt-common-features';\r\nimport * as events from '../../util/event-bus';\r\n\r\n/**\r\n * Displays articles, and helper blocks\r\n * @class Sidekick.Help\r\n * @memberOf Sidekick\r\n * @param {EasyDom} elem - Container {@link EasyDom} element\r\n * @param {Object} attrs\r\n * @param {Object} ctx\r\n * @param {Function} i18n - translation function\r\n * @emits header.help.article.click - Thrown when an article is clicked that doesn't have a url\r\n * @emits header.help.block.click - Thrown when an block is clicked that doesn't have a url\r\n * @example\r\n * articles: List of articles pertaining to the app\r\n * blocks: List of other links to different sections of the app.\r\n * title: Text to show the user\r\n * icon: Icon to show the user\r\n * url: Optional. If passed article/block will open a new window to that url. If omitted then\r\n * \theader.help.article.click/header.help.block.click will be thrown and the item will be the article/block. Extra\r\n * \tparams can optionally be added to the item when building the nav menu and they will be included back to you when the\r\n * \tnav item is clicked.\r\n * {\r\n\t'articles': [{\r\n\t\t'title': 'Getting Started with Frontline Central',\r\n\t\t'url': '/getting_started',\r\n\t\t'icon': 'file-text'\r\n\t}],\r\n\t'blocks': [{\r\n\t\t'title': 'Learn more about Frontline Central',\r\n\t\t'url': 'http://help1.frontlinek12.com/?b_id=13067',\r\n\t\t'icon': 'learning_center_logo'\r\n\t}]\r\n}\r\n */\r\nexport default function (elem, attrs, ctx, i18n) {\r\n\tconst { responsiveTopNav } = store.get('sk-config');\r\n\t/////\r\n\t// find dom elements that we care about\r\n\t//\r\n\tconst [domButton] = elem.find('.control');\r\n\tconst [domMenu] = elem.find('.menu');\r\n\tconst [domBlocks] = elem.find('.blocks');\r\n\tconst [domArticles] = elem.find('.articles');\r\n\tconst domButtonElements = document.querySelectorAll('.control');\r\n\tconst [domNavButton] = elem.find('.control-responsive');\r\n\tconst [domMenuMobile] = elem.find('.menu-mobile');\r\n\tconst [domBlocksMobile] = elem.find('.blocks-mobile');\r\n\tconst [domArticlesMobile] = elem.find('.articles-mobile');\r\n\r\n\tif (responsiveTopNav) {\r\n\t\tdomButtonElements.forEach((domButtonElement) => {\r\n\t\t\tdomButtonElement.classList.add('sk-help-responsive');\r\n\t\t});\r\n\r\n\t\tif (attrs.role === 'navitem') {\r\n\t\t\tdomNavButton.css('display', 'block');\r\n\t\t\tdomNavButton.on('click', (evt) => {\r\n\t\t\t\tevt.stopPropagation();\r\n\t\t\t\tevt.preventDefault();\r\n\t\t\t\tif (domMenuMobile.css('display') === 'none') {\r\n\t\t\t\t\tdomMenuMobile.css('display', 'block');\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdomMenuMobile.css('display', 'none');\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t// initialize with default values\r\n\tlet urlTemplateVars = getUrlTemplateVars();\r\n\r\n\t/////\r\n\t// handle initial state and data changes\r\n\t//\r\n\tupdateHelpData(ctx);\r\n\tstore.onValue('help', updateHelpData);\r\n\r\n\tstore.onValue('idm-data', (idmData) => {\r\n\t\turlTemplateVars = getUrlTemplateVars(idmData);\r\n\t\tupdateHelpData(ctx);\r\n\t});\r\n\r\n\t/////\r\n\t// listen for events and take action\r\n\t//\r\n\tcmptMenu(elem, domButton, domMenu);\r\n\r\n\t/////\r\n\t// helper functions\r\n\t//\r\n\t/**\r\n\t * Updates the display with the new data being passed in.\r\n\t * @param {Object} newCtx - New context object with the new data.\r\n\t */\r\n\tfunction updateHelpData(newCtx) {\r\n\t\t// update our context object\r\n\t\tif (ctx !== newCtx) {\r\n\t\t\tctx = newCtx;\r\n\t\t}\r\n\r\n\t\t// articles\r\n\t\tvar articles = ctx.articles;\r\n\t\tif (articles == null || articles.length === 0) {\r\n\t\t\t// no articles to display\r\n\t\t\tdomArticles.css('display', 'none');\r\n\t\t\tdomArticlesMobile.css('display', 'none');\r\n\t\t} else {\r\n\t\t\tdomArticles.css('display', 'block');\r\n\t\t\tdomArticlesMobile.css('display', 'block');\r\n\t\t\t// process the list of articles to display\r\n\t\t\t// max 3 articles\r\n\t\t\tconst articlesToDisplay = articles.slice(0, 3);\r\n\r\n\t\t\tdomArticles.children(\r\n\t\t\t\tarticlesToDisplay.map((article) =>\r\n\t\t\t\t\tcreateArticleElement(\r\n\t\t\t\t\t\tarticle,\r\n\t\t\t\t\t\turlTemplateVars,\r\n\t\t\t\t\t\telem,\r\n\t\t\t\t\t\tdomButton,\r\n\t\t\t\t\t\tdomArticles\r\n\t\t\t\t\t)\r\n\t\t\t\t)\r\n\t\t\t);\r\n\t\t\tdomArticlesMobile.children(\r\n\t\t\t\tarticlesToDisplay.map((article) =>\r\n\t\t\t\t\tcreateArticleElement(\r\n\t\t\t\t\t\tarticle,\r\n\t\t\t\t\t\turlTemplateVars,\r\n\t\t\t\t\t\telem,\r\n\t\t\t\t\t\tdomNavButton,\r\n\t\t\t\t\t\tdomArticles\r\n\t\t\t\t\t)\r\n\t\t\t\t)\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t// blocks\r\n\t\tvar blocks = ctx.blocks;\r\n\t\tif (blocks == null || blocks.length === 0) {\r\n\t\t\tdomBlocks.css('display', 'none');\r\n\t\t\tdomBlocksMobile.css('display', 'none');\r\n\t\t} else {\r\n\t\t\tdomBlocks.css('display', 'block');\r\n\t\t\tdomBlocksMobile.css('display', 'block');\r\n\t\t\t// process the list of blocks to display\r\n\t\t\tdomBlocks.children(\r\n\t\t\t\tblocks.map((block) =>\r\n\t\t\t\t\tcreateMenuItem(block, elem, domButton, domBlocks)\r\n\t\t\t\t)\r\n\t\t\t);\r\n\t\t\tdomBlocksMobile.children(\r\n\t\t\t\tblocks.map((block) =>\r\n\t\t\t\t\tcreateMenuItem(block, elem, domNavButton, domBlocks)\r\n\t\t\t\t)\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Extract values for URL 'template' string from IDM data. Use default values if the data is not provided.\r\n\t * @param {Object} [idmData] - IDM data object\r\n\t * @param {Object} {idmData.userContext} IDM user context object\r\n\t * @param {Object} {idmData.product} IDM product object\r\n\t */\r\n\tfunction getUrlTemplateVars({ identities, userContext, product } = {}) {\r\n\t\t// these names must match the placeholders values in the URL, which we control\r\n\t\tconst idTypes =\r\n\t\t\t(product && product.AssociatedRoles.map((x) => x.Type)) || [];\r\n\t\tconst idRecord =\r\n\t\t\tArray.isArray(identities) &&\r\n\t\t\tidentities.find((id) => idTypes.includes(id.Type));\r\n\t\tconst userKey = (idRecord && idRecord.Id) || '';\r\n\t\tconst orgId = (userContext && userContext.OrganizationId) || '';\r\n\r\n\t\treturn { userKey, orgId };\r\n\t}\r\n\r\n\t/**\r\n\t * Creates an article element and appends it to the DOM.\r\n\t * @param {Object} article - The article object containing details like title, url, and icon.\r\n\t * @param {Object} urlTemplateVars - An object containing variables to be interpolated into the article URL.\r\n\t * @param {HTMLElement} elem - The DOM element to which the article element will be appended.\r\n\t * @param {HTMLElement} domButton - The DOM button element associated with the article.\r\n\t * @param {HTMLElement} domArticles - The DOM element containing the list of articles.\r\n\t * @returns {HTMLElement} The created article element.\r\n\t */\r\n\tfunction createArticleElement(\r\n\t\tarticle,\r\n\t\turlTemplateVars,\r\n\t\telem,\r\n\t\tdomButton,\r\n\t\tdomArticles\r\n\t) {\r\n\t\tlet el;\r\n\t\tif (article.url == null || article.url.length === 0) {\r\n\t\t\tel = dom.parse(\r\n\t\t\t\t`${i18n('For your security and protection of your data, you have been signed out due to inactivity.')}
We don’t know what happened but something went wrong. Please wait a few minutes then try to sign in again.