UNPKG

@kwiz/common

Version:

KWIZ common utilities and helpers for M365 platform

1,353 lines 49.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DisableAnchorInterceptValue = exports.DisableAnchorInterceptAttribute = void 0; exports.triggerNativeEvent = triggerNativeEvent; exports.addEventHandler = addEventHandler; exports.saveFile = saveFile; exports.saveZipFile = saveZipFile; exports.downloadFile = downloadFile; exports.copyTextToClipboard = copyTextToClipboard; exports.copyToClipboard = copyToClipboard; exports.pasteTextAtCursor = pasteTextAtCursor; exports.elementFromHtml = elementFromHtml; exports.HtmlTextContents = HtmlTextContents; exports.registerDOMContentLoadedListener = registerDOMContentLoadedListener; exports.registerDocumentLoadComplete = registerDocumentLoadComplete; exports.registerModernInplaceNavigationOnInit = registerModernInplaceNavigationOnInit; exports.registerModernThemeChanged = registerModernThemeChanged; exports.registerDOMChangedObserver = registerDOMChangedObserver; exports.removeDOMChangedObserver = removeDOMChangedObserver; exports.isElementVisible = isElementVisible; exports.querySelectorAllFirstOrNull = querySelectorAllFirstOrNull; exports.querySelectorAllMaintainOrder = querySelectorAllMaintainOrder; exports.getScrollParent = getScrollParent; exports.getScrollbarWidth = getScrollbarWidth; exports.cumulativeOffset = cumulativeOffset; exports.computedStyleToInlineStyle = computedStyleToInlineStyle; exports.getPageHidden = getPageHidden; exports.getAnimationFlags = getAnimationFlags; exports.getAnimationEndEventName = getAnimationEndEventName; exports.isElement = isElement; exports.isNode = isNode; exports.emptyHTMLElement = emptyHTMLElement; exports.removeHTMLElement = removeHTMLElement; exports.removeAttributeFromHTMLElements = removeAttributeFromHTMLElements; exports.getSelectOptionByValue = getSelectOptionByValue; exports.getSelectOptionByIndex = getSelectOptionByIndex; exports.getSelectedOption = getSelectedOption; exports.setSelectOptionByValue = setSelectOptionByValue; exports.setSelectOptionByIndex = setSelectOptionByIndex; exports.composePath = composePath; exports.waitForWindowObject = waitForWindowObject; exports.waitFor = waitFor; exports.waitForAsync = waitForAsync; exports.delayAsync = delayAsync; exports.addStyleSheet = addStyleSheet; exports.createStylesheet = createStylesheet; exports.createHtmlElement = createHtmlElement; exports.isInsideIFrame = isInsideIFrame; exports.isIFrameAccessible = isIFrameAccessible; exports.HTMLEncode = HTMLEncode; exports.HTMLDecode = HTMLDecode; exports.ScriptEncode = ScriptEncode; exports.addEventListeners = addEventListeners; exports.debounce = debounce; exports.interval = interval; exports.throttle = throttle; exports.OnWindowResize = OnWindowResize; exports.dispatchCustomEvent = dispatchCustomEvent; exports.addStyleElement = addStyleElement; exports.getReactInstanceFromElement = getReactInstanceFromElement; exports.registerUrlChanged = registerUrlChanged; exports.DisableAnchorIntercept = DisableAnchorIntercept; exports.DisableAnchorInterceptInHtml = DisableAnchorInterceptInHtml; exports.DisableAnchorInterceptInElement = DisableAnchorInterceptInElement; exports.isChildOf = isChildOf; exports.findAcestor = findAcestor; exports.loadModernFormsCSS = loadModernFormsCSS; exports.showLoadingOverlay = showLoadingOverlay; exports.hideLoadingOverlay = hideLoadingOverlay; exports.getLoadingOverlayHtml = getLoadingOverlayHtml; exports.getUniqueElementId = getUniqueElementId; exports.stopEvent = stopEvent; exports.getCSSVariableValue = getCSSVariableValue; exports.convertImageToBase64 = convertImageToBase64; const collections_base_1 = require("./collections.base"); const constants_1 = require("./constants"); const images_1 = require("./images"); const objects_1 = require("./objects"); const random_1 = require("./random"); const strings_1 = require("./strings"); const typecheckers_1 = require("./typecheckers"); const url_1 = require("./url"); let _global = (0, objects_1.getGlobal)("browser", { registerUrlChangedCallbacks: [], urlChangedHandlerRegistered: false }, true); function triggerNativeEvent(ele, eventName) { if ((0, typecheckers_1.isNullOrUndefined)(ele)) { return; } if (!(0, typecheckers_1.isNullOrUndefined)(ele.fireEvent)) { // < IE9 ele.fireEvent('on' + eventName); } else { // Different events have different event classes. // If this switch statement can't map an eventName to an eventClass, // the event firing is going to fail. let eventClass = "Events"; switch (eventName) { case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead. case "mousedown": case "mouseup": eventClass = "MouseEvents"; break; case "focus": case "change": case "blur": case "select": eventClass = "HTMLEvents"; break; default: eventClass = "CustomEvent"; break; } var evt = document.createEvent(eventClass); evt.initEvent(eventName, true, true); ele.dispatchEvent(evt); } } function addEventHandler(elm, event, handler) { if ((0, typecheckers_1.isUndefined)(elm.addEventListener)) //IE8 elm.attachEvent("on" + event, handler); else elm.addEventListener(event, handler, false); } const saveFileLinkId = "kwizcom_download_link_tmp"; /** prompts user to save/download a text file */ function saveFile(fileName, fileData, type) { //Issue 6003 let blobObject = new Blob([fileData], { type: `${type};charset=utf-8;` }); if (window.Blob && window.navigator["msSaveOrOpenBlob"]) { //edge/IE window.navigator["msSaveOrOpenBlob"](blobObject, fileName); } else { //Issue 6025 //var encodedUri = `data:${type};charset=utf-8,` + encodeURIComponent(fileData); let link = document.getElementById(saveFileLinkId); if (link) { link.remove(); link = null; } var url = URL.createObjectURL(blobObject); if (!link) { link = document.createElement("a"); link.style.position = "fixed"; link.style.top = "-200px"; link.download = fileName; link.innerHTML = "Click Here to download"; DisableAnchorIntercept(link); link.id = saveFileLinkId; document.body.appendChild(link); // Required for FF link.href = url; } globalThis.setTimeout(() => { link.click(); }, 200); } } function saveZipFile(fileName, fileDataBase64) { let link = document.getElementById(saveFileLinkId); if (link) { link.remove(); link = null; } var url = `data:application/zip;base64,${fileDataBase64}`; if (!link) { link = document.createElement("a"); link.style.position = "fixed"; link.style.top = "-200px"; link.download = fileName; link.innerHTML = "Click Here to download"; DisableAnchorIntercept(link); link.id = saveFileLinkId; document.body.appendChild(link); link.href = url; } globalThis.setTimeout(() => { link.click(); }, 200); } /** force browser to download instead of opening a file */ function downloadFile(url) { var link = document.createElement('a'); link.href = url; var parts = link.href.replace(/\\/g, "/").split('/'); var fileName = parts[parts.length - 1]; link.download = fileName; DisableAnchorIntercept(link); document.body.appendChild(link); link.click(); document.body.removeChild(link); } function copyTextToClipboard(text, multiline) { var input = document.createElement(multiline ? "textarea" : "input"); input.value = text; input.style.position = "absolute"; input.style.top = "-100px"; input.style.left = "-100px"; document.body.appendChild(input); let copied = copyToClipboard(input); input.remove(); return copied; } /** copies the text of an element to the clipboard. if not supported by browser - will return false so caller must check and show * a message to the user asking him to hit ctrl+c */ function copyToClipboard(el) { // Copy textarea, pre, div, etc. if (document.body.createTextRange) { // IE var textRange = document.body.createTextRange(); textRange.moveToElementText(el); textRange.select(); textRange.execCommand("Copy"); return true; } else if (window.getSelection && document.createRange) { // non-IE var editable = el.contentEditable; // Record contentEditable status of element var readOnly = el.readOnly; // Record readOnly status of element el.contentEditable = true; // iOS will only select text on non-form elements if contentEditable = true; el.readOnly = false; // iOS will not select in a read only form element var range = document.createRange(); range.selectNodeContents(el); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); // Does not work for Firefox if a textarea or input if (el.nodeName === "TEXTAREA" || el.nodeName === "INPUT") el.select(); // Firefox will only select a form element with select() if (el.setSelectionRange && navigator.userAgent.match(/ipad|ipod|iphone/i)) el.setSelectionRange(0, 999999); // iOS only selects "form" elements with SelectionRange el.contentEditable = editable; // Restore previous contentEditable status el.readOnly = readOnly; // Restore previous readOnly status if (document.queryCommandSupported("copy")) { var successful = document.execCommand('copy'); if (successful) return true; else return false; } else { if (!navigator.userAgent.match(/ipad|ipod|iphone|android|silk/i)) return false; } } return false; } function pasteTextAtCursor(textArea, text) { if ((0, typecheckers_1.isNullOrEmptyString)(text)) return; text = text.replace(/\r/g, ''); //remove \r it messes up the cursor location when pasting with line break const selectionStart = textArea.selectionStart; const selectionEnd = textArea.selectionEnd; const value = textArea.value; const before = value.substring(0, selectionStart); const after = value.substring(selectionEnd); textArea.value = before + text + after; textArea.selectionStart = selectionStart + text.length; textArea.selectionEnd = selectionStart + text.length; } /** wraps the html in a div element and returns it */ function elementFromHtml(html) { var d = document.createElement("div"); d.innerHTML = html; return d; } function HtmlTextContents(htmlElement) { let innerText = ((0, typecheckers_1.isString)(htmlElement) ? elementFromHtml(htmlElement) : htmlElement).innerText; return (0, strings_1.stripRichTextWhitespace)(innerText.replace(/\n/g, " ").replace(/ {2}/g, " ")); } function registerDOMContentLoadedListener(doc) { return new Promise((resolve, reject) => { doc = doc || document; if ((0, typecheckers_1.isNullOrUndefined)(doc)) { reject(); return; } if (!(0, typecheckers_1.isNullOrUndefined)(doc) && doc.readyState === "loading") { doc.addEventListener("DOMContentLoaded", () => { resolve(); }); } else { resolve(); } }); } function registerDocumentLoadComplete(doc) { return new Promise((resolve, reject) => { doc = doc || document; if ((0, typecheckers_1.isNullOrUndefined)(doc) || !(0, typecheckers_1.isFunction)(doc.addEventListener)) { reject(); return; } if (doc.readyState === "complete") { resolve(); } else { doc.addEventListener("readystatechange", () => { if (doc.readyState === "complete") { resolve(); } }); } }); } /** on modern experience, using navagation does inplace-page update. * document ready, and all windows events will not trigger and global objects will remain. * our app loader will fire this event when the page does that navigation so we can hook up to be notified. */ function registerModernInplaceNavigationOnInit(handler) { addEventHandler(document, "kwOnInit", handler); } /** Triggers handler when theme changes on a modern page * When the user changes the site's theme, or when navigating to a sub-site, or clicking back * in the browser navigating back to parent site with different theme */ function registerModernThemeChanged(handler) { addEventHandler(document, "kwOnThemeChanged", handler); } ; let _DOMChangedObserverDefs = []; function _getDOMChangedObserverDef(ele, ignoreSubTree) { if (!isElement(ele)) { return null; } let existingDef = _DOMChangedObserverDefs.filter((observer) => { let observerEle = observer.ele; return observer.ignoreSubTree === ignoreSubTree && isElement(observerEle) && observerEle.isSameNode(ele); })[0]; return existingDef; } function _getDomObserverCallbackInfo(callbackOrHandler) { return { handler: (0, typecheckers_1.isNullOrUndefined)(callbackOrHandler) ? null : (0, typecheckers_1.isFunction)(callbackOrHandler) ? callbackOrHandler : callbackOrHandler.handler, key: (0, typecheckers_1.isNullOrUndefined)(callbackOrHandler) || (0, typecheckers_1.isFunction)(callbackOrHandler) ? null : callbackOrHandler.key, ignoreSubTree: (0, typecheckers_1.isNullOrUndefined)(callbackOrHandler) || (0, typecheckers_1.isFunction)(callbackOrHandler) ? false : callbackOrHandler.ignoreSubTree === true }; } function registerDOMChangedObserver(callbackOrHandler, ele) { let callbackInfo = _getDomObserverCallbackInfo(callbackOrHandler); if (!(0, typecheckers_1.isFunction)(callbackInfo.handler)) { return; } var win; var doc; if (ele) { try { doc = ele.ownerDocument; win = doc.defaultView || doc.parentWindow; } catch (ex) { } } else { win = window; doc = window && window.document; ele = doc.body; } if ((0, typecheckers_1.isNullOrUndefined)(win) || (0, typecheckers_1.isNullOrUndefined)(doc)) { return; } registerDOMContentLoadedListener(win.document).then(() => { let existingDef = _getDOMChangedObserverDef(ele, callbackInfo.ignoreSubTree); if (!(0, typecheckers_1.isNullOrUndefined)(existingDef)) { let existingCallbackIndex = (0, typecheckers_1.isNullOrEmptyString)(callbackInfo.key) ? -1 : (0, collections_base_1.firstIndexOf)(existingDef.callbacks, cb => cb.key === callbackInfo.key); if (existingCallbackIndex >= 0) { //replace existingDef.callbacks[existingCallbackIndex].handler = callbackInfo.handler; } else { existingDef.callbacks.push(callbackInfo); } return; } let newDef = { ele: ele, ignoreSubTree: callbackInfo.ignoreSubTree, callbacks: [callbackInfo] }; let onDomChanged = () => { if (!(0, typecheckers_1.isNullOrUndefined)(newDef) && !(0, typecheckers_1.isNullOrEmptyArray)(newDef.callbacks)) { newDef.callbacks.forEach((c) => { try { c.handler(); } catch (e) { } }); } }; if ("MutationObserver" in win) { let observer = new win.MutationObserver((mutations) => { let hasUpdates = mutations.some((mutation) => { return !!mutation.addedNodes && !!mutation.addedNodes.length || !!mutation.removedNodes && !!mutation.removedNodes.length; }); if (hasUpdates) { onDomChanged(); } }); observer.observe(ele, { childList: true, subtree: callbackInfo.ignoreSubTree === true ? false : true, attributes: false, characterData: false }); newDef.disconnect = () => { observer.disconnect(); observer = null; }; } else { let domEvents = ["DOMNodeInsertedIntoDocument", "DOMNodeRemovedFromDocument"]; domEvents.forEach((eventName) => { newDef.ele.addEventListener(eventName, onDomChanged, false); }); newDef.disconnect = () => { domEvents.forEach((eventName) => { newDef.ele.removeEventListener(eventName, onDomChanged, false); }); }; } _DOMChangedObserverDefs.push(newDef); }); } function removeDOMChangedObserver(callbackOrHandler, ele) { let callbackInfo = _getDomObserverCallbackInfo(callbackOrHandler); if (!(0, typecheckers_1.isFunction)(callbackInfo.handler) && (0, typecheckers_1.isNullOrEmptyString)(callbackInfo.key)) { return; //need function or key to remove } var win; var doc; if (ele) { try { doc = ele.ownerDocument; win = doc.defaultView || doc.parentWindow; } catch (ex) { } } else { win = window; doc = window && window.document; ele = doc.body; } if ((0, typecheckers_1.isNullOrUndefined)(win) || (0, typecheckers_1.isNullOrUndefined)(doc)) { return; } registerDOMContentLoadedListener(win.document).then(() => { let existingDef = _getDOMChangedObserverDef(ele, callbackInfo.ignoreSubTree); if ((0, typecheckers_1.isNullOrUndefined)(existingDef) || !isElement(existingDef.ele)) { return; } if (!(0, typecheckers_1.isNullOrEmptyString)(callbackInfo.key)) //find by key { existingDef.callbacks = existingDef.callbacks.filter((cb) => { return cb.key !== callbackInfo.key; }); } else //find by handler - probably won't work for functions that are declared inline { existingDef.callbacks = existingDef.callbacks.filter((cb) => { return (0, typecheckers_1.isNullOrEmptyString)(cb.key) && cb.handler !== callbackInfo.handler; }); } if (existingDef.callbacks.length === 0) { existingDef.disconnect(); _DOMChangedObserverDefs = _DOMChangedObserverDefs.filter((def) => { return def !== existingDef; }); } }); } function isElementVisible(ele) { //must be a valid element if (!isElement(ele) || !ele.getAttribute) { return false; } try { var doc = ele.ownerDocument; var win = doc.defaultView || doc.parentWindow; var computed = win.getComputedStyle(ele); return !!(computed.display.toLowerCase() !== "none" && computed.visibility.toLowerCase() !== "hidden" && (ele.offsetWidth !== 0 || ele.offsetHeight !== 0 || ele.offsetParent !== null || ele.getClientRects().length)); } catch (ex) { } return false; } function querySelectorAllFirstOrNull(selectors, maintainOrder = false) { if ((0, typecheckers_1.isNullOrUndefined)(selectors)) { return null; } if (maintainOrder) { return (querySelectorAllMaintainOrder(selectors)[0] || null); } else { var result = (0, typecheckers_1.isString)(selectors) && !(0, typecheckers_1.isNullOrEmptyString)(selectors) ? document.querySelectorAll(selectors)[0] : Array.isArray(selectors) ? document.querySelectorAll(selectors.join(","))[0] : null; return (result || null); } } function querySelectorAllMaintainOrder(selectors, parent) { if ((0, typecheckers_1.isNullOrUndefined)(selectors)) { return null; } var query; if ((0, typecheckers_1.isString)(selectors) && !(0, typecheckers_1.isNullOrEmptyString)(selectors)) { query = selectors.split(","); } if (Array.isArray(selectors)) { query = selectors; } var eles = []; parent = parent || document; query.forEach((selector) => { if ((0, typecheckers_1.isString)(selector) && !(0, typecheckers_1.isNullOrEmptyString)(selector)) { var result = Array.prototype.slice.call(parent.querySelectorAll(selector)); eles = eles.concat(result); } }); return eles; } function getScrollParent(node) { if (node === null) { return null; } if (node.scrollHeight > node.clientHeight) { return node; } else { return getScrollParent(node.parentNode); } } var _scrollbarWidth = -1; function getScrollbarWidth() { if (_scrollbarWidth < 0) { var outer = document.createElement("div"); outer.style.visibility = "hidden"; outer.style.width = "100px"; outer.style["msOverflowStyle"] = "scrollbar"; // needed for WinJS apps document.body.appendChild(outer); var widthNoScroll = outer.offsetWidth; // force scrollbars outer.style.overflow = "scroll"; // add innerdiv var inner = document.createElement("div"); inner.style.width = "100%"; outer.appendChild(inner); var widthWithScroll = inner.offsetWidth; // remove divs outer.parentNode.removeChild(outer); _scrollbarWidth = widthNoScroll - widthWithScroll; } return _scrollbarWidth; } function cumulativeOffset(element) { var top = 0, left = 0; do { top += element.offsetTop || 0; left += element.offsetLeft || 0; element = element.offsetParent; } while (element); return { top: top, left: left }; } function computedStyleToInlineStyle(elm, options = { recursive: true, removeClassNames: true }) { if (!elm) { return; } if (options.recursive && elm.children && elm.children.length) { var children = Array.prototype.slice.call(elm.children); children.forEach(child => { computedStyleToInlineStyle(child, options); }); } var computedStyle = window.getComputedStyle(elm); if (options.removeClassNames) { elm.removeAttribute("class"); } elm.setAttribute("style", computedStyle.cssText); } function getPageHidden(document = window.document) { var hiddenPropName; if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support hiddenPropName = "hidden"; } else if (typeof document.msHidden !== "undefined") { hiddenPropName = "msHidden"; } else if (typeof document.webkitHidden !== "undefined") { hiddenPropName = "webkitHidden"; } return (0, typecheckers_1.isString)(hiddenPropName) ? document[hiddenPropName] : false; } function getAnimationFlags() { var isSupported = false, animationstring = 'animation', keyframeprefix = '', domPrefixes = 'Webkit Moz O ms Khtml'.split(' '), pfx = '', elem = document.createElement('div'); if (elem.style.animationName !== undefined) { isSupported = true; } if (isSupported === false) { for (var i = 0; i < domPrefixes.length; i++) { if (elem.style[domPrefixes[i] + 'AnimationName'] !== undefined) { pfx = domPrefixes[i]; animationstring = pfx + 'Animation'; keyframeprefix = '-' + pfx.toLowerCase() + '-'; isSupported = true; break; } } } return { supported: isSupported, animationName: animationstring, keyFramePrefix: keyframeprefix, prefix: pfx }; } function getAnimationEndEventName() { var animations = { "animation": "animationend", "OAnimation": "oAnimationEnd", "MozAnimation": "animationend", "WebkitAnimation": "webkitAnimationEnd" }; var flags = getAnimationFlags(); if (flags.supported) { return animations[flags.animationName]; } } function isElement(ele) { return !(0, typecheckers_1.isNullOrUndefined)(ele) && (ele.nodeType === 1 || ele instanceof Element); } function isNode(ele) { return !(0, typecheckers_1.isNullOrUndefined)(ele) && ((ele.nodeName && ele.nodeType >= 1 && ele.nodeType <= 12) || ele instanceof Node); } function _eleOrSelectorToElementArray(eleOrSelector) { if ((0, typecheckers_1.isNullOrUndefined)(eleOrSelector)) { return []; } var elements; if ((0, typecheckers_1.isString)(eleOrSelector)) { elements = Array.from(document.querySelectorAll(eleOrSelector)); } else if (isElement(eleOrSelector)) { elements = [eleOrSelector]; } else if (Array.isArray(eleOrSelector)) { elements = eleOrSelector; } else if (eleOrSelector.length || (0, typecheckers_1.isFunction)(eleOrSelector.forEach) || eleOrSelector instanceof NodeList) { elements = Array.from(eleOrSelector); } return elements || []; } function emptyHTMLElement(eleOrSelector) { var elements = _eleOrSelectorToElementArray(eleOrSelector); elements.forEach((ele) => { if (ele && isElement(ele) && ele.firstChild) { while (ele.firstChild) { try { ele.removeChild(ele.firstChild); } catch (ex) { break; } } } }); } function removeHTMLElement(eleOrSelector) { var elements = _eleOrSelectorToElementArray(eleOrSelector); elements.forEach((ele) => { try { var parent = ele.parentNode || ele.parentElement; if (ele && isElement(ele) && parent && parent.removeChild) { parent.removeChild(ele); } } catch (ex) { } }); } function removeAttributeFromHTMLElements(eleOrSelector, attributeName) { var elements = _eleOrSelectorToElementArray(eleOrSelector); elements.forEach((elm) => { try { elm.removeAttribute(attributeName); } catch (ex) { } }); } function getSelectOptionByValue(selectElement, value) { if ((0, typecheckers_1.isNullOrUndefined)(selectElement) || (0, typecheckers_1.isNullOrUndefined)(value)) { return null; } var option = Array.from(selectElement.options).filter(o => { return o.value === value.toString(); })[0]; return option; } function getSelectOptionByIndex(selectElement, index) { if ((0, typecheckers_1.isNullOrUndefined)(selectElement) || !(0, typecheckers_1.isNumeric)(index)) { return null; } return selectElement.options[Number(index)]; } function getSelectedOption(selectElement) { if ((0, typecheckers_1.isNullOrUndefined)(selectElement)) { return null; } return selectElement.options[selectElement.selectedIndex] || Array.from(selectElement.options).filter((option) => { return option.selected; })[0]; } function setSelectOptionByValue(selectElement, value) { var option = getSelectOptionByValue(selectElement, value); if (option) { option.selected = true; return option; } return null; } function setSelectOptionByIndex(selectElement, index) { if ((0, typecheckers_1.isNullOrUndefined)(selectElement) || !(0, typecheckers_1.isNumeric)(index)) { return null; } var option = selectElement.options[Number(index)]; if (option) { option.selected = true; return option; } return null; } function composePath(evt) { var path = ((0, typecheckers_1.isFunction)(evt["composedPath"]) && evt["composedPath"]()) || evt.path, target = evt.target; if (path !== null) { // Safari doesn't include Window, and it should. path = (path.indexOf(window) < 0) ? path.concat([window]) : path; return path; } if (target === window) { return [window]; } function getParents(node, memo) { memo = memo || []; var parentNode = node.parentNode; if (!parentNode) { return memo; } else { return getParents(parentNode, memo.concat([parentNode])); } } return [target].concat(getParents(target)).concat([window]); } /** timeouts after 10 seconds by default */ function waitForWindowObject(typeFullName, windowOrParent, timeout = 10000) { return waitFor(() => !(0, typecheckers_1.isTypeofFullNameNullOrUndefined)(typeFullName, windowOrParent), timeout); } /** timeouts after 10 seconds by default */ function waitFor(checker, timeout = 10000, intervalLength = 50) { return new Promise((resolve, reject) => { var timeoutId = null; var max = Math.round(timeout / intervalLength); var count = 0; var exists = false; var _retry = () => { if (timeoutId) { globalThis.clearTimeout(timeoutId); } try { exists = checker(); } catch (ex) { resolve(false); return; } if (exists || count > max) { resolve(exists); } else { timeoutId = globalThis.setTimeout(_retry, intervalLength); } count++; }; _retry(); }); } /** * Waits for an async check to return true or times out. * @param checker Async function that returns boolean result. * @param timeout The timeout in milliseconds. Defaults to 10000ms. * @param intervalLength The interval length in milliseconds to retry the checker function. Defaults to 50ms. */ async function waitForAsync(checker, timeout = 10000, intervalLength = 50) { var max = Math.round(timeout / intervalLength); var count = 0; var exists = false; for (var count = 0; count < max; count++) { exists = await checker(); if (exists) { break; } await delayAsync(intervalLength); } return exists; } /** * An async function that returns after a set delay. * @param delay The delay in milliseconds. Defaults to 500ms. */ function delayAsync(delay = 500) { return new Promise((resolve) => { globalThis.setTimeout(() => { resolve(null); }, delay); }); } function addStyleSheet(options, doc) { doc = doc || document; var head = doc.head || doc.getElementsByTagName("head")[0]; if (head) { var link = createStylesheet(options, doc); head.appendChild(link); } } function createStylesheet(options, doc) { doc = doc || document; options = options || {}; options.properties = { ...{ type: "text/css", rel: "stylesheet", }, ...options.properties }; return createHtmlElement("link", options, doc); } function createHtmlElement(tagName, options, doc) { doc = doc || document; var element = doc.createElement(tagName); if (options) { if (options.attributes) { Object.keys(options.attributes).forEach((attribName) => { var attribValue = options.attributes[attribName]; if (!(0, typecheckers_1.isNullOrUndefined)(attribValue)) { element.setAttribute(attribName, attribValue); } }); } if (options.properties) { var mergedProps = { ...options.properties, ...{ style: options.style } }; Object.keys(mergedProps).forEach((propName) => { var obj = mergedProps[propName]; if (!(0, typecheckers_1.isNullOrUndefined)(obj)) { if ((0, typecheckers_1.isString)(obj) || (0, typecheckers_1.isBoolean)(obj) || (0, typecheckers_1.isNumber)(obj)) { element[propName] = obj; } else { if (!element[propName]) { element[propName] = obj; } else { Object.keys(obj).forEach((objName) => { element[propName][objName] = obj[objName]; }); } } } }); } } return element; } function isInsideIFrame(win) { win = win || window; try { return win.parent.location !== win.location; } catch (ex) { return true; } } function isIFrameAccessible(iframeEle) { try { var location = (iframeEle.contentWindow || iframeEle.contentDocument).location; return location && location.origin ? true : false; } catch (ex) { return false; } } function HTMLEncode(d) { if ((0, typecheckers_1.isNullOrEmptyString)(d)) { return ""; } var tempString = String(d); var result = []; for (var index = 0; index < tempString.length; index++) { var char = tempString.charAt(index); switch (char) { case "<": result.push("&lt;"); break; case ">": result.push("&gt;"); break; case "&": result.push("&amp;"); break; case '"': result.push("&quot;"); break; case "'": result.push("&#39;"); break; default: result.push(char); } } return result.join(""); } function HTMLDecode(text) { if (text === null || text === "") { return ""; } let entities = [/&lt;/g, /&gt;/g, /&quot;/g, /&#39;/g, /&#58;/g, /&#123;/g, /&#125;/g, /&amp;/g]; let decodedValues = ["<", ">", '"', "'", ":", "{", "}", "&"]; for (let c = 0; c < entities.length; c++) { text = text.replace(entities[c], decodedValues[c]); } return text; } function ScriptEncode(e) { if (null === e || typeof e === "undefined") return ""; for (var d = String(e), a = [], c = 0, g = d.length; c < g; c++) { var b = d.charCodeAt(c); if (b > 4095) a.push("\\u" + b.toString(16).toUpperCase()); else if (b > 255) a.push("\\u0" + b.toString(16).toUpperCase()); else if (b > 127) a.push("\\u00" + b.toString(16).toUpperCase()); else { var f = d.charAt(c); switch (f) { case "\n": a.push("\\n"); break; case "\r": a.push("\\r"); break; case '"': a.push("\\u0022"); break; case "%": a.push("\\u0025"); break; case "&": a.push("\\u0026"); break; case "'": a.push("\\u0027"); break; case "(": a.push("\\u0028"); break; case ")": a.push("\\u0029"); break; case "+": a.push("\\u002b"); break; case "/": a.push("\\u002f"); break; case "<": a.push("\\u003c"); break; case ">": a.push("\\u003e"); break; case "\\": a.push("\\\\"); break; default: a.push(f); } } } return a.join(""); } function addEventListeners(eles, events, listener, useCapture = false) { if (!(0, typecheckers_1.isFunction)(listener)) { return; } var eventNames; if ((0, typecheckers_1.isString)(events)) { eventNames = events.split(" "); } else if (Array.isArray(events)) { eventNames = events; } if ((0, typecheckers_1.isNullOrEmptyArray)(eventNames)) { return; } var elements = _eleOrSelectorToElementArray(eles); if ((0, typecheckers_1.isNullOrEmptyArray)(elements)) { return; } elements.forEach((ele) => { if (isElement(ele) && (0, typecheckers_1.isFunction)(ele.addEventListener)) { eventNames.forEach((eventName) => { ele.addEventListener(eventName, listener, useCapture); }); } }); } /** defer calling this function multiple times within X time frame to execute only once after the last call */ function debounce(callback, ms, thisArg = null) { let timeoutId = null; let func = (...args) => { globalThis.clearTimeout(timeoutId); timeoutId = globalThis.setTimeout(() => { callback.apply(thisArg, args); }, ms); }; return func; } /** call a funciton X number of times, on a specific interval. */ function interval(callback, msBetweenCalls, numberOfTimesToCall, thisArg = null) { for (let index = 1; index <= numberOfTimesToCall; index++) globalThis.setTimeout(() => { callback.apply(thisArg); }, msBetweenCalls * index); } /** throttle repeated calls to callback, makes sure it is only called once per *wait* at most, but won't defer it for longer than that. * Unlike debounce, which can end up waiting for 5 minutes if it is being called repeatedly. */ function throttle(callback, wait = 250, thisArg = null) { let previous = 0; let timeout = null; let result; let storedContext = thisArg; let storedArgs; const later = () => { previous = Date.now(); timeout = null; result = callback.apply(storedContext, storedArgs); if (!timeout) { storedArgs = []; } }; let wrapper = (...args) => { const now = Date.now(); const remaining = wait - (now - previous); storedArgs = args; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = callback.apply(storedContext, storedArgs); if (!timeout) { storedArgs = []; } } else if (!timeout) { timeout = globalThis.setTimeout(later, remaining); } return result; }; return wrapper; } var _resizeHandlers = {}; var _resizeRegistered = false; function _handleResize() { Object.keys(_resizeHandlers).forEach(key => { try { _resizeHandlers[key](); } catch (e) { } }); } /** allows you to register, re-register or remove a resize handler without ending up with multiple registrations. */ function OnWindowResize(handlerID, handler) { if (!(0, typecheckers_1.isNullOrUndefined)(handler)) _resizeHandlers[handlerID] = handler; else delete _resizeHandlers[handlerID]; if (!_resizeRegistered) { _resizeRegistered = true; addEventHandler(window, "resize", debounce(_handleResize, 250)); } } function dispatchCustomEvent(obj, eventName, params = { bubbles: false, cancelable: false, detail: null }) { if ((0, typecheckers_1.isNullOrUndefined)(obj) || !(0, typecheckers_1.isFunction)(obj.dispatchEvent)) { return; } params.bubbles = params.bubbles || false; params.cancelable = params.cancelable || false; params.detail = params.detail || null; let event = null; if ((0, typecheckers_1.isFunction)(window.CustomEvent)) { event = new CustomEvent(eventName, params); } else { event = document.createEvent('CustomEvent'); event.initCustomEvent(eventName, params.bubbles, params.cancelable, params.detail); } obj.dispatchEvent(event); } function addStyleElement(cssText, id) { var parent = document.head || document.getElementsByTagName("head")[0] || document; let cssElm = !(0, typecheckers_1.isNullOrEmptyString)(id) ? document.getElementById(id) : null; if (!cssElm) { cssElm = document.createElement("style"); if (!(0, typecheckers_1.isNullOrEmptyString)(id)) cssElm.id = id; parent.appendChild(cssElm); } cssElm.innerHTML = cssText; return cssElm; } function getReactInstanceFromElement(node) { if (!(0, typecheckers_1.isNullOrUndefined)(node)) { for (const key in node) { if ((key).startsWith("__reactInternalInstance$") || key.startsWith("__reactFiber$")) { return node[key]; } } } return null; } /** registers a listener to when the browser url changed */ function registerUrlChanged(callback) { if (!_global.registerUrlChangedCallbacks.includes(callback)) { _global.registerUrlChangedCallbacks.push(callback); } if (_global.urlChangedHandlerRegistered === false) { _global.urlChangedHandlerRegistered = true; let executeCallbacks = () => { _global.registerUrlChangedCallbacks.forEach((callbackFunc) => { try { if ((0, typecheckers_1.isFunction)(callbackFunc)) { callbackFunc(); } } catch { } }); }; if ("navigation" in window && (0, typecheckers_1.isFunction)(window.navigation.addEventListener)) { window.navigation.addEventListener("navigate", executeCallbacks); } else { let url = window.location.href; globalThis.setInterval(() => { if (url !== window.location.href) { url = window.location.href; executeCallbacks(); } }, 500); } } } exports.DisableAnchorInterceptAttribute = "data-interception"; exports.DisableAnchorInterceptValue = "off"; function DisableAnchorIntercept(link) { link.setAttribute(exports.DisableAnchorInterceptAttribute, exports.DisableAnchorInterceptValue); } /** go over HTML and add data-interception="off" to all <a> tags. */ function DisableAnchorInterceptInHtml(html) { return html.replace(/<a /g, `<a ${exports.DisableAnchorInterceptAttribute}="${exports.DisableAnchorInterceptValue}" `); } /** adding the disable attribute to all a links in the container that do not already have them. returning the number of links that were disabled (not ones that were already disabled before) */ function DisableAnchorInterceptInElement(container) { var links = container.querySelectorAll(`a:not([${exports.DisableAnchorInterceptAttribute}='${exports.DisableAnchorInterceptValue}'])`); links.forEach(link => DisableAnchorIntercept(link)); return links.length; } function isChildOf(node, parent) { let classes = ((0, typecheckers_1.isNotEmptyString)(parent.class) ? [parent.class] : (0, typecheckers_1.isNotEmptyArray)(parent.class) ? parent.class : []).map(c => `.${c}`); let ids = ((0, typecheckers_1.isNotEmptyString)(parent.id) ? [parent.id] : (0, typecheckers_1.isNotEmptyArray)(parent.id) ? parent.id : []).map(id => `#${id}`); let tagNames = ((0, typecheckers_1.isNotEmptyString)(parent.tagName) ? [parent.tagName.toUpperCase()] : (0, typecheckers_1.isNotEmptyArray)(parent.tagName) ? parent.tagName : []).map(tagName => `${tagName.toUpperCase()}`); let queySelectorText = [...classes, ...ids, ...tagNames].join(','); if ((0, typecheckers_1.isNullOrEmptyString)(queySelectorText)) return true; if (node instanceof HTMLElement) return node.closest(queySelectorText) ? true : false; else return false; } function findAcestor(ele, predicate) { if (!isElement(ele) || !(0, typecheckers_1.isFunction)(predicate)) { return null; } while (ele) { if (predicate(ele)) { return ele; } ele = ele.parentElement; } return null; } function loadModernFormsCSS() { let styleElm = document.getElementById('kw_modernui_css'); if (!styleElm) { styleElm = document.createElement("link"); styleElm.id = "kw_modernui_css"; styleElm.rel = "stylesheet"; styleElm.href = `${(0, constants_1.kwiz_cdn_root)()}/products/modern/css/app.min.css`; document.head.appendChild(styleElm); } } function showLoadingOverlay(elm, options) { let overlay = elm.querySelector('.kw-loading-overlay'); if (!overlay) { overlay = document.createElement("div"); overlay.className = "kw-loading-overlay"; overlay.style.position = "absolute"; overlay.style.top = "0"; overlay.style.left = "0"; overlay.style.right = "0"; overlay.style.bottom = "0"; overlay.style.zIndex = "9999999"; overlay.style.display = "flex"; overlay.style.justifyContent = "center"; overlay.style.alignItems = "center"; overlay.style.height = "100%"; overlay.style.width = "100%"; elm.appendChild(overlay); } overlay.innerHTML = options && options.innerHtml || `<img src="${images_1.LOGO_ANIM}" style="max-width: 30%;max-height: 30%;">`; overlay.style.backgroundColor = options && options.bgColor || "white"; } function hideLoadingOverlay(elm) { if (isElement(elm)) { let overlays = Array.from(elm.querySelectorAll('.kw-loading-overlay')); removeHTMLElement(overlays); } } function getLoadingOverlayHtml(options) { let overlay = document.createElement("div"); showLoadingOverlay(overlay, options); return overlay.innerHTML; } function getUniqueElementId(id = "") { return `${id}${(0, random_1.getUniqueId)()}`; } function stopEvent(e) { e.stopPropagation && e.stopPropagation(); e.preventDefault && e.preventDefault(); } /** send in --color or var(--color) and get the computed value for an element */ function getCSSVariableValue(value, elm = document.body) { if (value.startsWith("var(")) value = value.slice(4, value.length - 1); if (value.startsWith("--")) { var style = getComputedStyle(elm); var varValue = style.getPropertyValue(value); if (!(0, typecheckers_1.isNullOrEmptyString)(varValue)) return varValue; } return value; } /** * Converts an HTMLImageElement/SVGImageElement to base 64 and resizes the image to the exact dimensions of the element. * The following image types are supported: jpg, jpeg, gif, png, webp, bmp */ async function convertImageToBase64(imgEle, quality = "medium") { if (!isElement(imgEle) || ((0, typecheckers_1.isNullOrEmptyString)(imgEle.src) && (0, typecheckers_1.isNullOrEmptyString)(imgEle.getAttribute("xlink:href")))) { return null; } return new Promise((resolve) => { let xlinkHref = imgEle.getAttribute("xlink:href"); let useXlinkHref = !(0, typecheckers_1.isNullOrEmptyString)(xlinkHref); let src = useXlinkHref ? xlinkHref : imgEle.src; let type = "image/png"; if (!(0, url_1.isDataUrl)(src)) { let ext = (0, url_1.getURLExtension)(src); if (!(0, typecheckers_1.isNullOrEmptyString)(ext)) { ext = ext.toLowerCase(); if (ext !== "png") { type = "image/jpeg"; } } } let height = 0; let width = 0; if (imgEle instanceof SVGImageElement || useXlinkHref || imgEle.tagName === "image") { width = parseInt(imgEle.getAttribute("width")); height = parseInt(imgEle.getAttribute("height")); } else { width = imgEle.width; height = imgEle.height; } let canvas = document.createElement("canvas"); canvas.height = height; canvas.width = width; let ctx = canvas.getContext("2d"); ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = quality; let isCrossOrigin = !src.toLowerCase().startsWith(window.location.origin.toLowerCase()); let crossOriginImg = new Image(); crossOriginImg.onload = () => { let dataURL = null; try { ctx.drawImage(crossOriginImg, 0, 0, width, height); dataURL = canvas.toDataURL(type, quality === "high" ? 1 : quality === "medium" ? 0.75 : 0.5); } catch { dataURL = null; } canvas = null; ctx = null; crossOriginImg = null; resolve(dataURL); }; crossOriginImg.onerror = () => { canvas = null; ctx = null; crossOriginImg = null; resolve(null); }; if (isCrossOrigin === true) { crossOriginImg.crossOrigin = "anonymous"; } else { crossOriginImg.crossOrigin = "use-credentials"; } crossOriginImg.src = src; }); } //# sourceMappingURL=browser.js.map