{ "version": 3, "sources": ["../../../node_modules/what-input/dist/what-input.js", "../../../node_modules/ev-emitter/ev-emitter.js", "../../../node_modules/fg-loadjs/loadJS.js", "../../../node_modules/@threespot/freeze-scroll/index.js", "../../javascript/packs/syv-main.js", "../../../node_modules/@threespot/expand-toggle/index.js", "../../javascript/modules/a11y-menu.js", "../../javascript/modules/recite-me-toggle.js", "../../javascript/lib/form-validation.js", "../../javascript/modules/form-validation.js", "../../javascript/modules/story-template.js", "../../../node_modules/@threespot/freeze-scroll/index.mjs", "../../javascript/lib/modals.js", "../../javascript/modules/gallery-modal.js", "../../javascript/modules/share-your-vision-story-upload-form.js", "../../javascript/modules/share-your-vision-donation-url-generator.js", "../../javascript/modules/cta-hero.js", "../../javascript/modules/image-generator.js"], "sourcesContent": ["/**\n * what-input - A global utility for tracking the current input method (mouse, keyboard or touch).\n * @version v5.2.12\n * @link https://github.com/ten1seven/what-input\n * @license MIT\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(\"whatInput\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"whatInput\"] = factory();\n\telse\n\t\troot[\"whatInput\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \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\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\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.loaded = 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// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\n\t'use strict';\n\n\tmodule.exports = function () {\n\t /*\n\t * bail out if there is no document or window\n\t * (i.e. in a node/non-DOM environment)\n\t *\n\t * Return a stubbed API instead\n\t */\n\t if (typeof document === 'undefined' || typeof window === 'undefined') {\n\t return {\n\t // always return \"initial\" because no interaction will ever be detected\n\t ask: function ask() {\n\t return 'initial';\n\t },\n\n\t // always return null\n\t element: function element() {\n\t return null;\n\t },\n\n\t // no-op\n\t ignoreKeys: function ignoreKeys() {},\n\n\t // no-op\n\t specificKeys: function specificKeys() {},\n\n\t // no-op\n\t registerOnChange: function registerOnChange() {},\n\n\t // no-op\n\t unRegisterOnChange: function unRegisterOnChange() {}\n\t };\n\t }\n\n\t /*\n\t * variables\n\t */\n\n\t // cache document.documentElement\n\t var docElem = document.documentElement;\n\n\t // currently focused dom element\n\t var currentElement = null;\n\n\t // last used input type\n\t var currentInput = 'initial';\n\n\t // last used input intent\n\t var currentIntent = currentInput;\n\n\t // UNIX timestamp of current event\n\t var currentTimestamp = Date.now();\n\n\t // check for a `data-whatpersist` attribute on either the `html` or `body` elements, defaults to `true`\n\t var shouldPersist = false;\n\n\t // form input types\n\t var formInputs = ['button', 'input', 'select', 'textarea'];\n\n\t // empty array for holding callback functions\n\t var functionList = [];\n\n\t // list of modifier keys commonly used with the mouse and\n\t // can be safely ignored to prevent false keyboard detection\n\t var ignoreMap = [16, // shift\n\t 17, // control\n\t 18, // alt\n\t 91, // Windows key / left Apple cmd\n\t 93 // Windows menu / right Apple cmd\n\t ];\n\n\t var specificMap = [];\n\n\t // mapping of events to input types\n\t var inputMap = {\n\t keydown: 'keyboard',\n\t keyup: 'keyboard',\n\t mousedown: 'mouse',\n\t mousemove: 'mouse',\n\t MSPointerDown: 'pointer',\n\t MSPointerMove: 'pointer',\n\t pointerdown: 'pointer',\n\t pointermove: 'pointer',\n\t touchstart: 'touch',\n\t touchend: 'touch'\n\n\t // boolean: true if the page is being scrolled\n\t };var isScrolling = false;\n\n\t // store current mouse position\n\t var mousePos = {\n\t x: null,\n\t y: null\n\n\t // map of IE 10 pointer events\n\t };var pointerMap = {\n\t 2: 'touch',\n\t 3: 'touch', // treat pen like touch\n\t 4: 'mouse'\n\n\t // check support for passive event listeners\n\t };var supportsPassive = false;\n\n\t try {\n\t var opts = Object.defineProperty({}, 'passive', {\n\t get: function get() {\n\t supportsPassive = true;\n\t }\n\t });\n\n\t window.addEventListener('test', null, opts);\n\t } catch (e) {}\n\t // fail silently\n\n\n\t /*\n\t * set up\n\t */\n\n\t var setUp = function setUp() {\n\t // add correct mouse wheel event mapping to `inputMap`\n\t inputMap[detectWheel()] = 'mouse';\n\n\t addListeners();\n\t };\n\n\t /*\n\t * events\n\t */\n\n\t var addListeners = function addListeners() {\n\t // `pointermove`, `MSPointerMove`, `mousemove` and mouse wheel event binding\n\t // can only demonstrate potential, but not actual, interaction\n\t // and are treated separately\n\t var options = supportsPassive ? { passive: true, capture: true } : true;\n\n\t document.addEventListener('DOMContentLoaded', setPersist, true);\n\n\t // pointer events (mouse, pen, touch)\n\t if (window.PointerEvent) {\n\t window.addEventListener('pointerdown', setInput, true);\n\t window.addEventListener('pointermove', setIntent, true);\n\t } else if (window.MSPointerEvent) {\n\t window.addEventListener('MSPointerDown', setInput, true);\n\t window.addEventListener('MSPointerMove', setIntent, true);\n\t } else {\n\t // mouse events\n\t window.addEventListener('mousedown', setInput, true);\n\t window.addEventListener('mousemove', setIntent, true);\n\n\t // touch events\n\t if ('ontouchstart' in window) {\n\t window.addEventListener('touchstart', setInput, options);\n\t window.addEventListener('touchend', setInput, true);\n\t }\n\t }\n\n\t // mouse wheel\n\t window.addEventListener(detectWheel(), setIntent, options);\n\n\t // keyboard events\n\t window.addEventListener('keydown', setInput, true);\n\t window.addEventListener('keyup', setInput, true);\n\n\t // focus events\n\t window.addEventListener('focusin', setElement, true);\n\t window.addEventListener('focusout', clearElement, true);\n\t };\n\n\t // checks if input persistence should happen and\n\t // get saved state from session storage if true (defaults to `false`)\n\t var setPersist = function setPersist() {\n\t shouldPersist = !(docElem.getAttribute('data-whatpersist') === 'false' || document.body.getAttribute('data-whatpersist') === 'false');\n\n\t if (shouldPersist) {\n\t // check for session variables and use if available\n\t try {\n\t if (window.sessionStorage.getItem('what-input')) {\n\t currentInput = window.sessionStorage.getItem('what-input');\n\t }\n\n\t if (window.sessionStorage.getItem('what-intent')) {\n\t currentIntent = window.sessionStorage.getItem('what-intent');\n\t }\n\t } catch (e) {\n\t // fail silently\n\t }\n\t }\n\n\t // always run these so at least `initial` state is set\n\t doUpdate('input');\n\t doUpdate('intent');\n\t };\n\n\t // checks conditions before updating new input\n\t var setInput = function setInput(event) {\n\t var eventKey = event.which;\n\t var value = inputMap[event.type];\n\n\t if (value === 'pointer') {\n\t value = pointerType(event);\n\t }\n\n\t var ignoreMatch = !specificMap.length && ignoreMap.indexOf(eventKey) === -1;\n\n\t var specificMatch = specificMap.length && specificMap.indexOf(eventKey) !== -1;\n\n\t var shouldUpdate = value === 'keyboard' && eventKey && (ignoreMatch || specificMatch) || value === 'mouse' || value === 'touch';\n\n\t // prevent touch detection from being overridden by event execution order\n\t if (validateTouch(value)) {\n\t shouldUpdate = false;\n\t }\n\n\t if (shouldUpdate && currentInput !== value) {\n\t currentInput = value;\n\n\t persistInput('input', currentInput);\n\t doUpdate('input');\n\t }\n\n\t if (shouldUpdate && currentIntent !== value) {\n\t // preserve intent for keyboard interaction with form fields\n\t var activeElem = document.activeElement;\n\t var notFormInput = activeElem && activeElem.nodeName && (formInputs.indexOf(activeElem.nodeName.toLowerCase()) === -1 || activeElem.nodeName.toLowerCase() === 'button' && !checkClosest(activeElem, 'form'));\n\n\t if (notFormInput) {\n\t currentIntent = value;\n\n\t persistInput('intent', currentIntent);\n\t doUpdate('intent');\n\t }\n\t }\n\t };\n\n\t // updates the doc and `inputTypes` array with new input\n\t var doUpdate = function doUpdate(which) {\n\t docElem.setAttribute('data-what' + which, which === 'input' ? currentInput : currentIntent);\n\n\t fireFunctions(which);\n\t };\n\n\t // updates input intent for `mousemove` and `pointermove`\n\t var setIntent = function setIntent(event) {\n\t var value = inputMap[event.type];\n\n\t if (value === 'pointer') {\n\t value = pointerType(event);\n\t }\n\n\t // test to see if `mousemove` happened relative to the screen to detect scrolling versus mousemove\n\t detectScrolling(event);\n\n\t // only execute if scrolling isn't happening\n\t if ((!isScrolling && !validateTouch(value) || isScrolling && event.type === 'wheel' || event.type === 'mousewheel' || event.type === 'DOMMouseScroll') && currentIntent !== value) {\n\t currentIntent = value;\n\n\t persistInput('intent', currentIntent);\n\t doUpdate('intent');\n\t }\n\t };\n\n\t var setElement = function setElement(event) {\n\t if (!event.target.nodeName) {\n\t // If nodeName is undefined, clear the element\n\t // This can happen if click inside an element.\n\t clearElement();\n\t return;\n\t }\n\n\t currentElement = event.target.nodeName.toLowerCase();\n\t docElem.setAttribute('data-whatelement', currentElement);\n\n\t if (event.target.classList && event.target.classList.length) {\n\t docElem.setAttribute('data-whatclasses', event.target.classList.toString().replace(' ', ','));\n\t }\n\t };\n\n\t var clearElement = function clearElement() {\n\t currentElement = null;\n\n\t docElem.removeAttribute('data-whatelement');\n\t docElem.removeAttribute('data-whatclasses');\n\t };\n\n\t var persistInput = function persistInput(which, value) {\n\t if (shouldPersist) {\n\t try {\n\t window.sessionStorage.setItem('what-' + which, value);\n\t } catch (e) {\n\t // fail silently\n\t }\n\t }\n\t };\n\n\t /*\n\t * utilities\n\t */\n\n\t var pointerType = function pointerType(event) {\n\t if (typeof event.pointerType === 'number') {\n\t return pointerMap[event.pointerType];\n\t } else {\n\t // treat pen like touch\n\t return event.pointerType === 'pen' ? 'touch' : event.pointerType;\n\t }\n\t };\n\n\t // prevent touch detection from being overridden by event execution order\n\t var validateTouch = function validateTouch(value) {\n\t var timestamp = Date.now();\n\n\t var touchIsValid = value === 'mouse' && currentInput === 'touch' && timestamp - currentTimestamp < 200;\n\n\t currentTimestamp = timestamp;\n\n\t return touchIsValid;\n\t };\n\n\t // detect version of mouse wheel event to use\n\t // via https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event\n\t var detectWheel = function detectWheel() {\n\t var wheelType = null;\n\n\t // Modern browsers support \"wheel\"\n\t if ('onwheel' in document.createElement('div')) {\n\t wheelType = 'wheel';\n\t } else {\n\t // Webkit and IE support at least \"mousewheel\"\n\t // or assume that remaining browsers are older Firefox\n\t wheelType = document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';\n\t }\n\n\t return wheelType;\n\t };\n\n\t // runs callback functions\n\t var fireFunctions = function fireFunctions(type) {\n\t for (var i = 0, len = functionList.length; i < len; i++) {\n\t if (functionList[i].type === type) {\n\t functionList[i].fn.call(undefined, type === 'input' ? currentInput : currentIntent);\n\t }\n\t }\n\t };\n\n\t // finds matching element in an object\n\t var objPos = function objPos(match) {\n\t for (var i = 0, len = functionList.length; i < len; i++) {\n\t if (functionList[i].fn === match) {\n\t return i;\n\t }\n\t }\n\t };\n\n\t var detectScrolling = function detectScrolling(event) {\n\t if (mousePos.x !== event.screenX || mousePos.y !== event.screenY) {\n\t isScrolling = false;\n\n\t mousePos.x = event.screenX;\n\t mousePos.y = event.screenY;\n\t } else {\n\t isScrolling = true;\n\t }\n\t };\n\n\t // manual version of `closest()`\n\t var checkClosest = function checkClosest(elem, tag) {\n\t var ElementPrototype = window.Element.prototype;\n\n\t if (!ElementPrototype.matches) {\n\t ElementPrototype.matches = ElementPrototype.msMatchesSelector || ElementPrototype.webkitMatchesSelector;\n\t }\n\n\t if (!ElementPrototype.closest) {\n\t do {\n\t if (elem.matches(tag)) {\n\t return elem;\n\t }\n\n\t elem = elem.parentElement || elem.parentNode;\n\t } while (elem !== null && elem.nodeType === 1);\n\n\t return null;\n\t } else {\n\t return elem.closest(tag);\n\t }\n\t };\n\n\t /*\n\t * init\n\t */\n\n\t // don't start script unless browser cuts the mustard\n\t // (also passes if polyfills are used)\n\t if ('addEventListener' in window && Array.prototype.indexOf) {\n\t setUp();\n\t }\n\n\t /*\n\t * api\n\t */\n\n\t return {\n\t // returns string: the current input type\n\t // opt: 'intent'|'input'\n\t // 'input' (default): returns the same value as the `data-whatinput` attribute\n\t // 'intent': includes `data-whatintent` value if it's different than `data-whatinput`\n\t ask: function ask(opt) {\n\t return opt === 'intent' ? currentIntent : currentInput;\n\t },\n\n\t // returns string: the currently focused element or null\n\t element: function element() {\n\t return currentElement;\n\t },\n\n\t // overwrites ignored keys with provided array\n\t ignoreKeys: function ignoreKeys(arr) {\n\t ignoreMap = arr;\n\t },\n\n\t // overwrites specific char keys to update on\n\t specificKeys: function specificKeys(arr) {\n\t specificMap = arr;\n\t },\n\n\t // attach functions to input and intent \"events\"\n\t // funct: function to fire on change\n\t // eventType: 'input'|'intent'\n\t registerOnChange: function registerOnChange(fn, eventType) {\n\t functionList.push({\n\t fn: fn,\n\t type: eventType || 'input'\n\t });\n\t },\n\n\t unRegisterOnChange: function unRegisterOnChange(fn) {\n\t var position = objPos(fn);\n\n\t if (position || position === 0) {\n\t functionList.splice(position, 1);\n\t }\n\t },\n\n\t clearStorage: function clearStorage() {\n\t window.sessionStorage.clear();\n\t }\n\t };\n\t}();\n\n/***/ })\n/******/ ])\n});\n;", "/**\n * EvEmitter v2.1.1\n * Lil' event emitter\n * MIT License\n */\n\n( function( global, factory ) {\n // universal module definition\n if ( typeof module == 'object' && module.exports ) {\n // CommonJS - Browserify, Webpack\n module.exports = factory();\n } else {\n // Browser globals\n global.EvEmitter = factory();\n }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\nfunction EvEmitter() {}\n\nlet proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n if ( !eventName || !listener ) return this;\n\n // set events hash\n let events = this._events = this._events || {};\n // set listeners array\n let listeners = events[ eventName ] = events[ eventName ] || [];\n // only add once\n if ( !listeners.includes( listener ) ) {\n listeners.push( listener );\n }\n\n return this;\n};\n\nproto.once = function( eventName, listener ) {\n if ( !eventName || !listener ) return this;\n\n // add event\n this.on( eventName, listener );\n // set once flag\n // set onceEvents hash\n let onceEvents = this._onceEvents = this._onceEvents || {};\n // set onceListeners object\n let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n // set flag\n onceListeners[ listener ] = true;\n\n return this;\n};\n\nproto.off = function( eventName, listener ) {\n let listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) return this;\n\n let index = listeners.indexOf( listener );\n if ( index != -1 ) {\n listeners.splice( index, 1 );\n }\n\n return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n let listeners = this._events && this._events[ eventName ];\n if ( !listeners || !listeners.length ) return this;\n\n // copy over to avoid interference if .off() in listener\n listeners = listeners.slice( 0 );\n args = args || [];\n // once stuff\n let onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n for ( let listener of listeners ) {\n let isOnce = onceListeners && onceListeners[ listener ];\n if ( isOnce ) {\n // remove listener\n // remove before trigger to prevent recursion\n this.off( eventName, listener );\n // unset once flag\n delete onceListeners[ listener ];\n }\n // trigger listener\n listener.apply( this, args );\n }\n\n return this;\n};\n\nproto.allOff = function() {\n delete this._events;\n delete this._onceEvents;\n return this;\n};\n\nreturn EvEmitter;\n\n} ) );\n", "/*! loadJS: load a JS file asynchronously. [c]2014 @scottjehl, Filament Group, Inc. (Based on http://goo.gl/REQGQ by Paul Irish). Licensed MIT */\n(function( w ){\n\tvar loadJS = function( src, cb, ordered ){\n\t\t\"use strict\";\n\t\tvar tmp;\n\t\tvar ref = w.document.getElementsByTagName( \"script\" )[ 0 ];\n\t\tvar script = w.document.createElement( \"script\" );\n\n\t\tif (typeof(cb) === 'boolean') {\n\t\t\ttmp = ordered;\n\t\t\tordered = cb;\n\t\t\tcb = tmp;\n\t\t}\n\n\t\tscript.src = src;\n\t\tscript.async = !ordered;\n\t\tref.parentNode.insertBefore( script, ref );\n\n\t\tif (cb && typeof(cb) === \"function\") {\n\t\t\tscript.onload = cb;\n\t\t}\n\t\treturn script;\n\t};\n\t// commonjs\n\tif( typeof module !== \"undefined\" ){\n\t\tmodule.exports = loadJS;\n\t}\n\telse {\n\t\tw.loadJS = loadJS;\n\t}\n}( typeof global !== \"undefined\" ? global : this ));\n", "//------------------------------------------------------------------------\n// Disable scrolling (e.g. when modal window is open)\n//\n// Inspired by https://benfrain.com/preventing-body-scroll-for-modals-in-ios/\n//\n// Note: Once Safari and iOS Safari support the \u201Ctouch-action\u201D CSS property,\n// we can simply toggle a class that adds the following:\n//\n// html,\n// body {\n// overflow: hidden !important;\n// touch-action: none !important;\n// }\n//\n// /* Add class to elements like modal windows that still need to scroll */\n// .allow-scroll { touch-action: auto !important; }\n//\n// https://caniuse.com/#feat=css-touch-action\n//------------------------------------------------------------------------\n\"use strict\";\n\nmodule.exports = {\n // Save current scroll position when scrolling is disabled so we can reset it when enabled\n _scrollPos: 0,\n\n // Track whether or not we have injected CSS the already\n _hasCSS: false,\n\n // Inject \n // https://stackoverflow.com/a/524721/673457\n var styleEl = document.createElement('style');\n styleEl.type = 'text/css';\n styleEl.appendChild(document.createTextNode(css));\n document.head.appendChild(styleEl);\n\n // Update var so we can avoid loading the CSS multiple times\n this._hasCSS = true;\n }\n },\n\n _saveScrollPos: function() {\n this._scrollPos = window.pageYOffset || document.documentElement.scrollTop;\n },\n\n /**\n * Disable scrolling\n */\n freeze: function() {\n // Add required inline CSS (only runs first time)\n this._injectCSS();\n\n this._saveScrollPos();\n\n // Add class to prevent page scrolling (sets fixed position on body)\n document.documentElement.classList.add(\"js-no-scroll\");\n\n // Add inline styles if not already at top of page\n if (this._scrollPos > 0) {\n document.body.style.height = \"calc(100% + \" + this._scrollPos + \"px)\";\n document.body.style.top = -this._scrollPos + \"px\";\n }\n },\n\n /**\n * Enable scrolling\n */\n unfreeze: function() {\n // Remove js-no-scroll class\n document.documentElement.classList.remove(\"js-no-scroll\");\n\n if (this._scrollPos > 0) {\n // Remove inline styles on body, which causes the page to jump to the top.\n document.body.style.height = \"\";\n document.body.style.top = \"\";\n\n // Disable native smooth scrolling before resetting the scroll position.\n // Otherwise, there would be an annoying jump after scrolling is enabled.\n if (document.documentElement.style.hasOwnProperty('scrollBehavior')) {\n document.documentElement.style.scrollBehavior = \"auto\";\n }\n\n // Reset scroll position to what it was before scrolling was disabled.\n window.scrollTo(0, this._scrollPos);\n\n // Re-enable native smooth scrolling\n if (document.documentElement.style.hasOwnProperty('scrollBehavior')) {\n document.documentElement.style.scrollBehavior = \"\";\n }\n }\n }\n};\n", "// Detect input method in order to hide outlines in an accessible manner\n// https://github.com/ten1seven/what-input\nimport \"what-input\";\n\nconsole.log(\"Loading a11y-menu.js\");\n\n// Modules that do depend on the CSSOM\nimport \"../modules/a11y-menu\";\nimport \"../modules/recite-me-toggle\";\nimport \"../modules/form-validation\";\nimport \"../modules/story-template\";\nimport \"../modules/gallery-modal\";\nimport \"../modules/share-your-vision-story-upload-form\";\nimport \"../modules/share-your-vision-donation-url-generator\";\nimport CtaHero from \"../modules/cta-hero\";\n\nnew CtaHero('[data-controller=\"cta-hero\"]');\n\nimport ImageGenerator from \"../modules/image-generator\";\n\nnew ImageGenerator();\n\n// Navigation\nimport ExpandToggle from \"@threespot/expand-toggle\";\n\nconst burgerEl = document.querySelector('[data-expands=\"nav\"]');\n\nif (burgerEl) {\n let burgerToggle = new ExpandToggle(burgerEl);\n\n document.documentElement.addEventListener(\"nav-expanded\", () => {\n burgerToggle.updateExpandedHeight();\n });\n}\n\nconst navItems = document.querySelectorAll('[data-expands=\"nav-submenu\"]');\n\nnavItems.forEach((item) => {\n let toggle = new ExpandToggle(item);\n let event = new Event(\"nav-expanded\", { bubbles: true });\n\n toggle.on(\"expand\", () => {\n item.dispatchEvent(event);\n console.log(\"expanded\");\n });\n});\n", "/**\n * Wrap the last X words in an HTML tag to prevent them from wrapping (i.e. orphans)\n * @param {HTMLElement} el - Toggle button DOM node\n * @param {Object} opts - Options\n * @param {string} [opts.expandedClasses=\"\"] - Class(es) to apply when expanded\n * @param {string} [opts.activeToggleText=\"\"] - Expanded state toggle button text\n * @param {boolean} [opts.shouldStartExpanded=false] - Whether menu should start expanded\n * @param {function} [opts.onReady=\"\"] - Ready callback function\n */\n'use client';\n\nimport EventEmitter from \"ev-emitter\";\n\nexport default class ExpandToggle extends EventEmitter {\n constructor(el, opts) {\n // Have to call super() first before referencing \u201Cthis\u201D since we\u2019re extending EventEmitter\n // https://stackoverflow.com/a/43591507/673457\n super();\n\n this.el = el;\n this.targetId = this.el.getAttribute(\"data-expands\");\n this.targetEl = document.getElementById(this.targetId);\n this.targetParentEl = this.targetEl.parentNode;\n\n // Ensure target element exist before initializing\n if (!this.targetEl) {\n console.warn(`Can\u2019t find expandable target with id \u201C${this.targetId}\u201D`);\n return;\n }\n\n // Use Object.assign() to merge \u201Copts\u201D object with default values in this.options\n this.options = Object.assign(\n {},\n {\n expandedClasses: \"\", // string, accepts multiple space-separated classes\n activeToggleText: \"\", // expanded state toggle button text\n shouldStartExpanded: false, // component starts expanded on init\n onReady: null // ready callback function\n },\n opts\n );\n\n // Check for custom expanded class(es)\n this.expandedClasses = this.el.getAttribute(\"data-expands-class\") || this.options.expandedClasses;\n\n if (this.expandedClasses.length) {\n // Check if active class string contains multiple classes\n if (this.expandedClasses.indexOf(\" \") > -1) {\n // Convert to array and remove any empty string values\n // caused by having multiple spaces in a row.\n this.expandedClasses = this.expandedClasses\n .split(\" \")\n .filter(n => n.length);\n } else {\n // We still need to convert a single active class to an array\n // so we can use the spread syntax later in classList.add()\n this.expandedClasses = [this.expandedClasses];\n }\n }\n\n // Check if component should start expanded\n this.shouldStartExpanded =\n this.el.hasAttribute(\"data-expanded\") || this.options.shouldStartExpanded;\n\n // Check for custom toggle button text to use when expanded\n this.hasActiveText = false;\n this.textEl = this.el.querySelector(\"[data-expands-text]\");\n\n if (this.textEl) {\n this.defaultToggleText = this.textEl.textContent;\n this.activeToggleText =\n this.textEl.getAttribute(\"data-expands-text\") ||\n this.options.activeToggleText;\n this.hasActiveText = !!this.activeToggleText.length;\n }\n\n this.init();\n }\n\n init() {\n // Store state to avoid calling resize handler after component has been destroyed\n this.hasInitialized = true;\n\n // Accessibility setup\n this.el.setAttribute(\"aria-haspopup\", true);\n this.el.setAttribute(\"aria-expanded\", this.shouldStartExpanded);\n\n // Omit \u201Caria-controls\u201D for now\n // See https://inclusive-components.design/menus-menu-buttons/#ariacontrols\n // this.el.setAttribute(\"aria-controls\", this.targetId);\n this.targetEl.setAttribute(\"aria-hidden\", !this.shouldStartExpanded);\n\n if (this.el.tagName.toLowerCase() === \"a\") {\n this.el.setAttribute(\"role\", \"button\");\n }\n\n // Click event listener on toggle button\n // Note: Callback needs to be assigned to a let so we can remove it since we\u2019re using bind()\n // https://stackoverflow.com/a/22870717/673457\n this.clickHandler = this.toggle.bind(this);\n this.el.addEventListener(\"click\", this.clickHandler);\n\n // Keyboard listeners on toggle button\n this.keydownHandler = this.keyboardEvents.bind(this);\n this.el.addEventListener(\"keydown\", this.keydownHandler);\n\n // Check for onReady callback\n if (typeof this.options.onReady === \"function\") {\n this.options.onReady();\n }\n }\n\n destroy() {\n this.hasInitialized = false;\n\n // Remove event listeners\n this.el.removeEventListener(\"click\", this.clickHandler);\n this.el.removeEventListener(\"keydown\", this.keydownHandler);\n\n // Remove aria attributes\n this.el.removeAttribute(\"aria-haspopup\");\n this.el.removeAttribute(\"aria-expanded\");\n this.targetEl.removeAttribute(\"aria-hidden\");\n\n if (this.el.tagName.toLowerCase() === \"a\") {\n this.el.removeAttribute(\"role\");\n }\n\n // Reset toggle text\n if (this.hasActiveText) {\n this.textEl.textContent = this.defaultToggleText;\n }\n\n // Remove custom classes\n if (this.expandedClasses.length) {\n this.el.classList.remove(...this.expandedClasses);\n this.targetEl.classList.remove(...this.expandedClasses);\n }\n\n this.emitEvent(\"destroy\");\n }\n\n keyboardEvents(event) {\n // Expand with down arrow\n if (event.keyCode == 40) {\n this.expand();\n } else if (event.keyCode == 38 || event.keyCode == 27) {\n // Close with up arrow or escape key\n this.collapse();\n }\n }\n\n expand(event) {\n // Update toggle text\n if (this.hasActiveText) {\n this.textEl.textContent = this.activeToggleText;\n }\n\n // Add classes\n if (this.expandedClasses.length) {\n this.el.classList.add(...this.expandedClasses);\n this.targetEl.classList.add(...this.expandedClasses);\n }\n\n // Update aria attributes\n this.el.setAttribute(\"aria-expanded\", true);\n this.targetEl.setAttribute(\"aria-hidden\", false);\n\n // Emit event and include original event as an argument\n this.emitEvent(\"expand\", event);\n }\n\n collapse(event) {\n // Update toggle text\n if (this.hasActiveText) {\n this.textEl.textContent = this.defaultToggleText;\n }\n\n // Remove classes\n if (this.expandedClasses.length) {\n this.el.classList.remove(...this.expandedClasses);\n this.targetEl.classList.remove(...this.expandedClasses);\n }\n\n // Update aria attributes\n this.el.setAttribute(\"aria-expanded\", false);\n this.targetEl.setAttribute(\"aria-hidden\", true);\n\n // Emit event and include original event as an argument\n this.emitEvent(\"collapse\", event);\n }\n\n toggle(event) {\n // Prevent default in case toggle element is a link instead of a button\n event.preventDefault();\n\n if (this.el.getAttribute(\"aria-expanded\") === \"true\") {\n this.collapse(event);\n } else {\n this.expand(event);\n }\n }\n}\n", "//------------------------------------------------------------------------\n// Accessiblity menu functionality (font size and color theme chooser)\n//\n// NOTE: Saved theme preference is applied on load in critical.js to prevent a FOUC\n//------------------------------------------------------------------------\n\"use strict\";\n\nimport ExpandToggle from '@threespot/expand-toggle';\n\nclass A11yMenu {\n constructor(el) {\n var self = this;\n this.htmlEl = document.documentElement;\n this.el = el;\n this.textSizeEl = document.getElementById(\"text-size\");\n this.themeInputs = this.el.querySelectorAll(\".A11yMenu-theme input\");\n\n // Init toggle\n this.expandToggle = new ExpandToggle(\n document.querySelector(\".A11yMenu-toggle\")\n );\n\n // Update form fields on load to reflect currently selected theme and font size\n this.updateForm();\n\n // Expand the menu on load if the user has never collapsed it before\n if (typeof localStorage !== \"undefined\" && !localStorage.a11yMenu) {\n this.expandToggle.expand()\n }\n\n // Set cookie once menu is collapsed\n this.expandToggle.on(\"collapse\", () => {\n if (typeof localStorage !== \"undefined\" && !localStorage.a11yMenu) {\n localStorage.a11yMenu = true;\n }\n });\n\n // Listen for any changes within the form\n this.el.addEventListener(\"change\", function(evt) {\n var val = evt.target.value;\n\n // If the value of the element that changed is not a number, assume it\u2019s a theme class\n if (isNaN(parseInt(val, 10))) {\n self.updateTheme(val);\n } else {\n self.updateTextSize(val);\n }\n });\n\n // Close when click off of it\n window.addEventListener(\"click\", evt => {\n if (!evt.target.closest(\".A11yMenu\")) {\n this.expandToggle.collapse();\n }\n });\n }\n\n updateTextSize(size) {\n // Apply inline font-size to html element\n this.htmlEl.style.fontSize = size + \"%\";\n\n // Save value to localStorage\n if (typeof localStorage !== \"undefined\") {\n localStorage.textSize = size;\n }\n\n // Trigger window resize event to force all expandable components to recalc their height\n window.dispatchEvent(new Event('resize'));\n }\n\n updateTheme(themeColor) {\n // Find any class names starting with \u201Ct-\u201D and remove them\n var htmlClasses = this.htmlEl.className.replace(/\\b(\\s*?t-.+?)\\b/g, \"\");\n\n // Add new theme class\n this.htmlEl.className = htmlClasses + \" t-\" + themeColor;\n\n // Save to localStorage\n if (typeof localStorage !== \"undefined\") {\n localStorage.theme = themeColor;\n }\n }\n\n // Get current theme and font size values from localStorage and update form fields\n updateForm() {\n if (typeof localStorage !== \"undefined\") {\n if (localStorage.theme) {\n // Select the current theme radio button\n for (var i = 0, len = this.themeInputs.length; i < len; i++) {\n var input = this.themeInputs[i];\n\n if (input.value == localStorage.theme) {\n input.checked = true;\n }\n }\n }\n\n if (localStorage.textSize) {\n // Add \u201Cselected\u201D attribute to current font size\n this.textSizeEl.querySelector(\n '[value=\"' + localStorage.textSize + '\"]'\n ).selected = true;\n }\n }\n }\n}\n\n// Init\nvar a11Menu = new A11yMenu(document.querySelector(\".A11yMenu-form\"));\n", "//------------------------------------------------------------------------\n// Load the Recite Me toolbar when users click the toggle button\n// https://github.com/Threespot/blindness/issues/454\n// https://portal.reciteme.com/portal/product/installation/client/e5f6079d59bf23c13a8f868da5d273971977d547/p/1\n//------------------------------------------------------------------------\nimport loadJS from 'fg-loadjs';\n\nclass ReciteMeToggle {\n constructor(el) {\n // Check if Recite Me has previously been enabled,\n // and if so, load it immediately.\n if (sessionStorage.reciteme && sessionStorage.reciteme == 'true') {\n this.loadScript();\n }\n\n // Load Recite Me on toggle click\n el.addEventListener('click', evt => {\n // Check if it\u2019s already been loaded first\n if (typeof Recite == 'undefined') {\n this.loadScript();\n }\n });\n }\n\n loadScript() {\n loadJS('https://api.reciteme.com/asset/js?key=e5f6079d59bf23c13a8f868da5d273971977d547', () => {\n Recite.load({\n Tracker: {\n Ga: { enabled: true }\n }\n });\n\n Recite.Event.subscribe(\"Recite:load\", () => {\n // console.log('Recite:load');\n Recite.enable();\n sessionStorage.reciteme = true;\n });\n\n Recite.Event.subscribe(\"Recite:disable\", () => {\n // console.log('Recite:disable');\n sessionStorage.reciteme = false;\n });\n\n // These events can be used to check the current theme styles\n // to update the logo and icon colors.\n\n // Recite.Event.subscribe('Preferences:load', function() {\n // console.log('Preferences:load', Recite.Preferences.get());\n // });\n\n // Recite.Event.subscribe('Preferences:set', function() {\n // console.log('Preferences:set', Recite.Preferences.get());\n // });\n\n // Recite.Event.subscribe('Preferences:reset', function() {\n // console.log('Preferences:reset', Recite.Preferences.get());\n // });\n\n // Example output from Recite.Preferences.get('style')\n //\n // dictionary: {enabled: false}\n // language: null\n // magnifier: {enabled: false}\n // player: {autoplay: true, continuePlay: false, playbackSpeed: 1}\n // playerControls: {enabled: true}\n // style: {\n // backgroundColor: null\n // charSpacing: null\n // font: {color: null, face: null, size: null}\n // lineHeight: null\n // link: {color: null}\n // marginSize: null\n // ruler: {enabled: false, color: null}\n // screenMask: {enabled: false, color: null}\n // textAlign: null\n // wwHighlight: {color: null}\n // }\n // textMode: {enabled: false}\n // voice: {gender: \"f\"}\n // voices: {en: \"Amy\"}\n });\n }\n}\n\n// Init\ndocument.querySelectorAll('.A11yMenu-tools-toggle').forEach(el => {\n new ReciteMeToggle(el);\n});\n", "//------------------------------------------------------------------------\n// Basic form validation\n//\n// Usage Info:\n// \u2022 Add \u201Cjs-validate\u201D to
or other wrapper\n// \u2022 Add appropriate data-validate value to each input\n// - data-validate=\"email\"\n// - data-validate=\"phone\"\n// - data-validate=\"number\"\n// - data-validate=\"zip\"\n// - data-validate=\"notempty\"\n// \u2022 Add error message markup inside of