{ "version": 3, "sources": ["../../../../../../../src/node_modules/@cahmoraes93/maybe/src/index.ts", "../../../../../../../src/node_modules/@cahmoraes93/maybe/src/maybe/index.ts", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/webpack/universalModuleDefinition", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/webpack/bootstrap", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/index.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/browser.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/functions.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/html.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/image.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/init.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/json.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/modal.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/pdf.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/print.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/js/raw-html.js", "../../../../../../../src/node_modules/print-js/dist/webpack:/printJS/src/sass/index.scss", "../../../../../../../src/js/i18n/datepicker/jquery.ui.datepicker-nl.js", "../../../../../../../src/js/lib/gettext.js", "../../../../../../../src/js/i18n/nl.js", "../../../../../../../src/js/lib/polyfills/url-search-params.js", "../../../../../../../src/js/lib/text-utils.js", "../../../../../../../src/js/lib/errors.js", "../../../../../../../src/js/lib/tokens.js", "../../../../../../../src/js/lib/baby-lisp.js", "../../../../../../../src/js/lib/lenses.js", "../../../../../../../src/js/lib/functional.js", "../../../../../../../src/js/lib/baby-lisp-apply.js", "../../../../../../../src/js/lib/booleanbucket.js", "../../../../../../../src/js/lib/mode.js", "../../../../../../../src/js/lib/collect-values.js", "../../../../../../../src/js/lib/vars.js", "../../../../../../../src/js/lib/case-exit.js", "../../../../../../../src/js/lib/a11y-user-detect.js", "../../../../../../../src/js/lib/a11y.js", "../../../../../../../src/js/lib/escape.js", "../../../../../../../src/js/lib/notify.js", "../../../../../../../src/js/lib/conf.js", "../../../../../../../src/js/lib/location.js", "../../../../../../../src/js/lib/ajax.js", "../../../../../../../src/js/lib/settled.js", "../../../../../../../src/js/lib/bbi.js", "../../../../../../../src/js/lib/control-helpers.js", "../../../../../../../src/js/lib/quotable.js", "../../../../../../../src/js/lib/dates.js", "../../../../../../../src/js/lib/feature-queries.js", "../../../../../../../src/js/lib/form-widgets.js", "../../../../../../../src/js/lib/dynprops.js", "../../../../../../../src/js/lib/hooks.js", "../../../../../../../src/js/lib/control.js", "../../../../../../../src/js/lib/types.js", "../../../../../../../src/js/lib/control-validation.js", "../../../../../../../src/js/lib/groupings.js", "../../../../../../../src/js/lib/font-classes.js", "../../../../../../../src/js/lib/names.js", "../../../../../../../src/js/lib/form-groups.js", "../../../../../../../src/node_modules/@lit/reactive-element/src/css-tag.ts", "../../../../../../../src/node_modules/@lit/reactive-element/src/reactive-element.ts", "../../../../../../../src/node_modules/lit-html/src/lit-html.ts", "../../../../../../../src/node_modules/lit-element/src/lit-element.ts", "../../../../../../../src/js/lib/form-widgets-definitions.js", "../../../../../../../src/js/lib/numerals.js", "../../../../../../../src/js/lib/url-utils.js", "../../../../../../../src/js/lib/utils.js", "../../../../../../../src/js/lib/jumplist.js", "../../../../../../../src/js/lib/user-info.js", "../../../../../../../src/js/lib/permissions.js", "../../../../../../../src/js/lib/$.scrollTo.js", "../../../../../../../src/js/json.js", "../../../../../../../src/plugins/Dialogue/Dialogue.js", "../../../../../../../src/plugins/a11y-describedby/a11y-describedby.js", "../../../../../../../src/custom/rijks-cyberscan/plugins/a11y-errors/a11y-errors.js", "../../../../../../../src/plugins/auto-scroll/auto-scroll.js", "../../../../../../../src/js/lib/getcurrentchapterid.js", "../../../../../../../src/js/lib/getmetadata.js", "../../../../../../../src/node_modules/proxy-polyfill/proxy.min.js", "../../../../../../../src/js/lib/store.js", "../../../../../../../src/custom/rijks-cyberscan/plugins/actielijst/actielijst.js", "../../../../../../../src/plugins/change-title-on-tab-blur/change-title-on-tab-blur.js", "../../../../../../../src/custom/rijks-cyberscan/plugins/chapters-helper/chapters-helper.js", "../../../../../../../src/plugins/custom-radios/custom-radios.js", "../../../../../../../src/plugins/end-tools/end-tools.js", "../../../../../../../src/plugins/has-no-next-meta/has-no-next-meta.js", "../../../../../../../src/plugins/headings/headings.js", "../../../../../../../src/plugins/history/history.js", "../../../../../../../src/plugins/showdown/showdown.js", "../../../../../../../src/plugins/showdown-converter/showdown-converter.js", "../../../../../../../src/custom/rijks-cyberscan/plugins/info-sources/info-sources.js", "../../../../../../../src/custom/rijks-cyberscan/plugins/infographics/infographics.js", "../../../../../../../src/plugins/md-labels/md-labels.js", "../../../../../../../src/plugins/metadata-change-navtext/metadata-change-navtext.js", "../../../../../../../src/plugins/metadata-scoring/metadata-scoring.js", "../../../../../../../src/plugins/metaprogress/metaprogress.js", "../../../../../../../src/node_modules/ramda/es/internal/_isPlaceholder.js", "../../../../../../../src/node_modules/ramda/es/internal/_curry1.js", "../../../../../../../src/node_modules/ramda/es/internal/_curry2.js", "../../../../../../../src/node_modules/ramda/es/internal/_has.js", "../../../../../../../src/node_modules/ramda/es/hasPath.js", "../../../../../../../src/node_modules/ramda/es/has.js", "../../../../../../../src/plugins/mis-click-count/mis-click-count.js", "../../../../../../../src/plugins/mustache/mustache.js", "../../../../../../../src/plugins/nodename-css/nodename-css.js", "../../../../../../../src/plugins/non-indenting-jumplist/non-indenting-jumplist.js", "../../../../../../../src/custom/nta/plugins/dynamic-menu-items/clearmenu.js", "../../../../../../../src/custom/nta/plugins/dynamic-menu-items/createmenu.js", "../../../../../../../src/custom/nta/plugins/dynamic-menu-items/dynamic-menu-items.js", "../../../../../../../src/custom/nta/plugins/mopinion/mopinion.js", "../../../../../../../src/custom/nta/plugins/proxymap/proxymap.js", "../../../../../../../src/custom/nta/plugins/path-to-modelname/path-to-modelname.js", "../../../../../../../src/custom/nta/plugins/piwik/piwik.js", "../../../../../../../src/custom/nta/plugins/rijksoverheidshuisstijlfonts/rijksoverheidshuisstijlfonts.js", "../../../../../../../src/plugins/questionlabelgroup-ng/questionlabelgroup-ng.js", "../../../../../../../src/custom/rijks-cyberscan/plugins/record-link/record-link.js", "../../../../../../../src/plugins/savecase-email-link-popup/savecase-email-link-popup.js", "../../../../../../../src/plugins/savecase-auto-continue/savecase-auto-continue.js"], "sourcesContent": ["export { default as Maybe } from './maybe'\r\n", "type CallbackM = (value: T) => K\ntype CallbackChainM = (value: T) => Maybe\n\nexport default class Maybe {\n constructor(private value: T) {}\n\n public static of(value: T): Maybe {\n return new Maybe(value)\n }\n\n public map(callbackMap: CallbackM): Maybe {\n if (this.isEmpty()) return Maybe.of(null) as Maybe\n return Maybe.of(callbackMap(this.value))\n }\n\n public chain(callbackChain: CallbackChainM): Maybe {\n const chained = this.map(callbackChain).join() as Maybe\n if (chained === null) return Maybe.of(null) as Maybe\n return chained\n }\n\n public getOrElse(defaultValue: K): T | K {\n return this.isEmpty() ? defaultValue : this.value\n }\n\n private join(): T {\n return this.value\n }\n\n private isEmpty(): boolean {\n return this.value === null || this.value === undefined\n }\n}\n", "(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"printJS\"] = factory();\n\telse\n\t\troot[\"printJS\"] = factory();\n})(window, function() {\nreturn ", " \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n", "import './sass/index.scss'\nimport print from './js/init'\n\nconst printJS = print.init\n\nif (typeof window !== 'undefined') {\n window.printJS = printJS\n}\n\nexport default printJS\n", "const Browser = {\n // Firefox 1.0+\n isFirefox: () => {\n return typeof InstallTrigger !== 'undefined'\n },\n // Internet Explorer 6-11\n isIE: () => {\n return navigator.userAgent.indexOf('MSIE') !== -1 || !!document.documentMode\n },\n // Edge 20+\n isEdge: () => {\n return !Browser.isIE() && !!window.StyleMedia\n },\n // Chrome 1+\n isChrome: (context = window) => {\n return !!context.chrome\n },\n // At least Safari 3+: \"[object HTMLElementConstructor]\"\n isSafari: () => {\n return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 ||\n navigator.userAgent.toLowerCase().indexOf('safari') !== -1\n },\n // IOS Chrome\n isIOSChrome: () => {\n return navigator.userAgent.toLowerCase().indexOf('crios') !== -1\n }\n}\n\nexport default Browser\n", "import Modal from './modal'\nimport Browser from './browser'\n\nexport function addWrapper (htmlData, params) {\n const bodyStyle = 'font-family:' + params.font + ' !important; font-size: ' + params.font_size + ' !important; width:100%;'\n return '
' + htmlData + '
'\n}\n\nexport function capitalizePrint (obj) {\n return obj.charAt(0).toUpperCase() + obj.slice(1)\n}\n\nexport function collectStyles (element, params) {\n const win = document.defaultView || window\n\n // String variable to hold styling for each element\n let elementStyle = ''\n\n // Loop over computed styles\n const styles = win.getComputedStyle(element, '')\n\n for (let key = 0; key < styles.length; key++) {\n // Check if style should be processed\n if (params.targetStyles.indexOf('*') !== -1 || params.targetStyle.indexOf(styles[key]) !== -1 || targetStylesMatch(params.targetStyles, styles[key])) {\n if (styles.getPropertyValue(styles[key])) elementStyle += styles[key] + ':' + styles.getPropertyValue(styles[key]) + ';'\n }\n }\n\n // Print friendly defaults (deprecated)\n elementStyle += 'max-width: ' + params.maxWidth + 'px !important; font-size: ' + params.font_size + ' !important;'\n\n return elementStyle\n}\n\nfunction targetStylesMatch (styles, value) {\n for (let i = 0; i < styles.length; i++) {\n if (typeof value === 'object' && value.indexOf(styles[i]) !== -1) return true\n }\n return false\n}\n\nexport function addHeader (printElement, params) {\n // Create the header container div\n const headerContainer = document.createElement('div')\n\n // Check if the header is text or raw html\n if (isRawHTML(params.header)) {\n headerContainer.innerHTML = params.header\n } else {\n // Create header element\n const headerElement = document.createElement('h1')\n\n // Create header text node\n const headerNode = document.createTextNode(params.header)\n\n // Build and style\n headerElement.appendChild(headerNode)\n headerElement.setAttribute('style', params.headerStyle)\n headerContainer.appendChild(headerElement)\n }\n\n printElement.insertBefore(headerContainer, printElement.childNodes[0])\n}\n\nexport function cleanUp (params) {\n // If we are showing a feedback message to user, remove it\n if (params.showModal) Modal.close()\n\n // Check for a finished loading hook function\n if (params.onLoadingEnd) params.onLoadingEnd()\n\n // If preloading pdf files, clean blob url\n if (params.showModal || params.onLoadingStart) window.URL.revokeObjectURL(params.printable)\n\n // Run onPrintDialogClose callback\n let event = 'mouseover'\n\n if (Browser.isChrome() || Browser.isFirefox()) {\n // Ps.: Firefox will require an extra click in the document to fire the focus event.\n event = 'focus'\n }\n\n const handler = () => {\n // Make sure the event only happens once.\n window.removeEventListener(event, handler)\n\n params.onPrintDialogClose()\n\n // Remove iframe from the DOM\n const iframe = document.getElementById(params.frameId)\n\n if (iframe) {\n iframe.remove()\n }\n }\n\n window.addEventListener(event, handler)\n}\n\nexport function isRawHTML (raw) {\n const regexHtml = new RegExp('<([A-Za-z][A-Za-z0-9]*)\\\\b[^>]*>(.*?)')\n return regexHtml.test(raw)\n}\n", "import { collectStyles, addHeader } from './functions'\nimport Print from './print'\n\nexport default {\n print: (params, printFrame) => {\n // Get the DOM printable element\n const printElement = isHtmlElement(params.printable) ? params.printable : document.getElementById(params.printable)\n\n // Check if the element exists\n if (!printElement) {\n window.console.error('Invalid HTML element id: ' + params.printable)\n return\n }\n\n // Clone the target element including its children (if available)\n params.printableElement = cloneElement(printElement, params)\n\n // Add header\n if (params.header) {\n addHeader(params.printableElement, params)\n }\n\n // Print html element contents\n Print.send(params, printFrame)\n }\n}\n\nfunction cloneElement (element, params) {\n // Clone the main node (if not already inside the recursion process)\n const clone = element.cloneNode()\n\n // Loop over and process the children elements / nodes (including text nodes)\n const childNodesArray = Array.prototype.slice.call(element.childNodes)\n for (let i = 0; i < childNodesArray.length; i++) {\n // Check if we are skipping the current element\n if (params.ignoreElements.indexOf(childNodesArray[i].id) !== -1) {\n continue\n }\n\n // Clone the child element\n const clonedChild = cloneElement(childNodesArray[i], params)\n\n // Attach the cloned child to the cloned parent node\n clone.appendChild(clonedChild)\n }\n\n // Get all styling for print element (for nodes of type element only)\n if (params.scanStyles && element.nodeType === 1) {\n clone.setAttribute('style', collectStyles(element, params))\n }\n\n // Check if the element needs any state processing (copy user input data)\n switch (element.tagName) {\n case 'SELECT':\n // Copy the current selection value to its clone\n clone.value = element.value\n break\n case 'CANVAS':\n // Copy the canvas content to its clone\n clone.getContext('2d').drawImage(element, 0, 0)\n break\n }\n\n return clone\n}\n\nfunction isHtmlElement (printable) {\n // Check if element is instance of HTMLElement or has nodeType === 1 (for elements in iframe)\n return typeof printable === 'object' && printable && (printable instanceof HTMLElement || printable.nodeType === 1)\n}\n", "import { addHeader } from './functions'\nimport Print from './print'\nimport Browser from './browser'\n\nexport default {\n print: (params, printFrame) => {\n // Check if we are printing one image or multiple images\n if (params.printable.constructor !== Array) {\n // Create array with one image\n params.printable = [params.printable]\n }\n\n // Create printable element (container)\n params.printableElement = document.createElement('div')\n\n // Create all image elements and append them to the printable container\n params.printable.forEach(src => {\n // Create the image element\n const img = document.createElement('img')\n img.setAttribute('style', params.imageStyle)\n\n // Set image src with the file url\n img.src = src\n\n // The following block is for Firefox, which for some reason requires the image's src to be fully qualified in\n // order to print it\n if (Browser.isFirefox()) {\n const fullyQualifiedSrc = img.src\n img.src = fullyQualifiedSrc\n }\n\n // Create the image wrapper\n const imageWrapper = document.createElement('div')\n\n // Append image to the wrapper element\n imageWrapper.appendChild(img)\n\n // Append wrapper to the printable element\n params.printableElement.appendChild(imageWrapper)\n })\n\n // Check if we are adding a print header\n if (params.header) addHeader(params.printableElement, params)\n\n // Print image\n Print.send(params, printFrame)\n }\n}\n", "'use strict'\n\nimport Browser from './browser'\nimport Modal from './modal'\nimport Pdf from './pdf'\nimport Html from './html'\nimport RawHtml from './raw-html'\nimport Image from './image'\nimport Json from './json'\n\nconst printTypes = ['pdf', 'html', 'image', 'json', 'raw-html']\n\nexport default {\n init () {\n const params = {\n printable: null,\n fallbackPrintable: null,\n type: 'pdf',\n header: null,\n headerStyle: 'font-weight: 300;',\n maxWidth: 800,\n properties: null,\n gridHeaderStyle: 'font-weight: bold; padding: 5px; border: 1px solid #dddddd;',\n gridStyle: 'border: 1px solid lightgray; margin-bottom: -1px;',\n showModal: false,\n onError: (error) => { throw error },\n onLoadingStart: null,\n onLoadingEnd: null,\n onPrintDialogClose: () => {},\n onIncompatibleBrowser: () => {},\n modalMessage: 'Retrieving Document...',\n frameId: 'printJS',\n printableElement: null,\n documentTitle: 'Document',\n targetStyle: ['clear', 'display', 'width', 'min-width', 'height', 'min-height', 'max-height'],\n targetStyles: ['border', 'box', 'break', 'text-decoration'],\n ignoreElements: [],\n repeatTableHeader: true,\n css: null,\n style: null,\n scanStyles: true,\n base64: false,\n\n // Deprecated\n onPdfOpen: null,\n font: 'TimesNewRoman',\n font_size: '12pt',\n honorMarginPadding: true,\n honorColor: false,\n imageStyle: 'max-width: 100%;'\n }\n\n // Check if a printable document or object was supplied\n const args = arguments[0]\n if (args === undefined) {\n throw new Error('printJS expects at least 1 attribute.')\n }\n\n // Process parameters\n switch (typeof args) {\n case 'string':\n params.printable = encodeURI(args)\n params.fallbackPrintable = params.printable\n params.type = arguments[1] || params.type\n break\n case 'object':\n params.printable = args.printable\n params.fallbackPrintable = typeof args.fallbackPrintable !== 'undefined' ? args.fallbackPrintable : params.printable\n params.fallbackPrintable = params.base64 ? `data:application/pdf;base64,${params.fallbackPrintable}` : params.fallbackPrintable\n for (var k in params) {\n if (k === 'printable' || k === 'fallbackPrintable') continue\n\n params[k] = typeof args[k] !== 'undefined' ? args[k] : params[k]\n }\n break\n default:\n throw new Error('Unexpected argument type! Expected \"string\" or \"object\", got ' + typeof args)\n }\n\n // Validate printable\n if (!params.printable) throw new Error('Missing printable information.')\n\n // Validate type\n if (!params.type || typeof params.type !== 'string' || printTypes.indexOf(params.type.toLowerCase()) === -1) {\n throw new Error('Invalid print type. Available types are: pdf, html, image and json.')\n }\n\n // Check if we are showing a feedback message to the user (useful for large files)\n if (params.showModal) Modal.show(params)\n\n // Check for a print start hook function\n if (params.onLoadingStart) params.onLoadingStart()\n\n // To prevent duplication and issues, remove any used printFrame from the DOM\n const usedFrame = document.getElementById(params.frameId)\n\n if (usedFrame) usedFrame.parentNode.removeChild(usedFrame)\n\n // Create a new iframe for the print job\n const printFrame = document.createElement('iframe')\n\n if (Browser.isFirefox()) {\n // Set the iframe to be is visible on the page (guaranteed by fixed position) but hidden using opacity 0, because\n // this works in Firefox. The height needs to be sufficient for some part of the document other than the PDF\n // viewer's toolbar to be visible in the page\n printFrame.setAttribute('style', 'width: 1px; height: 100px; position: fixed; left: 0; top: 0; opacity: 0; border-width: 0; margin: 0; padding: 0')\n } else {\n // Hide the iframe in other browsers\n printFrame.setAttribute('style', 'visibility: hidden; height: 0; width: 0; position: absolute; border: 0')\n }\n\n // Set iframe element id\n printFrame.setAttribute('id', params.frameId)\n\n // For non pdf printing, pass an html document string to srcdoc (force onload callback)\n if (params.type !== 'pdf') {\n printFrame.srcdoc = '' + params.documentTitle + ''\n\n // Attach css files\n if (params.css) {\n // Add support for single file\n if (!Array.isArray(params.css)) params.css = [params.css]\n\n // Create link tags for each css file\n params.css.forEach(file => {\n printFrame.srcdoc += ''\n })\n }\n\n printFrame.srcdoc += ''\n }\n\n // Check printable type\n switch (params.type) {\n case 'pdf':\n // Check browser support for pdf and if not supported we will just open the pdf file instead\n if (Browser.isIE()) {\n try {\n console.info('Print.js doesn\\'t support PDF printing in Internet Explorer.')\n const win = window.open(params.fallbackPrintable, '_blank')\n win.focus()\n params.onIncompatibleBrowser()\n } catch (error) {\n params.onError(error)\n } finally {\n // Make sure there is no loading modal opened\n if (params.showModal) Modal.close()\n if (params.onLoadingEnd) params.onLoadingEnd()\n }\n } else {\n Pdf.print(params, printFrame)\n }\n break\n case 'image':\n Image.print(params, printFrame)\n break\n case 'html':\n Html.print(params, printFrame)\n break\n case 'raw-html':\n RawHtml.print(params, printFrame)\n break\n case 'json':\n Json.print(params, printFrame)\n break\n }\n }\n}\n", "import { capitalizePrint, addHeader } from './functions'\nimport Print from './print'\n\nexport default {\n print: (params, printFrame) => {\n // Check if we received proper data\n if (typeof params.printable !== 'object') {\n throw new Error('Invalid javascript data object (JSON).')\n }\n\n // Validate repeatTableHeader\n if (typeof params.repeatTableHeader !== 'boolean') {\n throw new Error('Invalid value for repeatTableHeader attribute (JSON).')\n }\n\n // Validate properties\n if (!params.properties || !Array.isArray(params.properties)) {\n throw new Error('Invalid properties array for your JSON data.')\n }\n\n // We will format the property objects to keep the JSON api compatible with older releases\n params.properties = params.properties.map(property => {\n return {\n field: typeof property === 'object' ? property.field : property,\n displayName: typeof property === 'object' ? property.displayName : property,\n columnSize: typeof property === 'object' && property.columnSize ? property.columnSize + ';' : 100 / params.properties.length + '%;'\n }\n })\n\n // Create a print container element\n params.printableElement = document.createElement('div')\n\n // Check if we are adding a print header\n if (params.header) {\n addHeader(params.printableElement, params)\n }\n\n // Build the printable html data\n params.printableElement.innerHTML += jsonToHTML(params)\n\n // Print the json data\n Print.send(params, printFrame)\n }\n}\n\nfunction jsonToHTML (params) {\n // Get the row and column data\n const data = params.printable\n const properties = params.properties\n\n // Create a html table\n let htmlData = ''\n\n // Check if the header should be repeated\n if (params.repeatTableHeader) {\n htmlData += ''\n }\n\n // Add the table header row\n htmlData += ''\n\n // Add the table header columns\n for (let a = 0; a < properties.length; a++) {\n htmlData += ''\n }\n\n // Add the closing tag for the table header row\n htmlData += ''\n\n // If the table header is marked as repeated, add the closing tag\n if (params.repeatTableHeader) {\n htmlData += ''\n }\n\n // Create the table body\n htmlData += ''\n\n // Add the table data rows\n for (let i = 0; i < data.length; i++) {\n // Add the row starting tag\n htmlData += ''\n\n // Print selected properties only\n for (let n = 0; n < properties.length; n++) {\n let stringData = data[i]\n\n // Support nested objects\n const property = properties[n].field.split('.')\n if (property.length > 1) {\n for (let p = 0; p < property.length; p++) {\n stringData = stringData[property[p]]\n }\n } else {\n stringData = stringData[properties[n].field]\n }\n\n // Add the row contents and styles\n htmlData += ''\n }\n\n // Add the row closing tag\n htmlData += ''\n }\n\n // Add the table and body closing tags\n htmlData += '
' + capitalizePrint(properties[a].displayName) + '
' + stringData + '
'\n\n return htmlData\n}\n", "const Modal = {\n show (params) {\n // Build modal\n const modalStyle = 'font-family:sans-serif; ' +\n 'display:table; ' +\n 'text-align:center; ' +\n 'font-weight:300; ' +\n 'font-size:30px; ' +\n 'left:0; top:0;' +\n 'position:fixed; ' +\n 'z-index: 9990;' +\n 'color: #0460B5; ' +\n 'width: 100%; ' +\n 'height: 100%; ' +\n 'background-color:rgba(255,255,255,.9);' +\n 'transition: opacity .3s ease;'\n\n // Create wrapper\n const printModal = document.createElement('div')\n printModal.setAttribute('style', modalStyle)\n printModal.setAttribute('id', 'printJS-Modal')\n\n // Create content div\n const contentDiv = document.createElement('div')\n contentDiv.setAttribute('style', 'display:table-cell; vertical-align:middle; padding-bottom:100px;')\n\n // Add close button (requires print.css)\n const closeButton = document.createElement('div')\n closeButton.setAttribute('class', 'printClose')\n closeButton.setAttribute('id', 'printClose')\n contentDiv.appendChild(closeButton)\n\n // Add spinner (requires print.css)\n const spinner = document.createElement('span')\n spinner.setAttribute('class', 'printSpinner')\n contentDiv.appendChild(spinner)\n\n // Add message\n const messageNode = document.createTextNode(params.modalMessage)\n contentDiv.appendChild(messageNode)\n\n // Add contentDiv to printModal\n printModal.appendChild(contentDiv)\n\n // Append print modal element to document body\n document.getElementsByTagName('body')[0].appendChild(printModal)\n\n // Add event listener to close button\n document.getElementById('printClose').addEventListener('click', function () {\n Modal.close()\n })\n },\n close () {\n const printModal = document.getElementById('printJS-Modal')\n\n if (printModal) {\n printModal.parentNode.removeChild(printModal)\n }\n }\n}\n\nexport default Modal\n", "import Print from './print'\nimport { cleanUp } from './functions'\n\nexport default {\n print: (params, printFrame) => {\n // Check if we have base64 data\n if (params.base64) {\n const bytesArray = Uint8Array.from(atob(params.printable), c => c.charCodeAt(0))\n createBlobAndPrint(params, printFrame, bytesArray)\n return\n }\n\n // Format pdf url\n params.printable = /^(blob|http|\\/\\/)/i.test(params.printable)\n ? params.printable\n : window.location.origin + (params.printable.charAt(0) !== '/' ? '/' + params.printable : params.printable)\n\n // Get the file through a http request (Preload)\n const req = new window.XMLHttpRequest()\n req.responseType = 'arraybuffer'\n\n req.addEventListener('error', () => {\n cleanUp(params)\n params.onError(req.statusText, req)\n\n // Since we don't have a pdf document available, we will stop the print job\n })\n\n req.addEventListener('load', () => {\n // Check for errors\n if ([200, 201].indexOf(req.status) === -1) {\n cleanUp(params)\n params.onError(req.statusText, req)\n\n // Since we don't have a pdf document available, we will stop the print job\n return\n }\n\n // Print requested document\n createBlobAndPrint(params, printFrame, req.response)\n })\n\n req.open('GET', params.printable, true)\n req.send()\n }\n}\n\nfunction createBlobAndPrint (params, printFrame, data) {\n // Pass response or base64 data to a blob and create a local object url\n let localPdf = new window.Blob([data], { type: 'application/pdf' })\n localPdf = window.URL.createObjectURL(localPdf)\n\n // Set iframe src with pdf document url\n printFrame.setAttribute('src', localPdf)\n\n Print.send(params, printFrame)\n}\n", "import Browser from './browser'\nimport { cleanUp } from './functions'\n\nconst Print = {\n send: (params, printFrame) => {\n // Append iframe element to document body\n document.getElementsByTagName('body')[0].appendChild(printFrame)\n\n // Get iframe element\n const iframeElement = document.getElementById(params.frameId)\n\n // Wait for iframe to load all content\n iframeElement.onload = () => {\n if (params.type === 'pdf') {\n // Add a delay for Firefox. In my tests, 1000ms was sufficient but 100ms was not\n if (Browser.isFirefox()) {\n setTimeout(() => performPrint(iframeElement, params), 1000)\n } else {\n performPrint(iframeElement, params)\n }\n return\n }\n\n // Get iframe element document\n let printDocument = (iframeElement.contentWindow || iframeElement.contentDocument)\n if (printDocument.document) printDocument = printDocument.document\n\n // Append printable element to the iframe body\n printDocument.body.appendChild(params.printableElement)\n\n // Add custom style\n if (params.type !== 'pdf' && params.style) {\n // Create style element\n const style = document.createElement('style')\n style.innerHTML = params.style\n\n // Append style element to iframe's head\n printDocument.head.appendChild(style)\n }\n\n // If printing images, wait for them to load inside the iframe\n const images = printDocument.getElementsByTagName('img')\n\n if (images.length > 0) {\n loadIframeImages(Array.from(images)).then(() => performPrint(iframeElement, params))\n } else {\n performPrint(iframeElement, params)\n }\n }\n }\n}\n\nfunction performPrint (iframeElement, params) {\n try {\n iframeElement.focus()\n\n // If Edge or IE, try catch with execCommand\n if (Browser.isEdge() || Browser.isIE()) {\n try {\n iframeElement.contentWindow.document.execCommand('print', false, null)\n } catch (e) {\n iframeElement.contentWindow.print()\n }\n } else {\n // Other browsers\n iframeElement.contentWindow.print()\n }\n } catch (error) {\n params.onError(error)\n } finally {\n if (Browser.isFirefox()) {\n // Move the iframe element off-screen and make it invisible\n iframeElement.style.visibility = 'hidden'\n iframeElement.style.left = '-1px'\n }\n\n cleanUp(params)\n }\n}\n\nfunction loadIframeImages (images) {\n const promises = images.map(image => {\n if (image.src && image.src !== window.location.href) {\n return loadIframeImage(image)\n }\n })\n\n return Promise.all(promises)\n}\n\nfunction loadIframeImage (image) {\n return new Promise(resolve => {\n const pollImage = () => {\n !image || typeof image.naturalWidth === 'undefined' || image.naturalWidth === 0 || !image.complete\n ? setTimeout(pollImage, 500)\n : resolve()\n }\n pollImage()\n })\n}\n\nexport default Print\n", "import Print from './print'\n\nexport default {\n print: (params, printFrame) => {\n // Create printable element (container)\n params.printableElement = document.createElement('div')\n params.printableElement.setAttribute('style', 'width:100%')\n\n // Set our raw html as the printable element inner html content\n params.printableElement.innerHTML = params.printable\n\n // Print html contents\n Print.send(params, printFrame)\n }\n}\n", "// extracted by mini-css-extract-plugin", "/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Mathias Bynens */\njQuery(function($){\n\t$.datepicker.regional.nl = {\n\t\tcloseText: 'Sluiten',\n\t\tprevText: '\u2190',\n\t\tnextText: '\u2192',\n\t\tcurrentText: 'Vandaag',\n\t\tmonthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',\n\t\t'juli', 'augustus', 'september', 'oktober', 'november', 'december'],\n\t\tmonthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',\n\t\t'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],\n\t\tdayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],\n\t\tdayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],\n\t\tdayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],\n\t\tweekHeader: 'Wk',\n\t\tdateFormat: 'dd-mm-yy',\n\t\tfirstDay: 1,\n\t\tisRTL: false,\n\t\tshowMonthAfterYear: false,\n\t\tyearSuffix: ''};\n\t$.datepicker.setDefaults($.datepicker.regional.nl);\n});\n", "/******* Translations ******/\n\nconst dicts = {};\n\nlet dict = {};\n\n// gettext stub\nfunction _(s, fb) {\n return dict[s] || fb || s;\n}\n\n_.tagged = (strings, ...values) =>\n strings.reduce((acc, cur, idx) => acc + cur + _(values[idx] || \"\"), \"\");\n\n_.taggedWithin =\n prefix =>\n (strings, ...values) =>\n strings.reduce(\n (acc, cur, idx) =>\n acc +\n cur +\n (_(prefix, { [values[idx]]: values[idx] })[values[idx]] ||\n values[idx] ||\n \"\"),\n \"\"\n );\n\n_.set = function (ob) {\n const lang = ob[\"lang\"] || _(\"lang\"); // Either provided or current lang?\n if (!dicts[lang]) {\n dicts[lang] = {};\n }\n for (let [key, val] of Object.entries(ob)) {\n // Set only if not set before (by _.set, or by _.addTranslations)\n dicts[lang][key] || (dicts[lang][key] = val);\n }\n dict = dicts[lang];\n};\n\n_.addTranslations = function (translations) {\n for (var term in translations) {\n if (translations.hasOwnProperty(term))\n for (var lang in translations[term]) {\n if (!dicts[lang]) dicts[lang] = {};\n // Always override what has been set before\n dicts[lang][term] = translations[term][lang];\n }\n }\n};\n\nObject.freeze(_);\n\nexport { _ };\n", "import { _ } from \"$json/lib/gettext\";\n\nconst strings = {\n \"lang\": \"nl\",\n \"Doubleclick to go back to this question\":\n \"Dubbelklikken om naar deze vraag terug te springen\",\n \"create a new case\": \"maak een nieuwe casus aan\",\n \"new\": \"nieuw\",\n \"Delete\": \"Verwijder\",\n \"case\": \"casus\",\n \"cases\": \"casus\",\n \"Last opened\": \"Laatst geopend\",\n \"created\": \"gemaakt\",\n \"report\": \"rapport\",\n \"Sun\": \"Zo\",\n \"Mon\": \"Ma\",\n \"Tue\": \"Di\",\n \"Wed\": \"Wo\",\n \"Thu\": \"Do\",\n \"Fri\": \"Vr\",\n \"Sat\": \"Za\",\n \"Jan\": \"Jan\",\n \"Feb\": \"Feb\",\n \"Mar\": \"Maart\",\n \"Apr\": \"April\",\n \"May\": \"Mei\",\n \"June\": \"Juni\",\n \"July\": \"Juli\",\n \"Aug\": \"Aug\",\n \"Sep\": \"Sep\",\n \"Oct\": \"Okt\",\n \"Nov\": \"Nov\",\n \"Dec\": \"Dec\",\n \"press enter to accept\": \"accepteer met ENTER\",\n \"filter cases by name\": \"zoek casus op naam\",\n \"field--value\": \"deze waarde\",\n \"field--date\": \"deze datum\",\n \"field--field\": \"dit veld\",\n \"field--list\": \"deze opties\",\n \"quoted--value\": \"de waarde \u201C{quotable}\u201D\",\n \"quoted--date\": \"de datum \u201C{quotable}\u201D\",\n \"quoted--field\": \"het veld \u201C{quotable}\u201D\",\n \"quoted--list\": \"de opties in \u201C{quotable}\u201D\",\n \"Date required\":\n \"{quotable--init} is verplicht; gebruik het formaat dd\u200A-\u200Amm\u200A-\u200Aj\u200Aj\u200Aj\u200Aj.\",\n \"Input required\": \"{quotable--init} is verplicht\",\n \"Choice required\": \"Keuze uit {quotable} is verplicht\",\n \"Field required\": \"{quotable--init} is verplicht\",\n \"Value has to lie between {minimum} and {maximum}\":\n \"{quotable--init} moet tussen {minimum} en {maximum} liggen\",\n \"Date has to lie between {minimum} and {maximum}\":\n \"{quotable--init} moet tussen {minimum} en {maximum} liggen; gebruik het formaat dd-mm-jjjj.\",\n \"Negative number or zero expected\":\n \"{quotable--init} moet negatief zijn of nul\",\n \"Negative number expected\": \"{quotable--init} moet negatief zijn\",\n \"Value has to lie below {maximum}\":\n \"{quotable--init} moet lager zijn dan {maximum+1}\",\n \"Positive number or zero expected\": \"{quotable} moet positief zijn of nul\",\n \"Positive number expected\": \"{quotable} moet hoger zijn dan nul\",\n \"Value has to lie above {minimum}\":\n \"{quotable--init} moet hoger zijn dan {minimum-1}\",\n \"A date after {maximum} is not allowed\":\n \"{quotable--init} n\u00E1 {maximum} is niet toegestaan; gebruik het formaat dd-mm-jjjj.\",\n \"A date before {minimum} is not allowed\":\n \"{quotable--init} v\u00F3\u00F3r {minimum} is niet toegestaan; gebruik het formaat dd-mm-jjjj.\",\n \"Invalid date\":\n \"{quotable--init} is ongeldig; gebruik het formaat dd-mm-jjjj.\",\n \"Invalid number\": \"{quotable--init} is geen getal\",\n \"Text length exceeds the maximum of {maxlength} characters\":\n \"{quotable--init} mag maximaal {maxlength} karakters bevatten\",\n \"click for more...\": \"klik voor meer...\",\n \" (click to open link)\": \" (klik om link te openen)\",\n \"Are you sure? This will reset all values.\":\n \"Weet u het zeker? Dit zal alle ingevulde velden leegmaken.\",\n \"Yesterday\": \"Gisteren\",\n \"No valid session\": \"Ongeldige gebruikersnaam of wachtwoord\",\n \"Maximum allowed characters: {0}\": \"Maximaal {0} karakters toegestaan\",\n \"No interfaces to show\":\n \"Geen zichtbare elementen (vragen, tekstvelden) gedefinieerd\",\n // feedback\n \"Feedback\": \"Feedback\",\n \"describe the problem\": \"omschrijf het probleem\",\n \"Please do not collate issues.\": \"Een melding per keer!\",\n \"Please send only feedback about the currently visible question or questions; information about these will be sent back to the developers.\":\n \"Geef alleen feedback over de vraag of vragen die je op dit moment op je scherm ziet; informatie over die vragen wordt namelijk meegezonden naar de ontwikkelaars.\",\n \"send\": \"verstuur\",\n \"Thanks for your feedback!\": \"Bedankt voor uw melding!\",\n \"Interface has failed (probably a failing SOAP or database connection)\":\n \"Interface gefaald (waarschijnlijk een falende SOAP- of databasekoppeling)\",\n \"Choose...\": \"Kies...\",\n \"Choose or type...\": \"Kies of typ...\",\n \"cUMWrongUserNamePassword\": \"Ongeldige gebruikersnaam of wachtwoord\",\n \"cWebCaseIsRunning\":\n \"Casus laden is niet gelukt; deze casus wordt al gedraaid in een andere sessie\",\n \"The model you are trying to open does not exist\":\n \"Het beslismodel dat u probeert te openen bestaat niet\",\n \"cWebIllegalAccess\": \"Je mag deze casus niet starten of openen.\",\n \"You may now safely close this window\": \"U kunt het venster nu sluiten\",\n \"user name\": \"gebruikersnaam\",\n \"password\": \"wachtwoord\",\n \"Your models\": \"Uw modellen\",\n \"Your sessions\": \"Uw sessies\",\n \"log in\": \"inloggen\",\n \"load session\": \"Lees uw gegevens in\",\n \"load\": \"inlezen\",\n \"Choose the session file you saved earlier\":\n \"Kies het gegevensbestand dat u de vorige keer hebt opgeslagen\",\n \"Error loading session (wrong data)\":\n \"Inlezen gegevens mislukt (verkeerde gegevens).\",\n \"Please login\": \"Gelieve in te loggen\",\n \"open\": \"open\",\n \"copy\": \"kopie\",\n 'You have no tickets left for model \"{0}\"':\n 'Uw strippenkaart voor model \"{0}\" is op',\n \"__digitgroupingchar__\": \".\",\n \"__radixpoint__\": \",\",\n \"__digitgroupingrules__\": [3],\n \"attachments\": \"bijlagen\",\n \"your documents\": \"uw documenten\",\n \"saved sessions\": \"bewaarde sessies\",\n \"We are currently updating. Please try again later.\":\n \"Er is momenteel een update aan de gang, probeert u het binnenkort nogmaals.\",\n \"case name\": \"casusnaam\",\n \"dateplaceholder\": \"dd\u200A-\u200Amm\u200A-\u200Aj\u200Aj\u200Aj\u200Aj\",\n \"Error: No response from server, server probably down\":\n \"Fout: Server is tijdelijk buiten gebruik. U moet zich opnieuw aanmelden.\",\n \"Session has timed out. Please log in again.\":\n \"De sessie is afgelopen. U moet zich opnieuw aanmelden.\",\n \"first {0} results\": \"eerste {0} resultaten\",\n \"previous {0} results\": \"vorige {0} resultaten\",\n \"next {0} results\": \"volgende {0} resultaten\",\n \"last {0} results\": \"laatste {0} resultaten\",\n \"results {0} to {1} from {2}\": \"resultaten {0} tot {1} van {2}\",\n \"add row\": \"Voeg rij toe\",\n \"insert row\": \"voeg rij in\",\n \"delete row\": \"verwijder rij\",\n \"There are errors, please double check your answers.\":\n \"Er zijn nog fouten, gelieve uw antwoorden nogmaals na te gaan.\",\n \"cancel\": \"annuleer\",\n \"Something went wrong; see the server log for more information.\":\n \"Er is iets misgegaan; bekijk de server log voor meer informatie\",\n \"There does not seem to be an open session.\":\n \"Er lijkt geen lopende sessie te zijn.\"\n};\n\n_.set(strings);\n\nexport { strings };\n", "/*! (c) Andrea Giammarchi - ISC */\nvar self = window || /* istanbul ignore next */ {};\ntry {\n (function (URLSearchParams, plus) {\n if (\n new URLSearchParams(\"q=%2B\").get(\"q\") !== plus ||\n new URLSearchParams({ q: plus }).get(\"q\") !== plus ||\n new URLSearchParams([[\"q\", plus]]).get(\"q\") !== plus ||\n new URLSearchParams(\"q=\\n\").toString() !== \"q=%0A\" ||\n new URLSearchParams({ q: \" &\" }).toString() !== \"q=+%26\" ||\n new URLSearchParams({ q: \"%zx\" }).toString() !== \"q=%25zx\"\n )\n throw URLSearchParams;\n self.URLSearchParams = URLSearchParams;\n })(URLSearchParams, \"+\");\n} catch (URLSearchParams) {\n (function (Object, String, isArray) {\n \"use strict\";\n var create = Object.create;\n var defineProperty = Object.defineProperty;\n var find = /[!'\\(\\)~]|%20|%00/g;\n var findPercentSign = /%(?![0-9a-fA-F]{2})/g;\n var plus = /\\+/g;\n var replace = {\n \"!\": \"%21\",\n \"'\": \"%27\",\n \"(\": \"%28\",\n \")\": \"%29\",\n \"~\": \"%7E\",\n \"%20\": \"+\",\n \"%00\": \"\\x00\"\n };\n var proto = {\n append: function (key, value) {\n appendTo(this._ungap, key, value);\n },\n delete: function (key) {\n delete this._ungap[key];\n },\n get: function (key) {\n return this.has(key) ? this._ungap[key][0] : null;\n },\n getAll: function (key) {\n return this.has(key) ? this._ungap[key].slice(0) : [];\n },\n has: function (key) {\n return key in this._ungap;\n },\n set: function (key, value) {\n this._ungap[key] = [String(value)];\n },\n forEach: function (callback, thisArg) {\n var self = this;\n for (var key in self._ungap) self._ungap[key].forEach(invoke, key);\n function invoke(value) {\n callback.call(thisArg, value, String(key), self);\n }\n },\n toJSON: function () {\n return {};\n },\n toString: function () {\n var query = [];\n for (var key in this._ungap) {\n var encoded = encode(key);\n for (var i = 0, value = this._ungap[key]; i < value.length; i++) {\n query.push(encoded + \"=\" + encode(value[i]));\n }\n }\n return query.join(\"&\");\n }\n };\n for (var key in proto)\n defineProperty(URLSearchParams.prototype, key, {\n configurable: true,\n writable: true,\n value: proto[key]\n });\n self.URLSearchParams = URLSearchParams;\n function URLSearchParams(query) {\n var dict = create(null);\n defineProperty(this, \"_ungap\", { value: dict });\n switch (true) {\n case !query:\n break;\n case typeof query === \"string\":\n if (query.charAt(0) === \"?\") {\n query = query.slice(1);\n }\n for (\n var pairs = query.split(\"&\"), i = 0, length = pairs.length;\n i < length;\n i++\n ) {\n var value = pairs[i];\n var index = value.indexOf(\"=\");\n if (-1 < index) {\n appendTo(\n dict,\n decode(value.slice(0, index)),\n decode(value.slice(index + 1))\n );\n } else if (value.length) {\n appendTo(dict, decode(value), \"\");\n }\n }\n break;\n case isArray(query):\n for (var i = 0, length = query.length; i < length; i++) {\n var value = query[i];\n appendTo(dict, value[0], value[1]);\n }\n break;\n case \"forEach\" in query:\n query.forEach(addEach, dict);\n break;\n default:\n for (var key in query) appendTo(dict, key, query[key]);\n }\n }\n\n function addEach(value, key) {\n appendTo(this, key, value);\n }\n\n function appendTo(dict, key, value) {\n var res = isArray(value) ? value.join(\",\") : value;\n if (key in dict) dict[key].push(res);\n else dict[key] = [res];\n }\n\n function decode(str) {\n return decodeURIComponent(\n str.replace(findPercentSign, \"%25\").replace(plus, \" \")\n );\n }\n\n function encode(str) {\n return encodeURIComponent(str).replace(find, replacer);\n }\n\n function replacer(match) {\n return replace[match];\n }\n })(Object, String, Array.isArray);\n}\n\n(function (URLSearchParamsProto) {\n var iterable = false;\n try {\n iterable = !!Symbol.iterator;\n } catch (o_O) {}\n\n /* istanbul ignore else */\n if (!(\"forEach\" in URLSearchParamsProto)) {\n URLSearchParamsProto.forEach = function forEach(callback, thisArg) {\n var self = this;\n var names = Object.create(null);\n this.toString()\n .replace(/=[\\s\\S]*?(?:&|$)/g, \"=\")\n .split(\"=\")\n .forEach(function (name) {\n if (!name.length || name in names) return;\n (names[name] = self.getAll(name)).forEach(function (value) {\n callback.call(thisArg, value, name, self);\n });\n });\n };\n }\n\n /* istanbul ignore else */\n if (!(\"keys\" in URLSearchParamsProto)) {\n URLSearchParamsProto.keys = function keys() {\n return iterator(this, function (value, key) {\n this.push(key);\n });\n };\n }\n\n /* istanbul ignore else */\n if (!(\"values\" in URLSearchParamsProto)) {\n URLSearchParamsProto.values = function values() {\n return iterator(this, function (value, key) {\n this.push(value);\n });\n };\n }\n\n /* istanbul ignore else */\n if (!(\"entries\" in URLSearchParamsProto)) {\n URLSearchParamsProto.entries = function entries() {\n return iterator(this, function (value, key) {\n this.push([key, value]);\n });\n };\n }\n\n /* istanbul ignore else */\n if (iterable && !(Symbol.iterator in URLSearchParamsProto)) {\n URLSearchParamsProto[Symbol.iterator] = URLSearchParamsProto.entries;\n }\n\n /* istanbul ignore else */\n if (!(\"sort\" in URLSearchParamsProto)) {\n URLSearchParamsProto.sort = function sort() {\n var entries = this.entries(),\n entry = entries.next(),\n done = entry.done,\n keys = [],\n values = Object.create(null),\n i,\n key,\n value;\n while (!done) {\n value = entry.value;\n key = value[0];\n keys.push(key);\n if (!(key in values)) {\n values[key] = [];\n }\n values[key].push(value[1]);\n entry = entries.next();\n done = entry.done;\n }\n // not the champion in efficiency\n // but these two bits just do the job\n keys.sort();\n for (i = 0; i < keys.length; i++) {\n this.delete(keys[i]);\n }\n for (i = 0; i < keys.length; i++) {\n key = keys[i];\n this.append(key, values[key].shift());\n }\n };\n }\n\n function iterator(self, callback) {\n var items = [];\n self.forEach(callback, items);\n return iterable\n ? items[Symbol.iterator]()\n : {\n next: function () {\n var value = items.shift();\n return { done: value === undefined, value: value };\n }\n };\n }\n\n /* istanbul ignore next */\n (function (Object) {\n var dP = Object.defineProperty,\n gOPD = Object.getOwnPropertyDescriptor,\n createSearchParamsPollute = function (search) {\n function append(name, value) {\n URLSearchParamsProto.append.call(this, name, value);\n name = this.toString();\n search.set.call(this._usp, name ? \"?\" + name : \"\");\n }\n function del(name) {\n URLSearchParamsProto.delete.call(this, name);\n name = this.toString();\n search.set.call(this._usp, name ? \"?\" + name : \"\");\n }\n function set(name, value) {\n URLSearchParamsProto.set.call(this, name, value);\n name = this.toString();\n search.set.call(this._usp, name ? \"?\" + name : \"\");\n }\n return function (sp, value) {\n sp.append = append;\n sp.delete = del;\n sp.set = set;\n return dP(sp, \"_usp\", {\n configurable: true,\n writable: true,\n value: value\n });\n };\n },\n createSearchParamsCreate = function (polluteSearchParams) {\n return function (obj, sp) {\n dP(obj, \"_searchParams\", {\n configurable: true,\n writable: true,\n value: polluteSearchParams(sp, obj)\n });\n return sp;\n };\n },\n updateSearchParams = function (sp) {\n var append = sp.append;\n sp.append = URLSearchParamsProto.append;\n URLSearchParams.call(sp, sp._usp.search.slice(1));\n sp.append = append;\n },\n verifySearchParams = function (obj, Class) {\n if (!(obj instanceof Class))\n throw new TypeError(\n \"'searchParams' accessed on an object that \" +\n \"does not implement interface \" +\n Class.name\n );\n },\n upgradeClass = function (Class) {\n var ClassProto = Class.prototype,\n searchParams = gOPD(ClassProto, \"searchParams\"),\n href = gOPD(ClassProto, \"href\"),\n search = gOPD(ClassProto, \"search\"),\n createSearchParams;\n if (!searchParams && search && search.set) {\n createSearchParams = createSearchParamsCreate(\n createSearchParamsPollute(search)\n );\n Object.defineProperties(ClassProto, {\n href: {\n get: function () {\n return href.get.call(this);\n },\n set: function (value) {\n var sp = this._searchParams;\n href.set.call(this, value);\n if (sp) updateSearchParams(sp);\n }\n },\n search: {\n get: function () {\n return search.get.call(this);\n },\n set: function (value) {\n var sp = this._searchParams;\n search.set.call(this, value);\n if (sp) updateSearchParams(sp);\n }\n },\n searchParams: {\n get: function () {\n verifySearchParams(this, Class);\n return (\n this._searchParams ||\n createSearchParams(\n this,\n new URLSearchParams(this.search.slice(1))\n )\n );\n },\n set: function (sp) {\n verifySearchParams(this, Class);\n createSearchParams(this, sp);\n }\n }\n });\n }\n };\n try {\n upgradeClass(HTMLAnchorElement);\n if (/^function|object$/.test(typeof URL) && URL.prototype)\n upgradeClass(URL);\n } catch (meh) {}\n })(Object);\n})(self.URLSearchParams.prototype, Object);\nexport default self.URLSearchParams;\n", "/******* positionalFormat() BEGIN ******/\n\n/* https://github.com/pft/javascript/blob/master/positionalformat.js\n *\n * Copyright (C) 2006-2013 Niels Giesen.\n *\n * Contact: \n *\n * Author: Niels Giesen\n * Keywords: JavaScript, formatting, String\n *\n * This file is dual-licensed under either the BSD license or the\n * GNU Affero General Public License.\n *\n * positionalFormat enables you to replace numbers enclosed in curly braces (C# format\n * apparently) with positional arguments (that can be reused), like\n * this:\n *\n * positionalFormat('argument { 1 } (or is it { 2 }, or { 0 }?) comes { 1 }',3,'first',1)\n *\n * evals to:\n *\n * \"argument first (or is it 1, or 3?) comes first\"\n */\n\nexport function positionalFormat(str) {\n var args = arguments;\n return str.replace(/{\\s*(\\d+)\\s*}/g, function (match, num) {\n return args[parseInt(num) + 1] !== undefined\n ? args[parseInt(num) + 1]\n : match;\n });\n}\n\n/******* positionalFormat() END ******/\n\nexport function format(str, ob = {}) {\n return str.replace(/{\\s*([^{]+?)\\s*}/g, function (match, sub) {\n return ob[sub] !== undefined ? ob[sub] : sub;\n });\n}\n\n// export function formatPlus(str, ob = {}) {\n// return str.replace(/{\\s*([^{]+?)\\s*}/g, function (match, subwithstuff) {\n// const subs = subwithstuff.split(/\\|/);\n// console.log(subs);\n// return subs.reduce((acc, cur) => {\n// if (ob[cur] === undefined) return acc;\n// return ob[cur];\n// }, subs[0]);\n// // if (ob[sub] === undefined) return sub;\n// // if (!directives) return ob[sub] !== undefined ? ob[sub] : sub;\n// // if (\n// // directives.startsWith(\"+\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// // if (\n// // directives.startsWith(\"-\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// // const [sub, directives] = subwithstuff.split(/\\|/);\n// // if (ob[sub] === undefined) return sub;\n// // if (!directives) return ob[sub] !== undefined ? ob[sub] : sub;\n// // if (\n// // directives.startsWith(\"+\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// // if (\n// // directives.startsWith(\"-\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// return ob[sub];\n// });\n// }\n\nexport const formatPlus = format;\n\n// (str, ob = {}) {\n// return str.replace(/{\\s*([^{]+?)\\s*}/g, function (match, subwithstuff) {\n// const subs = subwithstuff.split(/\\|/);\n// console.log(subs);\n// return subs.reduceRight((acc, cur) => {\n// if (ob[cur] === undefined) return acc;\n// return ob[cur];\n// }, subs[0]);\n// // if (ob[sub] === undefined) return sub;\n// // if (!directives) return ob[sub] !== undefined ? ob[sub] : sub;\n// // if (\n// // directives.startsWith(\"+\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// // if (\n// // directives.startsWith(\"-\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// // const [sub, directives] = subwithstuff.split(/\\|/);\n// // if (ob[sub] === undefined) return sub;\n// // if (!directives) return ob[sub] !== undefined ? ob[sub] : sub;\n// // if (\n// // directives.startsWith(\"+\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// // if (\n// // directives.startsWith(\"-\") &&\n// // !Number.isNaN(ob[sub]) &&\n// // !Number.isNaN(Number(directives.slice(1)))\n// // )\n// // return Number(ob[sub]) + Number(directives.slice(1));\n// return ob[sub];\n// });\n// }\n\n/** Function that count occurrences of a substring in a string;\n * @param {String} subString The sub string to search for\n * @param {String} string The string\n *\n * Based on https://gist.github.com/victornpb/7736865\n */\nexport function occurrences(subString, string) {\n string += \"\";\n subString += \"\";\n if (subString.length <= 0) return string.length + 1;\n\n var n = 0,\n pos = 0,\n step = subString.length;\n\n while (true) {\n pos = string.indexOf(subString, pos);\n if (pos >= 0) {\n ++n;\n pos += step;\n } else break;\n }\n return n;\n}\n", "import { positionalFormat } from \"./text-utils.js\";\nimport { _ } from \"./gettext.js\";\n\nconst CODES = {\n cException: 1,\n cHTMLFormLoadCaseNotFound: 2,\n cHTMLMenuFileNotFound: 3,\n cWebModelIDDifferent: 4,\n cWebPleaseLogin: 5,\n cGetFileNotAllowed: 6,\n cGetDocumentNotFound: 7,\n cUMWrongUserNamePassword: 8,\n cWebSessionTimeOut: 9,\n cWebNoModelID: 10,\n cWebIllegalAccess: 11,\n cWebModelNotFound: 12,\n cWebCaseIsRunning: 13,\n cEngineLoadCaseFailed: 14, // Was: 3\n cEngineUpgrading: 15,\n cEngineNoInterfacesToShow: 16,\n cEngineLoadCaseFailedNotFound: 17,\n cEngineLoadCaseFailedWrongType: 18,\n cEngineLoadCaseFailedWrongData: 19,\n cWebOpenIsCalledWithUniqueID: 20,\n cTechGraphVizNotInstalled: 21,\n cGraphVizSessionNotFound: 22,\n cUMUserNotFound: 23,\n cUMModelNotFound: 24,\n cUMCaseNotFound: 25,\n cWebAdminNotAllowed: 26,\n cEngineGotoNodeFailed: 27,\n cPreviewNoCaseFound: 28,\n cTechUploadedFileToLarge: 29,\n cWebSaveCaseNotAllowed: 30,\n cWebSaveCaseFailed: 31,\n cInvalidUpload: 53\n};\n\nconst CODESREV = Object.fromEntries(\n Object.entries(CODES).map(([key, value]) => [value, key])\n);\n\n// Translate error - put translation in message property, return\n// error.\nfunction translate(_error) {\n const error = Object.assign({}, _error);\n // New API\n switch (error.code) {\n case CODES.cException:\n error.message = _(\n \"Something went wrong; see the server log for more information.\"\n );\n break;\n case CODES.cWebSessionTimeOut:\n error.message = _(\"Session has timed out. Please log in again.\");\n break;\n case CODES.cEngineLoadCaseFailed:\n switch (error.subcode) {\n case 1004:\n error.message = positionalFormat(\n _('You have no tickets left for model \"{0}\"'),\n error.summary\n .substring(56, error.summary.length - 1)\n .replace(/_/g, \" \")\n );\n break;\n default:\n error.message = error.summary; // Won't translate for now, may be st. like \"Loading case failed (xxx.mdl)\"\n }\n break;\n case CODES.cEngineLoadCaseFailedWrongData:\n error.message = _(\"Error loading session (wrong data)\");\n break;\n default:\n switch (error.subcode) {\n case 1002:\n error.message = _(\n \"We are currently updating. Please try again later.\"\n );\n break;\n case 1009:\n case 1025:\n error.message = positionalFormat(\n _('Infinite loop detected in {0}\"'),\n // Might be embedded though (in 1 or in 14...)\n error.summary.slice(18, error.summary.indexOf(\", infinite\"))\n );\n break;\n case 1010:\n error.message = _(\n \"Interface has failed (probably a failing SOAP or database connection)\"\n );\n break;\n default:\n error.message = _(CODESREV[error.code], _(error.summary));\n }\n }\n return error;\n}\n\nexport { CODES, translate };\n", "let _token;\n\nexport const setToken = token => {\n _token = token;\n};\n\nexport async function digestMessage(message) {\n if (!(\"crypto\" in window)) return null;\n const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", msgUint8); // hash the message\n const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array\n const hashHex = hashArray.map(b => b.toString(16).padStart(2, \"0\")).join(\"\"); // convert bytes to hex string\n return hashHex;\n}\n\nexport const tokenChannel =\n \"BroadcastChannel\" in window ? new BroadcastChannel(\"token\") : \"\";\n\nexport const token = {\n addEventListener: (...args) =>\n tokenChannel && tokenChannel.addEventListener(...args),\n removeEventListener: (...args) =>\n tokenChannel && tokenChannel.removeEventListener(...args),\n getHash: () => digestMessage(_token),\n setToken,\n postMessage: message =>\n token.getHash().then(\n tokenHash =>\n // digestMessage will return null on missing crypto on older\n // browsers\n tokenHash &&\n tokenChannel &&\n tokenChannel.postMessage({ tokenHash, ...message })\n )\n};\n", "// https://gist.github.com/jameslaneconkling/24acb8ea326a1c8fdf64225aa7d0f44e\nconst rules = [\n { type: \"space\", regex: /^\\s/ },\n { type: \"lParen\", regex: /^\\(/ },\n { type: \"rParen\", regex: /^\\)/ },\n { type: \"number\", regex: /^[0-9.]+/ },\n { type: \"string\", regex: /^\".*?\"/ },\n { type: \"variable\", regex: /^[^\\s()]+/ } // take from the beginning 1+ characters until you hit a ' ', '(', or ')' // TODO - support escaped double quote\n];\n\nconst tokenizer = rules => input => {\n for (let i = 0; i < rules.length; i += 1) {\n let tokenized = rules[i].regex.exec(input);\n if (tokenized) {\n return {\n token: tokenized[0],\n type: rules[i].type,\n rest: input.slice(tokenized[0].length)\n };\n }\n }\n\n throw new Error(`no matching tokenize rule for ${JSON.stringify(input)}`);\n};\n\nconst parser = tokenize =>\n function parse(input, ast, parents = []) {\n if (input === \"\") {\n return ast;\n }\n\n const { token, type, rest } = tokenize(input);\n\n if (type === \"space\") {\n // do nothing\n return parse(rest, ast, parents);\n } else if (type === \"variable\") {\n ast.push(token);\n return parse(rest, ast, parents);\n } else if (type === \"number\") {\n ast.push(Number(token));\n return parse(rest, ast, parents);\n } else if (type === \"string\") {\n ast.push(token.replace(/(^\"|\"$)/g, \"'\"));\n return parse(rest, ast, parents);\n } else if (type === \"lParen\") {\n parents.push(ast);\n return parse(rest, [], parents);\n } else if (type === \"rParen\") {\n const parentAst = parents.pop();\n if (parentAst) {\n parentAst.push(ast);\n return parse(rest, parentAst, parents);\n }\n\n return parse(rest, ast, parents);\n }\n\n throw new Error(`Missing parse logic for rule ${JSON.stringify(type)}`);\n };\n\nexport default parser(tokenizer(rules));\n", "const Identity = x => ({ x, map: fn => Identity(fn(x)) });\n\nconst Const = x => ({ x, map: fn => Const(x) });\n\nconst lens = (getter, setter) => functor => target =>\n functor(getter(target)).map(focus => setter(focus, target));\n\nconst over = (lens, fn, obj) => lens(x => Identity(fn(x)))(obj).x;\n\nconst set = (lens, val, obj) => over(lens, () => val, obj);\n\nconst view = (lens, obj) => lens(Const)(obj).x;\n\nexport { lens, over, set, view };\n", "/** Map fn on array, then join it with joiner */\nimport * as Lenses from \"./lenses.js\";\n\nexport const applyTo = arg => fn => fn(arg);\n\nconst _apply = (fn, args) => fn(...args);\n\nexport const dec = arg => arg - 1;\n\nexport const inc = arg => arg + 1;\n\nexport function mapConcat(arr, fn, joiner) {\n return arr.map(fn).join(joiner);\n}\n\nexport const identity = x => x;\n\nexport const isNil = x => x == null;\n\nexport const not = a => !a;\n\n/**\n Differs from Ramda in that the first function in the pipe chain is\n called with a single argument.\n */\nexport const pipe =\n (...fns) =>\n value =>\n fns.reduce((acc, cur) => cur(acc), value);\n\n/**\n Differs from Ramda in that the first function in the compose chain is\n called with a single argument.\n */\nexport const compose =\n (...fns) =>\n value =>\n fns.reduceRight((acc, cur) => cur(acc), value);\n\n/**\n Same as Ramda pipe() in that the first function in the compose\n chain may be called with more than one argument.\n */\nexport const pipeX =\n (...fns) =>\n (...value) =>\n fns.reduce((acc, cur) => [cur.apply(null, acc)], value);\n\n/**\n Same as Ramda compose() in that the first function in the compose\n chain may be called with more than one argument.\n */\nexport const composeX =\n (...fns) =>\n (...value) =>\n fns.reduceRight((acc, cur) => [cur.apply(null, acc)], value);\n\nexport const curry = (fn, ...args) => {\n if (args.length >= fn.length) return fn(...args);\n return (...args2) => curry(fn, ...[...args, ...args2]);\n};\n\nexport const join = curry((sep, arr) => arr.join(sep));\n\nexport const split = curry((sep, arr) => arr.split(sep));\n\nexport const reverse = arr => [...arr].reverse();\n\nexport const type = compose(\n s => s.slice(8, -1),\n ob => Object.prototype.toString.call(ob)\n);\n\nexport const always = value => () => value;\n\nexport const F = always(false);\n\nexport const T = always(true);\n\nexport const propOr = curry((or, prop, obj) => {\n try {\n return ifElse(isNil, () => or, identity)(obj[prop]);\n } catch (_) {\n return or;\n }\n});\n\nexport const prop = propOr(undefined);\nexport const pathOr = curry((or, pathArg, obj) =>\n reduce((acc, cur) => propOr(or, cur, acc), obj, pathArg)\n);\n\nexport const path = pathOr(undefined);\n\nexport const tail = arr => Array.prototype.slice.call(arr, 1);\n\nconst _nth = (i, arr) => arr[i];\n\nexport const head = arr => arr[0];\n\nexport const last = arr => arr[arr.length - 1];\n\nexport const cond = curry((rules, ob) => {\n const cur = rules[0];\n if (!cur) return undefined;\n return ifElse(cur[0], cur[1], cond(tail(rules)))(ob);\n});\n\nexport const choose = curry((rules, ob) => {\n const cur = rules[0];\n if (!cur) return undefined;\n return cur[0](ob) ? cur[1] : choose(tail(rules))(ob);\n});\n\nexport const length = prop(\"length\");\n\nexport const strictUniq = arr =>\n reduce((acc, cur) => (acc.indexOf(cur) > -1 ? acc : [...acc, cur]), [])(arr);\n\nconst _uniqBy = (fn, arr) =>\n Object.values(\n arr.reduce((acc, cur) => {\n const key = fn(cur);\n return _has(key, acc) ? acc : { ...acc, [key]: cur };\n }, {})\n );\n\nexport const uniqBy = curry(_uniqBy);\n\nexport const uniq = uniqBy(_equals);\n\nexport const any = curry((fn, arr) => {\n return arr.length === 0\n ? false\n : compose(fn, head)(arr)\n ? true\n : any(fn, tail(arr));\n});\n\nexport const find = curry((fn, arr) => {\n return arr.length === 0\n ? undefined\n : fn(head(arr))\n ? head(arr)\n : find(fn, tail(arr));\n});\n\nconst _findIndex = (fn, arr) => arr.findIndex(fn);\n/**\n * Returns a function applying all arguments to a *manually* curried function.\n *\n * Behaves a bit strange (see tests), so keeping it private-ish\n **/\nexport const _uncurry =\n fn =>\n (...args) =>\n args.reduce((acc, cur) => {\n return acc(cur);\n }, fn);\n\n/** Curriable functions **/\n\n/**\n * Takes a function and two values and returns true if the values map\n * to the same value; false otherwise.\n */\nconst _eqBy = (fn, a, b) => _equals(fn(a), fn(b));\n\nconst _all = (fn, arr) =>\n reduce((acc, cur) => (acc ? fn(cur) : acc), true, arr);\n\nconst _none = (fn, arr) =>\n reduce((acc, cur) => (fn(cur) ? false : acc), true, arr);\n\nconst _append = (arg, arr) => [...((arr instanceof Array && arr) || []), arg];\n\nconst _test = (regex, string) => regex.test(string);\n\nconst _match = (regex, string) => string.match(regex) || [];\n\n// https://raphacmartin.medium.com/deep-equality-in-javascript-objects-1eea8abb3649\n/**\n *\n * @param a Object\n * @param b Object\n * @returns {boolean}\n */\nfunction _equals(a, b) {\n if (!(a instanceof Object) || !(b instanceof Object)) return a === b;\n // if the number of keys is different, they are different\n if (Object.keys(a).length !== Object.keys(b).length) {\n return false;\n }\n\n for (const key in a) {\n const a_value = a[key];\n const b_value = b[key];\n // If the value is an object, check if they're different objects\n // If it isn't, uses !== to check\n if (\n (a_value instanceof Object && !_equals(a_value, b_value)) ||\n (!(a_value instanceof Object) && a_value !== b_value)\n ) {\n return false;\n }\n }\n return true;\n}\n\nexport const equals = curry(_equals);\n\nconst _eqProps = (prop, a, b) => _equals(a[prop], b[prop]);\n\nconst _hasPath = (p, ob) => {\n if (p.length === 0) return true;\n return has(p[0], ob) && _hasPath(tail(p), prop(p[0], ob));\n};\n\n/** Associate prop with val in obj */\nfunction _assoc(prop, val, obj) {\n var result = {};\n for (var p in obj) {\n result[p] = obj[p];\n }\n result[prop] = val;\n return result;\n}\n\nconst _assocPath = (path, val, obj) => {\n if (path.length === 0) {\n return val;\n }\n var idx = path[0];\n if (path.length > 1) {\n var nextObj =\n !isNil(obj) && Object.prototype.hasOwnProperty.call(obj, idx)\n ? obj[idx]\n : Number.isInteger(path[1])\n ? []\n : {};\n val = assocPath(Array.prototype.slice.call(path, 1), val, nextObj);\n }\n if (Number.isInteger(idx) && Array.isArray(obj)) {\n var arr = [].concat(obj);\n arr[idx] = val;\n return arr;\n } else {\n return assoc(idx, val, obj);\n }\n};\n\n/**\n * Apply fun to all but first argN args */\nconst _consume =\n (fn, argN) =>\n (...args) => {\n return fn(...args.slice(argN));\n };\n\nconst _propEq = (key, value, ob) => _equals(prop(key, ob), value);\n\nconst _propSatisfies = (fn, key, ob) => fn(prop(key, ob));\n\nconst _pathSatisfies = (fn, key, ob) => fn(path(key, ob));\n\nconst _pathEq = (key, value, ob) => _pathSatisfies(equals(value), key, ob);\n\nconst _has = (prop, ob) =>\n complement(isNil)(ob) && Object.prototype.hasOwnProperty.call(ob, prop);\n\nconst _tryCatch = (tryer, catcher) => arg => {\n try {\n return tryer(arg);\n } catch (e) {\n return catcher(e, arg);\n }\n};\n\n/**\n Call arr.map(fn)\n\n Note: differs from Ramda, in that the callback will receive both the item, the index and the list.\n\n If you want the callback function `fn` to read only the first parameter, wrap `fn` in `unary(fn)`.\n */\nconst _map = (fn, arr) => arr.map(fn);\n\n/**\n Call arr.filter(fn)\n\n Note: differs from Ramda, in that the callback will receive both the item, the index and the list.\n\n If you want the callback function `fn` to read only the first parameter, wrap `fn` in `unary(fn)`.\n */\nconst _filter = (fn, arr) => arr.filter(fn);\n\nconst _when = (predicate, whenTrueFn, arg) =>\n predicate(arg) ? whenTrueFn(arg) : arg;\n\nconst _ifElse = (predicate, whenTrueFn, whenFalseFn, arg) =>\n predicate(arg) ? whenTrueFn(arg) : whenFalseFn(arg);\n\nconst _either = (fn1, fn2, arg) => fn1(arg) || fn2(arg);\n\nconst _allPass = (fns, arg) =>\n fns.reduce((mem, cur) => (!mem ? false : cur(arg)), true);\n\nconst _anyPass = (fns, arg) =>\n fns.reduce((mem, cur) => (mem ? true : cur(arg)), false);\n\nconst _both = (fn1, fn2, arg) => _allPass([fn1, fn2], arg);\n\nconst _complement = (fn, arg) => !fn(arg);\n\nconst _includes = (item, c) => c.includes(item);\n\nconst _lte = (first, second) => first <= second;\n\nconst _lt = (first, second) => first < second;\n\nconst _gte = (first, second) => first >= second;\n\nconst _gt = (first, second) => first > second;\n\n/**\n Call arr.reduce(fn, into);\n\n Note: differs from Ramda, in that the callback will receive the\n accumular, the item, the index and the list.\n\n If you want the callback function `fn` to read only the first two\n parameters, as with Ramda, wrap `fn` in `binary(fn)`.\n */\nconst _reduce = (fn, into, arr) => arr.reduce(fn, into);\n\nconst _tap = (fn, value) => (fn(value), value);\n\nconst _groupWith = (fn, arr) =>\n reduce(\n (acc, cur, index, arr) =>\n index === 0 || !fn(cur, arr[index - 1])\n ? [...acc, [cur]]\n : [...acc.slice(0, acc.length - 1), [...acc[acc.length - 1], cur]],\n []\n )(arr);\n\nconst _groupBy = (fn, arr) =>\n reduce((acc, cur) => over(lensProp(fn(cur)), append(cur), acc), {})(arr);\n\nconst _nthArg = (n, arg1, ...args) => [arg1, ...args][n];\n\n/** Dissociate props from obj */\nconst _omit = (props, obj) => {\n var result = {};\n for (var p in obj) {\n if (!props.includes(p)) result[p] = obj[p];\n }\n return result;\n};\n\nconst _pickBy = (pred, obj) => {\n var result = {};\n for (var k in obj) {\n if (pred(obj[k], k)) result[k] = obj[k];\n }\n return result;\n};\n\nconst _pick = (props, obj) => {\n var result = {};\n props.forEach(prop => {\n if (prop in obj) result[prop] = obj[prop];\n });\n return result;\n};\n\nconst _pickAll = (props, obj) => {\n var result = {};\n props.forEach(prop => {\n result[prop] = obj[prop];\n });\n return result;\n};\n\nfunction _dissoc(prop, obj) {\n return _omit([prop], obj);\n}\n\nconst _infichain = (fns, arg) =>\n fns.reduce(\n (acc, cur, index) => (index === 0 ? cur(arg) : cur(acc, arg)),\n null\n );\n\nconst _mergeRight = (ob1, ob2) => Object.assign({}, ob1, ob2);\n\nconst _mergeLeft = (ob1, ob2) => Object.assign({}, ob2, ob1);\n\nconst _strictWithout = (items, list) =>\n list.reduce((acc, cur) => (items.includes(cur) ? acc : [...acc, cur]), []);\n\nconst _unary = fn => arg => fn(arg);\n\nconst _binary = fn => (arg1, arg2) => fn(arg1, arg2);\n\nconst _strictDifference = (list1, list2) => {\n const out = new Set();\n const s1 = new Set(list1);\n const s2 = new Set(list2);\n for (let item of s1) {\n if (!s2.has(item)) out.add(item);\n }\n return [...out];\n};\n\nconst _mapWithRest = (fn, arr, rest1, ...rest) =>\n arr.map((cur, i, list) => fn(cur, i, list, rest1, ...rest));\n\nconst _andThen = (fn, promise) => Promise.resolve(promise).then(fn);\nconst _otherwise = (fn, promise) => promise.then(null, fn);\n\n/**\n * @param {Funcion} f f(await g(val), val)\n * @param {Funtion} g g(val) => Promise\n * @return Promise\n */\nconst _fChain = (f, g, val) => g(val).then(x => f(x, val));\n\nconst _chain = (f, g, val) => f(g(val), val);\n\nconst _juxt = (arr, arg1, ...argN) => {\n return arr.map(fn => fn(arg1, ...argN));\n};\n\nconst _slice = (from, to, arr) => arr.slice(from, to);\n\n// Copied verbatim from Ramda\nconst _is = function is(Ctor, val) {\n return (\n val instanceof Ctor ||\n (val != null &&\n (val.constructor === Ctor ||\n (Ctor.name === \"Object\" && typeof val === \"object\")))\n );\n};\n\nexport const toLower = s => s.toLowerCase();\nexport const toUpper = s => s.toUpperCase();\n\nexport const maybeNumber = string =>\n Number.isInteger(Number(string)) ? Number(string) : string;\n\nconst _applySpec =\n specs =>\n (...args) => {\n if (specs instanceof Function) {\n return specs(...args);\n }\n if (specs instanceof Array) {\n return specs.map(fn => _applySpec(fn)(...args));\n }\n const out = {};\n for (let [key, value] of Object.entries(specs)) {\n out[key] = _applySpec(value)(...args);\n }\n return out;\n };\n\nexport const applySpec = curry((specs, arg, ...args) =>\n _applySpec(specs)(arg, ...args)\n);\n\nconst _partial = (fn, args) => fn.bind(null, ...args);\n\nexport const all = curry(_all),\n partial = curry(_partial),\n nthArg = curry(_nthArg),\n andThen = curry(_andThen),\n append = curry(_append),\n apply = curry(_apply),\n assoc = curry(_assoc),\n assocPath = curry(_assocPath),\n anyPass = curry(_anyPass),\n both = curry(_both),\n consume = curry(_consume),\n chain = curry(_chain),\n strictDifference = curry(_strictDifference),\n dissoc = curry(_dissoc),\n eqProps = curry(_eqProps),\n filter = curry(_filter),\n has = curry(_has),\n hasPath = curry(_hasPath),\n is = curry(_is),\n juxt = curry(_juxt),\n map = curry(_map),\n nth = curry(_nth),\n otherwise = curry(_otherwise),\n propEq = curry(_propEq),\n propSatisfies = curry(_propSatisfies),\n tryCatch = curry(_tryCatch),\n when = curry(_when),\n ifElse = curry(_ifElse),\n either = curry(_either),\n allPass = curry(_allPass),\n complement = curry(_complement),\n includes = curry(_includes),\n infichain = curry(_infichain),\n mapWithRest = curry(_mapWithRest),\n mergeLeft = curry(_mergeLeft),\n mergeRight = curry(_mergeRight),\n omit = curry(_omit),\n pathEq = curry(_pathEq),\n pathSatisfies = curry(_pathSatisfies),\n pick = curry(_pick),\n pickBy = curry(_pickBy),\n pickAll = curry(_pickAll),\n lt = curry(_lt),\n lte = curry(_lte),\n fChain = curry(_fChain),\n gt = curry(_gt),\n gte = curry(_gte),\n reduce = curry(_reduce),\n groupBy = curry(_groupBy),\n groupWith = curry(_groupWith),\n tap = curry(_tap),\n eqBy = curry(_eqBy),\n lens = curry(Lenses.lens),\n over = curry(Lenses.over),\n set = curry(Lenses.set),\n view = curry(Lenses.view),\n test = curry(_test),\n match = curry(_match),\n none = curry(_none),\n findIndex = curry(_findIndex),\n slice = curry(_slice),\n strictWithout = curry(_strictWithout),\n unary = curry(_unary),\n binary = curry(_binary),\n lensPath = p => Lenses.lens(path(p), assocPath(p)),\n lensProp = p => Lenses.lens(prop(p), assoc(p));\n\nexport const uncurried = {\n is: _is,\n all: _all,\n apply: _apply,\n append: _append,\n assoc: _assoc,\n assocPath: _assocPath,\n both: _both,\n filter: _filter,\n propEq: _propEq,\n consume: _consume,\n tryCatch: _tryCatch,\n when: _when,\n ifElse: _ifElse,\n either: _either,\n allPass: _allPass,\n complement: _complement,\n includes: _includes,\n lt: _lt,\n lte: _lte,\n gt: _gt,\n gte: _gte,\n has: _has,\n hasPath: _hasPath,\n tap: _tap,\n groupBy: _groupBy,\n groupWith: _groupWith,\n nth: _nth,\n eqBy: _eqBy,\n eqProps: _eqProps,\n equals: _equals,\n omit: _omit,\n pathEq: _pathEq,\n pick: _pick,\n pickBy: _pickBy,\n pickAll: _pickAll,\n dissoc: _dissoc,\n test: _test,\n match: _match,\n mergeLeft: _mergeLeft,\n mergeRight: _mergeRight,\n partial: _partial,\n strictWithout: _strictWithout,\n unary: _unary,\n binary: _binary,\n slice: _slice,\n findIndex: _findIndex,\n toLower,\n toUpper,\n uniqBy: _uniqBy,\n ...Lenses\n};\n", "import parse from \"./baby-lisp.js\";\nimport * as L from \"./functional.js\";\n\n/**\n * @typedef {Object} Bucket\n * @property {method} get Method to get key\n */\n\n/**\n * Test string against a bucket's contents\n * @function\n * @param {Bucket} bucket with a get(key) method returning a Boolean\n * or undefined.\n * @param {String} string Lispy string to test against the bucket\n */\nexport const stringSaysDo = (bucket, string) => {\n const ast = parse(`(${string})`);\n return astSaysDo(bucket)(ast);\n};\n\n/**\n * Test ast against bucket's contents\n * @function\n * @param {Bucket} bucket with a get(key) method returning a Boolean\n * or undefined.\n * @param {Object} AST Lispy AST (nested array of strings) to test against the bucket\n */\nconst astSaysDo = bucket => ast => {\n if (ast instanceof Array) {\n if (ast[0] === \"and\") {\n return L.compose(L.all(astSaysDo(bucket)), L.tail)(ast);\n }\n if (ast[0] === \"or\") {\n return L.compose(L.any(astSaysDo(bucket)), L.tail)(ast);\n }\n if (ast[0] === \"not\") {\n return L.compose(L.not, L.any(astSaysDo(bucket)), L.tail)(ast);\n }\n return L.compose(L.any(astSaysDo(bucket)))(ast);\n } else {\n return bucket.get(ast);\n }\n};\n", "export class BooleanBucket {\n constructor() {\n this.booleans = [];\n }\n /**\n * @param {String} key Key to get\n */\n get(key) {\n return this.booleans[key];\n }\n /**\n * @param {String} key Key to set\n */\n set(key) {\n return this.toggle(key, true);\n }\n /**\n * @param {String} key Key to unset\n */\n unset(key) {\n return this.toggle(key, false);\n }\n /**\n * @param {String} key Key to toggle\n * @param {Boolean} [bool] New value\n */\n toggle(key, bool) {\n bool = typeof bool === \"boolean\" ? bool : !this.get(key);\n if (bool !== this.get(key)) {\n this.booleans[key] = bool;\n return [true, bool];\n } else {\n return [false, bool];\n }\n }\n}\n", "/* global $ */\nimport { stringSaysDo } from \"./baby-lisp-apply.js\";\nimport { BooleanBucket } from \"./booleanbucket.js\";\n\nclass BucketWithConsequences extends BooleanBucket {\n /**\n * @param {String} key Key to toggle\n * @param {Boolean} [bool] New value\n * @param {Boolean} [reflect] Reflect the key as a class in the \n\n * Will hide or show any element which has somewhere inside data-when or data-hide-when attribute.\n * Whether or not to show or hide is based on the parsing of those attributes.\n *\n * See baby-lisp.test.js for examples.\n */\n toggle(mode, bool, reflect = true) {\n if (mode.includes('\"')) {\n console.warn(\n \"Mode contains a double quote, that is not allowed - used in querySelectorAll\"\n );\n return this;\n }\n const [changedOrAdded, bool2] = super.toggle(mode, bool);\n // Refrain from unnecessary redraw (by checking previous value):\n if (changedOrAdded) {\n $(document).trigger(\"bb:mode:\" + mode, bool2);\n if (reflect) $(\"body\").toggleClass(mode, bool2);\n {\n [\n ...document.querySelectorAll(\n '[data-when*=\"' + mode + '\"], [data-hide-when*=\"' + mode + '\"]'\n )\n ].forEach(elt => {\n let hidden = false;\n const hideWhen = elt.dataset[\"hideWhen\"];\n if (hideWhen) {\n hidden = stringSaysDo(this, hideWhen);\n }\n // hideWhen is absent or yields false, so still shown, and\n // when becomes the judge:\n if (!hidden) {\n const when = elt.dataset[\"when\"];\n // If there is no when, still show.\n if (when) {\n hidden = !stringSaysDo(this, when);\n }\n }\n elt.hidden = hidden;\n });\n }\n }\n return this;\n }\n}\n\nconst Mode = new BucketWithConsequences();\n\nexport { Mode };\n", "/* global URLSearchParams FormData */\n\nimport { mapConcat, either, when } from \"./functional.js\";\n\nconst ATTR_SNAME = \"data-server-name\";\nconst ATTR_SVALUE = \"data-server-value\";\nconst CONTAINER_SELECTOR = \"#bb-q .group.selected\";\n\nconst INPUT_SELECTOR = mapConcat(\n [\"input\", \"textarea\", \"select\"],\n function (c) {\n return c + \"[name]:not([disabled])\";\n },\n \", \"\n);\n\nconst inputsOf = container => container.querySelectorAll(INPUT_SELECTOR);\n\nconst isEmptyRadioValue = val => val === null;\nconst isEmptyCheckboxValue = val => val === false;\nconst isCheckedCheckboxValue = val => val === true;\n\nfunction collectWithin({\n params = null, // Object with an .append method, taking two params\n flavor = URLSearchParams, // Constructor for an object with an .append method, taking two params, used when params is not provided\n container = document.querySelector(CONTAINER_SELECTOR),\n omitFn = isEmptyCheckboxValue,\n changeFn = when(isCheckedCheckboxValue, () => \"on\"),\n collector = inputsOf\n} = {}) {\n return _collectAll(\n collector(container),\n params || new flavor(),\n omitFn,\n changeFn\n );\n}\n\nfunction _collectAll(nodeList, params, omitFn, changeFn) {\n for (const node of nodeList) {\n const val = valueOf(node),\n name = node.getAttribute(ATTR_SNAME) || node.getAttribute(\"name\");\n if (!either(isEmptyRadioValue, omitFn, val)) {\n params.append(name, changeFn(val));\n }\n }\n return params;\n}\n\nfunction valueOf(node) {\n if (node.hasAttribute(ATTR_SVALUE)) return node.getAttribute(ATTR_SVALUE);\n switch (node.type) {\n case \"radio\":\n return node.checked ? node.value : null; // Do not collect unchecked radios -- stripped in collectAll.\n case \"checkbox\":\n /* Collect unchecked checkboxes as false -- goes against usual form submission,\n but we need this for Studio API (using JSON). Stripped out by collectAll() unless provided with a omitFn. */\n if (!node.checked) return false;\n return node.hasAttribute(\"value\") // NOT the property -- this would still be \"on\".\n ? node.value // A checkbox should send either its value or\n : true; // Return Boolean true instead of \"on\", to be changed by collectAll() with changeFn,\n // or leave it at true (for JSON communication for instance) */\n default:\n return String(node.value).replace(/\\r?\\n/g, \"\\r\\n\");\n }\n}\n\nconst serializeQuestions = () =>\n collectWithin({}).toString().replace(/\\r?\\n/g, \"%0D%0A\");\n\nexport { valueOf, serializeQuestions, collectWithin };\n", "/* global $ FormData URLSearchParams */\nlet _vars = {};\n\nconst SESSION_KEYS = [\"dbname\", \"sessionid\", \"uniqueid\"];\nconst NAV_KEYS = [\"screenid\", ...SESSION_KEYS];\n\nObject.freeze(SESSION_KEYS);\nObject.freeze(NAV_KEYS);\n\nfunction setValueInVars(data, key) {\n if (typeof data[key] != \"undefined\") _vars[key] = data[key];\n}\n\nexport function setVars(data) {\n setValueInVars(data, \"version\");\n setValueInVars(data, \"uniqueid\");\n setValueInVars(data, \"replyserveraddress\");\n setValueInVars(data, \"replyserverport\");\n setValueInVars(data, \"proxyredirect\");\n setValueInVars(data, \"sessionid\");\n setValueInVars(data, \"modelname\");\n setValueInVars(data, \"dbname\");\n setValueInVars(data, \"modelid\");\n setValueInVars(data, \"showdeleteinmenu\");\n setValueInVars(data, \"showdatecreated\");\n setValueInVars(data, \"showreport\");\n setValueInVars(data, \"userinfo\");\n setValueInVars(data, \"showcopycase\");\n setValueInVars(data, \"screenid\");\n var version = getVar(\"version\");\n if (typeof version === \"string\") _vars[\"version\"] = version.split(\".\");\n}\n\nexport function getVar(string, obj) {\n return $.extend({}, _vars, obj)[string];\n}\n\n/**\n * Unset either all vars, or only those present in param vars\n *\n * @param {Array} vars An array of variable keys to delete\n *\n **/\nfunction unsetVars(arr) {\n if (!arr) return (_vars = {});\n arr.forEach(function (key) {\n delete _vars[key];\n });\n return _vars;\n}\n\nfunction collect(keys, collector = new FormData(), obj) {\n function append(key) {\n const val = getVar(key, obj);\n if (val !== undefined) collector.append(key, getVar(key, obj));\n }\n if (Array.isArray(keys)) {\n keys.forEach(append);\n } else {\n append(keys);\n }\n return collector;\n}\n\nfunction querify(keys, obj) {\n const usp = collect(keys, new URLSearchParams(), obj);\n return usp.toString();\n}\n\nexport default {\n querify,\n setVars,\n getVar,\n unsetVars,\n collect,\n NAV_KEYS,\n SESSION_KEYS\n};\n", "/* global URLSearchParams */\nimport \"./polyfills/url-search-params.js\";\nimport { Mode } from \"./mode.js\";\nimport { serializeQuestions } from \"./collect-values.js\";\nimport Vars from \"./vars.js\";\n\nexport const shouldExit = () =>\n Mode.get(\"hasModel\") && Boolean(Vars.getVar(\"sessionid\"));\n\nexport const onEnd = () => {\n if (!shouldExit()) return;\n if (!navigator.sendBeacon) return;\n const data = [\n \"step=exitdelayed\",\n Vars.querify(Vars.NAV_KEYS),\n \"fmt=json\",\n serializeQuestions()\n ]\n .filter(Boolean)\n .join(\"&\");\n\n const usp = new URLSearchParams(data);\n\n navigator.sendBeacon(\"/action\", usp);\n};\n\nfunction addEndListener() {\n // Update state before navigating away, but do not logout\n if (\"onpagehide\" in window) {\n window.addEventListener(\"pagehide\", onEnd);\n } else {\n window.addEventListener(\"unload\", onEnd, false);\n }\n}\n\nexport function removeEndListener() {\n // Update state before navigating away, but do not logout\n if (\"onpagehide\" in window) {\n window.removeEventListener(\"pagehide\", onEnd);\n } else {\n window.removeEventListener(\"unload\", onEnd, false);\n }\n}\n\naddEndListener();\n", "/* a11y-user-detect:\n *\n * \"User Detect\" will dynamically toggle between\n * a-keyboard-user & a-mouse-user (described in a11y.less)\n * depending on user interaction on document.\n *\n * The idea is to give keyboard users more visual queues,\n * without effecting the aesthetics for non-keyboard users.\n *\n * Author: Tim Bauwens\n * Copyright 2017 Berkeley Bridge\n *\n */\n\nimport { Mode } from \"$json/lib/mode\";\n\nexport const isKeyboardUser = () => Mode.get(\"a-keyboard-user\");\n\nexport const isMouseUser = () => Mode.get(\"a-mouse-user\");\n\nexport const setKeyboardUser = () => {\n Mode.set(\"a-keyboard-user\");\n Mode.unset(\"a-mouse-user\");\n};\n\nexport const setMouseUser = () => {\n Mode.unset(\"a-keyboard-user\");\n Mode.set(\"a-mouse-user\");\n};\n\n$(function () {\n let openingMatch, mouse;\n try {\n // Could have no opener, or opener could be X-Origin\n if (window.opener.document.body) {\n openingMatch = window.opener.document.body.className.match(\n /\\ba-(keyboard|mouse)-user\\b/\n );\n if (openingMatch) mouse = openingMatch[1] === \"mouse\";\n }\n } catch (e) {\n mouse = false;\n }\n if (mouse) {\n setMouseUser();\n } else {\n setKeyboardUser();\n }\n $(document.body).on(\"mousedown touchstart\", function () {\n setMouseUser();\n });\n $(document.body).on(\"keydown\", function (e) {\n if (\n e.key === \"Tab\" ||\n e.target.matches(`input[type=\"radio\"], input[type=\"checkbox\"]`)\n ) {\n setKeyboardUser();\n }\n });\n});\n", "/* global $ */\nimport \"./a11y-user-detect.js\";\nimport { _ } from \"./gettext.js\";\n\n/*** A11y BEGIN ***/\n\nconst isLiveRegion = area =>\n area.role === \"alert\" ||\n [\"assertive\", \"polite\"].includes(area.getAttribute(\"aria-live\"));\n\nconst LIVE_REGION_SELECTOR = \"#a-logdiv\";\n\nconst _liveRegion = document.querySelector(LIVE_REGION_SELECTOR);\n\nif (!_liveRegion) {\n console.warn(\n `Live errors and such will not be announced to screen readers, as there is no ${LIVE_REGION_SELECTOR} at pageLoad!`\n );\n}\n\nif (_liveRegion && !isLiveRegion(_liveRegion)) {\n console.warn(`${LIVE_REGION_SELECTOR} is not actually an aria-live region.`);\n}\n\nconst liveRegion = _liveRegion;\n\nexport const A11y = {\n log: function (message, html = false) {\n if (!liveRegion) {\n return;\n }\n if (liveRegion && !liveRegion.isConnected) {\n console.warn(`${LIVE_REGION_SELECTOR} is not connected`);\n return;\n }\n if (html) {\n liveRegion.innerHTML = message;\n } else liveRegion.textContent = message;\n const textContent = liveRegion.textContent;\n setTimeout(() => {\n if (liveRegion.textContent === textContent) liveRegion.textContent = \"\";\n }, 500);\n }\n};\n\n/**\n * Datepicker a11y enhancements\n */\nexport const observeDatepickers = (function () {\n var init = false;\n return function initDateObservance() {\n var picker, observer;\n\n if (init || !(\"MutationObserver\" in window)) {\n init = true;\n return;\n }\n\n $(document).on(\"blur\", '[data-type=\"datetimepicker\"]', function () {\n A11y.log(\"\");\n });\n\n function observation(records, instance) {\n try {\n var infocus =\n document.activeElement.className.split(\" \").indexOf(\"hasDatepicker\") >\n -1;\n } catch (e) {\n // there mayn't be an activeElement, in which case className is undefined.\n }\n if (infocus) {\n var message = [\n $(\".ui-state-hover\").text(),\n $(\".ui-datepicker-month [selected]\").text(),\n $(\".ui-datepicker-year [selected]\").text()\n ].join(\" \");\n A11y.log(message + \", \" + _(\"press enter to accept\"));\n }\n }\n\n picker = document.getElementById(\"ui-datepicker-div\");\n\n if (picker) {\n observer = new window.MutationObserver(observation);\n observer.observe(picker, { attributes: true });\n init = true;\n }\n };\n})();\n", "let escapeHTML = (function () {\n var entityMap = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n \"/\": \"/\"\n };\n var re = new RegExp(\"[&<>\\\"'/]\", \"g\");\n return function escapeHTML(string) {\n return String(string).replace(re, function (s) {\n return entityMap[s];\n });\n };\n})();\n\nconst escaped = (strings, ...values) =>\n strings.reduce(\n (acc, cur, idx) =>\n acc + cur + (values.length > idx ? escapeHTML(values[idx]) : \"\"),\n \"\"\n );\n\nexport { escapeHTML, escaped };\n", "import { Mode } from \"./mode.js\";\nimport { A11y } from \"./a11y.js\";\n\n/*** NOTIFICATIONS BEGIN ***/\nlet message;\n// Notification can either be a String or an object with a message\n// property. When supplying an object, the message property will be\n// shown to the user, but the entire object will be given to\n// console.error.\nfunction notify(options = { keepalive: false, html: false }, notification) {\n if (!notification) return;\n var text = notification.message || notification,\n timeout = 5000;\n A11y.log(text, options.html);\n if (\n typeof console !== \"undefined\" &&\n console &&\n typeof console.error === \"function\"\n )\n console.error(notification);\n message = { notification, options };\n Mode.set(\"hasMessage\");\n if (options.html) {\n document\n .querySelectorAll(\".bb-notification\")\n .forEach(area => (area.innerHTML = text));\n } else {\n document\n .querySelectorAll(\".bb-notification\")\n .forEach(area => (area.textContent = text));\n }\n if (!options.keepalive) {\n window.setTimeout(Mode.unset.bind(Mode, \"hasMessage\"), timeout);\n window.setTimeout(\n () =>\n document\n .querySelectorAll(\".bb-notification\")\n .forEach(area => (area.textContent = \"\")),\n timeout\n );\n }\n}\n\nexport { notify, message };\n/*** NOTIFICATIONS END ***/\n", "/*** CONFIG BEGIN ***/\n\nimport conf from \"$conf.json\";\nimport { has } from \"./functional.js\";\n\nconf.a11y = Object.assign(\n {\n captions: false,\n optionfieldsets: false,\n strictlegends: false\n },\n conf.a11y\n);\n\nfunction propFinder(ob, prefix) {\n if (prefix) ob = find(prefix);\n\n function find(prop, fallback) {\n if (ob === undefined) return fallback;\n if (prop === undefined) return fallback;\n var leafs = prop.split(\".\").filter(Boolean),\n leaf = ob;\n while (has(leafs[0], leaf)) {\n leaf = leaf[leafs.shift()];\n }\n if (leafs.length === 0) return leaf;\n return fallback;\n }\n\n return find;\n}\n\nexport { conf, propFinder };\n\n/*** CONFIG END ***/\n", "import { conf } from \"./conf\";\nexport const fromApiServer = s =>\n s.startsWith(\"http://\") || s.startsWith(\"https://\")\n ? s\n : [conf.apiserver, s].filter(Boolean).join(\"/\");\n", "/* global jQuery */\nlet $ = jQuery;\n\nimport { escapeHTML } from \"./escape.js\";\nimport { notify } from \"./notify.js\";\nimport { _ } from \"./gettext.js\";\nimport { fromApiServer } from \"./location.js\";\n\n/**\n * Keep track of ajax requests + some convenience\n *\n * Exports busy and replace to bb.ajax object for plugins to use.\n */\nvar Ajax = {\n busy: false,\n last: null,\n direction: null,\n\n defaultOptions: {\n dataType: \"json\",\n type: \"POST\",\n url: \"action\",\n cache: false,\n async: true,\n success: checkJSON,\n error: onJSONError\n },\n\n post: function (options) {\n const _options = Object.assign({}, Ajax.defaultOptions, options, {\n url: fromApiServer(options.url || Ajax.defaultOptions.url)\n });\n $(document).trigger(\"bb:prePost\", _options);\n return $.ajax(_options);\n },\n\n replace: function (obj) {\n Ajax.last && Ajax.last.abort();\n Ajax.last = Ajax.post(obj);\n return Ajax.last;\n },\n\n release: function () {\n Ajax.busy = false;\n $(\".group.selected\").prop(\"disabled\", false);\n }\n};\n\n/**\n * Convenience method, like getJSON, but with POST\n *\n * @param {String} url URL where we POST to\n * @param {Object|String} data POST data\n *\n * Use Ajax.post instead if you want to overrule any default\n * settings from Ajax.defaultOptions.\n */\n$.postJSON = function (url, data) {\n return Ajax.post({ url: url, data: data });\n};\n\n/**\n * The default JSON error handler.\n *\n * Set appropriate flags, let user now what went wrong (as good as\n * possible).\n *\n * Trigger custom 'bb:jsonError' event on document.\n *\n * @param {Object} data XMLHTTPRequest object\n * @param {String} err Error message\n */\nfunction onJSONError(data, err) {\n Ajax.release();\n $(document).trigger(\"bb:jsonError\", data, err);\n if (data.responseText === undefined) {\n if (data.statusText === \"abort\");\n else {\n notify(\n { html: false, keepalive: true },\n _(\"Error: No response from server, server probably down\")\n );\n }\n } else if (data.responseText.trim() === \"\") {\n notify(\n { html: false, keepalive: true },\n _(\"Error: No response from server, server probably down\")\n );\n } else {\n notify(\n { html: true, keepalive: true },\n \"Error: \" +\n escapeHTML(err) +\n \"
Response was:
\" +\n \"
\" +\n        escapeHTML(data.responseText) +\n        \"
\"\n );\n }\n}\n\n/**\n * Indicate further processing ought to be skipped when this symbol is\n * set on JSON data.\n * @example\n import { stopDispatches } from \"$json/lib/ajax\";\n $(document).on(\"bb:preHandleData\", (event, data) => {\n event.stopImmediatePropagation(); // prevent further bb:preHandleData handlers.\n data[stopDispatches] = true;\n })\n * @constant\n * @type {Symbol}\n */\nexport const stopDispatches = Symbol(\"Skip all further dispatches\");\n\n/**\n Set this symbol to a promise on ajax data, and it shall be awaited\n before the next *handleData is run.\n*/\nconst awaiting = Symbol(\"awaiting promise\");\n\n/**\n * The default AJAX success handler. Perform actions on data.\n\n *\n * If data is not a JSON object, do nothing.\n *\n * @todo Either check data against JSON API, in some way or the\n * other, or make sure this function doesn't get called in the\n * first place when we're dealing with a non-core request; as\n * checkJSON is currently bound to ALL $.ajax requests,\n * this function may also fire for non-core requests.\n *\n * @param {Object} data 'JSON object according to BB JSON API'\n * @param {String} status Status of XHR\n * @param {Object} req The XHR object retrieving the resource\n *\n * @return undefined\n */\nasync function checkJSON(data, status, req) {\n if (typeof req.responseJSON !== \"undefined\") {\n // Since subsequent events may mess with the responseJSON\n // object, give (debuggers) the option to see the raw stuff.\n // Could be solved with a service worker instead.\n $(document).trigger(\"bb:responseText\", req.responseText);\n // use bb:preHandleData to change the JSON object for later invocations\n $(document).trigger(\"bb:preHandleData\", data);\n if (data[stopDispatches]) return;\n await data[awaiting];\n // handleData has the main stuff - the core rendering\n $(document).trigger(\"bb:handleData\", data);\n if (data[stopDispatches]) return;\n await data[awaiting];\n\n // use bb:postHandleData to change the DOM after initial rendering\n $(document).trigger(\"bb:postHandleData\", data);\n if (data[stopDispatches]) return;\n await data[awaiting];\n\n // finalHandleData may not change the DOM, but set focus for instance.\n $(document).trigger(\"bb:finalHandleData\", data);\n if (data[stopDispatches]) return;\n }\n}\n\nexport { Ajax, checkJSON, awaiting };\n", "import { Mode } from \"./mode.js\";\n\nexport const setSettled = () => Mode.set(\"isSettled\");\n", "/* global $ */\nimport { setSettled } from \"./settled.js\";\nimport { removeEndListener } from \"./case-exit.js\";\n\nfunction BBI(options) {\n options = options || {};\n if (options.redirect_uri) {\n /** Example response:\n *\n * {\n * \"bbis\" : \"test\",\n * \"authid\" : \"Stubby\",\n * \"redirect_uri\" : \"https:\\/\\/HOST:8078\\/login?returnurl=http%3A%2F%2Fhost%3A80%2Fbbisreturns%3Fbbis%3Dtest&state=1507301556%3AGUID&authid=Stubby\",\n * \"url\": \"http:\\/\\/HOST:80\\/bbisreturns?bbis=test\",\n * \"state\": \"1507301556:6F2146D3-E0E6-4EB2-9DE4-2F31670B80D6\"\n * }\n *\n */\n var path = window.location.pathname.split(\"/\"),\n template = path.pop() || \"inlog.html\",\n returnurl =\n window.location.origin +\n path.concat(template).join(\"/\") +\n \"?\" +\n $.param({ bbis: options.bbis }),\n server = options.redirect_uri.split(\"?\")[0]; // The identity server sans params\n this.params = Object.assign({}, options.extraparams, {\n returnurl,\n authid: options.authid,\n // Add specific HTML page to state:\n state: options.state\n });\n this.url = server + \"?\" + $.param(this.params);\n this.stage = 1;\n } else {\n this.params = $.extend($.parseQuery(), { fmt: \"json\" });\n this.stage = 2;\n }\n return this;\n}\n\nBBI.prototype.authenticate = function () {\n if (!this.stage) throw \"BBI was not properly initialized\";\n if (this.stage === 1) {\n removeEndListener();\n window.location.href = this.url;\n } else if (this.stage === 2) {\n $.postJSON(\"bbisreturns\", this.params).then(setSettled);\n }\n};\n\nexport { BBI };\n", "import { escapeHTML } from \"./escape.js\";\nimport {\n allPass,\n anyPass,\n both,\n complement,\n compose,\n either,\n F,\n has,\n ifElse,\n pipe,\n prop,\n propEq,\n type\n} from \"./functional.js\";\nexport const isOptional = allPass([\n complement(prop(\"notnull\")),\n either(\n complement(prop(\"stringmask\")),\n pipe(prop(\"stringmask\"), RegExp, re => re.test(\"\"))\n )\n]);\n\nexport const isVisible = prop(\"visible\");\n\nexport const isLabel = either(\n propEq(\"name\", \"label\"),\n propEq(\"controltype\", \"label\")\n);\n\nexport const isOption = either(\n propEq(\"controltype\", \"radio\"),\n propEq(\"controltype\", \"checkbox\")\n);\n\nexport const isLink = propEq(\"name\", \"linklabel\");\n\nexport const isTextual = either(isLabel, isLink);\n\nexport const isPicture = propEq(\"controltype\", \"picture\");\n\nexport const isButton = propEq(\"controltype\", \"button\");\n\nexport const isQuestion = complement(anyPass([isTextual, isPicture, isButton]));\n\nexport const isReadOnly = both(\n isQuestion,\n either(\n ifElse(has(\"originalreadonly\"), prop(\"originalreadonly\"), prop(\"readonly\")),\n propEq(\"visible\", false)\n )\n);\n\nexport const isValidatable = ifElse(\n either(isReadOnly, propEq(\"visible\", false)),\n F,\n anyPass([\n has(\"minimum\"),\n has(\"maximum\"),\n both(has(\"maxlength\"), complement(propEq(\"maxlength\", 0))),\n prop(\"notnull\"),\n compose(s => s === \"string\", type, prop(\"stringmask\"))\n ])\n);\n\nexport const renderAttribs = attr =>\n Object.entries(attr).reduce(\n (acc, [key, value]) => acc + ` ${key}=\"${escapeHTML(value)}\"`,\n \"\"\n );\n\nexport const setAttribs = (elt, attr) =>\n Object.entries(attr).forEach(([key, value]) => elt.setAttribute(key, value));\n\nexport const bbmClass = stylename =>\n `bbm-${stylename.toLowerCase().replace(/[^a-z0-9]/g, \"-\")}`;\n", "import {\n assoc,\n hasPath,\n chain,\n compose,\n either,\n path,\n prop,\n toLower,\n toUpper,\n ifElse,\n juxt,\n when\n} from \"./functional.js\";\nimport { format } from \"./text-utils.js\";\nimport { _ } from \"./gettext.js\";\n\nconst fieldDesignators = {\n datetimepicker: \"field--date\",\n numedit: \"field--value\",\n radio: \"field--list\",\n checkmultilist: \"field--list\",\n customlist: \"field--list\",\n combobox: \"field--list\",\n listbox: \"field--list\",\n multilist: \"field--list\",\n any: \"field--field\"\n};\n\nconst fieldKey = compose(\n controltype => fieldDesignators[controltype] || fieldDesignators[\"any\"],\n prop(\"controltype\")\n);\n\nconst generic = compose(key => _(key), fieldKey);\n\nconst genericQuoted = compose(\n key => _(key), // Runtime!\n key => key.replace(\"field--\", \"quoted--\"),\n fieldKey\n);\nexport const quotable = compose(\n when(\n prop(\"quotable\"),\n chain(\n assoc(\"quotable--init\"),\n compose(s => s.slice(0, 1).toUpperCase() + s.slice(1), prop(\"quotable\"))\n )\n ),\n when(\n prop(\"quotable\"),\n chain(assoc(\"quotable--upper\"), compose(toUpper, prop(\"quotable\")))\n ),\n when(\n prop(\"quotable\"),\n chain(assoc(\"quotable--lower\"), compose(toLower, prop(\"quotable\")))\n ),\n chain(assoc(\"quotable\"), either(path([\"metadata\", \"quotable\"]), generic)),\n ifElse(\n hasPath([\"metadata\", \"quotable\"]),\n compose(assoc(\"<<\", _(\"<<\", \"\u00AB\")), assoc(\">>\", _(\">>\", \"\u00BB\"))),\n compose(assoc(\"<<\", \"\"), assoc(\">>\", \"\"))\n ),\n chain(\n assoc(\"quoted--init\"),\n compose(s => s.slice(0, 1).toUpperCase() + s.slice(1), prop(\"quoted\"))\n ),\n ifElse(\n hasPath([\"metadata\", \"quotable\"]),\n chain(\n assoc(\"quoted\"),\n compose(\n arr => format(...arr),\n juxt([\n genericQuoted,\n compose(quotable => ({ quotable }), path([\"metadata\", \"quotable\"]))\n ])\n )\n ),\n chain(assoc(\"quoted\"), generic)\n )\n);\n", "/* global $ */\nimport { quotable } from \"./quotable.js\";\nimport {\n apply,\n assoc,\n cond,\n compose,\n dec,\n equals,\n identity,\n lensPath,\n mergeLeft,\n match,\n over,\n path,\n pipe,\n tail,\n test,\n T\n} from \"./functional.js\";\nimport { _ } from \"./gettext.js\";\nimport { format, formatPlus } from \"./text-utils.js\";\n\n/*** DATE UTILITIES BEGIN ***/\nDate.prototype.toHoursAndMinutes = function () {\n var hours = this.getHours();\n var minutes = this.getMinutes();\n if (hours < 10) hours = \"0\" + hours;\n if (minutes < 10) minutes = \"0\" + minutes;\n return hours + \":\" + minutes;\n};\nconst dateTimeRe = /^\\/Date\\((-?\\d+)\\)\\/$/,\n pureDateRe = /^(\\d{4})-(\\d{2})-(\\d{2})$/,\n ISO8601DateTimeInZuluRe =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{3})?)?Z$/;\n\n/*\n * Convert JSON date string to a Date object and return it.\n *\n * @{datestring}:\n *\n * An ISO-8601 datetime string in Zulu Time\n *\n * OR\n *\n * a JSON date string of the form\n *\n * \"/Date(102938293293)/\"\n *\n * where the numerical part is\n * seconds from epoch\n *\n * OR:\n *\n * a date formatted as \"yyyy-mm-dd\"\n *\n * OR:\n *\n * undefined -> undefined\n *\n */\nconst date = (...args) => new Date(...args);\n\nexport const parseDate = cond([\n [equals(0), () => undefined],\n [equals(undefined), identity],\n [equals(\"\"), identity],\n [\n test(pureDateRe),\n // Note if we were to pass pureDates to new Date as a valid\n // DateStamp, the engine will interpret it as 0:00 Zulu\n // time. Which, in this very case, is probably not what we\n // want. We want the date as in the minds of the case (min/max in\n // a calendar etc). It should be represented 'as is' to the user,\n // so 2022-02-09 may never become 2022-02-08 in users TZ, so\n // interpret it according in users TZ.\n pipe(match(pureDateRe), tail, over(lensPath([1]), dec), apply(date))\n ],\n [test(ISO8601DateTimeInZuluRe), date],\n [test(dateTimeRe), pipe(match(dateTimeRe), path([1]), parseInt, date)],\n [\n T,\n thing => {\n throw `Not a date in our book: ${thing}`;\n }\n ]\n]);\n\nexport const leadWithZeroes = string =>\n string.replace(/([^0-9]|^)([0-9]{3})([^0-9]|$)/, \"$10$2$3\");\n\n/**\n *\n * @param {Object} spec Object describing a control conforming to the BB json api.\n * @param {String} value The value to be checked\n * @returns {Boolean|Error} true when value is according to spec\n * @throws Localized error message\n */\nexport function checkDate(spec = { notnull: false }, value) {\n const UIFormat = $.datepicker._defaults.dateFormat;\n const formatDate = $.datepicker.formatDate.bind($.datepicker);\n var date, mindate, maxdate;\n if (!spec.notnull && value.trim() === \"\") {\n return true;\n }\n const metadata = spec.metadata || {};\n try {\n date = valueToDate(UIFormat, value); // $.datepicker.parseDate(UIFormat, value); // This line may throw an error.\n } catch (e) {\n //couldn't parse - throw a translatable error message\n throw formatPlus(\n metadata.errdateinvalid || _(\"Invalid date\"),\n compose(assoc(\"value\", value), quotable)(spec)\n );\n }\n if (date === null) {\n if (spec.notnull) {\n throw format(\n metadata.errrequired || _(\"Date required\"),\n compose(assoc(\"value\", value), quotable)(spec)\n );\n }\n return true;\n }\n (mindate = parseDate(spec.minimum)), (maxdate = parseDate(spec.maximum));\n if (!(mindate || maxdate)) return true; // Neither is set\n const fmindate = formatDate(UIFormat, mindate),\n fmaxdate = formatDate(UIFormat, maxdate);\n const quotableDate = compose(\n mergeLeft({\n value,\n minimum: fmindate,\n maximum: fmaxdate\n }),\n quotable\n )(spec);\n try {\n if (mindate && !maxdate && date < mindate)\n throw (\n metadata.errdatebeforemimimum ||\n _(\"A date before {minimum} is not allowed\")\n );\n else if (mindate && maxdate && (date < mindate || maxdate < date))\n throw (\n metadata.errdatenotinrange ||\n _(\"Date has to lie between {minimum} and {maximum}\")\n );\n else if (maxdate && !mindate && maxdate < date)\n throw (\n metadata.errdateaftermaximum ||\n _(\"A date after {maximum} is not allowed\")\n );\n } catch (e) {\n throw format(e, quotableDate);\n }\n return true;\n}\n\nexport const valueToDate = (format, value) => {\n let date;\n try {\n date = $.datepicker.parseDate(format, value);\n } catch (e) {\n const yyyycleanformat = format.replace(/[^mdy]/g, \"\").replace(\"yy\", \"yyyy\"),\n clean = value.replace(/[^0-9]/g, \"\");\n date = new Date();\n const yearindex = yyyycleanformat.indexOf(\"yyyy\");\n // If year was less than 4 digits, and not at end, adjust indices of other fields.\n const adjustment = yearindex === 0 ? clean.length - 8 : 0;\n let year = Number(clean.substr(yearindex, 4 + adjustment));\n if (year <= 99) {\n const cutoffyear = Number.isInteger(\n $.datepicker._defaults.shortYearCutoff\n )\n ? $.datepicker._defaults.shortYearCutoff\n : (date.getYear() % 100) +\n Number($.datepicker._defaults.shortYearCutoff);\n // Note: this will become odd if current year approaches end of\n // century. Let's say we live in 2099. User enters 98 -> fine.\n // Is below 109. User enters 02 => not fine. Still below 109.\n // But jQuery UI should also fix this. And it's still a long time.\n const century = (date.getFullYear() / 100) >> 0;\n if (year <= cutoffyear) {\n year += century * 100;\n } else {\n year += (century - 1) * 100;\n }\n }\n const month = Math.max(\n 0,\n Number(clean.substr(yyyycleanformat.indexOf(\"mm\") + adjustment, 2)) - 1\n );\n const dom = Number(\n clean.substr(yyyycleanformat.indexOf(\"dd\") + adjustment, 2)\n );\n date.setFullYear(year);\n date.setMonth(month);\n date.setDate(dom);\n if (\n date.getFullYear() !== year ||\n date.getMonth() !== month ||\n date.getDate() !== dom\n ) {\n throw \"invalid date\";\n }\n }\n return date;\n};\n\nexport const onChangeDate = ev => {\n let date;\n try {\n date = valueToDate($.datepicker._defaults.dateFormat, ev.target.value);\n } catch (e) {\n // ignore\n } finally {\n if (date) {\n ev.target.value = leadWithZeroes(\n $.datepicker.formatDate($.datepicker._defaults.dateFormat, date)\n );\n }\n }\n};\n\nexport const humanDate = (function () {\n var now = new Date();\n var hour0 = now.setHours(0, 0, 0, 0);\n var dayinms = 1000 * 60 * 60 * 24;\n var hour24 = hour0 + dayinms;\n var thisyear = now.getYear();\n var daysofweek = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map(\n function (day) {\n return _(day);\n }\n );\n var monthsofyear = [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"June\",\n \"July\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\"\n ].map(function (month) {\n return _(month);\n });\n function isToday(ms) {\n return ms > hour0 && ms < hour24;\n }\n function isYesterday(ms) {\n return hour0 > ms && ms > hour0 - dayinms;\n }\n function isLastWeek(ms) {\n return ms > hour0 - dayinms * 6;\n }\n function isThisYear(date) {\n return thisyear == date.getYear();\n }\n function humanDate(date) {\n if (!(date instanceof Date)) throw \"Expects a Date object\";\n var ms = date.valueOf();\n var hm = \"\";\n hm = date.toHoursAndMinutes();\n if (isToday(ms)) {\n return hm;\n }\n if (isYesterday(ms)) {\n return _(\"Yesterday\") + \", \" + hm;\n }\n if (isLastWeek(ms)) {\n return daysofweek[date.getDay()] + \" \" + hm;\n }\n return (\n date.getDate() +\n \" \" +\n monthsofyear[date.getMonth()] +\n (isThisYear(date) ? \"\" : \" \" + date.getFullYear()) +\n \", \" +\n hm\n );\n }\n return humanDate;\n})();\n", "import { compose, either, isNil, not, path } from \"./functional.js\";\n\n/* editPolicy may be \"return\", \"stay\", or undefined, meaning off */\nexport const editPolicy = path([\"arbitrary\", \"core\", \"editPolicy\"]);\n\nexport const canEditEarlier = compose(not, isNil, editPolicy);\n\nconst isLabelValueDynamic = compose(\n value => value === true,\n path([\"arbitrary\", \"core\", \"isLabelValueDynamic\"])\n);\n\nconst preferUpdate = compose(\n value => value === true,\n path([\"arbitrary\", \"core\", \"preferUpdate\"])\n);\n\nexport const mustUpdate = either(preferUpdate, canEditEarlier);\n\nexport const updateLabels = either(mustUpdate, isLabelValueDynamic);\n", "const _Widgets = {};\n\nexport function registerWidget(options) {\n _Widgets[options.name] = options;\n}\nexport function getWidget(name) {\n return _Widgets[name];\n}\n", "/* global $ */\n\nimport { parseDate } from \"./dates\";\nimport { isReadOnly, isValidatable } from \"./control-helpers\";\nimport { updateLabels } from \"./feature-queries.js\";\nimport { conf } from \"./conf.js\";\nimport { getWidget } from \"./form-widgets.js\";\nimport { anyPass, has, pathOr, prop } from \"./functional.js\";\nconst Dynprops = {};\n\n// Update the control element\nDynprops.update = function ($widget, control, Updates, requestor) {\n if (!$widget.get(0)) return;\n const oldval = $widget.val();\n\n const updates = Object.keys(Updates);\n const definition = getWidget(control.controltype);\n $widget.removeData([\"validated\"]);\n\n /** isForNotNull **/\n if (has(\"isForNotNull\", Updates)) {\n $widget.toggleClass(\"bb-for-required\", Boolean(control.isForNotNull));\n $widget.toggleClass(\"bb-for-optional\", !control.isForNotNull);\n }\n\n /** Placeholder **/\n if (has(\"placeholder\", Updates) > -1) {\n $widget.attr(\"placeholder\", control.placeholder);\n }\n\n /** Visible **/\n if (has(\"visible\", Updates)) {\n if (control.identifier === \"gformulier.gegevens.geschil_partner\")\n $widget.attr(\"aria-hidden\", !control.visible);\n $widget.attr(\"data-visible\", control.visible);\n\n if (control.visible) {\n window.setTimeout(function () {\n $widget.removeAttr(\"hidden\");\n }, 80);\n } else {\n window.setTimeout(function () {\n $widget.attr(\"hidden\", !control.visible);\n }, 80);\n }\n }\n\n /** Value **/\n if (has(\"value\", Updates)) {\n if (updateLabels(conf)) {\n /**\n @done: linklabel, listlabel, checkmultilist, memo, combobox, radio,\n checkbox, numedit, datetimepicker, edit, grid, multilist(?), listbox(?)\n @todo: freebox.\n\n NOTE: A widget currently can change itself *only* if\n they are registered with allowUpdatingSelf : true\n\n Widgets within a grid can update other widgets in a grid.\n */\n if (definition.setValue) {\n definition.setValue($widget.get(0), control.value, requestor, Updates);\n }\n }\n }\n\n /** Readonly **/\n if (\n anyPass([has(\"readonly\"), has(\"originalreadonly\"), has(\"visible\")], Updates)\n ) {\n const readonly = isReadOnly(control);\n if (typeof definition.onreadonly === \"function\") {\n definition.onreadonly($widget.get(0), readonly);\n } else {\n $widget.prop(\n pathOr(\"readonly\", [\"template\", \"readonly-prop\"], conf),\n readonly\n );\n }\n }\n\n /** Minimum **/\n if (has(\"minimum\", Updates)) {\n $widget.attr(\"min\", control.minimum);\n if (control.controltype === \"datetimepicker\") {\n if (control.minimum) {\n $widget.datepicker(\"option\", \"minDate\", parseDate(control.minimum));\n }\n }\n }\n\n /** Maximum **/\n if (has(\"maximum\", Updates)) {\n $widget.attr(\"max\", control.maximum);\n if (control.controltype === \"datetimepicker\") {\n if (control.maximum) {\n $widget.datepicker(\"option\", \"maxDate\", parseDate(control.maximum));\n }\n }\n }\n\n /** Maxlength **/\n if (has(\"maxlength\", Updates)) {\n if (control.maxlength === 0) $widget.removeAttr(\"maxlength\");\n else $widget.attr(\"maxlength\", control.maxlength);\n }\n\n /** Let user know something changed perhaps against their intent. **/\n if (oldval !== $widget.val()) {\n $widget.addClass(\"bb-programmatically-changed\");\n $widget.trigger(\"change\", { programmatically: true });\n self.setTimeout(function () {\n $widget.removeClass(\"bb-programmatically-changed\");\n }, 1000);\n }\n\n /** Notnull **/\n if (has(\"notnull\", Updates)) {\n if (typeof definition.onrequired === \"function\") {\n definition.onrequired($widget.get(0), control.notnull);\n } else {\n $widget.attr(\"aria-required\", control.notnull);\n }\n if (control.notnull) {\n $widget.addClass(\"notnull\");\n } else {\n $widget.removeClass(\"notnull\");\n }\n }\n\n if (isValidatable(control)) {\n $widget.attr(\"aria-errormessage\", `${control.id}--error`);\n $widget.addClass(\"validatable\");\n } else {\n $widget.removeAttr(\"aria-errormessage\");\n $widget.removeClass(\"validatable\");\n }\n\n if (updates.length > 0) {\n const event = new CustomEvent(\"bb:updatedControl\", {\n detail: { control, Updates },\n bubbles: true\n });\n $widget.get(0).dispatchEvent(event);\n $(document).trigger(\"bb:updated\", [$widget, control, updates]);\n }\n};\n\n$.fn.extend({\n updateControl: function (controls, requestor) {\n return this.each(function () {\n const $this = $(this),\n control = $this.data(\"control\");\n if (\n this === requestor &&\n !prop(\"allowUpdatingSelf\", getWidget(control.controltype))\n ) {\n // This was the one requesting an update\n return this;\n }\n if (!control) throw (\"No updateControl defined for\", $this);\n const id = control.id,\n update = controls.find(function (c) {\n return c.id === id;\n }),\n // updates = [],\n Updates = {},\n props = [\n \"maxlength\",\n \"isForNotNull\",\n \"minimum\",\n \"maximum\",\n \"notnull\",\n \"readonly\",\n \"originalreadonly\",\n \"placeholder\",\n \"precision\",\n \"stringmask\",\n \"errortext\",\n \"visible\",\n \"value\",\n \"columns\",\n \"text\"\n ];\n // Caron-syntax used in label, therefore no (text) interface\n // returned -- should not mix and match dynprops with empty\n // labels! Do not allow this to error on the user though!\n\n // Does also handle (cause to ignore) labels within a grid!\n if (typeof update === \"undefined\") {\n return this;\n // update = $.extend({}, control, {visible: false});\n }\n for (var i in props) {\n if (control[props[i]] !== update[props[i]]) {\n Updates[props[i]] = { from: control[props[i]], to: update[props[i]] };\n control[props[i]] = update[props[i]];\n // updates.push(props[i]);\n }\n }\n Dynprops.update($this, control, Updates, requestor);\n return this;\n });\n }\n});\n\nexport { Dynprops };\n", "const Hooks = new Map();\n\nexport const registerHook = key => hook => {\n if (typeof hook !== \"function\") throw \"Can only add a function as a hook\";\n Hooks.set(key, hook);\n};\n\nexport const runHook =\n key =>\n (...args) => {\n if (Hooks.has(key)) Hooks.get(key)(...args);\n };\n", "/* global $ */\nimport { bbmClass, isReadOnly, renderAttribs } from \"./control-helpers\";\nimport { Dynprops } from \"./dynprops\";\nimport { escaped, escapeHTML } from \"./escape.js\";\nimport { conf, propFinder } from \"./conf\";\nimport { getWidget } from \"./form-widgets.js\";\nimport {\n assoc,\n both,\n compose,\n complement,\n has,\n hasPath,\n isNil,\n not,\n prop\n} from \"./functional.js\";\nimport { runHook } from \"./hooks.js\";\nimport { Mode } from \"./mode.js\";\n\nconst arbitraryCoreProp = propFinder(conf, \"arbitrary.core\");\n\n/**\n * Create a control widget, then insert it into the DOM\n *\n * @param {Object} control A control object as defined in the JSON API. The one to render + add.\n * @param {Object} group The group object to which this control belongs.\n * @param {Element} wGroup Element whereto this control should be added. *NOTE* that this need not be a .bb-group\n *\n * @return undefined\n *\n * @todo Simplify parameter list.\n */\nfunction wControl(control, group, wGroup) {\n control._group = group;\n let attribs = {};\n let widget;\n const enabled = group.current || complement(isReadOnly)(control);\n // Has been rendered\n if (control.$elt) {\n $(wGroup).append(control.$elt);\n return control.$elt;\n }\n if (compose(has(\"fixup\"), getWidget)(control.controltype))\n compose(fn => fn(control), prop(\"fixup\"), getWidget)(control.controltype);\n\n if (control.datatype) attribs[\"data-datatype\"] = control.datatype;\n\n if (control.meta)\n for (let d in control.meta) {\n if (both(has(d), compose(not, isNil, prop(d)))(control.meta))\n attribs[\"data-\" + d] = escape(control.meta[d]);\n }\n if (control.metadata) {\n attribs[\"data-metadata-keys\"] = Object.keys(control.metadata)\n .map(s => s.replace(/\\s/g, \"-\"))\n .join(\" \");\n }\n if (control.aria)\n for (let a in control.aria) {\n if (has(a, control.aria)) attribs[\"aria-\" + a] = control.aria[a];\n }\n\n if (control.name) {\n attribs[\"name\"] = control.name;\n }\n\n const wdef = getWidget(control.controltype);\n if (!wdef) {\n console.warn(`No widget definition for ${control.controltype}`);\n return null;\n }\n const tagName = wdef.tagName;\n attribs = wdef.attribs(attribs, control, enabled);\n\n attribs[\"data-type\"] = control.controltype;\n if (tagName) {\n widget = $(\"<\" + tagName + \" \" + renderAttribs(attribs) + \"/>\");\n } else {\n widget = $(wdef.render(control, group, attribs));\n if (!widget) return null;\n }\n\n if (control.className) {\n widget.addClass(control.className);\n }\n control.$elt = widget;\n control._elt = widget.get(0);\n\n if (wdef && wdef.tagName) {\n /**\n Okay, some (older) definitions have a tagName definition ->\n from which a quite empty skeleton widget is created.\n\n Afterwards, they fill that very widget with a render function\n of a different signature than usual:\n\n Instead of (control (plain object), group (plain object), attribs (array)), they get\n (control (plain object), widget (jQuery collection), group (plain object))).\n\n */\n wdef.render(control, widget, group);\n }\n\n // attach an id whenever meaningful:\n // if (control.id && /\\d+$/.test(control.id))\n if (control.id) {\n // id used not to be safe, but now we prepend the groupid, making it safe.\n widget.attr(\"id\", control.id);\n }\n if (control._originalid) {\n // Use data-id for stuff refering to the interface, no matter in which group it is, such as informationsources.\n widget.attr(\"data-id\", control._originalid);\n }\n\n if (hasPath([\"metadata\", \"autocomplete\"], control)) {\n widget\n .attr(\"data-server-name\", control.name)\n .attr(\"name\", control.metadata.autocomplete)\n .attr(\"autocomplete\", control.metadata.autocomplete);\n }\n\n $(wGroup).append(widget);\n\n /* Insert a space between elements so that elements are reasonably\n * well-placed when CSS is disabled.\n */\n $(wGroup).append(\" \");\n\n // Tooltips:\n if (control.hint) {\n if (enabled) Mode.set(\"hasHints\");\n runHook(\"hinter\")(widget, assoc(\"enabled\", enabled, control));\n }\n widget.data(\"control\", control);\n\n /**\n * Dynamic properties\n */\n var dynprops = [\n \"maxlength\",\n \"minimum\",\n \"maximum\",\n \"notnull\",\n \"isForNotNull\",\n \"readonly\",\n \"precision\",\n \"stringmask\",\n \"errortext\",\n \"placeholder\"\n ],\n dynpropsforus = {};\n\n for (var ii in dynprops) {\n if (has(dynprops[ii], control))\n dynpropsforus[dynprops[ii]] = { to: control[dynprops[ii]] }; // .push(dynprops[ii]);\n }\n\n if (has(\"visible\", control) && control.visible === false) {\n dynpropsforus[\"visible\"] = { to: false }; // .push(dynprops[ii]);\n }\n // dynpropsforus.push(\"visible\");\n\n widget.data(\"anchor\", widget);\n\n if (wdef && wdef.afterRender) {\n wdef.afterRender(widget, control);\n }\n\n if (shouldWrap(control)) {\n wrapInlineInput(widget);\n }\n\n /* Allow class-based styling */\n if (control[\"font-class\"]) {\n widget.addClass(bbmClass(control[\"font-class\"]));\n }\n\n /**\n * Two things:\n * - Put control tags in data-tags of Element.\n * - Make TAG known to CSS as bb-tagged-TAG.\n */\n if (control[\"tags\"] instanceof Array) {\n $(widget).data(\"tags\", control[\"tags\"]);\n $.each(control[\"tags\"], function (i, tag) {\n widget.addClass(\"bb-tagged-\" + tag);\n });\n }\n\n Dynprops.update(widget, control, dynpropsforus);\n\n return widget;\n}\n\nfunction shouldWrap(control) {\n return (\n control.prelabel ||\n control.postlabel ||\n (arbitraryCoreProp(\"wrapAllSingleLiners\") === true &&\n compose(prop(\"couldWrap\"), getWidget)(control.controltype)) ||\n (control.placeholder &&\n arbitraryCoreProp(\"accessiblePlaceholders\") === true &&\n compose(prop(\"couldWrap\"), getWidget)(control.controltype))\n );\n}\n\nfunction wrapInlineInput(widget) {\n var control = widget.data(\"control\"),\n prelabel = control.prelabel,\n postlabel = control.postlabel;\n var anchor = widget.data(\"anchor\");\n var wraptag = \"span\";\n if (anchor.get(0).nodeName === \"DIV\") wraptag = \"div\";\n anchor.wrapAll(\n \"<\" +\n wraptag +\n ' data-wraps-type=\"' +\n control.controltype +\n '\" class=\"bb-input-wrap\">\"\n );\n anchor = anchor.parent();\n widget.data(\"anchor\", anchor);\n anchor.data({\n control: control,\n type: control.controltype\n });\n if (prelabel)\n anchor.prepend(\n '' +\n escapeHTML(prelabel) +\n \"\"\n );\n if (control.placeholder && arbitraryCoreProp(\"accessiblePlaceholders\")) {\n widget\n .get(0)\n .setAttribute(\n \"aria-describedby\",\n (\n (widget.get(0).getAttribute(\"aria-describedby\") || \"\") +\n ` ${control.id}--placeholder`\n ).trim()\n );\n anchor.append(\n `${escapeHTML(control.placeholder)}`\n );\n }\n if (postlabel)\n anchor.append(\n '' +\n escapeHTML(postlabel) +\n \"\"\n );\n}\n\nconst getControl = elt => $.data(elt, \"control\");\n\nexport { getControl, wControl };\n", "export const listtypes = {\n radio: \"LIST\",\n checkmultilist: \"LIST\",\n customlist: \"LIST\",\n combobox: \"BOX\",\n listbox: \"BOX\",\n multilist: \"BOX\"\n};\n", "/* global $ */\nimport { occurrences } from \"$json/lib/text-utils.js\";\nimport { getWidget } from \"./form-widgets.js\";\nimport {\n always,\n assoc,\n compose,\n cond,\n curry,\n either,\n path,\n propEq,\n T,\n tap\n} from \"./functional.js\";\nimport { _ } from \"./gettext.js\";\nimport { quotable } from \"./quotable.js\";\nimport { format, formatPlus } from \"./text-utils.js\";\nimport { listtypes } from \"./types.js\";\n\nconst numofnewlines = curry(occurrences)(\"\\n\");\n\n// Validate actual input, return true if it's ok, throw an error otherwise.\nexport function validateInput(node) {\n const $node = $(node),\n control = $node.data(\"control\");\n let ok = true,\n re,\n errortext,\n val,\n category;\n\n if (control === undefined) {\n throw \"Not a BB widget\";\n }\n\n if (control.visible === false) {\n return true;\n }\n category = listtypes[control.controltype];\n\n val = $node.val();\n\n if (control.stringmask) {\n re = new RegExp(control.stringmask);\n if (!re.test(val))\n throw format(\n control.errortext,\n compose(assoc(\"value\", val), quotable)(control)\n );\n }\n if (control.notnull) {\n if (category === \"LIST\") {\n ok = $node.is(\":has(:checked)\");\n } else if (category === \"BOX\") {\n // There could be a faux, checked, option telling us to\n // fill in the field. That is the second check here.\n ok = val !== null && val !== \"\";\n } else if (control.controltype == \"checkbox\") {\n ok = $node.is(\":checked\");\n } else if (control.controltype === \"grid\") {\n if (control.addallowed === false) {\n const checkable = control.columns.find(\n either(\n propEq(\"controltype\", \"radiobutton\"),\n propEq(\"controltype\", \"checkbox\")\n )\n );\n if (checkable) {\n ok = $node.is(\":has(:checked)\");\n }\n } else {\n // A required grid should have at least one row.\n // But if no rows **can** be added it would be rude and confusing to complain to the end-user.\n ok = control.value.length > 0 || control.addallowed === false;\n }\n } else {\n re = /\\S/;\n ok = re.test(val);\n }\n if (!ok) {\n throw cond([\n [path([\"metadata\", \"errrequired\"]), path([\"metadata\", \"errrequired\"])],\n [\n propEq(\"controltype\", \"datetimepicker\"),\n compose(c => formatPlus(_(\"Date required\"), c), quotable)\n ],\n [\n always([\"BOX\", \"LIST\"].indexOf(category) > -1),\n compose(c => format(_(\"Choice required\"), c), quotable)\n ],\n [T, compose(c => format(_(\"Field required\"), c), quotable)]\n ])(control);\n }\n }\n if (control.maxlength && control.maxlength > 0) {\n ok = val.length + numofnewlines(val) <= control.maxlength;\n if (!ok) {\n throw format(\n path([\"metadata\", \"errtexttoolong\"])(control) ||\n _(\"Text length exceeds the maximum of {maxlength} characters\"),\n quotable(control)\n );\n }\n }\n if (getWidget(control.controltype).validate) {\n return getWidget(control.controltype).validate(control, val);\n }\n return true;\n}\n", "import {\n groupWith,\n map,\n filter,\n pipe,\n path,\n strictUniq,\n lensPath\n} from \"./functional.js\";\n\nconst pathToGroup = [\"metadata\", \"group\"];\nexport const pathGroup = path(pathToGroup);\nexport const lensGroup = lensPath([\"metadata\", \"group\"]);\n\nconst areOfOneQuestion = (a, b) => {\n if (a.isfor === undefined && b.isfor === undefined) return false;\n return a.isfor === b.id || b.isfor === a.id;\n};\n\nexport const groupInner = groupWith(areOfOneQuestion);\n\nconst InfinityIfMinus1 = num => (num + 1 || Infinity) - 1;\nconst indexOfOrInfinity = (sub, s) => InfinityIfMinus1(s.indexOf(sub));\nexport const baseGroup = s => s.substr(0, indexOfOrInfinity(\".\", s));\nexport const tailGroup = s => s.substr(indexOfOrInfinity(\".\", s) + 1);\n\nconst belongTogether = (a, b) =>\n areOfOneQuestion(a, b) ||\n (pathGroup(a) &&\n pathGroup(b) &&\n baseGroup(pathGroup(a)) === baseGroup(pathGroup(b)));\n\nexport const groupOuter = groupWith(belongTogether);\n\nexport const groupClasses = pipe(\n map(path[(\"metadata\", \"groupClasses\")]),\n filter(Boolean),\n strictUniq\n);\n\nexport const doGrouping = path([\"arbitrary\", \"core\", \"form-group\", \"on\"]);\n", "export const normalize = s => s.toLowerCase().replace(/[^a-z0-9]/g, \"-\");\n", "import { path, either, compose, prop } from \"./functional.js\";\nimport { conf } from \"./conf.js\";\n\n/**\n\nName keys follow this pattern:\n\n__\n\n is any of:\n\n- GROUPING: subgroup of questions and/or texts and/or links\n- ITEM: a question and/or text and/or link\n- QUESTION: a question (is also an item)\n- TEXT: a top level text (not a label for a question)\n- LINK: a top level link (so: not inside markdown)\n- PICTURE: a top level image (so : nto inside markdown)\n\nGROUPING ::= ITEM+\nITEM ::= QUESTION | TEXT | LINK | PICTURE\n\n is any of:\n\n- _CLASS_ : the css class to put on this type \n- _PREFIX_: a css class prefix\n- _DATA_: a data- attribute\n\nwhere can be anything.\n\nThe default values for those keys, thus the strings that willl be used\nin the generated DOM, are provided in nameDefaults. They can be\noverwritten in the `conf.json` file in the property\n`core.form-group.names` in order to retrofit older or other naming\nschemes.\n\n*/\n\nexport const /* A grouping groups items */\n GROUPING_CLASS = \"grouping-class\", // Class of grouping\n GROUPING_PREFIX_TYPE = \"grouping-prefix-type\", // prefix for -question, -text or -author\n GROUPING_DATA_NAME = \"grouping-data-name\", // data attribute conveying author provided group name\n GROUPING_DATA_LEVEL = \"grouping-data-level\", // grouping level, 1-based\n ITEM_PREFIX_AUTHORCLASS = \"item-prefix-authorclass\", // prefix for author class set with cssclasses on the metadata\n QUESTION_CLASS = \"question-class\", //: \"bb-questionlabelgroup\",\n QUESTION_PREFIX_TYPE = \"question-prefix-type\", //: \"bb-itype\",\n QUESTION_PREFIX_PROPERTY = \"question-prefix-property\", //: \"bb-itype\",\n QUESTION_DATA_LAYOUT = \"question-data-layout\", //: \"data-form-group-layout\",\n QUESTION_PREFIX_AUTHORSTYLE = \"question-prefix-authorstyle\", //: \"bb-g-\",\n QUESTION_CLASS_NOLABEL = \"question-class-nolabel\"; //: \"form-group__question--no-label\",\n\nconst nameDefaults = {\n [GROUPING_CLASS]: \"form-group\",\n [GROUPING_PREFIX_TYPE]: \"form-group-\",\n [GROUPING_DATA_NAME]: \"data-form-group-name\",\n [GROUPING_DATA_LEVEL]: \"data-form-group-level\",\n [ITEM_PREFIX_AUTHORCLASS]: \"form-group__item--author-class-\",\n [QUESTION_CLASS]: \"bb-questionlabelgroup\",\n [QUESTION_PREFIX_TYPE]: \"bb-itype\",\n [QUESTION_PREFIX_PROPERTY]: \"question-\", //: \"bb-itype\",\n [QUESTION_DATA_LAYOUT]: \"data-form-group-layout\",\n [QUESTION_PREFIX_AUTHORSTYLE]: \"bb-g-\",\n [QUESTION_CLASS_NOLABEL]: \"form-group__question--no-label\"\n};\n\n// const fg = {\n// [GROUPING_CLASS]: \"no-form-group-outer\",\n// [GROUPING_PREFIX_TYPE]: \"form-group-\",\n// [QUESTION_CLASS]: \"bb-questionlabelgroup p-form-group\",\n// [QUESTION_PREFIX_TYPE]: \"bb-itype-\",\n// [QUESTION_DATA_LAYOUT]: \"data-p-form-group-layout-type\",\n// [QUESTION_CLASS_NOLABEL]: \"p-form-group-orphaned\"\n// };\n\n// const bem_example = {\n// [GROUPING_CLASS]: \"form-group\",\n// [GROUPING_PREFIX_TYPE]: \"form-group-\",\n// [ITEM_PREFIX_AUTHORCLASS]: \"form-group__item--author-class-\",\n// [QUESTION_CLASS]: \"bb-questionlabelgroup\",\n// [QUESTION_PREFIX_TYPE]: \"form-group__question-\",\n// [QUESTION_DATA_LAYOUT]: \"data-form-group-layout\",\n// [QUESTION_PREFIX_AUTHORSTYLE]: \"form-group__question--author-style-\"\n// };\n\nconst pathToNames = path([\"arbitrary\", \"core\", \"form-group\", \"names\"]);\n\nexport const names = propArg =>\n either(compose(prop(propArg), pathToNames), _ => prop(propArg, nameDefaults))(\n conf\n );\n", "/* global $ */\nimport {\n all,\n both,\n curry,\n filter,\n has,\n compose,\n ifElse,\n head,\n path,\n prop,\n propEq,\n any,\n find,\n pathOr,\n split,\n join,\n map,\n when,\n tap,\n cond,\n not\n} from \"./functional.js\";\nimport {\n isTextual,\n isPicture,\n isQuestion,\n isVisible\n} from \"./control-helpers.js\";\nimport { groupOuter, baseGroup, tailGroup, pathGroup } from \"./groupings\";\nimport { normalize } from \"./font-classes\";\nimport { getWidget } from \"./form-widgets.js\";\nimport { conf } from \"./conf\";\nimport * as n from \"./names.js\";\nimport { names } from \"./names.js\";\n\nconst doTopLevel = pathOr(true, [\n \"arbitrary\",\n \"core\",\n \"form-group\",\n \"toplevel\"\n]);\n\nconst doLegends = pathOr(true, [\n \"arbitrary\",\n \"core\",\n \"form-group\",\n \"doLegends\"\n]);\n\nconst getLayout = type =>\n pathOr(compose(prop(\"layout\"), getWidget)(type), [\n \"arbitrary\",\n \"form-group\",\n type\n ]);\n\nconst getGroupName = compose(when(Boolean, baseGroup), pathGroup, head);\n\n// Interface Font Style\nconst questionGroupClass = compose(\n s => names(n.QUESTION_PREFIX_AUTHORSTYLE) + s,\n normalize,\n prop(\"font-class\")\n);\n\n// interface metadata: cssclasses=\nexport const extraClasses = prefix =>\n compose(\n when(\n Boolean,\n compose(\n join(\" \"),\n map(compose(s => names(prefix) + s, normalize)),\n split(\" \")\n )\n ),\n path([\"metadata\", \"cssclasses\"])\n );\n\nconst asciify = s => s.replace(/[^a-z-]/g, \"-\");\n\nconst areAllInvisible = compose(not, any(isVisible));\nconst areAllReadonly = both(\n any(both(isQuestion, isVisible)),\n compose(all(prop(\"originalreadonly\")), filter(both(isQuestion, isVisible)))\n);\n\nconst areAllNotNull = both(\n any(both(isQuestion, isVisible)),\n compose(all(prop(\"notnull\")), filter(both(isQuestion, isVisible)))\n);\n\nconst updateClassWhen = curry((className, fn, controls, elt) => {\n elt.classList.toggle(className, fn(controls));\n});\n\nconst setReadonlyFGClass = updateClassWhen(\n names(n.GROUPING_PREFIX_TYPE) + \"-readonly\",\n areAllReadonly\n);\nconst setEmptyFGClass = updateClassWhen(\n names(n.GROUPING_PREFIX_TYPE) + \"-empty\",\n areAllInvisible\n);\nconst setRequiredFGClass = updateClassWhen(\n names(n.GROUPING_PREFIX_TYPE) + \"-required\",\n areAllNotNull\n);\n\nconst setReadonlyQClass = updateClassWhen(\n names(n.QUESTION_PREFIX_PROPERTY) + \"-readonly\",\n areAllReadonly\n);\nconst setEmptyQClass = updateClassWhen(\n names(n.QUESTION_PREFIX_PROPERTY) + \"-empty\",\n areAllInvisible\n);\nconst setRequiredQClass = updateClassWhen(\n names(n.QUESTION_PREFIX_PROPERTY) + \"-required\",\n areAllNotNull\n);\n\nexport const createFormGroup = (wControl, group, level) => c => {\n let formGroup;\n const groupName = getGroupName(c);\n\n if (\n groupName ||\n (doTopLevel(conf) &&\n (doLegends(conf) || !all(propEq(\"controltype\", \"legend\"))(c)))\n ) {\n formGroup = document.createElement(\"div\");\n formGroup.className = names(n.GROUPING_CLASS);\n formGroup.setAttribute(names(n.GROUPING_DATA_LEVEL), level);\n setEmptyFGClass(c, formGroup);\n setReadonlyFGClass(c, formGroup);\n setRequiredFGClass(c, formGroup);\n formGroup.addEventListener(\"bb:updatedControl\", ({ detail }) => {\n if (has(\"visible\", detail.Updates)) {\n setEmptyFGClass(c, formGroup);\n }\n if (has(\"readonly\", detail.Updates)) {\n setReadonlyFGClass(c, formGroup);\n }\n if (has(\"notnull\", detail.Updates)) {\n setRequiredFGClass(c, formGroup);\n }\n });\n if (groupName) {\n formGroup.setAttribute(names(n.GROUPING_DATA_NAME), asciify(groupName));\n formGroup.classList.add(names(n.GROUPING_PREFIX_TYPE) + \"-author\");\n } else if (find(isQuestion, c)) {\n formGroup.classList.add(names(n.GROUPING_PREFIX_TYPE) + \"-interface\");\n } else if (compose(isPicture, head)(c)) {\n formGroup.classList.add(names(n.GROUPING_PREFIX_TYPE) + \"-picture\");\n } else if (compose(isTextual, head)(c)) {\n formGroup.classList.add(names(n.GROUPING_PREFIX_TYPE) + \"-text\");\n }\n } else {\n formGroup = document.createDocumentFragment();\n }\n\n const cWithin = compose(\n groupOuter,\n map(\n when(\n pathGroup,\n tap(control =>\n compose(\n ifElse(\n s => s === \"\",\n () => delete control.metadata.group,\n group => (control.metadata.group = group)\n ),\n tailGroup\n )(control.metadata.group)\n )\n )\n )\n )(c);\n cWithin.forEach(\n cond([\n [\n getGroupName,\n compose(\n n => formGroup.appendChild(n),\n createFormGroup(wControl, group, level + 1)\n )\n ],\n [\n any(isQuestion),\n controls => {\n const answer = find(isQuestion, controls);\n const classes = [\n names(n.QUESTION_CLASS),\n `${names(n.QUESTION_PREFIX_TYPE)}-${answer.controltype}`,\n questionGroupClass(answer),\n extraClasses(n.ITEM_PREFIX_AUTHORCLASS)(answer),\n controls.length === 1 && names(n.QUESTION_CLASS_NOLABEL)\n ].filter(Boolean);\n const qlg = document.createElement(\"div\");\n qlg.setAttribute(\n names(n.QUESTION_DATA_LAYOUT),\n answer._layout || getLayout(answer.controltype)(conf)\n );\n qlg.className = classes.join(\" \");\n setEmptyQClass(controls, qlg);\n setReadonlyQClass(controls, qlg);\n setRequiredQClass(controls, qlg);\n qlg.addEventListener(\"bb:updatedControl\", ({ detail }) => {\n if (has(\"visible\", detail.Updates)) {\n setEmptyQClass(controls, qlg);\n }\n if (has(\"readonly\", detail.Updates)) {\n setReadonlyQClass(controls, qlg);\n }\n if (has(\"notnull\", detail.Updates)) {\n setRequiredQClass(controls, qlg);\n }\n });\n controls.forEach(c => wControl(c, group, $(qlg)));\n formGroup.appendChild(qlg);\n }\n ],\n [\n () => true,\n map(c => {\n const $widget = wControl(c, group, $(formGroup));\n if ($widget)\n $widget.addClass(extraClasses(n.ITEM_PREFIX_AUTHORCLASS)(c));\n })\n ]\n ])\n );\n return formGroup;\n};\n", "/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nconst NODE_MODE = false;\n\n// Allows minifiers to rename references to globalThis\nconst global = globalThis;\n\n/**\n * Whether the current browser supports `adoptedStyleSheets`.\n */\nexport const supportsAdoptingStyleSheets: boolean =\n global.ShadowRoot &&\n (global.ShadyCSS === undefined || global.ShadyCSS.nativeShadow) &&\n 'adoptedStyleSheets' in Document.prototype &&\n 'replace' in CSSStyleSheet.prototype;\n\n/**\n * A CSSResult or native CSSStyleSheet.\n *\n * In browsers that support constructible CSS style sheets, CSSStyleSheet\n * object can be used for styling along side CSSResult from the `css`\n * template tag.\n */\nexport type CSSResultOrNative = CSSResult | CSSStyleSheet;\n\nexport type CSSResultArray = Array;\n\n/**\n * A single CSSResult, CSSStyleSheet, or an array or nested arrays of those.\n */\nexport type CSSResultGroup = CSSResultOrNative | CSSResultArray;\n\nconst constructionToken = Symbol();\n\nconst cssTagCache = new WeakMap();\n\n/**\n * A container for a string of CSS text, that may be used to create a CSSStyleSheet.\n *\n * CSSResult is the return value of `css`-tagged template literals and\n * `unsafeCSS()`. In order to ensure that CSSResults are only created via the\n * `css` tag and `unsafeCSS()`, CSSResult cannot be constructed directly.\n */\nexport class CSSResult {\n // This property needs to remain unminified.\n ['_$cssResult$'] = true;\n readonly cssText: string;\n private _styleSheet?: CSSStyleSheet;\n private _strings: TemplateStringsArray | undefined;\n\n private constructor(\n cssText: string,\n strings: TemplateStringsArray | undefined,\n safeToken: symbol\n ) {\n if (safeToken !== constructionToken) {\n throw new Error(\n 'CSSResult is not constructable. Use `unsafeCSS` or `css` instead.'\n );\n }\n this.cssText = cssText;\n this._strings = strings;\n }\n\n // This is a getter so that it's lazy. In practice, this means stylesheets\n // are not created until the first element instance is made.\n get styleSheet(): CSSStyleSheet | undefined {\n // If `supportsAdoptingStyleSheets` is true then we assume CSSStyleSheet is\n // constructable.\n let styleSheet = this._styleSheet;\n const strings = this._strings;\n if (supportsAdoptingStyleSheets && styleSheet === undefined) {\n const cacheable = strings !== undefined && strings.length === 1;\n if (cacheable) {\n styleSheet = cssTagCache.get(strings);\n }\n if (styleSheet === undefined) {\n (this._styleSheet = styleSheet = new CSSStyleSheet()).replaceSync(\n this.cssText\n );\n if (cacheable) {\n cssTagCache.set(strings, styleSheet);\n }\n }\n }\n return styleSheet;\n }\n\n toString(): string {\n return this.cssText;\n }\n}\n\ntype ConstructableCSSResult = CSSResult & {\n new (\n cssText: string,\n strings: TemplateStringsArray | undefined,\n safeToken: symbol\n ): CSSResult;\n};\n\nconst textFromCSSResult = (value: CSSResultGroup | number) => {\n // This property needs to remain unminified.\n if ((value as CSSResult)['_$cssResult$'] === true) {\n return (value as CSSResult).cssText;\n } else if (typeof value === 'number') {\n return value;\n } else {\n throw new Error(\n `Value passed to 'css' function must be a 'css' function result: ` +\n `${value}. Use 'unsafeCSS' to pass non-literal values, but take care ` +\n `to ensure page security.`\n );\n }\n};\n\n/**\n * Wrap a value for interpolation in a {@linkcode css} tagged template literal.\n *\n * This is unsafe because untrusted CSS text can be used to phone home\n * or exfiltrate data to an attacker controlled site. Take care to only use\n * this with trusted input.\n */\nexport const unsafeCSS = (value: unknown) =>\n new (CSSResult as ConstructableCSSResult)(\n typeof value === 'string' ? value : String(value),\n undefined,\n constructionToken\n );\n\n/**\n * A template literal tag which can be used with LitElement's\n * {@linkcode LitElement.styles} property to set element styles.\n *\n * For security reasons, only literal string values and number may be used in\n * embedded expressions. To incorporate non-literal values {@linkcode unsafeCSS}\n * may be used inside an expression.\n */\nexport const css = (\n strings: TemplateStringsArray,\n ...values: (CSSResultGroup | number)[]\n): CSSResult => {\n const cssText =\n strings.length === 1\n ? strings[0]\n : values.reduce(\n (acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1],\n strings[0]\n );\n return new (CSSResult as ConstructableCSSResult)(\n cssText,\n strings,\n constructionToken\n );\n};\n\n/**\n * Applies the given styles to a `shadowRoot`. When Shadow DOM is\n * available but `adoptedStyleSheets` is not, styles are appended to the\n * `shadowRoot` to [mimic spec behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets).\n * Note, when shimming is used, any styles that are subsequently placed into\n * the shadowRoot should be placed *before* any shimmed adopted styles. This\n * will match spec behavior that gives adopted sheets precedence over styles in\n * shadowRoot.\n */\nexport const adoptStyles = (\n renderRoot: ShadowRoot,\n styles: Array\n) => {\n if (supportsAdoptingStyleSheets) {\n (renderRoot as ShadowRoot).adoptedStyleSheets = styles.map((s) =>\n s instanceof CSSStyleSheet ? s : s.styleSheet!\n );\n } else {\n for (const s of styles) {\n const style = document.createElement('style');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nonce = (global as any)['litNonce'];\n if (nonce !== undefined) {\n style.setAttribute('nonce', nonce);\n }\n style.textContent = (s as CSSResult).cssText;\n renderRoot.appendChild(style);\n }\n }\n};\n\nconst cssResultFromStyleSheet = (sheet: CSSStyleSheet) => {\n let cssText = '';\n for (const rule of sheet.cssRules) {\n cssText += rule.cssText;\n }\n return unsafeCSS(cssText);\n};\n\nexport const getCompatibleStyle =\n supportsAdoptingStyleSheets ||\n (NODE_MODE && global.CSSStyleSheet === undefined)\n ? (s: CSSResultOrNative) => s\n : (s: CSSResultOrNative) =>\n s instanceof CSSStyleSheet ? cssResultFromStyleSheet(s) : s;\n", "/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Use this module if you want to create your own base class extending\n * {@link ReactiveElement}.\n * @packageDocumentation\n */\n\nimport {\n getCompatibleStyle,\n adoptStyles,\n CSSResultGroup,\n CSSResultOrNative,\n} from './css-tag.js';\nimport type {\n ReactiveController,\n ReactiveControllerHost,\n} from './reactive-controller.js';\n\n// In the Node build, this import will be injected by Rollup:\n// import {HTMLElement, customElements} from '@lit-labs/ssr-dom-shim';\n\nexport * from './css-tag.js';\nexport type {\n ReactiveController,\n ReactiveControllerHost,\n} from './reactive-controller.js';\n\n/**\n * Removes the `readonly` modifier from properties in the union K.\n *\n * This is a safer way to cast a value to a type with a mutable version of a\n * readonly field, than casting to an interface with the field re-declared\n * because it preserves the type of all the fields and warns on typos.\n */\ntype Mutable = Omit & {\n -readonly [P in keyof Pick]: P extends K ? T[P] : never;\n};\n\n// TODO (justinfagnani): Add `hasOwn` here when we ship ES2022\nconst {\n is,\n defineProperty,\n getOwnPropertyDescriptor,\n getOwnPropertyNames,\n getOwnPropertySymbols,\n getPrototypeOf,\n} = Object;\n\nconst NODE_MODE = false;\n\n// Lets a minifier replace globalThis references with a minified name\nconst global = globalThis;\n\nif (NODE_MODE) {\n global.customElements ??= customElements;\n}\n\nconst DEV_MODE = true;\n\nlet issueWarning: (code: string, warning: string) => void;\n\nconst trustedTypes = (global as unknown as {trustedTypes?: {emptyScript: ''}})\n .trustedTypes;\n\n// Temporary workaround for https://crbug.com/993268\n// Currently, any attribute starting with \"on\" is considered to be a\n// TrustedScript source. Such boolean attributes must be set to the equivalent\n// trusted emptyScript value.\nconst emptyStringForBooleanAttribute = trustedTypes\n ? (trustedTypes.emptyScript as unknown as '')\n : '';\n\nconst polyfillSupport = DEV_MODE\n ? global.reactiveElementPolyfillSupportDevMode\n : global.reactiveElementPolyfillSupport;\n\nif (DEV_MODE) {\n // Ensure warnings are issued only 1x, even if multiple versions of Lit\n // are loaded.\n const issuedWarnings: Set = (global.litIssuedWarnings ??=\n new Set());\n\n // Issue a warning, if we haven't already.\n issueWarning = (code: string, warning: string) => {\n warning += ` See https://lit.dev/msg/${code} for more information.`;\n if (!issuedWarnings.has(warning)) {\n console.warn(warning);\n issuedWarnings.add(warning);\n }\n };\n\n issueWarning(\n 'dev-mode',\n `Lit is in dev mode. Not recommended for production!`\n );\n\n // Issue polyfill support warning.\n if (global.ShadyDOM?.inUse && polyfillSupport === undefined) {\n issueWarning(\n 'polyfill-support-missing',\n `Shadow DOM is being polyfilled via \\`ShadyDOM\\` but ` +\n `the \\`polyfill-support\\` module has not been loaded.`\n );\n }\n}\n\n/**\n * Contains types that are part of the unstable debug API.\n *\n * Everything in this API is not stable and may change or be removed in the future,\n * even on patch releases.\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace ReactiveUnstable {\n /**\n * When Lit is running in dev mode and `window.emitLitDebugLogEvents` is true,\n * we will emit 'lit-debug' events to window, with live details about the update and render\n * lifecycle. These can be useful for writing debug tooling and visualizations.\n *\n * Please be aware that running with window.emitLitDebugLogEvents has performance overhead,\n * making certain operations that are normally very cheap (like a no-op render) much slower,\n * because we must copy data and dispatch events.\n */\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace DebugLog {\n export type Entry = Update;\n export interface Update {\n kind: 'update';\n }\n }\n}\n\ninterface DebugLoggingWindow {\n // Even in dev mode, we generally don't want to emit these events, as that's\n // another level of cost, so only emit them when DEV_MODE is true _and_ when\n // window.emitLitDebugEvents is true.\n emitLitDebugLogEvents?: boolean;\n}\n\n/**\n * Useful for visualizing and logging insights into what the Lit template system is doing.\n *\n * Compiled out of prod mode builds.\n */\nconst debugLogEvent = DEV_MODE\n ? (event: ReactiveUnstable.DebugLog.Entry) => {\n const shouldEmit = (global as unknown as DebugLoggingWindow)\n .emitLitDebugLogEvents;\n if (!shouldEmit) {\n return;\n }\n global.dispatchEvent(\n new CustomEvent('lit-debug', {\n detail: event,\n })\n );\n }\n : undefined;\n\n/*\n * When using Closure Compiler, JSCompiler_renameProperty(property, object) is\n * replaced at compile time by the munged name for object[property]. We cannot\n * alias this function, so we have to use a small shim that has the same\n * behavior when not compiling.\n */\n/*@__INLINE__*/\nconst JSCompiler_renameProperty =

(\n prop: P,\n _obj: unknown\n): P => prop;\n\n/**\n * Converts property values to and from attribute values.\n */\nexport interface ComplexAttributeConverter {\n /**\n * Called to convert an attribute value to a property\n * value.\n */\n fromAttribute?(value: string | null, type?: TypeHint): Type;\n\n /**\n * Called to convert a property value to an attribute\n * value.\n *\n * It returns unknown instead of string, to be compatible with\n * https://github.com/WICG/trusted-types (and similar efforts).\n */\n toAttribute?(value: Type, type?: TypeHint): unknown;\n}\n\ntype AttributeConverter =\n | ComplexAttributeConverter\n | ((value: string | null, type?: TypeHint) => Type);\n\n/**\n * Defines options for a property accessor.\n */\nexport interface PropertyDeclaration {\n /**\n * When set to `true`, indicates the property is internal private state. The\n * property should not be set by users. When using TypeScript, this property\n * should be marked as `private` or `protected`, and it is also a common\n * practice to use a leading `_` in the name. The property is not added to\n * `observedAttributes`.\n */\n readonly state?: boolean;\n\n /**\n * Indicates how and whether the property becomes an observed attribute.\n * If the value is `false`, the property is not added to `observedAttributes`.\n * If true or absent, the lowercased property name is observed (e.g. `fooBar`\n * becomes `foobar`). If a string, the string value is observed (e.g\n * `attribute: 'foo-bar'`).\n */\n readonly attribute?: boolean | string;\n\n /**\n * Indicates the type of the property. This is used only as a hint for the\n * `converter` to determine how to convert the attribute\n * to/from a property.\n */\n readonly type?: TypeHint;\n\n /**\n * Indicates how to convert the attribute to/from a property. If this value\n * is a function, it is used to convert the attribute value a the property\n * value. If it's an object, it can have keys for `fromAttribute` and\n * `toAttribute`. If no `toAttribute` function is provided and\n * `reflect` is set to `true`, the property value is set directly to the\n * attribute. A default `converter` is used if none is provided; it supports\n * `Boolean`, `String`, `Number`, `Object`, and `Array`. Note,\n * when a property changes and the converter is used to update the attribute,\n * the property is never updated again as a result of the attribute changing,\n * and vice versa.\n */\n readonly converter?: AttributeConverter;\n\n /**\n * Indicates if the property should reflect to an attribute.\n * If `true`, when the property is set, the attribute is set using the\n * attribute name determined according to the rules for the `attribute`\n * property option and the value of the property converted using the rules\n * from the `converter` property option.\n */\n readonly reflect?: boolean;\n\n /**\n * A function that indicates if a property should be considered changed when\n * it is set. The function should take the `newValue` and `oldValue` and\n * return `true` if an update should be requested.\n */\n hasChanged?(value: Type, oldValue: Type): boolean;\n\n /**\n * Indicates whether an accessor will be created for this property. By\n * default, an accessor will be generated for this property that requests an\n * update when set. If this flag is `true`, no accessor will be created, and\n * it will be the user's responsibility to call\n * `this.requestUpdate(propertyName, oldValue)` to request an update when\n * the property changes.\n */\n readonly noAccessor?: boolean;\n\n /**\n * Whether this property is wrapping accessors. This is set by `@property`\n * to control the initial value change and reflection logic.\n *\n * @internal\n */\n wrapped?: boolean;\n}\n\n/**\n * Map of properties to PropertyDeclaration options. For each property an\n * accessor is made, and the property is processed according to the\n * PropertyDeclaration options.\n */\nexport interface PropertyDeclarations {\n readonly [key: string]: PropertyDeclaration;\n}\n\ntype PropertyDeclarationMap = Map;\n\ntype AttributeMap = Map;\n\n/**\n * A Map of property keys to values.\n *\n * Takes an optional type parameter T, which when specified as a non-any,\n * non-unknown type, will make the Map more strongly-typed, associating the map\n * keys with their corresponding value type on T.\n *\n * Use `PropertyValues` when overriding ReactiveElement.update() and\n * other lifecycle methods in order to get stronger type-checking on keys\n * and values.\n */\n// This type is conditional so that if the parameter T is not specified, or\n// is `any`, the type will include `Map`. Since T is not\n// given in the uses of PropertyValues in this file, all uses here fallback to\n// meaning `Map`, but if a developer uses\n// `PropertyValues` (or any other value for T) they will get a\n// strongly-typed Map type.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type PropertyValues = T extends object\n ? PropertyValueMap\n : Map;\n\n/**\n * Do not use, instead prefer {@linkcode PropertyValues}.\n */\n// This type must be exported such that JavaScript generated by the Google\n// Closure Compiler can import a type reference.\nexport interface PropertyValueMap extends Map {\n get(k: K): T[K] | undefined;\n set(key: K, value: T[K]): this;\n has(k: K): boolean;\n delete(k: K): boolean;\n}\n\nexport const defaultConverter: ComplexAttributeConverter = {\n toAttribute(value: unknown, type?: unknown): unknown {\n switch (type) {\n case Boolean:\n value = value ? emptyStringForBooleanAttribute : null;\n break;\n case Object:\n case Array:\n // if the value is `null` or `undefined` pass this through\n // to allow removing/no change behavior.\n value = value == null ? value : JSON.stringify(value);\n break;\n }\n return value;\n },\n\n fromAttribute(value: string | null, type?: unknown) {\n let fromValue: unknown = value;\n switch (type) {\n case Boolean:\n fromValue = value !== null;\n break;\n case Number:\n fromValue = value === null ? null : Number(value);\n break;\n case Object:\n case Array:\n // Do *not* generate exception when invalid JSON is set as elements\n // don't normally complain on being mis-configured.\n // TODO(sorvell): Do generate exception in *dev mode*.\n try {\n // Assert to adhere to Bazel's \"must type assert JSON parse\" rule.\n fromValue = JSON.parse(value!) as unknown;\n } catch (e) {\n fromValue = null;\n }\n break;\n }\n return fromValue;\n },\n};\n\nexport interface HasChanged {\n (value: unknown, old: unknown): boolean;\n}\n\n/**\n * Change function that returns true if `value` is different from `oldValue`.\n * This method is used as the default for a property's `hasChanged` function.\n */\nexport const notEqual: HasChanged = (value: unknown, old: unknown): boolean =>\n !is(value, old);\n\nconst defaultPropertyDeclaration: PropertyDeclaration = {\n attribute: true,\n type: String,\n converter: defaultConverter,\n reflect: false,\n hasChanged: notEqual,\n};\n\n/**\n * A string representing one of the supported dev mode warning categories.\n */\nexport type WarningKind =\n | 'change-in-update'\n | 'migration'\n | 'async-perform-update';\n\nexport type Initializer = (element: ReactiveElement) => void;\n\n// Temporary, until google3 is on TypeScript 5.2\ndeclare global {\n interface SymbolConstructor {\n readonly metadata: unique symbol;\n }\n}\n\n// Ensure metadata is enabled. TypeScript does not polyfill\n// Symbol.metadata, so we must ensure that it exists.\n(Symbol as {metadata: symbol}).metadata ??= Symbol('metadata');\n\ndeclare global {\n // This is public global API, do not change!\n // eslint-disable-next-line no-var\n var litPropertyMetadata: WeakMap<\n object,\n Map\n >;\n}\n\n// Map from a class's metadata object to property options\n// Note that we must use nullish-coalescing assignment so that we only use one\n// map even if we load multiple version of this module.\nglobal.litPropertyMetadata ??= new WeakMap<\n object,\n Map\n>();\n\n/**\n * Base element class which manages element properties and attributes. When\n * properties change, the `update` method is asynchronously called. This method\n * should be supplied by subclasses to render updates as desired.\n * @noInheritDoc\n */\nexport abstract class ReactiveElement\n // In the Node build, this `extends` clause will be substituted with\n // `(globalThis.HTMLElement ?? HTMLElement)`.\n //\n // This way, we will first prefer any global `HTMLElement` polyfill that the\n // user has assigned, and then fall back to the `HTMLElement` shim which has\n // been imported (see note at the top of this file about how this import is\n // generated by Rollup). Note that the `HTMLElement` variable has been\n // shadowed by this import, so it no longer refers to the global.\n extends HTMLElement\n implements ReactiveControllerHost\n{\n // Note: these are patched in only in DEV_MODE.\n /**\n * Read or set all the enabled warning categories for this class.\n *\n * This property is only used in development builds.\n *\n * @nocollapse\n * @category dev-mode\n */\n static enabledWarnings?: WarningKind[];\n\n /**\n * Enable the given warning category for this class.\n *\n * This method only exists in development builds, so it should be accessed\n * with a guard like:\n *\n * ```ts\n * // Enable for all ReactiveElement subclasses\n * ReactiveElement.enableWarning?.('migration');\n *\n * // Enable for only MyElement and subclasses\n * MyElement.enableWarning?.('migration');\n * ```\n *\n * @nocollapse\n * @category dev-mode\n */\n static enableWarning?: (warningKind: WarningKind) => void;\n\n /**\n * Disable the given warning category for this class.\n *\n * This method only exists in development builds, so it should be accessed\n * with a guard like:\n *\n * ```ts\n * // Disable for all ReactiveElement subclasses\n * ReactiveElement.disableWarning?.('migration');\n *\n * // Disable for only MyElement and subclasses\n * MyElement.disableWarning?.('migration');\n * ```\n *\n * @nocollapse\n * @category dev-mode\n */\n static disableWarning?: (warningKind: WarningKind) => void;\n\n /**\n * Adds an initializer function to the class that is called during instance\n * construction.\n *\n * This is useful for code that runs against a `ReactiveElement`\n * subclass, such as a decorator, that needs to do work for each\n * instance, such as setting up a `ReactiveController`.\n *\n * ```ts\n * const myDecorator = (target: typeof ReactiveElement, key: string) => {\n * target.addInitializer((instance: ReactiveElement) => {\n * // This is run during construction of the element\n * new MyController(instance);\n * });\n * }\n * ```\n *\n * Decorating a field will then cause each instance to run an initializer\n * that adds a controller:\n *\n * ```ts\n * class MyElement extends LitElement {\n * @myDecorator foo;\n * }\n * ```\n *\n * Initializers are stored per-constructor. Adding an initializer to a\n * subclass does not add it to a superclass. Since initializers are run in\n * constructors, initializers will run in order of the class hierarchy,\n * starting with superclasses and progressing to the instance's class.\n *\n * @nocollapse\n */\n static addInitializer(initializer: Initializer) {\n this.__prepare();\n (this._initializers ??= []).push(initializer);\n }\n\n static _initializers?: Initializer[];\n\n /*\n * Due to closure compiler ES6 compilation bugs, @nocollapse is required on\n * all static methods and properties with initializers. Reference:\n * - https://github.com/google/closure-compiler/issues/1776\n */\n\n /**\n * Maps attribute names to properties; for example `foobar` attribute to\n * `fooBar` property. Created lazily on user subclasses when finalizing the\n * class.\n * @nocollapse\n */\n private static __attributeToPropertyMap: AttributeMap;\n\n /**\n * Marks class as having been finalized, which includes creating properties\n * from `static properties`, but does *not* include all properties created\n * from decorators.\n * @nocollapse\n */\n protected static finalized: true | undefined;\n\n /**\n * Memoized list of all element properties, including any superclass\n * properties. Created lazily on user subclasses when finalizing the class.\n *\n * @nocollapse\n * @category properties\n */\n static elementProperties: PropertyDeclarationMap;\n\n /**\n * User-supplied object that maps property names to `PropertyDeclaration`\n * objects containing options for configuring reactive properties. When\n * a reactive property is set the element will update and render.\n *\n * By default properties are public fields, and as such, they should be\n * considered as primarily settable by element users, either via attribute or\n * the property itself.\n *\n * Generally, properties that are changed by the element should be private or\n * protected fields and should use the `state: true` option. Properties\n * marked as `state` do not reflect from the corresponding attribute\n *\n * However, sometimes element code does need to set a public property. This\n * should typically only be done in response to user interaction, and an event\n * should be fired informing the user; for example, a checkbox sets its\n * `checked` property when clicked and fires a `changed` event. Mutating\n * public properties should typically not be done for non-primitive (object or\n * array) properties. In other cases when an element needs to manage state, a\n * private property set with the `state: true` option should be used. When\n * needed, state properties can be initialized via public properties to\n * facilitate complex interactions.\n * @nocollapse\n * @category properties\n */\n static properties: PropertyDeclarations;\n\n /**\n * Memoized list of all element styles.\n * Created lazily on user subclasses when finalizing the class.\n * @nocollapse\n * @category styles\n */\n static elementStyles: Array = [];\n\n /**\n * Array of styles to apply to the element. The styles should be defined\n * using the {@linkcode css} tag function, via constructible stylesheets, or\n * imported from native CSS module scripts.\n *\n * Note on Content Security Policy:\n *\n * Element styles are implemented with `