{"version":3,"sources":["utils/globals.js","utils/events/onReady.js","utils/typeCheckers.js","utils/forEach.js","utils/filter.js","utils/events/onWindowResize.js","utils/events/triggerCustomEvent.js","utils/dom/elementProperties.js","utils/splitter.js","utils/dom/classList.js","utils/dom/scrollLock.js","utils/dom/setStyles.js","utils/dom/siblings.js","utils/dom/elementManipulation.js","utils/dom/createElement.js","utils/dom/cssProps.js","utils/events/onScroll.js","utils/events/events.js","utils/network/loadImage.js","utils/dom/lazyLoad.js","utils/events/onClickOutside.js","utils/dom/scrollTo.js","utils/dom/debounce.js","utils/dom/throttle.js","utils/helpers/typeCheckers.js","utils/helpers/splitter.js","utils/helpers/forEach.js","utils/bootstrapper.js","main.js","components/modal/modal.js","components/external-link/external-link.js","components/navigation/navigation.js","components/accordion/accordion.js","components/references/references.js","components/ribbon-image/ribbon-image.js","components/hero/hero.js","components/video/video.js","components/overlay/overlay.js","components/scroll-top/scroll-top.js","components/in-page-navigation/in-page-navigation.js","utils/events/bindScrollToElement.js","components/gated-content/gated-content.js","components/multi-column-carousel/multi-column-carousel.js","components/multi-column-carousel/multi-column-carousel-video.js","components/information-modal/information-modal.js","components/static-iframe/static-iframe.js","components/rcc-calculator/rcc-calculator.js","components/threeq/3q.js","utils/events/scrollDirection.js"],"names":["eisai","threeQVideoServiceId","threeQBaseURL","threeQPath","threeQAPIKey","triggerList","window","whitelistUrls","functionReferences","readyState","document","isReadyEventBound","runAutomatically","emptyCallbackArrays","length","tempArray","slice","funcArray","sort","a","b","priority","forEach","funcRef","func","bindReadyEvent","addEventListener","attachEvent","onReady","functionReference","push","isElement","element","Element","Document","Window","isArray","collection","constructor","Array","iterator","allowNullValues","NodeList","HTMLCollection","i","item","name","index","Node","Object","keys","key","hasOwnProperty","filter","predicateFunction","filteredObject","value","Boolean","values","functionQueue","currentWindowWidth","currentWindowHeight","breakpointIndex","unknown","screenSizes","sizeCounter","siteSettings","screensizes","size","sizeName","Number","replace","currentBreakpoint","currentBreakpointName","getWindowSizes","innerWidth","innerHeight","lastFoundWidth","targetScreenWidth","associatedBreakpointName","performCalculationCallback","throttledCalculationCallback","throttle","onWindowResize","callback","triggerCustomEvent","target","eventName","eventData","event","CustomEvent","detail","bubbles","cancelable","createEvent","initCustomEvent","dispatchEvent","documentMode","params","useParams","undefined","customEvent","prototype","Event","isElementInViewport","expandMargin","rect","getBoundingClientRect","expandMarginX","isNaN","x","expandMarginY","y","spanY","top","Math","max","height","spanX","left","width","min","getElementPosition","relativeTo","useElement","getElementById","Error","useRelativeTo","pageYOffset","documentElement","scrollTop","pageXOffset","scrollLeft","relativeToRect","getElementScroll","scrollX","scrollY","setAttribute","elementCollection","attributeName","attributeValue","setAttributes","attribute","isElementTag","elements","tagNames","acceptedTagNames","elementTagNames","from","map","tis","tagName","toLowerCase","reduce","tagNameMatch","indexOf","splitter","input","inputArray","trim","split","inputEntry","addClass","classNames","className","classList","add","hasClass","contains","RegExp","test","removeClass","remove","join","isScrollLocked","enableScrollLock","scrollPosition","scrollTo","htmlTag","style","marginTop","position","overflow","body","disableScrollLock","knownDOMObjects","Map","setStyles","styles","currentElement","isHardReset","setStylesTo","originalInlineStyles","get","cssText","resetStyles","overwriteExisting","set","getAttribute","saveStylesAsDefault","match","toUpperCase","getSiblings","includeOriginalElement","fromElement","untilElement","siblings","nextElement","parentNode","firstElementChild","sameAsOriginalElement","nextElementSibling","children","appendElement","container","fragment","createDocumentFragment","appendChild","createTextNode","wrapElement","existingElement","newWrapper","insertBefore","createElement","options","newElement","optionValue","optionKey","text","innerHTML","innerText","getNavHeight","setProperty","querySelector","clientHeight","getInPageNavigationScrollHeight","inPageNavigation","inPageNavigationInnerClone","cloneNode","div","parentElement","getInPageNavigationHeight","getInPageNavigationOffset","inPageNavigationInner","wrapper","wrapperStyle","getComputedStyle","wrapperMargin","parseInt","marginBottom","inPageNavigationStyle","inPageNavigationPadding","paddingBottom","createSubscriberForDOMElement","throttleValueMs","existingData","baseObservable","Observable","fromEvent","throttlers","subscribers","callbacks","throttleTime","animationFrame","trailing","subscribe","onScroll","elementList","callbackList","baseData","handleEvent","this","elementHandlers","eventType","type","eventHandler","once","removeEvent","eventTypes","eventHandlerToRemove","callbackObject","removeEventListener","addEvent","useCapture","runOnce","addEventOnce","decodeImage","newImage","decode","then","Promise","resolve","loadImage","source","useSrcset","sizes","Image","reject","image","defaultSettings","base","initialized","loading","loaded","error","loadManually","loadImmediately","reloadOnResize","globalSettings","bufferMarginPx","onScrollThrottleMs","isEventListenerSet","scroll","resize","elementsLoaded","elementsNotLoaded","elementsHandledManually","slowConnectionEffectiveTypes","allSourceAttributes","accumulated","concat","LAZY_EVENTS","TRIGGER","LOADING","LOADED","ERROR","LAZY_EVENT_TARGET","notifiers","data","triggerNotifiers","action","callbackName","charAt","elementNeedsWrapper","controls","detectElementsInViewport","outer","setSource","getSourcesFromAttribute","callbackListToRemove","remainingCallbacks","unsubscribe","throttleIdx","subscription","delete","removeScrollCallback","useSourceChildren","sources","isSrcsetSyntax","breakpointCount","sourceElements","hasAttribute","sourceChildren","sourceElement","sourceData","newSource","closestBreakpoint","closestBreakpointName","currentConnectionType","navigator","connection","effectiveType","minimumConnectionTypeIndex","foundAttributeValue","JSON","parse","encodeURI","trimmedItem","colonIndex","substring","sourcesKeys","thisBreakpoint","setPlaceholder","hasLoaded","control","isImgWithoutSrc","src","elementWithPlaceholderData","parseFloat","getPlaceholder","updateSourceAttribute","setLoadEventListeners","isPlaceholder","useCanPlay","loadEvent","setClassName","loaderFunction","elementClone","elementCloneImg","sourceTag","querySelectorAll","load","isImage","isBackgroundImage","backgroundUrl","backgroundImage","srcset","catch","has","sanitizeCallbacks","resetElementsWithResponsiveSources","handleResponsive","state","classes","eventsMap","onClickOutside","clickElement","onlyOnce","thisElementHandlers","e","handleElement","splice","setTimeout","doScroll","isElementWindow","durationMs","targetElement","offsetPx","isInterruptible","useDurationMs","useTargetElement","useTarget","elementIsWindow","scrollCount","oldTimestamp","Date","now","detectedScrollPosition","scrollPos","elementPosition","cosParameters","scrollDone","interruptScrollFlag","interruptScroll","requestAnimationFrame","step","moveStep","newTimestamp","timeDifferenceMs","PI","round","cos","debounce","timeout","context","args","arguments","cancelAnimationFrame","apply","fn","fnTimer","timeDelay","destroyEventName","bootstrappedInstances","counts","spawnInstance","moduleName","domObject","ConstructorReference","initializedTargetClass","console","warn","instance","killEventHandler","handlerFunction","stopPropagation","destroy","doNotPropagateDown","createInstanceKillerCallback","spawnInstancesFromObject","objectData","treatConstructorsAsAsyncLoaders","domElements","constructorType","ResolvedConstructor","modules","modal","domReference","modalId","dom","backdrop","modalActive","newsletterSignup","newsletterSignupInput","preventKeyEventsClass","hiddenClass","navigationWrapper","navigationWrapperOpen","init","openModal","preventDefault","emailInput","focus","closeModal","isMobile","lg","isNavOpen","handleKeyEvent","handleClickOpenEvent","trigger","activeElement","click","handleClickOutsideEvent","hrefs","close","currentTarget","dataset","modalTrigger","externalLinkSetter","modalSiteSwitch","modalCloseButton","modalTargetLink","modalCancelButton","modalBackdrop","gatedContent","gatedContentButton","overlayTrigger","navigationLink","currentHost","linkElement","host","location","externalLink","includes","siteSwitchLink","hostname","attachAllLinkProperties","href","url","startsWith","removeAttribute","onAttachExternalLinkClickEvent","resetLinkProperties","onAttachSiteSwitchLinkClickEvent","attachExternalSiteSwitchEvent","link","open","reload","targetLinkExternal","targetLinkSiteSwitch","bindEvents","bind","siteSwitchLinkSetter","siteSwitchExternalLink","cancelTrigger","navigation","hash","pathname","navHeight","navigationListWrapper","navigationListWrapperOpen","navigationList","navigationBackTop","navigationListOpen","navigationButton","navigationMenu","navigationClose","navigationBack","navigationPanel","navigationPanelOpen","subNavigationList","subNavigationWrapper","subNavigationTrigger","subNavigationBack","subNavigationOpen","subNavigationActive","mobileNavigationTrigger","samePageNavigationLink","togglePanel","resetSubNavigation","expanded","navigations","currentNavigation","id","handleAnimation","nav","resetMainNavigation","closest","tempThisElementHandlers","handler","removeOnClickOutside","toggleMobileNavigation","elem","buttons","button","attachScrollEvent","navigationCloseActive","handleSamePageNavitation","page","currentPage","handleExternalLinkEvent","self","mainNavigationTrigger","mainNavigationList","samePageNavigationLinks","prepareNav","samePageLink","section","newLoc","history","replaceState","navBar","navElems","onclick","level","call","dataLevel","subNavigationItems","subItem","leftPos","startNav","accordion","openClass","onAccordionClickEvent","accordionTrigger","references","openWrapperClass","openListClass","onReferencesClickEvent","parent","referencesTrigger","hero","videoPlayer","cookieConsent","consent","UC_UI","isInitialized","getServicesBaseInfo","find","status","onHeroVideoLoadEvent","videoElem","js3q","videoId","js3qVideoPlayer","dataid","autoplay","allowmutedautoplay","loop","muted","handleConsentEvent","consentType","hasConsent","some","service","video","observer","isAutoplayEnabled","configLoader","MainStage","config","IntersectionObserver","entries","entry","isIntersecting","play","pause","observe","on","dataLayer","category","metadata","Title","timeValue","setInterval","originalProcessedConfig","vlength","findImagePoster","param","newSrc","clearInterval","onCookieConsentEvent","cookieStatus","consentWrapper","disconnect","overlay","overlayId","objJs3qVideoPlayer","overlayActive","overlayClose","audioTrigger","overlayVideo","overlayAudio","overlayPdf","overlayImage","openOverlay","closeOverlay","onPdfLoadEvent","pdfId","AdobeDC","dataId","View","clientId","divId","previewFile","content","metaData","fileName","onImageLoadEvent","imgSrc","resetPdfOverlay","resetImageOverlay","mediaTracking","media","onVideoLoadEvent","destroyVideo","layout","onAudioLoadEvent","audioId","destroyAudio","audioElem","handleOverlayReset","isVideo","isAudio","videoWrapper","audioWrapper","pdfClose","imgClose","imageTriggerId","isPDF","pdfTriggerId","videoTriggerId","audioTriggerId","onScrollTopClickEvent","interval","transition","activeClass","onInPageNavigationLoad","template","insertAdjacentHTML","onInPageNavigationScroll","links","sectionTop","offsetTop","onInPageNavigationClick","scrollIntoView","lastPos","checkPos","newPos","elem1","elem2","buffer","onscroll","elem1Height","scrollHeight","elem1Offset","elem2Offset","scrollWidth","offsetWidth","bindScrollToElement","attachGatedContentProperties","carousel","currentItem","lastWidth","carouselItemWrapper","carouselLeftButton","carouselRightButton","carouselItem","carouselCircleWrapper","setColumns","carouselEnable","carouselColumns","childElementCount","ariaHidden","setActiveAttributes","carouselCircles","items","resetCarousel","transform","setSelected","previousItem","slideWidth","clientWidth","nextItem","generateCarouselCircle","circle","scrolllength","offsetLeft","nthchild","videoPlayers","consentWrappers","videoElements","videoElement","onCarouselVideoLoadEvent","img","cookieConsentHeight","loader","informationModal","InformationModalActive","InformationModalClose","setCookie","date","setTime","getTime","expires","toUTCString","cookie","getCookie","showInformationModal","hideInformationModal","areAllConsentsAccepted","cookieName","iframe","usercentricsId","initCharts","initialDataId","json","chartData","barChart","Chart","getChartOptions","leftGraphJson","barchart","updateTableContent","updateContainers","doughnutChart","rightGraphJson","circlediagram","getDoughnutChartOptions","plugins","getDoughnutLabel","datasets","backgroundColor","doughnutChart2","setupDropdown","maintainAspectRatio","responsive","legend","labels","usePointStyle","color","scales","grid","display","ticks","stepSize","textStrokeColor","title","stacked","cutout","generateLabels","chart","originalLabels","overrides","doughnut","font","weight","dotColor","beforeDatasetsDraw","ctx","save","getDatasetMeta","beginPath","arc","fillStyle","fill","closePath","textAlign","textBaseline","fillText","restore","mobileTable","desktopTable","tableFooter","tableDescriptionText","leftContainer","rightContainer","updateContainerData","leftGraphBottomDescription","leftGraphTitle","leftGraphDescription","rightGraphBottomDescription","rightGraphTitle","rightGraphDescription","captionText","titleText","descriptionText","caption","description","dropdown","disclaimer","disclaimerText","barData","doughnutData","doughnutData2","update","threeq","onThreeQLoadEvent","baseURL","path","apiKey","region","fetch","method","headers","res","Projects","Label","stringify","bootstrapper","last_known_scroll_position","ticking","inPageNavigationOffsetTop","elementsToLoad","settings","onLoading","onLoaded","onError","setResizeEventListener","elementToLoad","defaultElement","visibility","margin","border","padding","elementData","isResponsive","lazyLoad","attachScrollLoadEvent","lazyLoadBackgroundImage","offsetHeight","previousScrollPos","previous_known_scroll_position"],"mappings":"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","file":"static/js/main.modern.71505db2.chunk.js","sourcesContent":["const eisai = {\r\n threeQVideoServiceId: \"qxiCD5aN_\",\r\n threeQBaseURL: \"https://sdn.3qsdn.com\",\r\n threeQPath: \"/api/v2\",\r\n threeQAPIKey: \"XXXXXX\",\r\n triggerList: window.triggerList || [],\r\n whitelistUrls: window.whitelistUrls || []\r\n};\r\n\r\nwindow.eisai = eisai;\r\n","/**\r\n * Handler to trigger callbacks once the browser is ready for them.\r\n *\r\n * The onReady() function is one of the cornerstones of Frontline. You basically feed it a function, or a lot\r\n * of functions, and they will be executed automatically once the browser's readystate changes to something\r\n * close to \"ready\". You can add a priority to move your scripts up in the queue, but the default should suit\r\n * most use cases perfectly.\r\n *\r\n * You can keep adding references using onReady() even after the page is loaded. In that case they will be\r\n * run at once.\r\n *\r\n *\r\n * @module utils/events/onReady\r\n * @author Anders Gissel \r\n *\r\n * @example\r\n * import { onReady } from \"./utils/events/onReady\";\r\n *\r\n * onReady(yourFunctionHere);\r\n *\r\n *\r\n * @example To set a task to high priority:\r\n * onReady(yourFunctionHere, 50);\r\n *\r\n *\r\n * @example To disable automatic execution so you can trigger the ready-state yourself, do this:\r\n * import { documentIsReady, setRunAutomatically, onReady } from \"./utils/events/onReady\";\r\n *\r\n * setRunAutomatically(false); // This must happen BEFORE the first use of onReady()!\r\n * onReady(yourCallbackHere);\r\n * window.setTimeout(documentIsReady, 5000);\r\n *\r\n */\r\n\r\nlet functionReferences = [];\r\n\r\n// Set the initial readyState based on the browser's current state. If the script has been loaded\r\n// asynchronously, the DOM might be ready for us already, in which case there's no reason to delay\r\n// any further processing. The following will evaluate as true if the DOM is ready, or the page is\r\n// complete.\r\nlet readyState =\r\n document.readyState === \"interactive\" || document.readyState === \"complete\";\r\n\r\n// Defines whether or not the window.onReady event has been bound, so we won't do it twice. That\r\n// would just be stupid.\r\nlet isReadyEventBound = false;\r\n\r\n/**\r\n * Whether or not the callbacks are run automatically\r\n *\r\n * @type {boolean}\r\n */\r\nexport let runAutomatically = true;\r\n\r\n/**\r\n * Sort and run the given array of callback functions.\r\n *\r\n * @private\r\n * @param {Array} funcArray\r\n */\r\nfunction runFunctionArray(funcArray) {\r\n funcArray.sort((a, b) => a.priority - b.priority);\r\n\r\n funcArray.forEach(funcRef => funcRef.func());\r\n}\r\n\r\n/**\r\n * Empty the callback arrays\r\n *\r\n * @private\r\n */\r\nfunction emptyCallbackArrays() {\r\n // Keep iterating through the function references until there are none left.\r\n while (functionReferences.length) {\r\n // Set up a temporary array that mirrors the list of callbacks, and empty the real one.\r\n const tempArray = functionReferences.slice(0);\r\n functionReferences = [];\r\n\r\n // Run the callbacks. The callbacks themselves may set up more callbacks, which\r\n // is why we keep looping the array until we're done.\r\n runFunctionArray(tempArray);\r\n }\r\n\r\n // At this point we'll assume we're ready for anything!\r\n readyState = true;\r\n}\r\n\r\n/**\r\n * Make sure the \"ready\"-event is set.\r\n *\r\n * @private\r\n */\r\nfunction bindReadyEvent() {\r\n if (!isReadyEventBound) {\r\n // Set up our own document-ready-function to run when the DOM is ready, or whatever.\r\n if (window.addEventListener) {\r\n window.addEventListener(\"load\", emptyCallbackArrays, false);\r\n } else {\r\n window.attachEvent(\"onload\", emptyCallbackArrays);\r\n }\r\n\r\n isReadyEventBound = true;\r\n }\r\n}\r\n\r\n/**\r\n * External function to mark the code as being ready. Must be used if runAutomatically is set to false.\r\n */\r\nexport function documentIsReady() {\r\n // Continue at once if the DOM is ready; otherwise wait for the browser to catch up by\r\n // attaching an event listener.\r\n if (readyState) {\r\n emptyCallbackArrays();\r\n } else {\r\n bindReadyEvent();\r\n }\r\n}\r\n\r\n/**\r\n * Set whether or not the tasks should be run automatically when the page is ready or not.\r\n *\r\n * @param {boolean} state - Whether or not to run the tasks automatically.\r\n */\r\nexport function setRunAutomatically(state = true) {\r\n runAutomatically = state;\r\n}\r\n\r\n/**\r\n * Register a function to run when the page is ready.\r\n *\r\n * @param {Function} functionReference - The function you want to run.\r\n * @param {Number} [priority=100] - Priority of your callback. Default should be 100, anything under 25 is very-high priority and should be avoided unless you know what you're doing!\r\n */\r\nexport function onReady(functionReference, priority = 100) {\r\n if (typeof functionReference === \"function\") {\r\n if (readyState && runAutomatically) {\r\n functionReference();\r\n } else {\r\n if (runAutomatically) {\r\n bindReadyEvent();\r\n }\r\n\r\n functionReferences.push({\r\n func: functionReference,\r\n priority\r\n });\r\n }\r\n }\r\n}\r\n","/**\r\n * A bunch of utilities to check whether or not a symbol fits certain criteria.\r\n *\r\n * @module utils/typeCheckers\r\n * @author Anders Gissel \r\n */\r\n\r\n/**\r\n * Find out whether or not the given argument is an element that would react somewhat normally to DOM-manipulations.\r\n *\r\n * @since 3.7.0\r\n * @param {*} element - The element to check.\r\n * @returns {boolean} `true` if the given argument is an element (or document, or window), and `false` otherwise.\r\n */\r\nexport function isElement(element) {\r\n return (\r\n element instanceof Element ||\r\n element instanceof Document ||\r\n element instanceof Window\r\n );\r\n}\r\n\r\n/**\r\n * Find out whether or not the given collection (or whatever) is an array.\r\n *\r\n * @since 3.7.0\r\n * @param {*} collection - The collection to check.\r\n * @returns {boolean} `true` if the given collection is an array, `false` otherwise.\r\n */\r\nexport function isArray(collection) {\r\n return collection && collection.constructor === Array;\r\n}\r\n","/**\r\n * **Iterate over just about any iterable object type** - primarily for node lists, arrays and objects, but will also\r\n * yield results for single elements such as elements (nodes), strings or numbers.\r\n *\r\n * @module utils/forEach\r\n * @author Anders Gissel \r\n *\r\n * @example Iterating through an array:\r\n * import { forEach } from \"./utils/forEach\";\r\n * forEach([value1, value2, value3], (value, index) => {\r\n * // Loop through the values in the array\r\n * });\r\n *\r\n *\r\n * @example Iterating through an object:\r\n * import { forEach } from \"./utils/forEach\";\r\n * forEach({\"key1\": value1, \"key2\": value2}, (value, key) => {\r\n * // Loop through the values in the object\r\n * });\r\n *\r\n *\r\n * @example Iterating through a DOM-collection:\r\n * import { forEach } from \"./utils/forEach\";\r\n *\r\n * const collection = document.querySelectorAll(\"div\");\r\n * forEach(collection, element => {\r\n * // \"element\" is a reference to the current DOM-element.\r\n * });\r\n *\r\n */\r\n\r\nimport { isArray } from \"./typeCheckers\";\r\n\r\n/**\r\n *\r\n * @param {Node|NodeList|Window|Document|Array|object|HTMLCollection|*} collection - Collection to iterate over. Can be a single element, too.\r\n * @param {function} iterator - Callback function for iterator. Will be called with (value, key) as arguments.\r\n * @param {boolean} [allowNullValues=false] Whether or not to allow the iterator to run if null/undefined is given as a collection.\r\n */\r\nexport function forEach(collection, iterator, allowNullValues = false) {\r\n // ** NODE LISTS\r\n // If we're dealing with a node list (see document.querySelectorAll()) or HTMLCollections (see eg. document.getElementByClassName, node.children),\r\n // we'll iterate through it the old fashioned way.\r\n if (\r\n collection instanceof NodeList ||\r\n collection instanceof HTMLCollection\r\n ) {\r\n for (let i = 0; i < collection.length; i += 1) {\r\n iterator(collection.item(i), i);\r\n }\r\n }\r\n\r\n // ** ARRAYS\r\n // Regular arrays are, you know, completely easy.\r\n else if (isArray(collection)) {\r\n // Why not use `Array.prototype.forEach()`? Because for all the optimizations behind\r\n // the scenes, it's still much slower than a simple for-loop.\r\n for (let i = 0; i < collection.length; i += 1) {\r\n iterator(collection[i], i);\r\n }\r\n }\r\n\r\n // ** ITERATORS\r\n // If we have an iterator object we'll use the \"for ... of\" method of iterating through it.\r\n else if (collection && collection.constructor.name === \"Iterator\") {\r\n let index = 0;\r\n for (const item of collection) {\r\n iterator(item, index);\r\n index += 1;\r\n }\r\n }\r\n\r\n // ** REGULAR OBJECTS\r\n // Objects that are *NOT* HTML-elements of some kind get special treatment.\r\n else if (\r\n collection &&\r\n typeof collection === \"object\" &&\r\n !(\r\n collection instanceof Node ||\r\n collection instanceof Window ||\r\n collection instanceof Document\r\n )\r\n ) {\r\n forEach(Object.keys(collection), key => {\r\n // We only want to deal with properties that exist on the object itself,\r\n // not some prototyped stuff.\r\n if (collection.hasOwnProperty(key)) {\r\n iterator(collection[key], key);\r\n }\r\n });\r\n }\r\n\r\n // ** SINGLE NODES OR ELEMENTS\r\n // Anything that doesn't fit in the cases above will be handled here. We'll just fire the iterator once with the\r\n // given collection argument, and 0 as the key, and hope that is enough for the use case.\r\n else {\r\n if (collection || allowNullValues) {\r\n iterator(collection, 0);\r\n }\r\n }\r\n}\r\n","/**\r\n * Filter an array, an object or a NodeList based on a given predicate function.\r\n *\r\n * @module utils/filter\r\n * @author Anders Gissel \r\n *\r\n * @example Filtering an array:\r\n * import { filter } from \"./utils/filter\";\r\n *\r\n * const inputArray = [1,2,3,4,5];\r\n * const filteredArray = filter(inputArray, value => value % 2);\r\n * // Returns [1, 3, 5]\r\n *\r\n *\r\n * @example Filtering an object:\r\n * import { filter } from \"./utils/filter\";\r\n *\r\n * const inputObject = { a: 1, b: 2, c: 3, d: 4, e: 5 };\r\n * const filteredObject = filter(inputObject, (value, key) => value % 2 || key === \"d\");\r\n * // Returns { a: 1, c: 3, d: 4, e: 5 }\r\n *\r\n *\r\n * @example Filtering a NodeList:\r\n * import { filter } from \"./utils/filter\";\r\n *\r\n * const inputObject = document.querySelectorAll(\"button\");\r\n * const filteredObject = filter(inputObject, element => !element.disabled);\r\n * // Returns an array (!) of buttons that are not disabled.\r\n */\r\n\r\nimport { forEach } from \"./forEach\";\r\nimport { isArray } from \"./typeCheckers\";\r\n\r\n/**\r\n *\r\n * @param {Array|object|NodeList} collection - Collection to filter. Can be an array, an object or a NodeList.\r\n * @param {function} predicateFunction - Predicate function. Must return a truthy value for filter to include option.\r\n * @returns {Array|Object} An object of the same type as the input collection, containing all entries that pass the predicate function. However, if you pass a NodeList, it will come back as an array instead.\r\n */\r\nexport function filter(collection, predicateFunction) {\r\n if (isArray(collection)) {\r\n return collection.filter(predicateFunction);\r\n } else if (typeof collection === \"object\") {\r\n const filteredObject = {};\r\n forEach(collection, (value, key) => {\r\n if (Boolean(predicateFunction(value, key)) === true) {\r\n filteredObject[key] = value;\r\n }\r\n });\r\n\r\n // If a NodeList was passed, return as an array. If not, just throw an object back instead.\r\n return collection.constructor === NodeList\r\n ? Object.values(filteredObject)\r\n : filteredObject;\r\n }\r\n\r\n return collection;\r\n}\r\n","/**\r\n * Responsive window handler to detect **window resizing**, **orientation changes** and **active breakpoints**.\r\n *\r\n * This module exposes a set of tools to detect when the window has been resized or the orientation has\r\n * changed. It also figures out which breakpoint is currently active, and provides a set of tools to compare\r\n * breakpoint sizes programmatically.\r\n *\r\n * All callbacks are throttled to avoid using too many CPU cycles.\r\n *\r\n * Breakpoints are imported from `src/site-settings.json` automatically. Please remember to add them in order.\r\n *\r\n *\r\n * @module utils/events/onWindowResize\r\n * @author Anders Gissel \r\n *\r\n * @example Basic usage\r\n * import { onWindowResize } from \"./utils/events/onWindowResize\";\r\n *\r\n * function resizeHasHappened() {}\r\n * onWindowResize(resizeHasHappened);\r\n *\r\n *\r\n * @example To figure out the active breakpoint, as well as some other stuff:\r\n * import { currentWindowWidth,\r\n * currentWindowHeight,\r\n * currentBreakpoint,\r\n * breakpointIndex,\r\n * onWindowResize\r\n * } from \"./utils/events/onWindowResize\";\r\n *\r\n * function resizeHasHappened() {\r\n * window.console.log(currentWindowWidth, currentWindowHeight);\r\n *\r\n * if (currentBreakpoint >= breakpointIndex.md) {\r\n * window.console.info(\"Breakpoint is at least 'md'.\");\r\n * }\r\n * }\r\n *\r\n * onWindowResize(resizeHasHappened);\r\n *\r\n */\r\n\r\nimport { forEach } from \"../forEach\";\r\nimport throttle from \"lodash-es/throttle\";\r\nimport { filter } from \"../filter\";\r\nimport { onReady } from \"./onReady\";\r\nimport siteSettings from \"../../../site-settings\";\r\n\r\nlet functionQueue = [];\r\n\r\n/**\r\n * The current width of the window.\r\n *\r\n * @type {number}\r\n */\r\nexport let currentWindowWidth = 0;\r\n\r\n/**\r\n * The current height of the window.\r\n *\r\n * @type {number}\r\n */\r\nexport let currentWindowHeight = 0;\r\n\r\n/**\r\n * An array of screen sizes, in order to easily being able to identify the current breakpoint corresponding\r\n * to the active media query. Will be populated automatically from screen sizes set in \"site-settings.json\".\r\n */\r\nexport const breakpointIndex = {\r\n unknown: 0\r\n};\r\n\r\n/**\r\n * The timeout for the resize throttle. Set to \"0\" to disable (!) throttling.\r\n *\r\n * @type {number}\r\n * @private\r\n */\r\nconst resizeThrottleTimeoutMs = 500;\r\n\r\n/**\r\n * An object containing pre-parsed target screen sizes for our breakpoints. Will also be populated\r\n * automatically. Used internally only.\r\n *\r\n * @private\r\n */\r\nconst screenSizes = {\r\n unknown: 0\r\n};\r\n\r\nlet sizeCounter = 1;\r\n\r\n// Run through the screen sizes in \"site-settings.json\", and populate our \"size objects\" with them.\r\nforEach(siteSettings.screensizes, (size, sizeName) => {\r\n // This index allows us to perform simple size comparisons on the breakpoints.\r\n breakpointIndex[sizeName] = sizeCounter;\r\n\r\n // This parses the breakpoint size as raw pixels for use in screen width detections later.\r\n screenSizes[sizeName] = Number(size.replace(/[^0-9]/g, \"\"));\r\n\r\n // This increases the counter by one. Oh my, yes.\r\n sizeCounter += 1;\r\n});\r\n\r\n/**\r\n * The current break point. This will correspond to one of the predefined breakpoints, as seen above, so you can\r\n * use it to compare breakpoints directly:\r\n *\r\n * if (currentBreakpoint >= breakpointIndex.md) { ... }\r\n *\r\n * @type {number}\r\n */\r\nexport let currentBreakpoint = 0;\r\n\r\n/**\r\n * The name of the current break point, in case you need it.\r\n *\r\n * @type {string}\r\n */\r\nexport let currentBreakpointName = \"unknown\";\r\n\r\n/**\r\n * Get various window sizes - width, height etc.\r\n * This function is fired automatically upon page load. and throttled each time the window changes size.\r\n *\r\n * @private\r\n */\r\nfunction getWindowSizes() {\r\n currentWindowWidth = window.innerWidth;\r\n currentWindowHeight = window.innerHeight;\r\n\r\n // Calculate which breakpoint is currently active, based on the screen width compared to the pre-parsed\r\n // breakpoint definitions.\r\n let lastFoundWidth = 0;\r\n forEach(screenSizes, (targetScreenWidth, associatedBreakpointName) => {\r\n if (\r\n currentWindowWidth >= targetScreenWidth &&\r\n targetScreenWidth > lastFoundWidth\r\n ) {\r\n lastFoundWidth = targetScreenWidth;\r\n currentBreakpoint = breakpointIndex[associatedBreakpointName];\r\n currentBreakpointName = associatedBreakpointName;\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * This function is run every time the window is resized. It's on a throttle, though, so it won't be fired too\r\n * often.\r\n *\r\n * @private\r\n */\r\nfunction performCalculationCallback() {\r\n // Get our current window size(s)\r\n getWindowSizes();\r\n\r\n // Fire all queued functions that other scripts may have registered.\r\n functionQueue.forEach(funcRef => {\r\n funcRef({\r\n currentWindowWidth,\r\n currentWindowHeight,\r\n currentBreakpoint,\r\n currentBreakpointName\r\n });\r\n });\r\n}\r\n\r\n// Set up a throttle, so our callback function isn't fired too often.\r\nconst throttledCalculationCallback = resizeThrottleTimeoutMs\r\n ? throttle(performCalculationCallback, resizeThrottleTimeoutMs)\r\n : performCalculationCallback;\r\n\r\n// Utilize our own \"onready\"-function to bind an event for handling window resizes and orientation changes.\r\nonReady(\r\n () => {\r\n window.addEventListener(\"resize\", throttledCalculationCallback);\r\n window.addEventListener(\r\n \"orientationchange\",\r\n throttledCalculationCallback\r\n );\r\n\r\n // Get our current window size, because we might need the data at once.\r\n getWindowSizes();\r\n },\r\n // Set to priority \"25\", which will put it behind the DOM initiator, but still before all default functions.\r\n 25\r\n);\r\n\r\n/**\r\n * Schedule a callback to fire each time the window changes shape (on a throttle, so don't worry).\r\n * Your function will be called every time the window is resized, or the window orientation changes.\r\n *\r\n * @param {Function} callback - The callback to fire when the window changes shape.\r\n */\r\nexport function onWindowResize(callback) {\r\n if (typeof callback === \"function\") {\r\n functionQueue.push(callback);\r\n }\r\n}\r\n\r\n/**\r\n * Check if the current breakpoint is less than or equal to a specified breakpoint name\r\n * Similar to CSS's `@media (max-width: ...px)`\r\n *\r\n * @param {string} breakpointName - The breakpoint name to check for, ie. `md`.\r\n * @returns {boolean} `true` if the current breakpoint is less or equal to the given breakpoint name.\r\n */\r\nexport function breakpointMax(breakpointName) {\r\n if (breakpointIndex.hasOwnProperty(breakpointName)) {\r\n return breakpointIndex[breakpointName] >= currentBreakpoint;\r\n }\r\n}\r\n\r\n/**\r\n * Check if the current breakpoint is greater than or equal to a specified breakpoint name\r\n * Similar to CSS's `@media (min-width: ...px)`\r\n *\r\n * @param {string} breakpointName - The breakpoint name to check for, ie. `md`.\r\n * @returns {boolean} `true` if the current breakpoint is above or equal to the given breakpoint name.\r\n */\r\nexport function breakpointMin(breakpointName) {\r\n if (breakpointIndex.hasOwnProperty(breakpointName)) {\r\n return breakpointIndex[breakpointName] <= currentBreakpoint;\r\n }\r\n}\r\n\r\n/**\r\n * Remove callback function from callback stack.\r\n *\r\n * @param {function} callback - The callback to remove.\r\n */\r\nexport function removeCallback(callback) {\r\n if (typeof callback === \"function\") {\r\n functionQueue = filter(\r\n functionQueue,\r\n functionReference => functionReference !== callback\r\n );\r\n }\r\n}\r\n","/**\r\n * Dispatch a **custom event** on the given HTML element. Similar to jQuery's `.trigger()`.\r\n *\r\n * @module utils/events/triggerCustomEvent\r\n * @author Anders Gissel \r\n *\r\n * @example Trigger an event on an element\r\n * import { triggerCustomEvent } from \"./utils/events/triggerCustomEvent\";\r\n *\r\n * const target = document.querySelector(\"button\");\r\n *\r\n * triggerCustomEvent(target, \"click\");\r\n *\r\n *\r\n * @example Trigger an event on an element and send along data as well.\r\n * import { triggerCustomEvent } from \"./utils/events/triggerCustomEvent\";\r\n *\r\n * const target = document.querySelector(\"button\");\r\n *\r\n * addEvent(target, \"my-own-event\", dataObject => { ... });\r\n * triggerCustomEvent(target, \"my-own-event\", { dataKey: \"data value\" });\r\n */\r\n\r\nimport { forEach } from \"../forEach\";\r\n\r\nif (document.documentMode && document.documentMode <= 11) {\r\n // \"new CustomEvent()\" is broken in IE, apparently. However, this polyfill/hack works.\r\n // See http://stackoverflow.com/a/26596324\r\n (function() {\r\n function CustomEvent(event, params) {\r\n const useParams = params || {\r\n bubbles: false,\r\n cancelable: false,\r\n detail: undefined\r\n };\r\n const customEvent = document.createEvent(\"CustomEvent\");\r\n customEvent.initCustomEvent(\r\n event,\r\n useParams.bubbles,\r\n useParams.cancelable,\r\n useParams.detail\r\n );\r\n return customEvent;\r\n }\r\n\r\n CustomEvent.prototype = window.Event.prototype;\r\n\r\n window.CustomEvent = CustomEvent;\r\n })();\r\n}\r\n\r\n/**\r\n * Trigger a custom event on an element.\r\n *\r\n * @param {Element|Element[]|Document|Window|NodeList} target - The element(s) to fire the event on.\r\n * @param {string} eventName - Name of the custom event, ie. `\"akqa:my-custom-event\"`.\r\n * @param {object} [eventData] - Optional object of data to send along to the event handler.\r\n */\r\nexport function triggerCustomEvent(target, eventName, eventData = {}) {\r\n forEach(target, element => {\r\n let event;\r\n\r\n if (window.CustomEvent) {\r\n event = new CustomEvent(eventName, {\r\n detail: eventData,\r\n bubbles: true,\r\n cancelable: true\r\n });\r\n } else {\r\n event = document.createEvent(\"CustomEvent\");\r\n event.initCustomEvent(eventName, true, true, eventData);\r\n }\r\n\r\n element.dispatchEvent(event);\r\n });\r\n}\r\n","/**\r\n * Utilities for checking properties and states of elements.\r\n *\r\n * @module utils/dom/elementProperties\r\n * @author Lars Munkholm \r\n * @author Nicolaj Lund Hummel\r\n * @author Anders Gissel \r\n */\r\n\r\nimport {\r\n currentWindowWidth,\r\n currentWindowHeight\r\n} from \"../events/onWindowResize\";\r\nimport { isElement } from \"../typeCheckers\";\r\nimport { forEach } from \"../forEach\";\r\n\r\n/**\r\n * Check if an element is empty.\r\n *\r\n * @param {Node} element - Check if this element is empty.\r\n * @param {boolean} [strict=true] - Set this to **false** to ignore nodes with whitespace.\r\n * @returns {boolean} **True** if the element is empty.\r\n */\r\nexport function isElementEmpty(element, strict = true) {\r\n return strict\r\n ? !element.childNodes.length\r\n : !element.innerHTML.trim().length;\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const elementIsEmpty = isElementEmpty;\r\n\r\n/**\r\n * Check if an element is hidden in the DOM with `display: none;`\r\n *\r\n * @param {HTMLElement} element - The element to check.\r\n * @returns {boolean} **True** if element is hidden, otherwise **false**.\r\n */\r\nexport function isElementHidden(element) {\r\n return element.offsetParent === null;\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const elementIsHidden = isElementHidden;\r\n\r\n/**\r\n * Check if a given element is within the client viewport.\r\n *\r\n * @param {Element} element - Element to check against viewport bounds.\r\n * @param {number|{x: number, y: number}} expandMargin - Number of pixels to expand viewport-detection-area with. Can be set as an object specifying expansion for `x` and `y`.\r\n * @returns {boolean} True if element is in viewport.\r\n *\r\n *\r\n * @example Basic usage:\r\n * import { isElementInViewport } from \"./utils/dom/elementProperties\";\r\n *\r\n * if (isElementInViewport(element)) {\r\n * // The element is visible in the viewport\r\n * };\r\n *\r\n * if (isElementInViewport(element, 100)) {\r\n * // The element is within 100 pixels of the viewport\r\n * };\r\n *\r\n * if (isElementInViewport(element, { x: 100, y: 200 })) {\r\n * // The element is within 100 pixels of the viewport on the x-axis,\r\n * // and within 200 pixels on the y-axis.\r\n * };\r\n */\r\nexport function isElementInViewport(element, expandMargin = 0) {\r\n const rect = element.getBoundingClientRect();\r\n const expandMarginX = isNaN(expandMargin) ? expandMargin.x : expandMargin;\r\n const expandMarginY = isNaN(expandMargin) ? expandMargin.y : expandMargin;\r\n const spanY = rect.top + Math.max(rect.height, 1) + expandMarginY;\r\n const spanX = rect.left + Math.max(rect.width, 1) + expandMarginX;\r\n\r\n return (\r\n spanY >= Math.min(0, expandMarginY) + 1 &&\r\n rect.top <= currentWindowHeight + expandMarginY - 1 &&\r\n spanX >= Math.min(0, expandMarginX) + 1 &&\r\n rect.left <= currentWindowWidth + expandMarginX - 1\r\n );\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const elementInViewport = isElementInViewport;\r\n\r\n/**\r\n * Return the position of an element\r\n *\r\n * @param {Element|String} element - The HTML element to work with or its ID\r\n * @param {Element|String|Window} [relativeTo=window] - The HTML element to return the position relative to or its ID\r\n * @returns {{top: Number, left: Number}} An object with top and left positions in pixels\r\n *\r\n *\r\n * @example Basic usage:\r\n * import { getElementPosition } from \"./utils/dom/elementProperties\";\r\n *\r\n * const element = document.querySelector(\".anElement\");\r\n * getElementPosition(element);\r\n *\r\n *\r\n * @example Perform a search for an element with an ID equal to the string, i.e. \"elementId\", and get the position of that:\r\n * import { getElementPosition } from \"./utils/dom/elementProperties\";\r\n *\r\n * getElementPosition(\"elementId\");\r\n */\r\nexport function getElementPosition(element, relativeTo = window) {\r\n const useElement =\r\n typeof element === \"string\"\r\n ? document.getElementById(element)\r\n : element;\r\n\r\n // Throw error if element wasn't found\r\n if (!useElement) {\r\n throw new Error(\"getElementPosition did not find an element.\");\r\n }\r\n\r\n const useRelativeTo =\r\n typeof relativeTo === \"string\"\r\n ? document.getElementById(relativeTo)\r\n : relativeTo;\r\n\r\n // Throw error if relative element wasn't found\r\n if (!useRelativeTo) {\r\n throw new Error(\r\n \"getElementPosition did not find an element to show the position relative to.\"\r\n );\r\n }\r\n\r\n const rect = useElement.getBoundingClientRect();\r\n\r\n if (relativeTo === window) {\r\n // Return position relative to window\r\n return {\r\n top:\r\n rect.top +\r\n (window.pageYOffset || document.documentElement.scrollTop),\r\n left:\r\n rect.left +\r\n (window.pageXOffset || document.documentElement.scrollLeft)\r\n };\r\n } else {\r\n const relativeToRect = relativeTo.getBoundingClientRect();\r\n\r\n // Return position relative to declared element\r\n return {\r\n top: rect.top - relativeToRect.top,\r\n left: rect.left - relativeToRect.left\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Check if an element is within the bounds of another element.\r\n *\r\n * @since 3.9.0\r\n * @param {Element|String} element - The HTML element to work with or its ID.\r\n * @param {Element|String|Window} [relativeTo=window] - The HTML element to return the position relative to or its ID.\r\n * @param {boolean} [mustBeFullyInside=false] - Set this to `true` if 100% of the element _must_ be withing the bounds of the other element.\r\n * @returns {boolean} True if the element is within the bounds of the other element.\r\n */\r\nexport function isElementInside(\r\n element,\r\n relativeTo = window,\r\n mustBeFullyInside = false\r\n) {\r\n const useElement =\r\n typeof element === \"string\"\r\n ? document.getElementById(element)\r\n : element;\r\n const useRelativeTo =\r\n typeof relativeTo === \"string\"\r\n ? document.getElementById(relativeTo)\r\n : relativeTo;\r\n const elementPosition = getElementPosition(useElement, useRelativeTo);\r\n\r\n const insideTop =\r\n elementPosition.top + useElement.offsetHeight >=\r\n (mustBeFullyInside ? useElement.offsetHeight : 1);\r\n const insideRight =\r\n elementPosition.left <=\r\n useRelativeTo.offsetWidth -\r\n (mustBeFullyInside ? useElement.offsetWidth : 1);\r\n const insideBottom =\r\n elementPosition.top <=\r\n useRelativeTo.offsetHeight -\r\n (mustBeFullyInside ? useElement.offsetHeight : 1);\r\n const insideLeft =\r\n elementPosition.left + useElement.offsetWidth >=\r\n (mustBeFullyInside ? useElement.offsetWidth : 1);\r\n\r\n return insideTop && insideRight && insideBottom && insideLeft;\r\n}\r\n\r\n/**\r\n * Get the current scroll values of the given element (or window). Will return an object containing\r\n * \"left\" and \"top\" properties, which are set to the scroll values, or false if no compatible element\r\n * was given.\r\n *\r\n * @param {Element|Window} [element=window]\r\n * @returns {{ left: number, top: number } | boolean}\r\n */\r\nexport function getElementScroll(element = window) {\r\n if (isElement(element)) {\r\n if (element instanceof Window) {\r\n return {\r\n left:\r\n element.pageXOffset || document.documentElement.scrollLeft,\r\n top: element.pageYOffset || document.documentElement.scrollTop\r\n };\r\n } else {\r\n return {\r\n left: element.scrollX || element.scrollLeft,\r\n top: element.scrollY || element.scrollTop\r\n };\r\n }\r\n } else {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Calculate the scale of an element from its transform matrix.\r\n *\r\n * @since 3.12.0\r\n * @param {string} transform\r\n * @returns {string}\r\n */\r\nfunction getScaleFromTransformMatrix(transform) {\r\n let scale = 0;\r\n\r\n if (transform && transform !== \"none\") {\r\n const matrix = transform\r\n .split(\"(\")[1]\r\n .split(\")\")[0]\r\n .split(\",\")\r\n .map(value => parseFloat(value));\r\n\r\n scale = Math.sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1]);\r\n }\r\n\r\n return scale.toFixed(3);\r\n}\r\n\r\n/**\r\n * Get both width and height of element\r\n *\r\n * @param {HTMLElement} element - The HTML element to work with\r\n * @param {Object} [options={}] - Object of options\r\n * @param {boolean} [options.includeTransformScale=false] - Include transform scale\r\n * @param {boolean} [options.includePadding=false] - Get size including padding (defaults to true)\r\n * @param {boolean} [options.includeBorder=false] - Get size including border (defaults to true)\r\n * @param {boolean} [options.includeMargin=true] - Get size including margin (defaults to false)\r\n * @param {null|\":before\"|\":after\"} [options.pseudoElement=null] - Get size of pseudo element \":before\" or \":after\"\r\n * @returns {{width: number, height: number}} An object with the width and height as numbers\r\n */\r\nexport function getElementSize(element, options = {}) {\r\n // Get styles\r\n const elementStyle = window.getComputedStyle(\r\n element,\r\n options.pseudoElement\r\n );\r\n\r\n return {\r\n width: getElementWidth(element, options, elementStyle),\r\n height: getElementHeight(element, options, elementStyle)\r\n };\r\n}\r\n\r\n/**\r\n * Get width of element\r\n *\r\n * @param {HTMLElement} element - The HTML element to work with\r\n * @param {Object} [options={}] - Object of options\r\n * @param {boolean} [options.includeTransformScale=false] - Include transform scale\r\n * @param {boolean} [options.includeMargin=false] - Get width including margin (defaults to false)\r\n * @param {boolean} [options.includeBorder=true] - Get width including border (defaults to true)\r\n * @param {boolean} [options.includePadding=true] - Get width including padding (defaults to true)\r\n * @param {null|\":before\"|\":after\"} [options.pseudoElement=null] - Get width of pseudo element \":before\" or \":after\"\r\n * @param {CSSStyleDeclaration} [elementStyle] - Style declaration of element (in case you already have called .getComputedStyle(), pass its returned value here)\r\n * @returns {number} The width as a number\r\n */\r\nexport function getElementWidth(element, options = {}, elementStyle = null) {\r\n // Keep supplied values or set to defaults\r\n options.includeMargin = options.includeMargin === true;\r\n options.includeBorder = options.includeBorder !== false;\r\n options.includePadding = options.includePadding !== false;\r\n\r\n // Get styles\r\n const style =\r\n elementStyle || window.getComputedStyle(element, options.pseudoElement);\r\n const scale = options.includeTransformScale\r\n ? getScaleFromTransformMatrix(style.transform)\r\n : 1;\r\n\r\n // Get width including border and padding\r\n let width = element.offsetWidth;\r\n\r\n // Calculate width with margin\r\n if (options.includeMargin) {\r\n width += parseFloat(style.marginLeft) + parseFloat(style.marginRight);\r\n }\r\n\r\n // Calculate width without border\r\n if (!options.includeBorder) {\r\n width -=\r\n parseFloat(style.borderLeftWidth) +\r\n parseFloat(style.borderRightWidth);\r\n }\r\n\r\n // Calculate width without padding\r\n if (!options.includePadding) {\r\n width -= parseFloat(style.paddingLeft) + parseFloat(style.paddingRight);\r\n }\r\n\r\n return width * scale;\r\n}\r\n\r\n/**\r\n * Get height of element\r\n *\r\n * @param {HTMLElement} element - The HTML element to work with\r\n * @param {Object} [options={}] - Object of options\r\n * @param {boolean} [options.includeTransformScale=false] - Include transform scale\r\n * @param {boolean} [options.includeMargin=false] - Get height including margin (defaults to false)\r\n * @param {boolean} [options.includeBorder=true] - Get height including border (defaults to true)\r\n * @param {boolean} [options.includePadding=true] - Get height including padding (defaults to true)\r\n * @param {null|\":before\"|\":after\"} [options.pseudoElement=null] - Get height of pseudo element \":before\" or \":after\"\r\n * @param {CSSStyleDeclaration} [elementStyle] - Style declaration of element (in case you already have called .getComputedStyle(), pass its returned value here)\r\n * @returns {number} The height as a number\r\n */\r\nexport function getElementHeight(element, options = {}, elementStyle = null) {\r\n // Keep supplied values or set to defaults\r\n options.includeMargin = options.includeMargin === true;\r\n options.includeBorder = options.includeBorder !== false;\r\n options.includePadding = options.includePadding !== false;\r\n\r\n // Get styles\r\n const style =\r\n elementStyle || window.getComputedStyle(element, options.pseudoElement);\r\n const scale = options.includeTransformScale\r\n ? getScaleFromTransformMatrix(style.transform)\r\n : 1;\r\n\r\n // Get height including border and padding\r\n let height = element.offsetHeight;\r\n\r\n // Calculate height with margin\r\n if (options.includeMargin) {\r\n height += parseFloat(style.marginTop) + parseFloat(style.marginBottom);\r\n }\r\n\r\n // Calculate height without border\r\n if (!options.includeBorder) {\r\n height -=\r\n parseFloat(style.borderTopWidth) +\r\n parseFloat(style.borderBottomWidth);\r\n }\r\n\r\n // Calculate height without padding\r\n if (!options.includePadding) {\r\n height -=\r\n parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);\r\n }\r\n\r\n return height * scale;\r\n}\r\n\r\n/**\r\n * Set a single attribute for the given element. This tiny helper really only exists so `setAttributes()`\r\n * has someone to do the actual work.\r\n *\r\n * @since 3.7.0\r\n * @param {Element|Element[]|NodeList} elementCollection - The collection to manipulate.\r\n * @param {string} attributeName - The name of the attribute, ie. `disabled` or `data-something`\r\n * @param {string|boolean|Number} attributeValue - The value of the attribute, ie. `\"someString\"` or `true`.\r\n * @private\r\n */\r\nconst setAttribute = (elementCollection, attributeName, attributeValue) =>\r\n forEach(elementCollection, element => {\r\n if (isElement(element)) {\r\n // If the option value is a boolean, we'll check the value of the element's property. If that's a\r\n // boolean as well, we'll set the property \"directly\". This will get rid of those pesky use-cases\r\n // with `disabled=\"true\"` instead of just `disabled`.\r\n if (\r\n typeof attributeValue === \"boolean\" &&\r\n typeof element[attributeName] === \"boolean\"\r\n ) {\r\n element[attributeName] = attributeValue;\r\n } else {\r\n element.setAttribute(attributeName, attributeValue);\r\n }\r\n }\r\n });\r\n/**\r\n * Set one or more attributes on one or more elements.\r\n *\r\n * @since 3.7.0\r\n * @param {Element|Element[]|NodeList} element - The element(s) to manipulate\r\n * @param {string|object} attribute - The attribute(s) to manipulate. If sent as a string (ie. `\"disabled\"` or `\"data-value\"`), it will be used as the attribute name, and `attributeValue` will provide the value for it. You can also set this as a key/value object, with the key being the attribute to set, and the value being the... well, the value.\r\n * @param {string|boolean|Number|null} [attributeValue=null] - The value to set. Will be ignored if `attribute` is an object.\r\n *\r\n * @example Basic usage. In this case, though, you might as well just use `element.setAttribute(disabled, \"disabled\")`, or better yet: `element.disabled = true`\r\n * import { setAttributes } from \"./utils/dom/elementProperties\";\r\n *\r\n * const element = document.querySelector(\".my-element\");\r\n * setAttributes(element, \"disabled\", true);\r\n *\r\n *\r\n * @example Setting multiple properties on multiple elements. This is more like it!\r\n * import { setAttributes } from \"./utils/dom/elementProperties\";\r\n *\r\n * const elements = document.querySelectorAll(\"div\");\r\n * setAttributes(elements, {\r\n * \"data-value\": \"some value\",\r\n * \"data-ill-take-a-pound-of-nuts\": \"That's a lot of nuts!\",\r\n * \"data-he-just-left\": \"With nuts!\",\r\n * });\r\n *\r\n */\r\nexport function setAttributes(element, attribute, attributeValue = null) {\r\n if (typeof attribute === \"object\") {\r\n forEach(attribute, (value, attribute) =>\r\n setAttribute(element, attribute, value)\r\n );\r\n } else {\r\n setAttribute(element, attribute, attributeValue);\r\n }\r\n}\r\n\r\n/**\r\n * Remove one or more attributes from one or more elements.\r\n *\r\n * @since 3.7.0\r\n * @param {Element|Element[]|NodeList} elements - Element(s) to remove the given attributes for.\r\n * @param {string|string[]} attributes - The attributes to remove, ie. `style` or `data-something`. Can be a single attribute or an array of attribute names.\r\n *\r\n * @example Remove a list of attributes from a list of elements:\r\n * import { removeAttributes } from \"./utils/dom/elementProperties\";\r\n *\r\n * const elements = document.querySelectorAll(\"div\");\r\n * removeAttributes(elements, [\"data-value\", \"data-name\", \"data-sausage\", \"value\"]);\r\n */\r\nexport function removeAttributes(elements, attributes) {\r\n forEach(elements, element => {\r\n if (isElement(element)) {\r\n forEach(attributes, attribute =>\r\n element.removeAttribute(attribute)\r\n );\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Match one or more elements' tags against one or more tag names.\r\n *\r\n * @since 3.10.0\r\n * @param {Element|Element[]|NodeList} elements - One or more elements to test.\r\n * @param {...string|string[]} tagNames - The tag names to match against.\r\n * @returns {boolean} True if an element's tag name matches one of the supplied tag names. False if none of the elements matched.\r\n *\r\n *\r\n * @example Basic usage:\r\n * import { isElementTag } from \"./utils/dom/elementProperties\";\r\n *\r\n * const allElements = document.querySelectorAll(\".testElements\");\r\n * const divElements = document.getElementsByTagName(\"div\");\r\n * const singleAudioElement = document.getElementsByById(\"audio\");\r\n * const singleVideoElement = document.getElementsByById(\"video\");\r\n *\r\n * // Match one or more elements against a single tag name.\r\n * if (isElementTag(divElements, \"div\")) {\r\n * // This is true, it's a DIV.\r\n * };\r\n *\r\n * // Match a single element against multiple tag names.\r\n * if (isElementTag(singleAudioElement, [\"audio\", \"video\"])) {\r\n * // This is true, element tag matches \"audio\".\r\n * };\r\n *\r\n * // Match multiple elements against multiple tag names.\r\n * if (isElementTag(allElements, \"section\", \"article\", \"span\")) {\r\n * // This is false.\r\n * // None of the elements matched any of the tag names.\r\n * };\r\n *\r\n * // Match multiple elements against a single tag name.\r\n * if (isElementTag([audioElement, videoElement], \"video\")) {\r\n * // This is true.\r\n * // One of the elements matched the tag name.\r\n * };\r\n */\r\nexport function isElementTag(elements, ...tagNames) {\r\n const acceptedTagNames =\r\n tagNames.length === 1 && tagNames[0] instanceof Array\r\n ? tagNames[0]\r\n : tagNames;\r\n const elementTagNames = elements.length\r\n ? Array.from(elements).map(tis => tis.tagName.toLowerCase())\r\n : [elements.tagName.toLowerCase()];\r\n\r\n return acceptedTagNames.reduce(\r\n (tagNameMatch, tagName) =>\r\n tagNameMatch || elementTagNames.indexOf(tagName.toLowerCase()) > -1,\r\n false\r\n );\r\n}\r\n\r\n/**\r\n * Match a number of elements' tags against one or more tag names.\r\n *\r\n * @since 3.10.0\r\n * @param {Element|Element[]|NodeList} elements - One or more elements to test.\r\n * @param {...string|string[]} tagNames - The tag names to match against.\r\n * @returns {boolean} True if all elements match one of the supplied tag names. False if one of the elements doesn't match.\r\n *\r\n *\r\n * @example Basic usage:\r\n * import { areAllElementsTag } from \"./utils/dom/elementProperties\";\r\n *\r\n * const sections = document.querySelectorAll(\"section\");\r\n * const articles = document.querySelectorAll(\"article\");\r\n * const allElements = document.querySelectorAll(\"section, article\");\r\n *\r\n * // Match similar elements against a single tag name.\r\n * if (areAllElementsTag(sections, \"section\")) {\r\n * // This is true, their are all sections\r\n * };\r\n *\r\n * // The same as above, but this time it's false.\r\n * if (areAllElementsTag(article, \"section\"])) {\r\n * // This is false, articles are not sections\r\n * };\r\n *\r\n * // Match multiple elements against multiple tag names.\r\n * if (areAllElementsTag(allElements, \"section\", \"article\")) {\r\n * // This is true.\r\n * // The elements are either sections or articles.\r\n * };\r\n *\r\n * // The same as above, but this time it's false.\r\n * if (areAllElementsTag(allElements, \"section\")) {\r\n * // This is false.\r\n * // Some of the elements are not sections.\r\n * };\r\n */\r\nexport function areAllElementsTag(elements, ...tagNames) {\r\n const acceptedTagNames =\r\n tagNames.length === 1 && tagNames[0] instanceof Array\r\n ? tagNames[0]\r\n : tagNames;\r\n const elementTagNames = elements.length\r\n ? Array.from(elements).map(tis => tis.tagName.toLowerCase())\r\n : [elements.tagName.toLowerCase()];\r\n\r\n return !elementTagNames.reduce(\r\n (tagNameNegativeMatch, tagName) =>\r\n tagNameNegativeMatch ||\r\n acceptedTagNames.indexOf(tagName.toLowerCase()) === -1,\r\n false\r\n );\r\n}\r\n","/**\r\n * Split a string into an array, and then run an optional callback function on each item.\r\n *\r\n * If a string is given, it will be **split by spaces and commas to get an array**.\r\n * If an array is given, no pre-processing happens, but the callback will still be executed (however, in this case please use `forEach()` instead).\r\n * All other input types are ignored.\r\n *\r\n * @module utils/splitter\r\n * @author Anders Gissel \r\n *\r\n *\r\n * @example Split a string into an array:\r\n * import { splitter } from \"./utils/splitter\";\r\n *\r\n * const str = \"apple pear orange\";\r\n * splitter(str); // Returns [\"apple\", \"pear\", \"orange\"]\r\n *\r\n *\r\n * @example Split a string and log each item to the console:\r\n * import { splitter } from \"./utils/splitter\";\r\n *\r\n * const str = \"apple pear orange\";\r\n * splitter(str, item => window.console.log(item)); // Logs \"apple\", \"pear\", \"orange\" into the console. Returns [\"apple\",\"pear\",\"orange\"].\r\n */\r\n\r\nimport { isArray } from \"./typeCheckers\";\r\n\r\n/**\r\n * Split a string into an array.\r\n *\r\n * @param {string|Array} input - String containing one or more items, separated by space/comma, or an array of entries.\r\n * @param {function} [callback] - Optional callback to run for each entry in the given array.\r\n * @returns {Array} The processed data in the form of an array.\r\n */\r\nexport function splitter(input, callback) {\r\n const inputArray =\r\n typeof input === \"string\"\r\n ? input\r\n .replace(/,/gm, \" \") // First, replace commas with spaces\r\n .replace(/[\\s]{2,}/gm, \" \") // Then, replace two or more spaces with just one.\r\n .trim() // Remove leading/trailing whitespace and similar crap\r\n .split(\" \")\r\n : isArray(input)\r\n ? input\r\n : [];\r\n\r\n if (typeof callback === \"function\") {\r\n inputArray.forEach(inputEntry => {\r\n if (inputEntry !== undefined) {\r\n callback(inputEntry);\r\n }\r\n });\r\n }\r\n\r\n return inputArray;\r\n}\r\n","/**\r\n * A classlist \"polyfill\" and utility tool.\r\n *\r\n * Native classlist cannot be polyfilled properly on IE10 and IE11, since they support the basic functions but\r\n * do not have support for `toggle`, for example. This file provides working classList implementation, with\r\n * hacks to make everything work in IE9 and below as well. However, the usual perks of Frontline are available\r\n * as well, which allows you to add several classes at once, to several elements at once.\r\n *\r\n * When importing, please use the `addClass`, `removeClass`, `toggleClass` and `hasClass` names,\r\n * because they're much easier to understand without having to alias them.\r\n *\r\n * @module utils/dom/classList\r\n * @author Nicolaj Lund Hummel\r\n * @author Anders Gissel \r\n * @example Basic usage:\r\n * import { addClass, removeClass } from \"./utils/dom/classList\";\r\n *\r\n * const element = document.querySelector(\".anElement\");\r\n * addClass(element, \"someClass someOtherClass\");\r\n * removeClass(element, \"anotherClass\");\r\n */\r\n\r\nimport { forEach } from \"../forEach\";\r\nimport { splitter } from \"../splitter\";\r\n\r\n/**\r\n * This function adds a class to the given element.\r\n * Checking for classList since this isn't supported in IE9 / IE8\r\n *\r\n * @param {Element|Element[]|NodeList} input\r\n * @param {string|string[]} classNames\r\n */\r\nexport function addClass(input, classNames) {\r\n forEach(input, element => {\r\n splitter(classNames, className => {\r\n if (element.classList) {\r\n element.classList.add(className);\r\n } else {\r\n element.className += ` ${className}`;\r\n }\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const add = addClass;\r\n\r\n/**\r\n * This function checks if given element has the class specified.\r\n * Checking for classList since this isn't supported in IE9 / IE8.\r\n * This function does NOT support nodelists or arrays.\r\n *\r\n * @param {Element} element\r\n * @param {string} className\r\n * @returns {boolean}\r\n */\r\nexport function hasClass(element, className) {\r\n if (element && (element.classList || element.className)) {\r\n if (element.classList) {\r\n return element.classList.contains(className);\r\n } else {\r\n return new RegExp(`(^| ) ${className}( |$)`, \"gi\").test(\r\n element.className\r\n );\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const contains = hasClass;\r\n\r\n/**\r\n * This function removes a class from the given element.\r\n * Checking for classList since this isn't supported in IE9 / IE8\r\n *\r\n * @param {Element|Element[]|NodeList} input\r\n * @param {string|string[]} classNames\r\n */\r\nexport function removeClass(input, classNames) {\r\n forEach(input, element => {\r\n splitter(classNames, className => {\r\n if (element.classList) {\r\n element.classList.remove(className);\r\n } else {\r\n element.className = element.className.replace(\r\n new RegExp(\r\n `(^|\\\\b)${className.split(\" \").join(\"|\")}(\\\\b|$)`,\r\n \"gi\"\r\n ),\r\n \" \"\r\n );\r\n }\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const remove = removeClass;\r\n\r\n/**\r\n * Toggle a class.\r\n *\r\n * @param {Element|Element[]|NodeList} input - The HTML element to work with\r\n * @param {string|string[]} classNames - The class name(s) we'll be toggling\r\n * @param {boolean} [condition] - Optional condition. If set to true or false, the toggle will use the given value to add or remove the class. If undefined, a regular toggle will be performed.\r\n */\r\nexport function toggleClass(input, classNames, condition) {\r\n forEach(input, element => {\r\n splitter(classNames, className => {\r\n let classShouldBeIncluded;\r\n const classIsIncludedAlready = hasClass(element, className);\r\n\r\n // If a condition is given, we'll use that to figure out if the class should be added or not.\r\n if (condition !== undefined) {\r\n // We'll only continue if the condition doesn't match the current state. So we'll only remove the\r\n // class if it added already and the condition is \"false\", and vice versa.\r\n if (condition !== classIsIncludedAlready) {\r\n classShouldBeIncluded = condition;\r\n }\r\n } else {\r\n // No condition was given, so we'll just toggle the class.\r\n classShouldBeIncluded = !classIsIncludedAlready;\r\n }\r\n\r\n // Only continue if a new mode is defined. Otherwise there's no point.\r\n if (classShouldBeIncluded !== undefined) {\r\n if (classShouldBeIncluded) {\r\n addClass(element, className);\r\n } else {\r\n removeClass(element, className);\r\n }\r\n }\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const toggle = toggleClass;\r\n","/**\r\n * A utility to **lock the viewport** at the current position in order to **stop scrolling**.\r\n *\r\n * This is very useful when opening modal windows and the likes.\r\n *\r\n * @module utils/dom/scrollLock\r\n * @author Lars Munkholm \r\n * @author Anders Gissel \r\n *\r\n * @example Basic usage\r\n * import { enableScrollLock, disableScrollLock } from \"./utils/dom/scrollLock\";\r\n *\r\n * enableScrollLock();\r\n * window.setTimeout(disableScrollLock, 3000);\r\n */\r\n\r\nimport { triggerCustomEvent } from \"../events/triggerCustomEvent\";\r\nimport { getElementScroll } from \"./elementProperties\";\r\nimport { addClass, removeClass } from \"./classList\";\r\n\r\nconst className = \"akqa-scroll-lock\";\r\nlet scrollTop = 0;\r\n\r\n/**\r\n * Get the current state of the scroll lock. `true` if the scroll lock is enabled, otherwise `false`.\r\n *\r\n * @type {boolean}\r\n */\r\nexport let isScrollLocked = false;\r\n\r\n/**\r\n * Enable the scroll lock.\r\n */\r\nexport function enableScrollLock() {\r\n if (!isScrollLocked) {\r\n // Get scroll position\r\n const scrollPosition = getElementScroll();\r\n\r\n // Reset scroll position\r\n window.scrollTo(scrollPosition.left, 0);\r\n\r\n const htmlTag = document.documentElement;\r\n addClass(htmlTag, className);\r\n htmlTag.style.marginTop = `${-scrollPosition.top}px`;\r\n htmlTag.style.position = \"fixed\";\r\n htmlTag.style.overflow = \"hidden\";\r\n htmlTag.style.width = \"100%\";\r\n\r\n // Trigger event on target. You can listen for it using document.body.addEventListener(\"akqa.scrollLock:enable\", callbackHere)\r\n triggerCustomEvent(document.body, \"akqa.scrollLock:enable\");\r\n\r\n // Remember state\r\n isScrollLocked = true;\r\n scrollTop = scrollPosition.top;\r\n }\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const enable = enableScrollLock;\r\n\r\n/**\r\n * Disable the scroll lock\r\n */\r\nexport function disableScrollLock() {\r\n if (isScrollLocked) {\r\n const scrollPosition = getElementScroll();\r\n\r\n const htmlTag = document.documentElement;\r\n removeClass(htmlTag, className);\r\n htmlTag.style.marginTop = \"\";\r\n htmlTag.style.position = \"\";\r\n htmlTag.style.overflow = \"\";\r\n htmlTag.style.width = \"\";\r\n\r\n // Set the scroll position to what it was before\r\n window.scrollTo(scrollPosition.left, scrollTop);\r\n\r\n // Trigger event on target. You can listen for it using document.body.addEventListener(\"akqa.scrollLock:disable\", callbackHere)\r\n triggerCustomEvent(document.body, \"akqa.scrollLock:disable\");\r\n\r\n // Remember state\r\n isScrollLocked = false;\r\n }\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const disable = disableScrollLock;\r\n\r\n/**\r\n * Toggle the scroll lock between on and off\r\n */\r\nexport function toggleScrollLock() {\r\n if (isScrollLocked) {\r\n disableScrollLock();\r\n } else {\r\n enableScrollLock();\r\n }\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const toggle = toggleScrollLock;\r\n","/**\r\n * Set (or reset) an object of styles on multiple elements at the same time.\r\n *\r\n * @module utils/dom/setStyles\r\n * @since 3.6.0\r\n * @author Lars Munkholm \r\n *\r\n * @example Basic usage:\r\n * import { setStyles, resetStyles } from \"./utils/dom/setStyles\";\r\n *\r\n * const uglyElements = document.querySelectorAll(\"figure, aside, article .box\");\r\n * setStyles(uglyElements, {\r\n * color: \"#FFF\",\r\n * boxShadow: \"0 1px 10px #000\",\r\n * });\r\n *\r\n * // And reset styles like this:\r\n * resetStyles(uglyElements);\r\n *\r\n *\r\n * @example If you don't speak camelCase, use kebab-case like this:\r\n * setStyles(document.getElementById(\"anotherUglyElement\"), {\r\n * \"background-color\": \"#FFF\",\r\n * \"border-radius\": \"50%\",\r\n * \"padding-top\": 0,\r\n * });\r\n *\r\n *\r\n * @example\r\n * You can set your own styles as the default:\r\n * import {\r\n * setStyles,\r\n * resetStyles,\r\n * saveStylesAsDefault\r\n * } from \"./utils/dom/setStyles\";\r\n *\r\n * const element = document.getElementById(\"uglyElement\");\r\n *\r\n * // Set the background color to white\r\n * setStyles(element, {\r\n * \"background-color\": \"#FFF\",\r\n * });\r\n *\r\n * // Save the current inline styling as the default\r\n * saveStylesAsDefault(element);\r\n *\r\n * // Change styling again\r\n * setStyles(element, {\r\n * \"background-color\": \"#000\",\r\n * });\r\n *\r\n * // Now reset - this will set the background-color to white again\r\n * resetStyles(element);\r\n */\r\n\r\nimport { forEach } from \"../forEach\";\r\n\r\n// We'll be using Map and not a regular object, since Map supports using objects as keys.\r\n// This requires you to include the required polyfill. \"default-3.6\" from polyfill.io is fine.\r\nconst knownDOMObjects = new Map();\r\n\r\n/**\r\n * Set multiple styles on one or more elements.\r\n *\r\n * @param {HTMLElement|HTMLElement[]|NodeList} element - One or more elements that need some stylin'.\r\n * @param {Object} styles - An object with styles. Properties can be in both camelCase and kebab-case.\r\n */\r\nexport function setStyles(element, styles) {\r\n forEach(element, currentElement => {\r\n // Reset styles\r\n if (styles === null) {\r\n resetStyles(currentElement);\r\n }\r\n\r\n // Set new styles\r\n else {\r\n // Save original styling in case the element needs to be reset to its default state later\r\n saveStylesAsDefault(currentElement, false);\r\n\r\n // Do the changes!\r\n forEach(\r\n styles,\r\n (value, key) =>\r\n (currentElement.style[\r\n key.replace(/-([a-z])/g, match =>\r\n match[1].toUpperCase()\r\n )\r\n ] = value)\r\n );\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Save the current inline styling of one or more elements as the default.\r\n *\r\n * @param {HTMLElement|HTMLElement[]|NodeList} element - One or more elements to get the inline styling from.\r\n * @param {boolean} [overwriteExisting=true] - Set to **false** if you don't want to overwrite an already existing default.\r\n */\r\nexport function saveStylesAsDefault(element, overwriteExisting = true) {\r\n forEach(element, currentElement => {\r\n const originalInlineStyles = knownDOMObjects.get(currentElement);\r\n if (\r\n overwriteExisting ||\r\n !(originalInlineStyles && typeof originalInlineStyles === \"string\")\r\n ) {\r\n knownDOMObjects.set(\r\n currentElement,\r\n currentElement.getAttribute(\"style\") || \"\"\r\n );\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Reset the styling of one or more elements.\r\n *\r\n * If an element had inline styling before you used `setStyles()` on it, we'll reset to that.\r\n * If you want to remove inline styles completely, set the second argument `hardReset` to *true*.\r\n *\r\n * @param {HTMLElement|HTMLElement[]|NodeList} element - One or more elements that you wish to remove inline styling from.\r\n * @param {boolean} [isHardReset=false] - Set this to **true** to remove inline styling completely.\r\n */\r\nexport function resetStyles(element, isHardReset = false) {\r\n forEach(element, currentElement => {\r\n let setStylesTo = \"\";\r\n\r\n if (!isHardReset) {\r\n // If the element's original inline styling has been saved, reset to that\r\n const originalInlineStyles = knownDOMObjects.get(currentElement);\r\n if (\r\n originalInlineStyles &&\r\n typeof originalInlineStyles === \"string\"\r\n ) {\r\n setStylesTo = originalInlineStyles || \"\";\r\n }\r\n }\r\n\r\n currentElement.style.cssText = setStylesTo;\r\n });\r\n}\r\n","/**\r\n * Utility to get **all the siblings** for the given DOM-element, or a subset thereof.\r\n *\r\n * @module utils/dom/siblings\r\n * @author Lars Munkholm \r\n */\r\n\r\nimport { forEach } from \"../forEach\";\r\n\r\n/**\r\n * Get all siblings of element, or a subset thereof.\r\n *\r\n * @param {Node} element - The target element.\r\n * @param {Boolean} [includeOriginalElement=false] - Set to true to include the original element among the siblings\r\n * @param {Node|Null} [fromElement=null] - Return the siblings starting at this element\r\n * @param {Node|Null} [untilElement=null] - Return the siblings stopping at this element\r\n * @returns {Node[]} Array of elements that are siblings to the given element.\r\n */\r\nexport function getSiblings(\r\n element,\r\n includeOriginalElement = false,\r\n fromElement = null,\r\n untilElement = null\r\n) {\r\n if (includeOriginalElement && !fromElement && !untilElement) {\r\n // Return array including the original element and all its siblings\r\n return Array.from(element.parentNode.children);\r\n } else {\r\n const siblings = [];\r\n\r\n // Set the element to start looking for siblings from\r\n let nextElement = fromElement || element.parentNode.firstElementChild;\r\n\r\n do {\r\n const currentElement = nextElement;\r\n const sameAsOriginalElement = element === currentElement;\r\n\r\n // Set next element to look at\r\n nextElement = nextElement.nextElementSibling;\r\n\r\n // Add this element to the list of sibling\r\n // unless it is the same as the original element (and this should be left out)\r\n if (!sameAsOriginalElement || includeOriginalElement) {\r\n siblings.push(currentElement);\r\n }\r\n\r\n // Stop looking for siblings, if the loop is set to stop at the current element\r\n if (currentElement === untilElement) {\r\n break;\r\n }\r\n } while (nextElement);\r\n\r\n // Return array of elements\r\n return siblings;\r\n }\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const siblings = getSiblings;\r\n\r\n/**\r\n * Get all the siblings **after** the given element.\r\n *\r\n * @param {Node} element - The target element.\r\n * @param {Boolean} [includeOriginalElement=false] - Set to true to include the original element among the siblings\r\n * @returns {Node[]} An array containing the elements following the given element (and possibly the element itself).\r\n */\r\nexport function getNextSiblings(element, includeOriginalElement = false) {\r\n return getSiblings(element, includeOriginalElement, element);\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const nextSiblings = getNextSiblings;\r\n\r\n/**\r\n * Get previous siblings of element\r\n *\r\n * @param {Node} element - The target element.\r\n * @param {Boolean} [includeOriginalElement=false] - Set to true to include the original element among the siblings\r\n * @returns {Node[]} An array containing the elements preceding the given element (and possibly the element itself).\r\n */\r\nexport function getPreviousSiblings(element, includeOriginalElement = false) {\r\n return getSiblings(element, includeOriginalElement, null, element);\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const previousSiblings = getPreviousSiblings;\r\n\r\n/**\r\n * Check if two elements are siblings.\r\n *\r\n * @param {Element} element1 - Check if this is a sibling to element2.\r\n * @param {Element} element2 - Check if this is a sibling to element1.\r\n * @param {boolean} [adjacentOnly=false] - Set this to **true** to only looks for adjacent siblings (meaning just before or after).\r\n * @returns {boolean} **True** if the element is a parent to the other element.\r\n */\r\nexport function areElementsSiblings(element1, element2, adjacentOnly = false) {\r\n if (adjacentOnly) {\r\n return (\r\n element1.nextElementSibling === element2 ||\r\n element1.previousElementSibling === element2\r\n );\r\n } else {\r\n // We'll start off with assuming that the elements aren't siblings, since most aren't\r\n let siblingsCheck = false;\r\n\r\n // Get siblings of element1\r\n const siblingElements = getSiblings(element1);\r\n\r\n // Loop though siblings and check if any of them are element2\r\n forEach(siblingElements, sibling =>\r\n sibling === element2 ? (siblingsCheck = true) : null\r\n );\r\n\r\n // If element2 wasn't found amongst element1's children, return false\r\n return siblingsCheck;\r\n }\r\n}\r\n\r\n/**\r\n * @type {function}\r\n * @ignore\r\n * @deprecated\r\n */\r\nexport const elementsAreSiblings = areElementsSiblings;\r\n","/**\r\n * Helper-utilities for inserting, moving and emptying DOM-elements.\r\n *\r\n * When inserting elements, they are first added to a document fragment, keeping the repainting and\r\n * recalculating of the DOM to a minimum.\r\n *\r\n * These have also been tested to be way faster than solutions using `innerHTML` and `insertAdjecentHTML`.\r\n *\r\n * @module utils/dom/elementManipulation\r\n * @since 3.6.0\r\n * @author Lars Munkholm \r\n */\r\n\r\nimport { getSiblings } from \"./siblings\";\r\nimport { forEach } from \"../forEach\";\r\nimport { createElement } from \"./createElement\";\r\n\r\n/**\r\n * Parse a string into an array of DOM nodes.\r\n *\r\n * @since 3.6.5\r\n * @param {Node|string} input - String to parse. If input is already a node or an element, nothing will be done to it.\r\n * @returns {Node[]} An array of DOM nodes.\r\n *\r\n * @example\r\n * import { parseHTML } from \"./utils/dom/elementManipulation\";\r\n *\r\n * const HTMLString = \"An example with text and HTML...\";\r\n * const nodes = parseHTML(HTMLString);\r\n *\r\n * const nodeNames = nodes.map(node => node.nodeName);\r\n * // Outputs [\"#text\", \"B\", \"#text\", \"I\", \"#text\"]\r\n *\r\n * const textOnly = nodes.map(node => node.nodeName === \"#text\" ? node.textContent : \"\").join(\"\");\r\n * // Outputs \"An example with and ...\"\r\n *\r\n * const htmlOnly = nodes.map(node => node.nodeName !== \"#text\" ? node.outerHTML : \"\").join(\"\");\r\n * // Outputs \"HTMLstuff\"\r\n */\r\nexport const parseHTML = input =>\r\n typeof input === \"string\"\r\n ? Array.from(createElement(\"div\", { html: input }).childNodes)\r\n : [input];\r\n\r\n/**\r\n * Delete an element from the DOM.\r\n *\r\n * @param {Node|Node[]|NodeList} element - Element(s) to delete.\r\n */\r\nexport function deleteElement(element) {\r\n forEach(element, currentElement =>\r\n currentElement.parentNode\r\n ? currentElement.parentNode.removeChild(currentElement)\r\n : null\r\n );\r\n}\r\n\r\n/**\r\n * **Append an element** (or multiple) inside another element, which means it will be placed as the last child.\r\n *\r\n * @param {Node|NodeList|string|Array.<(Node|string)>} element - The element(s) to append.\r\n * @param {Node} container - Append the element inside this container.\r\n */\r\nexport function appendElement(element, container) {\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Use createTextNode() before appending text to fragment\r\n forEach(element, currentElement =>\r\n fragment.appendChild(\r\n typeof currentElement === \"string\"\r\n ? document.createTextNode(currentElement)\r\n : currentElement\r\n )\r\n );\r\n\r\n container.appendChild(fragment);\r\n}\r\n\r\n/**\r\n * **Prepend an element** (or multiple) inside another element, which means it will be placed as the first child.\r\n *\r\n * @param {Node|NodeList|string|Array.<(Node|string)>} element - The element(s) to prepend.\r\n * @param {Node} container - Prepend the element inside this container.\r\n */\r\nexport function prependElement(element, container) {\r\n const fragment = document.createDocumentFragment();\r\n let lastInsertedElement;\r\n\r\n forEach(element, currentElement => {\r\n // Make sure strings are converted to text nodes before moving on\r\n const node =\r\n typeof currentElement === \"string\"\r\n ? document.createTextNode(currentElement)\r\n : currentElement;\r\n\r\n if (lastInsertedElement) {\r\n insertElementAfter(node, lastInsertedElement);\r\n } else if (fragment.firstChild) {\r\n insertElementBefore(node, fragment.firstChild);\r\n } else {\r\n fragment.appendChild(node);\r\n }\r\n\r\n lastInsertedElement = node;\r\n });\r\n\r\n if (container.firstChild) {\r\n insertElementBefore(fragment, container.firstChild);\r\n } else {\r\n appendElement(fragment, container);\r\n }\r\n}\r\n\r\n/**\r\n * Insert one or more elements **after** another element.\r\n *\r\n * @param {Node|NodeList|string|Array.<(Node|string)>} newElement - The element(s) to insert after another.\r\n * @param {Node} existingElement - The existing element to insert after.\r\n */\r\nexport function insertElementAfter(newElement, existingElement) {\r\n const parent = existingElement.parentNode;\r\n\r\n if (parent) {\r\n const fragment = document.createDocumentFragment();\r\n let lastInsertedElement;\r\n\r\n forEach(newElement, currentElement => {\r\n // Make sure strings are converted to text nodes before moving on\r\n const node =\r\n typeof currentElement === \"string\"\r\n ? document.createTextNode(currentElement)\r\n : currentElement;\r\n\r\n if (lastInsertedElement) {\r\n fragment.insertBefore(node, lastInsertedElement.nextSibling);\r\n } else {\r\n fragment.appendChild(node);\r\n }\r\n\r\n lastInsertedElement = node;\r\n });\r\n\r\n parent.insertBefore(fragment, existingElement.nextSibling);\r\n }\r\n}\r\n\r\n/**\r\n * Insert one or more elements **before** another element.\r\n *\r\n * @param {Node|NodeList|string|Array.<(Node|string)>} newElement - The element(s) to insert before another.\r\n * @param {Node} existingElement - The existing element to insert before.\r\n */\r\nexport function insertElementBefore(newElement, existingElement) {\r\n const fragment = document.createDocumentFragment();\r\n\r\n // Use createTextNode() before inserting text into fragment\r\n forEach(newElement, currentElement =>\r\n fragment.appendChild(\r\n typeof currentElement === \"string\"\r\n ? document.createTextNode(currentElement)\r\n : currentElement\r\n )\r\n );\r\n\r\n existingElement.parentNode.insertBefore(fragment, existingElement);\r\n}\r\n\r\n/**\r\n * **Swap two elements** with each other.\r\n *\r\n * @param {Node} element1 - This will be replaced with `element2`\r\n * @param {Node} element2 - This will be replaced with `element1`\r\n */\r\nexport function swapElements(element1, element2) {\r\n // Remember the location of element2\r\n const parent2 = element2.parentNode;\r\n const next2 = element2.nextSibling;\r\n\r\n // If element1 is the next sibling of element2\r\n if (next2 === element1) {\r\n parent2.insertBefore(element1, element2);\r\n }\r\n\r\n // Otherwise, insert element2 right before element1\r\n else {\r\n element1.parentNode.insertBefore(element2, element1);\r\n\r\n // And now insert element1 where element2 was\r\n if (next2) {\r\n // If there was an element after element2, then insert element1 right before that\r\n parent2.insertBefore(element1, next2);\r\n } else {\r\n // Otherwise, just append as last child\r\n parent2.appendChild(element1);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * **Replace an element** with another one.\r\n *\r\n * @param {Node} oldElement - The existing element to be replaced.\r\n * @param {Node} newElement - The new element to take its place.\r\n */\r\nexport function replaceElement(oldElement, newElement) {\r\n insertElementAfter(newElement, oldElement);\r\n oldElement.parentElement.removeChild(oldElement);\r\n}\r\n\r\n/**\r\n * **Wrap an element** in a new element.\r\n *\r\n * @param {Node} existingElement - The existing element, which is about to be wrapped.\r\n * @param {Node} newWrapper - The new element which the existing one should be wrapped inside.\r\n *\r\n * @example\r\n * import { wrapElement } from \"./utils/dom/elementManipulation\";\r\n * import { createElement } from \"./utils/dom/createElement\";\r\n *\r\n * const newWrapper = createElement(\"div\", { className: \"wrapper\" });\r\n * const wrapThis = document.getElementById(\"wrapThis\");\r\n *\r\n * wrapElement(wrapThis, newWrapper);\r\n */\r\nexport function wrapElement(existingElement, newWrapper) {\r\n existingElement.parentNode.insertBefore(newWrapper, existingElement);\r\n newWrapper.appendChild(existingElement);\r\n}\r\n\r\n/**\r\n * **Inner wrap an element** in a new element.\r\n *\r\n * Actually, the children are what will be wrapped.\r\n *\r\n * @param {Node} existingElement - The existing element, which is about have its children wrapped.\r\n * @param {Node} newWrapper - The new element which the existing one should be wrapped inside.\r\n */\r\nexport function wrapInnerElement(existingElement, newWrapper) {\r\n while (existingElement.childNodes.length > 0) {\r\n newWrapper.appendChild(existingElement.childNodes[0]);\r\n }\r\n\r\n appendElement(newWrapper, existingElement);\r\n}\r\n\r\n/**\r\n * **Unwrap an element** by moving said element out on its parent and deleting the parent.\r\n *\r\n * @param {Node} element - The element to unwrap.\r\n * @param {boolean} [keepSiblings=true] - The element to unwrap.\r\n *\r\n * @example\r\n * import { unwrapElement } from \"./utils/dom/elementManipulation\";\r\n * const unwrapThis = document.getElementById(\"unwrapThis\");\r\n * wrapElement(unwrapThis);\r\n * // The element just lost its parent and now lives with its grandparent.\r\n */\r\nexport function unwrapElement(element, keepSiblings = true) {\r\n const parent = element.parentElement;\r\n\r\n if (keepSiblings) {\r\n const allSiblings = getSiblings(element, true);\r\n forEach(allSiblings, sibling => insertElementBefore(sibling, parent));\r\n deleteElement(parent);\r\n } else {\r\n replaceElement(parent, element);\r\n }\r\n}\r\n\r\n/**\r\n * Empty one or more elements by removing all children.\r\n *\r\n * This is more than 75% faster than `innerHTML = \"\"` according to performance tests on jsPerf.com.\r\n *\r\n * @param {Node|Node[]|NodeList} element - The element(s) to be emptied.\r\n */\r\nexport function emptyElement(element) {\r\n forEach(element, currentElement => {\r\n while (currentElement.firstChild) {\r\n currentElement.removeChild(currentElement.firstChild);\r\n }\r\n });\r\n}\r\n","/**\r\n * Helper-utility for creating a DOM-element. Allows you to make a whole lot of shortcuts when creating elements\r\n * dynamically. Special setters are included to make setting certain attributes easier, but the rest will simply\r\n * be overloaded onto the element. For example, the attribute `id` is not in the list and requires no processing,\r\n * so if you include `options.id=\"whatever\"`, your finished element will have `id=\"whatever\"` set.\r\n *\r\n * @module utils/dom/createElement\r\n * @author Anders Gissel \r\n *\r\n * @example Create a label with various options and containing an input field.\r\n * import { createElement } from \"./utils/dom/createElement\";\r\n *\r\n * const inputField = createElement(\"input\", {\r\n * className: \"input input--text\",\r\n * type: \"text\",\r\n * id: \"myField\",\r\n * value: 45722,\r\n * });\r\n *\r\n * const label = createElement(\"label\", {\r\n * html: inputField,\r\n * title: \"My field lives here.\",\r\n * });\r\n *\r\n * document.getElementById(\"target\").appendChild(label);\r\n * // Output will be: \r\n */\r\n\r\nimport { addClass } from \"./classList\";\r\nimport { forEach } from \"../forEach\";\r\nimport { setStyles } from \"./setStyles\";\r\nimport { appendElement } from \"./elementManipulation\";\r\nimport { setAttributes } from \"./elementProperties\";\r\n\r\n/**\r\n * Create a DOM element with the given options. Basically an interface for `document.createElement();`. Any option not described in the parameter list will be added to the tag as a regular attribute.\r\n *\r\n * @param {string} tagName - The tag name of the element, ie. `\"p\"` to create a `

`-tag. Required!\r\n * @param {object} [options] - Additional options for the new element. Any option that's not on the list will be added as a \"regular\" attribute.\r\n * @param {string|array} [options.className] - Classname(s) of element. Can be given as just about anything.\r\n * @param {string} [options.text] - Text-content of element. Will be set using innerText, and is thus XSS-safe.\r\n * @param {string|Node|Node[]|NodeList} [options.html] - HTML-content of element. Will be set as innerHTML if string is given; or else appended if at all possible.\r\n * @param {Object|string} [options.style] - The style of an element given as an object or a string.\r\n * @param {object} [options.attributes] - DEPRECATED: Key/value pairs of additional attributes, ie.: { readonly: true, \"data-whatever\": \"yes\" }. This syntax is still supported, but you should just add your extra properties to the main options.\r\n * @returns {HTMLElement|Element}\r\n */\r\nexport function createElement(tagName, options = {}) {\r\n const newElement = document.createElement(tagName);\r\n\r\n forEach(options, (optionValue, optionKey) => {\r\n switch (optionKey) {\r\n case \"className\":\r\n addClass(newElement, optionValue || \"\");\r\n break;\r\n\r\n case \"attributes\":\r\n setAttributes(newElement, optionValue);\r\n break;\r\n\r\n case \"html\":\r\n // We'll only set the HTML contents if the \"text\" property hasn't ALSO been set.\r\n if (!options.text && typeof optionValue !== \"undefined\") {\r\n if (typeof optionValue === \"string\") {\r\n newElement.innerHTML = optionValue;\r\n } else {\r\n appendElement(optionValue, newElement);\r\n }\r\n }\r\n break;\r\n\r\n case \"text\":\r\n newElement.innerText = options.text;\r\n break;\r\n\r\n case \"style\":\r\n if (typeof options.style === \"object\") {\r\n setStyles(newElement, optionValue);\r\n } else {\r\n setAttributes(newElement, optionKey, optionValue);\r\n }\r\n break;\r\n\r\n default:\r\n // Any unknown option key will be treated as a raw attribute.\r\n setAttributes(newElement, optionKey, optionValue);\r\n }\r\n });\r\n\r\n return newElement;\r\n}\r\n","import { createElement } from \"./createElement\";\r\n\r\nexport const getScrollBarWidth = () => {\r\n return document.documentElement.style.setProperty(\r\n \"--scrollbar-width\",\r\n window.innerWidth - document.documentElement.clientWidth + \"px\"\r\n );\r\n};\r\n\r\nexport const getNavHeight = () => {\r\n return document.documentElement.style.setProperty(\r\n \"--nav-height\",\r\n document.querySelector(\"header\")?.clientHeight + \"px\"\r\n );\r\n};\r\n\r\nexport const getInPageNavigationScrollHeight = () => {\r\n const inPageNavigation = document.querySelector(\".in-page-navigation\");\r\n if (inPageNavigation !== null) {\r\n const inPageNavigationInner = inPageNavigation.querySelector(\r\n \".in-page-navigation__inner\"\r\n );\r\n const inPageNavigationInnerClone = inPageNavigationInner.cloneNode(\r\n true\r\n );\r\n inPageNavigationInnerClone.classList.add(\"in-page-navigation--temp\");\r\n const div = createElement(\"div\");\r\n div.appendChild(inPageNavigationInnerClone);\r\n div.classList.add(\r\n \"in-page-navigation\",\r\n \"in-page-navigation__cloned\",\r\n \"scroll--active\",\r\n \"in-page-navigation--active\"\r\n );\r\n inPageNavigation.parentElement.appendChild(div);\r\n document.documentElement.style.setProperty(\r\n \"--in-page-navigation-scroll-height\",\r\n document.querySelector(\".in-page-navigation--temp\")?.clientHeight +\r\n \"px\"\r\n );\r\n div.remove();\r\n }\r\n};\r\n\r\nexport const getInPageNavigationHeight = () => {\r\n document.documentElement.style.setProperty(\r\n \"--in-page-navigation-height\",\r\n document.querySelector(\".in-page-navigation__inner\")?.clientHeight +\r\n \"px\"\r\n );\r\n};\r\n\r\nexport const getInPageNavigationOffset = () => {\r\n const inPageNavigation = document.querySelector(\".in-page-navigation\");\r\n if (inPageNavigation !== null) {\r\n const inPageNavigationInner = inPageNavigation.querySelector(\r\n \".in-page-navigation__inner\"\r\n );\r\n if (document.querySelector(\".hero__tertiary\") !== null) {\r\n const wrapper = document.querySelector(\"main > .component-margin\");\r\n const wrapperStyle = getComputedStyle(wrapper);\r\n const wrapperMargin = parseInt(wrapperStyle.marginBottom);\r\n document.documentElement.style.setProperty(\r\n \"--in-page-navigation-offset\",\r\n inPageNavigationInner?.clientHeight + wrapperMargin + \"px\"\r\n );\r\n } else if (document.querySelector(\".hero__product\") !== null) {\r\n const inPageNavigationStyle = getComputedStyle(inPageNavigation);\r\n const inPageNavigationPadding = parseInt(\r\n inPageNavigationStyle.paddingBottom\r\n );\r\n document.documentElement.style.setProperty(\r\n \"--in-page-navigation-offset\",\r\n inPageNavigationInner?.clientHeight +\r\n inPageNavigationPadding +\r\n \"px\"\r\n );\r\n } else {\r\n document.documentElement.style.setProperty(\r\n \"--in-page-navigation-offset\",\r\n inPageNavigationInner?.clientHeight + \"px\"\r\n );\r\n }\r\n }\r\n};\r\n","/**\r\n * **onScroll handler for elements and window.**\r\n *\r\n * This module provides a method for listening to the \"scroll\"-event of any element, be it a regular DOM\r\n * element or the window, and report the current scroll position back. Call throttling is built in, which means\r\n * you can set up your listeners as eagerly or lazily as you want or need. The entire thing is based on\r\n * observables, provided by **RxJS**, which adds a layer of complexity to the code inside this file (and a larger\r\n * payload by about 18KB, pre-gzip), but will also give you maximum flexibility with regards to throttling and\r\n * how you register and unregister scroll-events.\r\n *\r\n * While the previous version of this module exposed the current scroll position of the window automatically,\r\n * this is no longer the case. You can use the `getElementScroll` utility, which is a dependency of this\r\n * utility anyway, to get the current position of any element you wish.\r\n *\r\n * If you want maximum control, RxJS is a dependency of this utility, so you can just write your own observables\r\n * and subscribers instead. This utility is intended to make things as easy as possible.\r\n *\r\n * @module utils/events/onScroll\r\n * @author Anders Gissel \r\n *\r\n *\r\n */\r\n\r\nimport { Observable } from \"rxjs/Observable\";\r\nimport { animationFrame } from \"rxjs/scheduler/animationFrame\";\r\nimport \"rxjs/add/observable/fromEvent\";\r\nimport \"rxjs/add/operator/throttleTime\";\r\nimport { isArray, isElement } from \"../typeCheckers\";\r\nimport { forEach } from \"../forEach\";\r\nimport { filter } from \"../filter\";\r\nimport { getElementScroll } from \"../dom/elementProperties\";\r\n\r\n// We'll be using Map and not a regular object, since Map supports using objects as keys.\r\n// This requires you to include the required polyfill. \"default-3.6\" from polyfill.io is fine.\r\nconst knownDOMObjects = new Map();\r\n\r\n/**\r\n * @typedef {object} SubscriberDefinition\r\n * @private\r\n * @property {Observable} baseObservable\r\n * @property {object} throttlers\r\n * @property {object} subscribers\r\n * @property {object} callbacks\r\n */\r\n\r\n/**\r\n * Create a new subscriber for the given DOM-element and throttle-combination, or return an existing one if found.\r\n *\r\n * @private\r\n * @param {Element|Window} element\r\n * @param {number} [throttleValueMs=0]\r\n * @returns {SubscriberDefinition}\r\n */\r\nfunction createSubscriberForDOMElement(element, throttleValueMs = 0) {\r\n let existingData = knownDOMObjects.get(element);\r\n\r\n // If no data exists yet, create it now.\r\n if (!existingData || typeof existingData !== \"object\") {\r\n const baseObservable = Observable.fromEvent(element, \"scroll\");\r\n\r\n existingData = {\r\n baseObservable,\r\n throttlers: {},\r\n subscribers: {},\r\n callbacks: {}\r\n };\r\n }\r\n\r\n // Only continue if there is a throttle value, or there isn't but we haven't set up the \"base listener\" yet.\r\n if (\r\n throttleValueMs ||\r\n (throttleValueMs === 0 && !existingData.throttlers[throttleValueMs])\r\n ) {\r\n // Make sure we have a callback array for the given throttle value.\r\n if (!isArray(existingData.callbacks[throttleValueMs])) {\r\n existingData.callbacks[throttleValueMs] = [];\r\n }\r\n\r\n // Make sure we have a throttled version of the base observable\r\n if (throttleValueMs && !existingData.throttlers[throttleValueMs]) {\r\n existingData.throttlers[\r\n throttleValueMs\r\n ] = existingData.baseObservable.throttleTime(\r\n throttleValueMs,\r\n animationFrame,\r\n { trailing: true }\r\n );\r\n }\r\n\r\n // Make sure we have a subscriber for when something happens for the given throttle value.\r\n if (!existingData.subscribers[throttleValueMs]) {\r\n existingData.subscribers[throttleValueMs] =\r\n // Use a throttled observer if a throttle value is given, or the base observable if not.\r\n (throttleValueMs\r\n ? existingData.throttlers[throttleValueMs]\r\n : existingData.baseObservable\r\n )\r\n // Subscribe to the thing!\r\n .subscribe(event => {\r\n const { top, left } = getElementScroll(element);\r\n existingData.callbacks[\r\n throttleValueMs\r\n ].forEach(funcRef => funcRef({ event, top, left }));\r\n });\r\n }\r\n }\r\n\r\n return existingData;\r\n}\r\n\r\n/**\r\n * Add a callback when the element is scrolled.\r\n *\r\n * @param {Element|Element[]|NodeList|Window} elementList - List of element(s) to add callback to.\r\n * @param {function|function[]} callbackList - Function or array of functions to add.\r\n * @param {number} [throttleValueMs=0] - Optional throttle value, given in milliseconds. If omitted, no throttling is employed.\r\n *\r\n * @example To add a listener/callback:\r\n * import { onScroll } from \"./utils/events/onScroll\";\r\n *\r\n * let element = document.querySelector(\".element\");\r\n * onScroll(element, yourEventHandlerHere);\r\n *\r\n * // Both \"element\" and \"yourEventHandlerHere\" can be single instances (like \"window\" or a\r\n * // single element for the former, and a single function for the latter), or multiple ones\r\n * // (like a node list for the former and an array of functions for the latter). The callback\r\n * // functions, when called, will receive a single object as their argument, containing the\r\n * // original event as well as the current left- and top scroll position of the targeted element.\r\n *\r\n *\r\n * @example To add a throttled listener:\r\n * // This will ensure the callback is fired four times per second. Trailing calls are enabled.\r\n * onScroll(element, yourEventHandlerHere, 250);\r\n */\r\nexport function onScroll(elementList, callbackList, throttleValueMs = 0) {\r\n forEach(elementList, element => {\r\n if (isElement(element)) {\r\n // Make sure we have an observable to work with\r\n const baseData = createSubscriberForDOMElement(\r\n element,\r\n throttleValueMs\r\n );\r\n\r\n // Add all given callbacks to the element's observable\r\n forEach(callbackList, callback =>\r\n baseData.callbacks[throttleValueMs].push(callback)\r\n );\r\n\r\n // Store the data for later use.\r\n knownDOMObjects.set(element, baseData);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Remove a given callback for a given throttle value, remove all callbacks, or just all callbacks for the given throttle value.\r\n *\r\n * @param {NodeList|Element[]|Element|Window} elementList\r\n * @param {function|function[]} [callbackListToRemove] Function or array of functions to remove for the given element (and possibly given throttle value)\r\n * @param {number} [throttleValueMs=-1] The specific throttle to remove the callback(s) for. Defaults to -1 and not 0, because a zero-value just means no throttle.\r\n *\r\n *\r\n * @example To remove the throttled event:\r\n * import { removeScrollCallback } from \"./utils/events/onScroll\";\r\n *\r\n * removeScrollCallback(element, yourEventHandlerHere, 250);\r\n *\r\n *\r\n * @example To remove \"yourEventHandlerHere\", regardless of throttle value (_both_ immediate and throttled calls):\r\n * import { removeScrollCallback } from \"./utils/events/onScroll\";\r\n *\r\n * removeScrollCallback(element, yourEventHandlerHere);\r\n *\r\n *\r\n * @example To remove all callbacks for a certain throttle value:\r\n * import { removeScrollCallback } from \"./utils/events/onScroll\";\r\n *\r\n * removeScrollCallback(element, null, 250);\r\n *\r\n *\r\n * @example To remove _all_ scroll callbacks from the element:\r\n * import { removeScrollCallback } from \"./utils/events/onScroll\";\r\n *\r\n * removeScrollCallback(element);\r\n */\r\nexport function removeScrollCallback(\r\n elementList,\r\n callbackListToRemove,\r\n throttleValueMs = -1\r\n) {\r\n forEach(elementList, element => {\r\n if (isElement(element)) {\r\n // Get the throttle- and callback lists for the current element.\r\n let baseData = knownDOMObjects.get(element);\r\n\r\n if (baseData && typeof baseData === \"object\") {\r\n let remainingCallbacks = 0;\r\n\r\n // If the throttle value is 0 or above, we are given a specific throttle value to remove the callback(s) for.\r\n if (throttleValueMs > -1) {\r\n // If a specific callback (or list thereof) is given, remove only those for the specific throttle value.\r\n if (callbackListToRemove) {\r\n forEach(callbackListToRemove, callback => {\r\n if (isArray(baseData.callbacks[throttleValueMs])) {\r\n // Filter the callbacks to only include those that don't match the given callback\r\n baseData.callbacks[throttleValueMs] = filter(\r\n baseData.callbacks[throttleValueMs],\r\n funcRef => funcRef !== callback\r\n );\r\n }\r\n });\r\n } else {\r\n // If we're here, no specific callbacks were given. Just remove all of them.\r\n baseData.subscribers[throttleValueMs].unsubscribe();\r\n delete baseData.callbacks[throttleValueMs];\r\n delete baseData.subscribers[throttleValueMs];\r\n }\r\n } else {\r\n // If we're here, no throttle value was given, so we'll just remove the given callbacks (or all\r\n // of them) for all throttle values.\r\n if (callbackListToRemove) {\r\n // Remove the given callbacks for all throttle values.\r\n forEach(callbackListToRemove, callback => {\r\n forEach(\r\n baseData.callbacks,\r\n (callbackList, throttleIdx) => {\r\n baseData.callbacks[throttleIdx] = filter(\r\n callbackList,\r\n funcRef => funcRef !== callback\r\n );\r\n }\r\n );\r\n });\r\n } else {\r\n // Remove all callbacks for all throttle values. Yowza.\r\n baseData.callbacks = {};\r\n }\r\n }\r\n\r\n // Clean up by removing subscribers and throttles if there are no callbacks left.\r\n forEach(baseData.callbacks, (callbackList, throttleIdx) => {\r\n remainingCallbacks += callbackList.length;\r\n\r\n if (callbackList.length === 0) {\r\n baseData.subscribers[throttleIdx].unsubscribe();\r\n delete baseData.callbacks[throttleIdx];\r\n delete baseData.subscribers[throttleIdx];\r\n }\r\n });\r\n\r\n // If no callbacks exist at all, just remove the base data.\r\n if (remainingCallbacks === 0) {\r\n forEach(baseData.subscribers, subscription =>\r\n subscription.unsubscribe()\r\n );\r\n baseData = null;\r\n }\r\n }\r\n\r\n if (baseData) {\r\n knownDOMObjects.set(element, baseData);\r\n } else {\r\n knownDOMObjects.delete(element);\r\n }\r\n }\r\n });\r\n}\r\n","/**\r\n * This module provides a set of functions for adding and removing events to any DOM element through an event\r\n * proxy. The underlying system is vanilla JS and uses addEventListener()/removeEventListener(), but the proxy\r\n * makes it possible to remove any and all events, even though they are bound to other scopes or exist inside\r\n * constructor instantiations.\r\n *\r\n * Under normal circumstances, you probably won't need this. But as soon as you start removing constructed\r\n * instances, and need to clean up after yourself, adding and removing events using these functions will help\r\n * you a lot.\r\n *\r\n * Please note that you will NOT be able to remove these events using removeEventListener(); nor will you\r\n * be able to use these functions to remove events created using addEventListener().\r\n *\r\n *\r\n * @module utils/events/events\r\n * @author Anders Gissel \r\n *\r\n * @example To add an event:\r\n * import { addEvent } from \"./utils/events/events\";\r\n * const element = document.querySelector(\".element\");\r\n * addEvent(element, \"click\", yourEventHandlerHere);\r\n *\r\n *\r\n * @example To remove that event again:\r\n * import { removeEvent } from \"./utils/events/events\";\r\n * removeEvent(element, \"click\", yourEventHandlerHere);\r\n *\r\n *\r\n * @example To remove all click-events from the element:\r\n * removeEvent(element, \"click\");\r\n *\r\n *\r\n * @example To remove all events from the element:\r\n * import { removeAllEvents } from \"./utils/events/events\";\r\n * removeAllEvents(element);\r\n *\r\n *\r\n * @example To add an event to be fired only once and then removed automatically:\r\n * import { addEventOnce } from \"./utils/events/events\";\r\n * const element = document.querySelector(\".element\");\r\n * addEventOnce(element, \"click\", yourEventHandlerHere);\r\n *\r\n */\r\n\r\nimport { forEach } from \"../forEach\";\r\nimport { filter } from \"../filter\";\r\nimport { splitter } from \"../splitter\";\r\nimport { isArray } from \"../typeCheckers\";\r\n\r\n// We'll be using Map and not a regular object, since Map supports using objects as keys.\r\n// This requires you to include the required polyfill. \"default-3.6\" from polyfill.io is fine.\r\nconst knownDOMObjects = new Map();\r\n\r\n/**\r\n * The actual event handler that will be fired by any event bound using addEvent(). Internal use only.\r\n *\r\n * @private\r\n * @param {Event} event\r\n */\r\nfunction handleEvent(event) {\r\n /** @type {Node|*} */\r\n const element = this;\r\n const elementHandlers = knownDOMObjects.get(element);\r\n const eventType = event.type;\r\n\r\n if (elementHandlers && typeof elementHandlers === \"object\") {\r\n const callbackList = elementHandlers[eventType];\r\n\r\n // Fire all associated event handlers!\r\n if (isArray(callbackList) && callbackList.length) {\r\n forEach(callbackList, callback => {\r\n callback.eventHandler(event);\r\n\r\n // Remove event if it is only to be fired once\r\n if (callback.once) {\r\n removeEvent(element, eventType, callback.eventHandler);\r\n }\r\n });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Remove an event from the given DOM element(s). Can individual or all callbacks for an event type, depending on whether\r\n * \"eventHandlerToRemove\" is set.\r\n *\r\n * @param {Node|Node[]|NodeList|Window|Document} elements - The DOM element(s) we'll be working on.\r\n * @param {string|string[]} eventTypes - A string containing one or more event names to remove, separated by comma/space, or given as an array.\r\n * @param {function} [eventHandlerToRemove] - A specific event handler to remove. If set, only that particular callback will be removed from the event type. If not, all callbacks for the event type are removed.\r\n */\r\nexport function removeEvent(elements, eventTypes, eventHandlerToRemove) {\r\n forEach(elements, element => {\r\n const elementHandlers = knownDOMObjects.get(element);\r\n\r\n if (elementHandlers) {\r\n splitter(eventTypes, event => {\r\n if (event) {\r\n if (eventHandlerToRemove !== undefined) {\r\n let callbackList = elementHandlers[event];\r\n\r\n // If there's a list of callbacks for the event type, filter it so it doesn't contain the given \"target callback\".\r\n if (isArray(callbackList) && callbackList.length > 0) {\r\n callbackList = filter(\r\n callbackList,\r\n callbackObject =>\r\n callbackObject.eventHandler !==\r\n eventHandlerToRemove\r\n );\r\n\r\n // If there are any callbacks left, store them now, and then return to avoid hitting\r\n // the final \"remove everything\"-block.\r\n if (callbackList.length > 0) {\r\n elementHandlers[event] = callbackList;\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // If we're here, no usable event handlers are left, or we should just kill anything anyway (if no\r\n // eventHandlerToRemove was provided). Destroy the entire event handler to clean up memory.\r\n element.removeEventListener(event, handleEvent);\r\n delete elementHandlers[event];\r\n }\r\n });\r\n\r\n // Update the event handler cache.\r\n knownDOMObjects.set(element, elementHandlers);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Remove ALL event handlers set on the given DOM element(s).\r\n *\r\n * @param {Node|Node[]|NodeList|Window|Document} elements - The element(s) to clean up.\r\n */\r\nexport function removeAllEvents(elements) {\r\n forEach(elements, element => {\r\n const elementHandlers = knownDOMObjects.get(element);\r\n\r\n if (elementHandlers) {\r\n // Remove all the event handlers we can possibly find.\r\n forEach(Object.keys(elementHandlers), eventType => {\r\n removeEvent(element, eventType);\r\n\r\n // Remove event listeners and clean up memory.\r\n element.removeEventListener(eventType, handleEvent);\r\n });\r\n\r\n knownDOMObjects.delete(element);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Add an event to the given element(s).\r\n *\r\n * @param {Node|Node[]|NodeList|Window|Document} elements - The element(s) we'll be working on.\r\n * @param {string|string[]} eventTypes - A string containing one or more events to add (ie. \"click\", \"mouseenter\" etc.), separated by comma/space, or given as an array.\r\n * @param {function} eventHandler - The event handler function that'll handle the event.\r\n * @param {boolean} [useCapture=false] - Whether or not to use event capturing. See JS-docs for more.\r\n * @param {boolean} [runOnce=false] - Whether or not to only run the event once and then remove it.\r\n */\r\nexport function addEvent(\r\n elements,\r\n eventTypes,\r\n eventHandler,\r\n useCapture = false,\r\n runOnce = false\r\n) {\r\n forEach(elements, element => {\r\n const elementHandlers = knownDOMObjects.get(element) || {};\r\n\r\n splitter(eventTypes, event => {\r\n if (!isArray(elementHandlers[event])) {\r\n elementHandlers[event] = [];\r\n element.addEventListener(event, handleEvent, useCapture);\r\n }\r\n\r\n elementHandlers[event].push({ runOnce, eventHandler });\r\n });\r\n\r\n knownDOMObjects.set(element, elementHandlers);\r\n });\r\n}\r\n\r\n/**\r\n * Add an event to the given element(s) and remove it after its first run\r\n *\r\n * @param {Node|Node[]|NodeList|Window|Document} elements - The element(s) we'll be working on.\r\n * @param {string|string[]} eventTypes - A string containing one or more events to add (ie. \"click\", \"mouseenter\" etc.), separated by space.\r\n * @param {function} eventHandler - The event handler function that'll handle the event.\r\n * @param {boolean} [useCapture=false] - Whether or not to use event capturing. See JS-docs for more.\r\n */\r\nexport function addEventOnce(\r\n elements,\r\n eventTypes,\r\n eventHandler,\r\n useCapture = false\r\n) {\r\n addEvent(elements, eventTypes, eventHandler, useCapture, true);\r\n}\r\n\r\n/**\r\n * Create an eventListener on a parent DOMElement to handle events triggered on multiple elements\r\n * elements triggering the eventHandler is determined by selector given.\r\n * Bonus: Works even on elements created after the event listener was added.\r\n * Depends on experimental code `Element.prototype.closest`, which isn't supported in IE, so a polyfill is required.\r\n *\r\n * @param {string} selector - Selector-string of element to trigger eventHandler on\r\n * @param {string|string[]} eventTypes - A string containing one or more events to add (ie. \"click\", \"mouseenter\" etc.), separated by comma/space, or given as an array.\r\n * @param {function} eventHandler - The event handler function that'll be triggered once event is fired inside selected element. Will be called with object as single parameter, containing event and event target (to avoid scope trouble).\r\n * @param {Node|Node[]|NodeList|HTMLDocument|Window|Document} elementScope - Parent DOM-element to set eventListener on (optional, defaults to document).\r\n */\r\nexport function delegateEvent(\r\n selector,\r\n eventTypes,\r\n eventHandler,\r\n elementScope = document\r\n) {\r\n addEvent(elementScope, eventTypes, event => {\r\n const listeningTarget = event.target.closest(selector);\r\n if (listeningTarget) {\r\n eventHandler({\r\n event,\r\n target: listeningTarget\r\n });\r\n }\r\n });\r\n}\r\n","/**\r\n * @module utils/network/loadImage\r\n * @author Lars Munkholm \r\n */\r\n\r\nimport { addEvent, removeEvent } from \"../events/events\";\r\n\r\n/**\r\n * Try to decode the image, after it's loaded, and resolve the Promise.\r\n *\r\n * @private\r\n * @param {Element} newImage\r\n * @returns {Promise}\r\n */\r\nexport const decodeImage = newImage =>\r\n \"decode\" in newImage\r\n ? newImage.decode().then(() => newImage)\r\n : Promise.resolve(newImage);\r\n\r\n/**\r\n * Load an image, and return a Promise that resolves once the image is loaded.\r\n *\r\n * @param {string} source - The path to the image.\r\n * @param {Object} [options] - Object of settings.\r\n * @param {boolean} [options.useSrcset=false] - Set to true to use the `srcset` attribute instead of `src`.\r\n * @param {string} [options.sizes=\"\"] - If you're using `srcset`, you can also add a `sizes` attribute.\r\n * @returns {Promise} Promise that will resolve with the loaded image once it's ready.\r\n */\r\nexport function loadImage(source, { useSrcset = false, sizes = \"\" } = {}) {\r\n const newImage = new Image();\r\n\r\n if (useSrcset && sizes && \"sizes\" in newImage) {\r\n newImage.sizes = sizes;\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n addEvent(newImage, \"load\", () => {\r\n removeEvent(newImage, \"load error\");\r\n decodeImage(newImage).then(image => resolve(image));\r\n });\r\n\r\n addEvent(newImage, \"error\", () => {\r\n removeEvent(newImage, \"load error\");\r\n reject();\r\n });\r\n\r\n newImage[useSrcset ? \"srcset\" : \"src\"] = source;\r\n });\r\n}\r\n","/**\r\n * **Lazy load element sources, background images and more.**\r\n *\r\n * Lazy load the source for `img`, `picture`, `audio`, `video`, `embed`, `iframe`, `script` and `link`.\r\n * If this is used on any other type of element, the utility will set the given source as a background image. Or you can\r\n * define your own loader function. The possibilities are endless 🎈\r\n *\r\n * Images are loaded and decoded asynchronously to prevent blocking of the main thread.\r\n *\r\n *\r\n * #### Setting the source\r\n *\r\n * You set the source with the attribute `data-lazy`. The syntax for both `src` and `srcset` is supported.\r\n *\r\n * If you want to use `srcset` (only applicable for images), just use the\r\n * [srcset syntax for img](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)\r\n * or the [srcset syntax for picture](https://www.w3schools.com/tags/att_source_srcset.asp).\r\n *\r\n * Otherwise you should just set the source as a path to a file. `data-lazy=\"path/to/file.ext\"`.\r\n *\r\n * Setting different sources for specific breakpoints is done with a comma separated list or JSON:\r\n * - `data-lazy=\"sm: small.jpg, md: medium.jpg, lg: large.jpg\"`.\r\n * - `data-lazy='{ \"xxs\": \"mobile.jpg\", \"md\": \"tablet.jpg\", \"xl\": \"desktop.jpg\" }'`.\r\n *\r\n *\r\n * #### Slow speed networks\r\n *\r\n * You can set alternative sources in case a user is visiting the site on a slow speed network (2G or 3G) by defining\r\n * the attributes `data-lazy-2g` and/or `data-lazy-3g`.\r\n *\r\n * If we can tell that the user has a slow network speed, the data attributes aimed at those connection types will be\r\n * prioritized.\r\n *\r\n * **Be aware** that this is dependent on an _experimental technology_, and might not be widely supported yet. Always make\r\n * sure that your code works if this is technology is not supported. Stay updated on\r\n * [caniuse](https://caniuse.com/#search=connection) and\r\n * [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/effectiveType)\r\n *\r\n *\r\n * #### Setting placeholders\r\n *\r\n * You can set placeholders using the attribute `data-lazy-placeholder`. By doing this, you can prevent content reflow,\r\n * where the content below or around lazy loaded content get moved around to make room for the newly loaded content.\r\n * Reflow is a user-blocking operation, which slows down the browser by forcing it to recalculate the layout of any\r\n * element that changes position.\r\n *\r\n * Placeholders can be defined with a path to the file, that you want to show until the correct source is loaded. Or you\r\n * can set it to an aspect ratio, which will generate an inline SVG source.\r\n *\r\n * - A single aspect ratio
`data-lazy-placeholder=\"480x320\"`.\r\n * - A single path
`data-lazy-placeholder=\"path/to/placeholder.jpg\"`.\r\n * - Breakpoint specific list
`data-lazy-placeholder=\"xxs: 480x320, md: 768x500, xl: path/to/placeholder.jpg\"`.\r\n * - Breakpoint specific JSON
`data-lazy-placeholder='{ \"xxs\": \"image.jpg\", \"md\": \"768x500\", \"xl\": \"1540x700\" }'`.\r\n *\r\n *\r\n * @since 3.10.0\r\n * @module utils/dom/lazyLoad\r\n * @author Lars Munkholm \r\n *\r\n *\r\n * @example Basic JavaScript for lazy loading anything:\r\n * import { lazyLoad } from \"./utils/dom/lazyLoad\";\r\n *\r\n * // Lazy load sources for elements with the .lazy class name.\r\n * lazyLoad(\".lazy\");\r\n *\r\n * // Lazy load anything with the \"data-lazy\" attribute.\r\n * lazyLoad();\r\n *\r\n *\r\n * @example Possible settings in JavaScript:\r\n * import { lazyLoad, setLazyLoadGlobalSettings } from \"./utils/dom/lazyLoad\";\r\n *\r\n * // Don't load sources before the element has moved 100 px into the viewport\r\n * // and set the scroll throttle to 500 ms.\r\n * setLazyLoadGlobalSettings({\r\n * bufferMarginPx: -100,\r\n * onScrollThrottleMs: 500,\r\n * });\r\n *\r\n * // This is bonkers, but you can do it if you'd like\r\n * lazyLoad(\".slow\", {\r\n * classNames: {\r\n * base: \"slow\",\r\n * initialized: \"init\",\r\n * loading: \"getting\",\r\n * loaded: \"got\",\r\n * error: \"not-got\",\r\n * wrapper: \"parent\",\r\n * },\r\n * loadManually: true,\r\n * loadImmediately: true,\r\n * reloadOnResize: false,\r\n * onLoading: element => element.style.opacity = .5,\r\n * onLoaded: [\r\n * element => window.console.log(\"Callback 1 for\", element),\r\n * element => window.console.log(\"Callback 2 for\", element),\r\n * ],\r\n * onError: element => element.style.display = \"none\",\r\n * loaderFunction: null,\r\n * });\r\n *\r\n *\r\n * @example JavaScript for handling lazy loading manually:\r\n * import { lazyLoad, LAZY_EVENTS } from \"./utils/dom/lazyLoad\";\r\n * import { triggerCustomEvent } from \"./utils/events/triggerCustomEvent\";\r\n * import { forEach } from \"./utils/forEach\";\r\n *\r\n * const images = document.querySelectorAll(\".lazy\");\r\n * lazyLoad(images, { loadManually: true });\r\n *\r\n * // Lazy load all the images after 2 seconds, including those outside the viewport.\r\n * setTimeout(() => forEach(images, image => triggerCustomEvent(image, LAZY_EVENTS.TRIGGER)), 2000);\r\n *\r\n *\r\n * @example\r\n * \r\n * JavaScript for loading sources immediately. That's not lazy at all, but the utility will still be used for setting\r\n * the relevant source and handling responsiveness:\r\n * \r\n * import { lazyLoad } from \"./utils/dom/lazyLoad\";\r\n * lazyLoad(images, { loadImmediately: true });\r\n *\r\n *\r\n * @example\r\n * \r\n * Finally, you can also specify the loader function yourself, which opens up for all kinds of possibilities, like lazy\r\n * bootstrapping a module:\r\n * \r\n * import { lazyLoad } from \"./utils/dom/lazyLoad\";\r\n *\r\n * const lazyModule = document.getElementById(\"lazy-module\");\r\n *\r\n * lazyLoad(lazyModule, {\r\n * loaderFunction: element => import(\"./modules/example\").then(module => {\r\n * new module.Example(element);\r\n * }),\r\n * });\r\n *\r\n *\r\n * @example Basic HTML for lazy loading a responsive image:\r\n * {@lang html}\r\n * \"Dummy\r\n *\r\n *\r\n * @example Basic HTML for lazy loading an image using `srcset` with a 2G network alternative:\r\n * {@lang html}\r\n * \"Dummy\r\n *\r\n *\r\n * @example It is possible to define placeholders for images to prevent reflow:\r\n * {@lang html}\r\n * // This automatically generates an inline SVG in the correct aspect ratio.\r\n * \"Dummy\r\n *\r\n * // Define different breakpoint specific aspect ratios.\r\n * \"Dummy\r\n *\r\n * // Define your own fallback sources.\r\n * // Be aware that this will make requests for the placeholders on page load.\r\n * \"Dummy\r\n *\r\n *\r\n * @example HTML for lazy loading a video in a suiting format and quality:\r\n * {@lang html}\r\n * \r\n *\r\n *\r\n * @example\r\n * \r\n * HTML for lazy loading a responsive background image with an alternative image for slow network connections:\r\n * \r\n * {@lang html}\r\n *

\r\n * ...\r\n *
\r\n *\r\n *\r\n * @example Other examples of HTML:\r\n * {@lang html}\r\n * \r\n *\r\n * \r\n *\r\n * \r\n *\r\n * \r\n *\r\n * \r\n *\r\n * \r\n *\r\n * \r\n * \r\n * \r\n * \"Dummy\r\n * \r\n *\r\n */\r\nimport { hasClass, addClass, removeClass } from \"./classList\";\r\nimport { onScroll, removeScrollCallback } from \"../events/onScroll\";\r\nimport {\r\n breakpointIndex,\r\n currentBreakpoint,\r\n onWindowResize\r\n} from \"../events/onWindowResize\";\r\nimport { isElementInViewport, isElementTag } from \"./elementProperties\";\r\nimport { decodeImage, loadImage } from \"../network/loadImage\";\r\nimport { addEvent, removeEvent } from \"../events/events\";\r\nimport { createElement } from \"./createElement\";\r\nimport { wrapElement } from \"./elementManipulation\";\r\nimport { triggerCustomEvent } from \"../events/triggerCustomEvent\";\r\nimport { forEach } from \"../forEach\";\r\n\r\n/**\r\n * All possible settings for the lazy load utility and their default values.\r\n *\r\n * @typedef {Object} LazyLoadSettings\r\n * @property {Object} [classNames]\r\n * @property {string} [classNames.base=\"lazy\"] - The base class name.\r\n * @property {string} [classNames.initialized=\"initialized\"] - The class modifier added when an element has been initialized to lazy load.\r\n * @property {string} [classNames.loading=\"loading\"] - The class modifier added when a source has started loading.\r\n * @property {string} [classNames.loaded=\"loaded\"] - The class modifier added when a source has been loaded.\r\n * @property {string} [classNames.error=\"error\"] - The class modifier added when a source has failed to load.\r\n * @property {string} [classNames.wrapper=\"wrapper\"] - The class modifier added to the wrapping elements created for `script`, `link` and `audio` (without the \"control\" property).\r\n * @property {boolean} [loadManually=false] - Set to true to trigger load manually. Otherwise sources will load as elements scroll into the viewport.\r\n * @property {boolean} [loadImmediately=false] - Set to true to load sources immediately.\r\n * @property {boolean} [reloadOnResize=true] - Reload the source on window resize, if the element makes use of the responsive data attributes (`xs`, `md`, `lg` etc.)\r\n * @property {function|function[]} [onLoading] - Optional callback(s) to fire when a source starts loading. Single function or array of functions.\r\n * @property {function|function[]} [onLoaded] - Optional callback(s) to fire when a source has loaded. Single function or array of functions.\r\n * @property {function|function[]} [onError] - Optional callback(s) to fire in case a source fails to load. Single function or array of functions.\r\n * @property {function} [loaderFunction] - If you want to define your own loader function, you can do it here.\r\n */\r\n\r\n/**\r\n * All the data (including settings) used for lazy loading elements.\r\n *\r\n * @ignore\r\n * @typedef {Object} LazyLoadData\r\n * @property {boolean} handleResponsive - True if lazyLoad should handle responsiveness.\r\n * @property {boolean} useSourceChildren - True if the element has source (or track) tags. Can be true for picture, video and audio.\r\n * @property {boolean} hasLoaded - True if a source has been loaded at some point.\r\n * @property {Object} elements - Object of elements.\r\n * @property {Element} elements.base - Base element.\r\n * @property {Element} elements.outer - Wrapper element.\r\n * @property {Element} elements.control - The element with the visible source and events (img in picture, otherwise same as base).\r\n * @property {Node|NodeList} elements.sourceChildren - Child elements with sources ( and ).\r\n */\r\n\r\n/**\r\n * All global settings for the lazy load utility.\r\n *\r\n * @typedef {Object} LazyLoadGlobalSettings\r\n * @property {number} [bufferMarginPx=100] - The number of pixels outside of the viewport to start loading elements.\r\n * @property {number} [onScrollThrottleMs=250] - Optional throttle value, given in milliseconds. If omitted, no throttling is employed.\r\n */\r\n\r\n/**\r\n * @ignore\r\n * @type {LazyLoadSettings}\r\n */\r\nconst defaultSettings = {\r\n classNames: {\r\n base: \"lazy\",\r\n initialized: \"initialized\",\r\n loading: \"loading\",\r\n loaded: \"loaded\",\r\n error: \"error\",\r\n wrapper: \"wrapper\"\r\n },\r\n loadManually: false,\r\n loadImmediately: false,\r\n reloadOnResize: true\r\n};\r\n\r\n/**\r\n * @ignore\r\n * @type {LazyLoadGlobalSettings}\r\n */\r\nlet globalSettings = {\r\n bufferMarginPx: 100,\r\n onScrollThrottleMs: 250\r\n};\r\n\r\nconst isEventListenerSet = {\r\n scroll: false,\r\n resize: false\r\n};\r\n\r\n// We'll be using Map and not a regular object, since Map supports using objects as keys.\r\n// To support IE11 you must include the required polyfill. The default polyfill from polyfill.io v3 is fine.\r\nconst elementsLoaded = new Map();\r\nconst elementsNotLoaded = new Map();\r\nconst elementsHandledManually = new Map();\r\n\r\nconst sourceAttribute = \"data-lazy\";\r\nconst placeholderAttribute = \"data-lazy-placeholder\";\r\nconst slowConnectionEffectiveTypes = [\"2g\", \"3g\"]; // These must be ordered from slow to fast.\r\n\r\n// An array of all possible data attributes defining sources.\r\nconst allSourceAttributes = [\r\n sourceAttribute,\r\n ...slowConnectionEffectiveTypes.reduce(\r\n (accumulated, type) => accumulated.concat(`${sourceAttribute}-${type}`),\r\n []\r\n )\r\n];\r\n\r\n/**\r\n * Event names used when triggering ... events!\r\n * @type {{TRIGGER: string, LOADING: string, LOADED: string, ERROR: string}}\r\n *\r\n *\r\n * @example Basic usage:\r\n * import { addEvent } from \"./utils/events/events\";\r\n * import {\r\n * lazyLoad,\r\n * LAZY_EVENTS,\r\n * LAZY_EVENT_TARGET,\r\n * } from \"./utils/dom/lazyLoad\";\r\n *\r\n * addEvent(LAZY_EVENT_TARGET, LAZY_EVENTS.LOADING, event => {\r\n * window.console.log(\"Source started loading\", event.detail.element);\r\n * });\r\n *\r\n * addEvent(LAZY_EVENT_TARGET, LAZY_EVENTS.LOADED, event => {\r\n * window.console.log(\"Source has loaded\", event.detail.element);\r\n * });\r\n *\r\n * addEvent(LAZY_EVENT_TARGET, LAZY_EVENTS.ERROR, event => {\r\n * window.console.log(\"Something went wrong\", event.detail.element);\r\n * });\r\n *\r\n * lazyLoad(\".lazy\");\r\n *\r\n *\r\n * @example Lazy load an element manually:\r\n * import { addEvent } from \"./utils/events/events\";\r\n * import { triggerCustomEvent } from \"./utils/events/triggerCustomEvent\";\r\n * import {\r\n * lazyLoad,\r\n * LAZY_EVENTS,\r\n * LAZY_EVENT_TARGET,\r\n * } from \"./utils/dom/lazyLoad\";\r\n *\r\n * const element = document.querySelector(\".lazy\");\r\n * lazyLoad(element, { loadManually: true });\r\n *\r\n * triggerCustomEvent(element, LAZY_EVENTS.TRIGGER);\r\n *\r\n * addEvent(LAZY_EVENT_TARGET, LAZY_EVENTS.LOADED, event => {\r\n * window.console.log(\"Element loaded manually\", event.detail.element);\r\n * });\r\n */\r\nexport const LAZY_EVENTS = {\r\n TRIGGER: \"akqa.lazyLoad:trigger\",\r\n LOADING: \"akqa.lazyLoad:loading\",\r\n LOADED: \"akqa.lazyLoad:loaded\",\r\n ERROR: \"akqa.lazyLoad:error\"\r\n};\r\n\r\n/**\r\n * The element on which events will be triggered.\r\n * @type {HTMLElement}\r\n */\r\nexport const LAZY_EVENT_TARGET = document.documentElement;\r\n\r\n/**\r\n * Trigger notifiers (callbacks and events).\r\n * @ignore\r\n * @type {{loading: function, loaded: function, error: function}}\r\n */\r\nconst notifiers = {\r\n loading: data => triggerNotifiers(\"loading\", data),\r\n loaded: data => triggerNotifiers(\"loaded\", data),\r\n error: data => triggerNotifiers(\"error\", data)\r\n};\r\n\r\n/**\r\n * Trigger notifiers (callbacks and events).\r\n *\r\n * @ignore\r\n * @param {string} action\r\n * @param {LazyLoadData} data\r\n */\r\nfunction triggerNotifiers(action, data) {\r\n const callbackName = `on${action.charAt(0).toUpperCase() +\r\n action.slice(1)}`;\r\n const eventName = LAZY_EVENTS[action.toUpperCase()];\r\n\r\n data[callbackName].forEach(funcRef => funcRef(data.elements.base));\r\n triggerCustomEvent(LAZY_EVENT_TARGET, eventName, {\r\n element: data.elements.base\r\n });\r\n}\r\n\r\n/**\r\n * Check if an element needs a wrapper.\r\n *\r\n * @ignore\r\n * @param {Element|HTMLAudioElement} element\r\n * @returns {boolean}\r\n */\r\nconst elementNeedsWrapper = element =>\r\n isElementTag(element, \"script\", \"link\", \"embed\") ||\r\n (isElementTag(element, \"audio\") && !element.controls);\r\n\r\n/**\r\n * Detect and load elements that are visible in the viewport.\r\n * @ignore\r\n */\r\nfunction detectElementsInViewport() {\r\n if (elementsNotLoaded.size) {\r\n elementsNotLoaded.forEach(data => {\r\n if (\r\n isElementInViewport(\r\n data.elements.outer,\r\n globalSettings.bufferMarginPx\r\n )\r\n ) {\r\n const newSource = getSourcesFromAttribute(data);\r\n setSource(newSource, data);\r\n }\r\n });\r\n } else {\r\n removeScrollCallback(window, detectElementsInViewport);\r\n isEventListenerSet.scroll = false;\r\n }\r\n}\r\n\r\n/**\r\n * Get sources from the most relevant attribute.\r\n *\r\n * @ignore\r\n * @param {LazyLoadData} data\r\n * @param {string} [attributeName] - Optional attribute name. If none is defined, we'll find the most appropriate.\r\n * @returns {{sources: string[], breakpointCount: number, attribute: string}}\r\n */\r\nfunction getSourcesFromAttribute(\r\n { useSourceChildren, elements },\r\n attributeName\r\n) {\r\n const defaultSourceName = \"default\";\r\n const sources = [];\r\n let isSrcsetSyntax = true;\r\n let breakpointCount = 0;\r\n\r\n let sourceElements = elements.base;\r\n\r\n if (\r\n useSourceChildren &&\r\n (!attributeName || !elements.base.hasAttribute(attributeName))\r\n ) {\r\n sourceElements = elements.sourceChildren;\r\n }\r\n\r\n forEach(sourceElements, sourceElement => {\r\n let newSource = {};\r\n let sourceData;\r\n let closestBreakpoint = 0;\r\n let closestBreakpointName = defaultSourceName;\r\n\r\n // An attribute name was supplied. Let's get whatever data is in that attribute.\r\n if (attributeName) {\r\n sourceData = sourceElement.getAttribute(attributeName);\r\n }\r\n\r\n // No attribute name was supplied - let's find one that suits the network speed,\r\n // and get whatever data is in that attribute.\r\n else {\r\n // Get the current connection effective type (\"2g\", \"3g\" or \"4g\" - we don't care about \"slow-2g\").\r\n // This is determined using a combination of recently observed round-trip time and estimated bandwidth.\r\n const currentConnectionType =\r\n \"connection\" in navigator &&\r\n \"effectiveType\" in navigator.connection\r\n ? navigator.connection.effectiveType.slice(-2)\r\n : null;\r\n\r\n // Find the index of the current connection effective type in our array of slow connection effective types.\r\n const minimumConnectionTypeIndex = slowConnectionEffectiveTypes.indexOf(\r\n currentConnectionType\r\n );\r\n\r\n // Search for an attribute with a source fitting the current connection effective type, by going through our\r\n // array of slow connection effective types, looking for something equal to or better than the current\r\n // effective type of the user's network.\r\n sourceData =\r\n slowConnectionEffectiveTypes.reduce(\r\n (foundAttributeValue, value, index) => {\r\n // If we already found a suiting attribute, let's just keep that.\r\n // If the user's connection type isn't in the array, it must be fast (4g or faster),\r\n // and then there's no need for checking attributes aimed at slow speed networks.\r\n if (\r\n minimumConnectionTypeIndex === -1 ||\r\n foundAttributeValue\r\n ) {\r\n return foundAttributeValue;\r\n }\r\n\r\n // User is on a slow connection - look for a suiting data attribute.\r\n if (index >= minimumConnectionTypeIndex) {\r\n return (\r\n sourceElement.getAttribute(\r\n `${sourceAttribute}-${value}`\r\n ) || \"\"\r\n );\r\n }\r\n\r\n return \"\";\r\n },\r\n \"\"\r\n ) || sourceElement.getAttribute(sourceAttribute); // If no slow speed attributes were found, use the default attribute.\r\n }\r\n\r\n if (sourceData) {\r\n // Parse the data from the attribute.\r\n // This can be either JSON or comma separated like \"xxs: [...], md: [...], xl: [...]\".\r\n try {\r\n newSource = JSON.parse(sourceData);\r\n } catch (error) {\r\n isSrcsetSyntax = /\\s[0-9]+(w|x)\\s*(,|$)/g.test(sourceData);\r\n\r\n if (isSrcsetSyntax) {\r\n const srcsetFileRegex = /((?:[^\\s,][^,]+?(?=\\s[0-9]+(?:w|x)\\s*(,|$)))|(^(?!\\s[0-9]+(?:w|x))).*$)/g;\r\n newSource[\r\n defaultSourceName\r\n ] = sourceData.replace(srcsetFileRegex, match =>\r\n encodeURI(match)\r\n );\r\n } else {\r\n const dataArray = sourceData.split(/,\\s?/);\r\n\r\n dataArray.forEach(item => {\r\n if (item) {\r\n const trimmedItem = item.trim();\r\n const colonIndex = trimmedItem.indexOf(\":\");\r\n let key = trimmedItem.substring(0, colonIndex);\r\n let value = trimmedItem;\r\n\r\n if (key in breakpointIndex) {\r\n value = trimmedItem.substring(colonIndex + 1);\r\n } else {\r\n key = defaultSourceName;\r\n }\r\n\r\n value = value.trim().replace(/^\"|'|\"|'$/g, \"\");\r\n\r\n newSource[key] = encodeURI(value);\r\n }\r\n });\r\n }\r\n }\r\n\r\n // Find the most relevant source for the current breakpoint.\r\n const sourcesKeys = Object.keys(newSource);\r\n breakpointCount = Math.max(breakpointCount, sourcesKeys.length);\r\n\r\n if (breakpointCount === 1) {\r\n closestBreakpointName = sourcesKeys[0];\r\n } else {\r\n forEach(newSource, (source, key) => {\r\n const thisBreakpoint = breakpointIndex[key];\r\n\r\n if (\r\n thisBreakpoint &&\r\n (thisBreakpoint === currentBreakpoint ||\r\n (closestBreakpoint !== currentBreakpoint &&\r\n (!closestBreakpoint ||\r\n (thisBreakpoint <= currentBreakpoint &&\r\n thisBreakpoint > closestBreakpoint))))\r\n ) {\r\n closestBreakpoint = thisBreakpoint;\r\n closestBreakpointName = key;\r\n }\r\n });\r\n }\r\n }\r\n\r\n sources.push(newSource[closestBreakpointName]);\r\n });\r\n\r\n return {\r\n attribute: isElementTag(elements.base, \"link\")\r\n ? \"href\"\r\n : isSrcsetSyntax\r\n ? \"srcset\"\r\n : \"src\",\r\n breakpointCount,\r\n sources\r\n };\r\n}\r\n\r\n/**\r\n * Get the most appropriate placeholder source.\r\n *\r\n * The value of the data attribute must be `path/to/source.jpg` or a comma separated list (or JSON) of breakpoints\r\n * `xxs: path/to/xxs.jpg, md: path/to/xxs.jpg`. Instead of paths you can also define aspect ratios which will generate\r\n * an SVG data URI: `4x3` or `sm: 4x3, md: 16x9, lg: 16x10` or `{ \"sm\": \"4x3\", \"md\": \"16:9\" }`.\r\n *\r\n * @ignore\r\n * @param {Element} element\r\n * @param {LazyLoadData} data\r\n * @returns {string}\r\n */\r\nfunction getPlaceholder(element, data) {\r\n let source;\r\n let x;\r\n let y;\r\n\r\n if (element.hasAttribute(placeholderAttribute)) {\r\n source = getSourcesFromAttribute(data, placeholderAttribute);\r\n\r\n // Test if the source string matches the pattern {number}x{number}\r\n if (/^[0-9]+x[0-9]+$/.test(source.sources[0])) {\r\n const [width, height] = source.sources[0].split(\"x\");\r\n x = parseFloat(width);\r\n y = parseFloat(height);\r\n }\r\n } else {\r\n x = 1;\r\n y = 1;\r\n }\r\n\r\n return isNaN(x) || isNaN(y)\r\n ? source\r\n : {\r\n attribute: \"src\",\r\n breakpointCount: source ? source.breakpointCount : 1,\r\n sources: [\r\n `data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"${x}\" height=\"${y}\" viewBox=\"0 0 ${x} ${y}\"%3E%3C/svg%3E`\r\n ]\r\n };\r\n}\r\n\r\n/**\r\n * Set placeholder on an element.\r\n *\r\n * @ignore\r\n * @param {LazyLoadData} data\r\n */\r\nfunction setPlaceholder(data) {\r\n const { elements, hasLoaded } = data;\r\n\r\n if (!hasLoaded && elements.control) {\r\n const isImgWithoutSrc =\r\n isElementTag(elements.control, \"img\") && !elements.control.src;\r\n const elementWithPlaceholderData = elements.base.hasAttribute(\r\n placeholderAttribute\r\n )\r\n ? elements.base\r\n : elements.control.hasAttribute(placeholderAttribute)\r\n ? elements.control\r\n : undefined;\r\n\r\n // Continue if the element has an attribute with a defined placeholder,\r\n // or if it's an image with no src. Src is mandatory, you know.\r\n if (elementWithPlaceholderData || isImgWithoutSrc) {\r\n const newSource = getPlaceholder(\r\n elementWithPlaceholderData || elements.control,\r\n data\r\n );\r\n\r\n setSource(newSource, data, true);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Update source attribute.\r\n *\r\n * @ignore\r\n * @param {Element} element\r\n * @param {string} attribute\r\n * @param {string} source\r\n */\r\nfunction updateSourceAttribute(element, attribute, source) {\r\n if (source && element[attribute] !== source) {\r\n element[attribute] = source;\r\n }\r\n}\r\n\r\n/**\r\n * Set event listeners for load and error.\r\n *\r\n * @ignore\r\n * @param {LazyLoadData} data\r\n * @param {boolean} [isPlaceholder=false]\r\n * @param {boolean} [useCanPlay=false]\r\n */\r\nfunction setLoadEventListeners(\r\n data,\r\n { isPlaceholder = false, useCanPlay = false }\r\n) {\r\n const element = data.elements.control;\r\n const loadEvent = useCanPlay ? \"canplay\" : \"load\";\r\n\r\n addEvent(element, loadEvent, () => {\r\n removeEvent(element, `${loadEvent} error`);\r\n\r\n if (!isPlaceholder) {\r\n setClassName(data, \"loaded\");\r\n notifiers.loaded(data);\r\n }\r\n });\r\n\r\n addEvent(element, \"error\", () => {\r\n removeEvent(element, `${loadEvent} error`);\r\n\r\n if (!isPlaceholder) {\r\n setClassName(data, \"error\");\r\n notifiers.error(data);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set the source of an element or trigger the custom loader function.\r\n *\r\n * @ignore\r\n * @param {Object} newSource\r\n * @param {LazyLoadData} data\r\n * @param {boolean} data.useSourceChildren - Set to true if we are setting the source to a placeholder, and the classes won't change and notifiers won't be executed.\r\n * @param {boolean} [isPlaceholder=false]\r\n */\r\nfunction setSource(newSource, data, isPlaceholder = false) {\r\n const { useSourceChildren, loaderFunction, elements } = data;\r\n\r\n // Only continue if the new source is not the same as the one already in use.\r\n if (loaderFunction && !isPlaceholder) {\r\n setClassName(data, \"loaded\");\r\n notifiers.loading(data);\r\n notifiers.loaded(data);\r\n loaderFunction(elements.base);\r\n } else {\r\n // Element uses source tags (picture, video, audio)\r\n if (useSourceChildren) {\r\n if (!isPlaceholder) {\r\n setClassName(data, \"loading\");\r\n notifiers.loading(data);\r\n }\r\n\r\n // Picture (load and decode)\r\n if (isElementTag(elements.base, \"picture\")) {\r\n const elementClone = elements.base.cloneNode(true);\r\n const elementCloneImg = elementClone.querySelector(\"img\");\r\n\r\n addEvent(elementCloneImg, \"load\", () => {\r\n removeEvent(elementCloneImg, \"load error\");\r\n\r\n decodeImage(elementCloneImg).then(() => {\r\n if (isPlaceholder) {\r\n updateSourceAttribute(\r\n elements.control,\r\n \"src\",\r\n newSource.sources[0]\r\n );\r\n } else {\r\n let i = 0;\r\n forEach(elements.sourceChildren, sourceTag => {\r\n updateSourceAttribute(\r\n sourceTag,\r\n \"srcset\",\r\n newSource.sources[i]\r\n );\r\n i += 1;\r\n });\r\n\r\n setClassName(data, \"loaded\");\r\n notifiers.loaded(data);\r\n }\r\n });\r\n });\r\n\r\n addEvent(elementCloneImg, \"error\", () => {\r\n removeEvent(elementCloneImg, \"load error\");\r\n\r\n if (!isPlaceholder) {\r\n setClassName(data, \"error\");\r\n notifiers.error(data);\r\n }\r\n });\r\n\r\n if (isPlaceholder) {\r\n updateSourceAttribute(\r\n elementCloneImg,\r\n \"src\",\r\n newSource.sources[0]\r\n );\r\n } else {\r\n let i = 0;\r\n forEach(\r\n elementClone.querySelectorAll(\"source\"),\r\n sourceTag => {\r\n updateSourceAttribute(\r\n sourceTag,\r\n \"srcset\",\r\n newSource.sources[i]\r\n );\r\n i += 1;\r\n }\r\n );\r\n }\r\n }\r\n\r\n // Audio and video\r\n else {\r\n setLoadEventListeners(data, {\r\n isPlaceholder,\r\n useCanPlay: true\r\n });\r\n\r\n forEach(elements.sourceChildren, sourceTag =>\r\n updateSourceAttribute(\r\n sourceTag,\r\n \"src\",\r\n newSource.sources[0]\r\n )\r\n );\r\n\r\n elements.base.load();\r\n }\r\n }\r\n\r\n // Element doesn't use source tags\r\n else {\r\n const isImage = isElementTag(elements.base, \"img\");\r\n const isBackgroundImage = !isElementTag(\r\n elements.base,\r\n \"img\",\r\n \"iframe\",\r\n \"audio\",\r\n \"video\",\r\n \"embed\",\r\n \"script\",\r\n \"link\"\r\n );\r\n const backgroundUrl = `url(${newSource.sources[0]})`;\r\n\r\n // Stop now if the found source is the same as the one currently in use\r\n if (\r\n isBackgroundImage\r\n ? elements.outer.style.backgroundImage === backgroundUrl\r\n : elements.control[newSource.sources.attribute] ===\r\n newSource.sources[0]\r\n ) {\r\n return;\r\n }\r\n\r\n if (!isPlaceholder) {\r\n setClassName(data, \"loading\");\r\n notifiers.loading(data);\r\n }\r\n\r\n // Handle the loading (or failing thereof) and decoding of images\r\n if (isImage || isBackgroundImage) {\r\n const useSrcset = newSource.attribute === \"srcset\";\r\n\r\n loadImage(newSource.sources[0], {\r\n useSrcset,\r\n sizes: elements.base.sizes\r\n })\r\n .then(() => {\r\n if (isBackgroundImage) {\r\n elements.outer.style.backgroundImage = backgroundUrl;\r\n } else {\r\n elements.control.srcset = \"\";\r\n elements.control[newSource.attribute] =\r\n newSource.sources[0];\r\n }\r\n\r\n if (!isPlaceholder) {\r\n setClassName(data, \"loaded\");\r\n notifiers.loaded(data);\r\n }\r\n })\r\n .catch(() => {\r\n if (!isPlaceholder) {\r\n setClassName(data, \"error\");\r\n notifiers.error(data);\r\n }\r\n });\r\n }\r\n\r\n // Handle embed - sadly, we can't rely on the events to be fired.\r\n // The load and error events work with some content in embed elements, but not with everything. :-(\r\n else if (isElementTag(elements.base, \"embed\")) {\r\n setLoadEventListeners(data, {\r\n isPlaceholder,\r\n useCanPlay: true\r\n });\r\n updateSourceAttribute(\r\n elements.control,\r\n \"src\",\r\n newSource.sources[0]\r\n );\r\n\r\n if (!isPlaceholder) {\r\n setClassName(data, \"loaded\");\r\n notifiers.loaded(data);\r\n }\r\n }\r\n\r\n // Handle the loading of audio and video\r\n else if (isElementTag(elements.base, \"audio\", \"video\")) {\r\n setLoadEventListeners(data, {\r\n isPlaceholder,\r\n useCanPlay: true\r\n });\r\n updateSourceAttribute(\r\n elements.control,\r\n \"src\",\r\n newSource.sources[0]\r\n );\r\n elements.base.load();\r\n }\r\n\r\n // Handle the loading of everything else\r\n else {\r\n setLoadEventListeners(data, { isPlaceholder });\r\n updateSourceAttribute(\r\n elements.control,\r\n newSource.attribute,\r\n newSource.sources[0]\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (!isPlaceholder) {\r\n if (elementsNotLoaded.has(elements.base)) {\r\n elementsNotLoaded.delete(elements.base);\r\n elementsLoaded.set(elements.base, { ...data, hasLoaded: true });\r\n } else if (elementsHandledManually.has(elements.base)) {\r\n elementsHandledManually.set(elements.base, {\r\n ...data,\r\n hasLoaded: true\r\n });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Ensure that callbacks are in arrays.\r\n *\r\n * @ignore\r\n * @param {function|function[]} callbackList\r\n * @returns {Array}\r\n */\r\nfunction sanitizeCallbacks(callbackList) {\r\n return callbackList instanceof Array\r\n ? callbackList\r\n : typeof callbackList === \"function\"\r\n ? [callbackList]\r\n : [];\r\n}\r\n\r\n/**\r\n * Reset elements so they can be updated to match the current breakpoint when appropriate.\r\n * @ignore\r\n */\r\nfunction resetElementsWithResponsiveSources() {\r\n elementsLoaded.forEach((data, element) => {\r\n if (data.handleResponsive) {\r\n if (data.loadImmediately) {\r\n const newSource = getSourcesFromAttribute(data);\r\n setSource(newSource, data);\r\n } else {\r\n elementsLoaded.delete(element);\r\n elementsNotLoaded.set(element, data);\r\n }\r\n }\r\n });\r\n\r\n if (elementsNotLoaded.size) {\r\n if (!isEventListenerSet.scroll) {\r\n onScroll(\r\n window,\r\n detectElementsInViewport,\r\n globalSettings.onScrollThrottleMs\r\n );\r\n isEventListenerSet.scroll = true;\r\n }\r\n\r\n elementsNotLoaded.forEach(data => setPlaceholder(data));\r\n\r\n detectElementsInViewport();\r\n }\r\n\r\n if (elementsHandledManually.size) {\r\n elementsHandledManually.forEach(\r\n data => data.hasLoaded || setPlaceholder(data)\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Set class name on element.\r\n *\r\n * @ignore\r\n * @param {LazyLoadData} data\r\n * @param {(\"initialized\"|\"loading\"|\"error\"|\"loaded\"|null)} state - Set to \"initialized\", \"loading\", \"error\" or \"loaded\". Or null to remove all class names.\r\n */\r\nfunction setClassName({ classNames, elements }, state) {\r\n const classes = {\r\n initialized: `${classNames.base}--${classNames.initialized}`,\r\n loading: `${classNames.base}--${classNames.loading}`,\r\n loaded: `${classNames.base}--${classNames.loaded}`,\r\n error: `${classNames.base}--${classNames.error}`\r\n };\r\n\r\n removeClass(\r\n elements.outer,\r\n [classes.loading, classes.loaded, classes.error].concat(\r\n state ? [] : classes.initialized\r\n )\r\n );\r\n\r\n if (state) {\r\n addClass(elements.outer, classes[state]);\r\n }\r\n}\r\n\r\n/**\r\n * Setup lazy load. If you wanna lazy load something, you've come to the right place.\r\n *\r\n * @param {string|NodeList|Element|Element[]} [elements] - The elements to lazy load or a selector to query. If none is given, a selector will be generated from all the possible data attributes.\r\n * @param {LazyLoadSettings} [options={}] - An object with settings.\r\n */\r\nexport function lazyLoad(elements, options = {}) {\r\n const settings = {\r\n ...defaultSettings,\r\n ...options,\r\n classNames: {\r\n ...defaultSettings.classNames,\r\n ...(options && options.classNames)\r\n },\r\n onLoading: sanitizeCallbacks(options.onLoading),\r\n onLoaded: sanitizeCallbacks(options.onLoaded),\r\n onError: sanitizeCallbacks(options.onError)\r\n };\r\n let elementsToLoad;\r\n\r\n // Find elements to load from a given selector string\r\n // or create a selector string of all the possible data attributes.\r\n if (!elements || typeof elements === \"string\") {\r\n elementsToLoad = document.querySelectorAll(\r\n elements || `[${sourceAttribute}]`\r\n );\r\n }\r\n\r\n // A NodeList or an array of elements was given.\r\n else if (typeof elements === \"object\" && elements.length) {\r\n elementsToLoad = elements;\r\n }\r\n\r\n // A single element was given.\r\n else if (elements instanceof Element) {\r\n elementsToLoad = [elements];\r\n }\r\n\r\n if (!elementsToLoad) {\r\n throw new Error(\r\n \"lazyLoad's elements argument was not given as a string or a nodeList.\"\r\n );\r\n }\r\n\r\n if (elementsToLoad.length) {\r\n let setResizeEventListener = false;\r\n\r\n forEach(elementsToLoad, elementToLoad => {\r\n const {\r\n classNames,\r\n loadManually,\r\n loadImmediately,\r\n reloadOnResize\r\n } = settings;\r\n const defaultElement = isElementTag(\r\n elementToLoad,\r\n \"source\",\r\n \"track\"\r\n )\r\n ? elementToLoad.parentElement\r\n : elementToLoad;\r\n const elements = {\r\n base: defaultElement,\r\n outer: defaultElement,\r\n control: defaultElement,\r\n sourceChildren: defaultElement\r\n };\r\n let useSourceChildren = false;\r\n\r\n // Only continue if element hasn't already been initialized.\r\n if (\r\n !elementsLoaded.has(elements.base) &&\r\n !elementsNotLoaded.has(elements.base) &&\r\n !elementsHandledManually.has(elements.base)\r\n ) {\r\n // Some elements need a wrapper.\r\n if (elementNeedsWrapper(elements.base)) {\r\n // If the element already has a wrapper, we should just skip it.\r\n if (\r\n hasClass(\r\n elements.base.parentElement,\r\n `${classNames.base}--${classNames.wrapper}`\r\n )\r\n ) {\r\n return;\r\n }\r\n\r\n elements.outer = createElement(\"div\", {\r\n className: [\r\n `${classNames.base}--${classNames.wrapper}`,\r\n `${\r\n classNames.base\r\n }--${elements.base.tagName.toLowerCase()}`\r\n ],\r\n style: isElementTag(elements.base, \"embed\")\r\n ? {}\r\n : {\r\n display: \"inline-block\",\r\n visibility: \"hidden\",\r\n margin: 0,\r\n border: 0,\r\n padding: 0,\r\n height: 0,\r\n width: 0\r\n }\r\n });\r\n\r\n wrapElement(elements.base, elements.outer);\r\n }\r\n\r\n // Some elements have children of the source and track variety and need to be handled differently.\r\n if (isElementTag(elements.base, \"picture\", \"audio\", \"video\")) {\r\n const sources = elements.base.querySelectorAll(\r\n \"source, track\"\r\n );\r\n\r\n if (sources.length) {\r\n elements.sourceChildren = sources;\r\n useSourceChildren = true;\r\n }\r\n\r\n if (isElementTag(elements.base, \"picture\")) {\r\n elements.control = elements.base.querySelector(\"img\");\r\n }\r\n }\r\n\r\n const elementData = {\r\n ...settings,\r\n handleResponsive: false,\r\n useSourceChildren,\r\n elements,\r\n hasLoaded: loadImmediately\r\n };\r\n\r\n elementData.handleResponsive =\r\n reloadOnResize &&\r\n allSourceAttributes.reduce(\r\n (isResponsive, attribute) =>\r\n isResponsive ||\r\n getSourcesFromAttribute(elementData, attribute)\r\n .breakpointCount > 1,\r\n false\r\n );\r\n\r\n // If any of the elements have attributes for breakpoints,\r\n // that must mean we should handle responsiveness,\r\n // thus we'll need to listen for the window resize event.\r\n if (elementData.handleResponsive) {\r\n setResizeEventListener = true;\r\n }\r\n\r\n if (!hasClass(elements.outer, classNames.base)) {\r\n addClass(elements.outer, classNames.base);\r\n }\r\n\r\n setClassName(elementData, \"initialized\");\r\n\r\n // Store the element in the appropriate Map object.\r\n (loadManually\r\n ? elementsHandledManually\r\n : loadImmediately\r\n ? elementsLoaded\r\n : elementsNotLoaded\r\n ).set(elements.base, elementData);\r\n\r\n // Listen for the TRIGGER event.\r\n addEvent(elements.base, LAZY_EVENTS.TRIGGER, () => {\r\n const data =\r\n elementsHandledManually.get(elements.base) ||\r\n elementsLoaded.get(elements.base) ||\r\n elementsNotLoaded.get(elements.base);\r\n const newSource = getSourcesFromAttribute(data);\r\n setSource(newSource, data);\r\n });\r\n\r\n // Load source immediately if that's what's up.\r\n if (loadImmediately) {\r\n const newSource = getSourcesFromAttribute(elementData);\r\n setSource(newSource, elementData);\r\n }\r\n\r\n // Set placeholder SVGs for images. For IMG elements, src is a mandatory attribute,\r\n // so if no src or placeholder is defined, it will be set to a blank 1x1px SVG.\r\n else {\r\n setPlaceholder(elementData);\r\n }\r\n }\r\n });\r\n\r\n // Show elements that are already visible in the viewport.\r\n detectElementsInViewport();\r\n\r\n // Set event listeners if they are needed and haven't been set already.\r\n if (!isEventListenerSet.scroll && elementsNotLoaded.size) {\r\n onScroll(\r\n window,\r\n detectElementsInViewport,\r\n globalSettings.onScrollThrottleMs\r\n );\r\n isEventListenerSet.scroll = true;\r\n }\r\n\r\n if (!isEventListenerSet.resize && setResizeEventListener) {\r\n onWindowResize(resetElementsWithResponsiveSources);\r\n isEventListenerSet.resize = true;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Remove lazy load functionality from element.\r\n *\r\n * @param {Element|Element[]|NodeList} elements\r\n */\r\nexport function removeLazyLoad(elements) {\r\n if (elements) {\r\n forEach(elements, element => {\r\n const data =\r\n elementsLoaded.get(element) ||\r\n elementsNotLoaded.get(element) ||\r\n elementsHandledManually.get(element);\r\n\r\n if (data) {\r\n setClassName(data, null);\r\n removeEvent(element, LAZY_EVENTS.TRIGGER);\r\n removeEvent(data.elements.control, \"load canplay error\");\r\n elementsLoaded.delete(element) ||\r\n elementsNotLoaded.delete(element) ||\r\n elementsHandledManually.delete(element);\r\n }\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Change the global settings. If you're gonna use this, you should do it before running `lazyLoad()`.\r\n *\r\n * @param {LazyLoadGlobalSettings} options - Global settings to overwrite.\r\n */\r\nexport function setLazyLoadGlobalSettings(options) {\r\n globalSettings = {\r\n ...globalSettings,\r\n ...options\r\n };\r\n}\r\n","/**\r\n * This utility will check if a clicked element matches a specific element or any of its\r\n * children and then executes a custom function once.\r\n *\r\n * This could be handy for closing popover boxes or open menus by clicking elsewhere.\r\n *\r\n * Use `onClickOutsideContinuously()` to keep the event listener running.\r\n * Use `removeOnClickOutside()` to remove event listeners.\r\n *\r\n * @module utils/events/onClickOutside\r\n * @author Lars Munkholm \r\n */\r\n\r\nimport { addEvent, removeEvent } from \"./events\";\r\nimport { forEach } from \"../forEach\";\r\nimport { isArray } from \"../typeCheckers\";\r\n\r\n// We'll be using Map and not a regular object, since Map supports using objects as keys.\r\n// This requires you to include the required polyfill. \"default-3.6\" from polyfill.io is fine.\r\nconst eventsMap = new Map();\r\n\r\n/**\r\n * Listen for clicks outside the given element - but only once.\r\n *\r\n * @param {HTMLElement|Element} element - Element to match with clicked element.\r\n * @param {function} eventHandler - Callback function to execute when clicked outside element.\r\n * @param {HTMLElement|Element|HTMLDocument|Window} [clickElement=window] - Element to attach event listener to. Defaults to window.\r\n * @param {boolean} [onlyOnce=true] - Whether or not to run the event continuously or remove it after its first run.\r\n *\r\n * @example Basic usage\r\n * import { onClickOutside } from './utils/onClickOutside';\r\n *\r\n * onClickOutside(\r\n * this.dom.myElement,\r\n * () => {\r\n * // Do stuff\r\n * }\r\n * );\r\n *\r\n *\r\n * @example Usage with custom click area\r\n * import { onClickOutside } from './utils/onClickOutside';\r\n * onClickOutside(\r\n * this.dom.myElement,\r\n * () => {\r\n * // Do stuff\r\n * },\r\n * this.dom.myClickArea\r\n * );\r\n */\r\nexport function onClickOutside(\r\n element,\r\n eventHandler,\r\n clickElement = window,\r\n onlyOnce = true\r\n) {\r\n if (typeof eventHandler === \"function\") {\r\n const elementHandlers = eventsMap.get(clickElement) || new Map();\r\n const thisElementHandlers = elementHandlers.get(element) || [];\r\n\r\n const handleEvent = e => {\r\n if (elementHandlers && typeof elementHandlers === \"object\") {\r\n elementHandlers.forEach((callbackList, handleElement) => {\r\n if (!handleElement.contains(e.target)) {\r\n if (isArray(callbackList) && callbackList.length) {\r\n // Fire all associated event handlers!\r\n const tempCallbackList = callbackList.slice(0);\r\n forEach(tempCallbackList, callback => {\r\n callback.eventHandler(e);\r\n\r\n // Remove event if it is only to be fired once\r\n if (callback.onlyOnce) {\r\n callbackList.splice(\r\n callbackList.indexOf(callback),\r\n 1\r\n );\r\n\r\n // Clean eventsMap\r\n if (callbackList.length) {\r\n elementHandlers.set(\r\n handleElement,\r\n callbackList\r\n );\r\n } else {\r\n elementHandlers.delete(handleElement);\r\n }\r\n if (!elementHandlers.size) {\r\n removeEvent(\r\n clickElement,\r\n \"click touchstart\",\r\n handleEvent\r\n );\r\n eventsMap.delete(clickElement);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n });\r\n }\r\n };\r\n\r\n thisElementHandlers.push({ onlyOnce, eventHandler, handleEvent });\r\n\r\n // Only listen for this event on the given element, is said element hasn't already got an event listener\r\n if (!eventsMap.get(clickElement)) {\r\n // In case this function was called from within an event, set the new click handler inside\r\n // a timeout to allow the original event to finish propagating.\r\n setTimeout(() =>\r\n addEvent(clickElement, \"click touchstart\", handleEvent)\r\n );\r\n }\r\n\r\n elementHandlers.set(element, thisElementHandlers);\r\n eventsMap.set(clickElement, elementHandlers);\r\n }\r\n}\r\n\r\n/**\r\n * Stop listening for clicks outside an element.\r\n *\r\n * @param {HTMLElement|Element} element - The DOM element we'll be working on.\r\n * @param [eventHandlerToRemove] - A specific event handler to remove. If set, only that particular callback will be removed from the event type. If not, all callbacks for the event type are removed.\r\n * @param {HTMLElement|Element|HTMLDocument|Window} [clickElement=window] - Element which the event listener is attached to. Defaults to window.\r\n */\r\nexport function removeOnClickOutside(\r\n element,\r\n eventHandlerToRemove,\r\n clickElement = window\r\n) {\r\n const elementHandlers = eventsMap.get(clickElement);\r\n\r\n if (elementHandlers && typeof elementHandlers === \"object\") {\r\n const thisElementHandlers = elementHandlers.get(element);\r\n\r\n if (isArray(thisElementHandlers) && thisElementHandlers.length > 0) {\r\n const tempThisElementHandlers = thisElementHandlers.slice(0);\r\n forEach(tempThisElementHandlers, handler => {\r\n // If a specific event handler is set to be removed, remove that - or else: remove all handlers.\r\n if (\r\n typeof eventHandlerToRemove !== \"function\" ||\r\n eventHandlerToRemove === handler.handleEvent\r\n ) {\r\n thisElementHandlers.splice(\r\n thisElementHandlers.indexOf(handler),\r\n 1\r\n );\r\n\r\n // Clean eventsMap\r\n if (thisElementHandlers.length) {\r\n elementHandlers.set(element, thisElementHandlers);\r\n } else {\r\n elementHandlers.delete(element);\r\n }\r\n if (!elementHandlers.size) {\r\n removeEvent(clickElement, \"click\", handler.handleEvent);\r\n eventsMap.delete(clickElement);\r\n }\r\n }\r\n });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Listen for clicks outside the given element - continuously.\r\n *\r\n * @param {HTMLElement|Element} element - Element to match with clicked element.\r\n * @param {function} callback - Callback function to execute when clicked outside element.\r\n * @param {HTMLElement|Element|HTMLDocument|Window} [clickElement=window] - Element to attach event listener to. Defaults to window.\r\n */\r\nexport function onClickOutsideContinuously(\r\n element,\r\n callback,\r\n clickElement = window\r\n) {\r\n onClickOutside(element, callback, clickElement, false);\r\n}\r\n","/**\r\n * **Scroll the window** or **an element** smoothly to the desired position, with a promise-based callback.\r\n *\r\n * `Promise` is not supported in IE <= 11 and Safari <= 8. Make sure `Promise` is supplied by the\r\n * polyfill (version `default-3.4` and up).\r\n *\r\n * @module utils/dom/scrollTo\r\n * @author Lars Munkholm \r\n *\r\n *\r\n * @example Scroll window to 100px down on the Y-axis (using default duration of 1000ms)\r\n * import { scrollTo } from \"./utils/dom/scrollTo\";\r\n * scrollTo(100);\r\n *\r\n *\r\n * @example Your editor may warn you about ignoring the promise returned from `scrollTo()`. If you want to avoid this, use the `void` operator:\r\n * void scrollTo(100);\r\n *\r\n *\r\n * @example Scroll `window` to 1024px on the X-axis and 100px on the Y-axis (500ms duration)\r\n * void scrollTo([1024, 100], 500);\r\n *\r\n *\r\n * @example Scroll `#test` to 500px on the X- and Y-axis (1500ms duration), and output a string to the console when done\r\n * const scrollElement = document.getElementById(\"test\");\r\n * scrollTo([500, 500], 1500, scrollElement).then(() => window.console.log(\"Scroll done\"));\r\n * // or:\r\n * scrollTo([500, 500], 1500, \"test\").then(() => window.console.log(\"Scroll done\"));\r\n *\r\n *\r\n * @example Scroll `window` to reveal `#target` with -150 pixel offset on Y-axis\r\n * const targetElement = document.getElementById(\"target\");\r\n * void scrollTo(targetElement, 1000, window, -150);\r\n * // or:\r\n * void scrollTo(\"target\", 1000, window, -150);\r\n *\r\n *\r\n * @example Scroll `window` to reveal `#target` with 100 pixel offset on X-axis and -200 pixel offset on Y-axis\r\n * const targetElement = document.getElementById(\"target\");\r\n * void scrollTo(targetElement, 2000, window, [100, -200]);\r\n * // or:\r\n * void scrollTo(\"target\", 2000, window, [100, -200]);\r\n */\r\n\r\nimport { getElementPosition, getElementScroll } from \"./elementProperties\";\r\nimport { addEventOnce, removeEvent } from \"../events/events\";\r\nimport { isArray } from \"../typeCheckers\";\r\n\r\nconst defaultDuration = 1000;\r\n\r\n/**\r\n * Perform the scroll action\r\n *\r\n * @private\r\n * @param {Array} position - An array [x, y] of where to scroll to.\r\n * @param {HTMLElement|Window} element - Element to scroll inside.\r\n * @param {Boolean} isElementWindow - Is the element window.\r\n */\r\nfunction doScroll(position, element, isElementWindow) {\r\n if (isElementWindow) {\r\n element.scrollTo(position[0], position[1]);\r\n } else {\r\n element.scrollLeft = position[0];\r\n element.scrollTop = position[1];\r\n }\r\n}\r\n\r\n/**\r\n * Smooth scroll effect\r\n *\r\n * @param {Number|Number[]|HTMLElement|String} target - Where to scroll to.\r\n * If a number is given, it will be interpreted as pixels on the Y-axis.\r\n * If an array is given, it will be interpreted as `[x, y]`. Must be array of numbers.\r\n * If an HTML element is given, that will be the target instead.\r\n * If a string is given, an element with that string as its ID will be found and used.\r\n * @param {Number|Boolean|Null} [durationMs=1000] - Duration of scroll effect in ms. Defaults to `1000`.\r\n * @param {HTMLElement|String|Window} [targetElement=window] - Element to scroll inside. Defaults to `window`.\r\n * @param {Number|Number[]} [offsetPx=0] - Offset value in pixels for Y-axis, or as an array (`[x, y]`) that offsets both X and Y-axis. Defaults to `0`.\r\n * @param {Boolean} [isInterruptible=true] - Whether the scrolling is interruptible by mousewheel scrolling. Defaults to `true`.\r\n * @returns {Promise} A promise that resolves when the scrolling is done.\r\n */\r\nexport function scrollTo(\r\n target,\r\n durationMs = defaultDuration,\r\n targetElement = window,\r\n offsetPx = 0,\r\n isInterruptible = true\r\n) {\r\n // Make sure Promise is supported\r\n if (typeof Promise !== \"function\") {\r\n throw new Error(\r\n \"scrollTo needs support for Promise - Please read the notes in js/utils/scrollTo.js\"\r\n );\r\n }\r\n\r\n // Set duration to default if it isn't defined as a number\r\n const useDurationMs =\r\n typeof durationMs !== \"number\" ? defaultDuration : durationMs;\r\n\r\n // If target element is a string, find the element by its ID\r\n const useTargetElement =\r\n typeof targetElement === \"string\"\r\n ? document.getElementById(targetElement)\r\n : targetElement;\r\n\r\n // Throw error if target element wasn't found\r\n if (!useTargetElement) {\r\n throw new Error(\"getElementPosition did not find an element.\");\r\n }\r\n\r\n const elementIsWindow = useTargetElement === window;\r\n let scrollCount = 0;\r\n let oldTimestamp = Date.now();\r\n\r\n // Get current scroll position\r\n const detectedScrollPosition = getElementScroll(useTargetElement);\r\n const scrollPos = [detectedScrollPosition.left, detectedScrollPosition.top];\r\n\r\n let useTarget;\r\n\r\n // If target is a number and not an array, make an array for scrolling on the Y-axis\r\n if (typeof target === \"number\") {\r\n useTarget = [scrollPos[0], target];\r\n }\r\n\r\n // If target is not an array by now we'll try to find the position of an element\r\n else if (!isArray(target)) {\r\n const elementPosition = getElementPosition(target, useTargetElement);\r\n\r\n useTarget = [elementPosition.left, elementPosition.top];\r\n }\r\n\r\n // Target is already an array - just use it as it is\r\n else {\r\n useTarget = target;\r\n }\r\n\r\n // If no X or Y position is stated, keep the current position\r\n if (typeof useTarget[0] !== \"number\") {\r\n useTarget[0] = scrollPos[0];\r\n }\r\n if (typeof useTarget[1] !== \"number\") {\r\n useTarget[1] = scrollPos[1];\r\n }\r\n\r\n // Modify the target scroll position if 'offset' parameter is given and is of type array or number\r\n if (isArray(offsetPx)) {\r\n // If array, add offset to X and Y-axis\r\n useTarget[0] += offsetPx[0];\r\n useTarget[1] += offsetPx[1];\r\n } else if (typeof offsetPx === \"number\") {\r\n // If number, only offset the Y-axis\r\n useTarget[1] += offsetPx;\r\n }\r\n\r\n // Calculate\r\n const cosParameters = [\r\n (scrollPos[0] - useTarget[0]) / 2,\r\n (scrollPos[1] - useTarget[1]) / 2\r\n ];\r\n\r\n return new Promise(resolve => {\r\n // If duration is set to 0, just jump to the stated target/position\r\n if (useDurationMs <= 0) {\r\n doScroll(useTarget, useTargetElement, elementIsWindow);\r\n resolve();\r\n return;\r\n }\r\n\r\n let scrollDone = false;\r\n let interruptScrollFlag = false;\r\n\r\n // If interruptible, add an eventListener once on mousewheel scroll that calls 'interruptScroll'\r\n if (isInterruptible) {\r\n addEventOnce(useTargetElement, \"wheel\", interruptScroll);\r\n }\r\n\r\n // Once this function is called, set 'interruptScrollFlag' to true, which resolves the promise\r\n function interruptScroll() {\r\n interruptScrollFlag = true;\r\n }\r\n\r\n function step() {\r\n if (interruptScrollFlag) {\r\n resolve();\r\n // Since resolving does not prevent the rest of the function from running, we also need to return\r\n return;\r\n }\r\n\r\n const newTimestamp = Date.now();\r\n const timeDifferenceMs = newTimestamp - oldTimestamp;\r\n let moveStep;\r\n\r\n // Pi is used to make easing\r\n scrollCount += Math.PI / (useDurationMs / timeDifferenceMs);\r\n\r\n // As soon as we cross over Pi, we're about where we need to be\r\n if (scrollCount >= Math.PI) {\r\n moveStep = useTarget;\r\n scrollDone = true;\r\n } else {\r\n // Calculate and set scroll position\r\n moveStep = [\r\n Math.round(\r\n useTarget[0] +\r\n cosParameters[0] +\r\n cosParameters[0] * Math.cos(scrollCount)\r\n ),\r\n Math.round(\r\n useTarget[1] +\r\n cosParameters[1] +\r\n cosParameters[1] * Math.cos(scrollCount)\r\n )\r\n ];\r\n }\r\n\r\n // Perform scroll action\r\n doScroll(moveStep, useTargetElement, elementIsWindow);\r\n\r\n if (scrollDone) {\r\n removeEvent(useTargetElement, \"wheel\", interruptScroll);\r\n resolve();\r\n } else {\r\n oldTimestamp = newTimestamp;\r\n window.requestAnimationFrame(step);\r\n }\r\n }\r\n\r\n window.requestAnimationFrame(step);\r\n });\r\n}\r\n","export const debounce = func => {\r\n // Setup a timer\r\n let timeout;\r\n // Return a function to run debounced\r\n return function() {\r\n // Setup the arguments\r\n let context = this;\r\n let args = arguments;\r\n // If there's a timer, cancel it\r\n if (timeout) {\r\n window.cancelAnimationFrame(timeout);\r\n }\r\n // Setup the new requestAnimationFrame()\r\n timeout = window.requestAnimationFrame(function() {\r\n func.apply(context, args);\r\n });\r\n };\r\n};\r\n","export const throttle = (fn, timeDelay = 1000) => {\r\n let fnTimer;\r\n return (...args) => {\r\n if (!fnTimer) {\r\n fn(...args);\r\n fnTimer = setTimeout(() => {\r\n fnTimer = null;\r\n }, timeDelay);\r\n }\r\n };\r\n};\r\n","/**\r\n * A bunch of utilities to check whether or not a symbol fits certain criteria.\r\n *\r\n * @module utils/typeCheckers\r\n * @author Anders Gissel \r\n */\r\n\r\n/**\r\n * Find out whether or not the given argument is an element that would react somewhat normally to DOM-manipulations.\r\n *\r\n * @since 3.7.0\r\n * @param {*} element - The element to check.\r\n * @returns {boolean} `true` if the given argument is an element (or document, or window), and `false` otherwise.\r\n */\r\nexport function isElement(element) {\r\n return (\r\n element instanceof Element ||\r\n element instanceof Document ||\r\n element instanceof Window\r\n );\r\n}\r\n\r\n/**\r\n * Find out whether or not the given collection (or whatever) is an array.\r\n *\r\n * @since 3.7.0\r\n * @param {*} collection - The collection to check.\r\n * @returns {boolean} `true` if the given collection is an array, `false` otherwise.\r\n */\r\nexport function isArray(collection) {\r\n return collection && collection.constructor === Array;\r\n}\r\n","/**\r\n * Split a string into an array, and then run an optional callback function on each item.\r\n *\r\n * If a string is given, it will be **split by spaces and commas to get an array**.\r\n * If an array is given, no pre-processing happens, but the callback will still be executed (however, in this case please use `forEach()` instead).\r\n * All other input types are ignored.\r\n *\r\n * @module utils/splitter\r\n * @author Anders Gissel \r\n *\r\n *\r\n * @example Split a string into an array:\r\n * import { splitter } from './utils/splitter';\r\n *\r\n * const str = \"apple pear orange\";\r\n * splitter(str); // Returns [\"apple\", \"pear\", \"orange\"]\r\n *\r\n *\r\n * @example Split a string and log each item to the console:\r\n * import { splitter } from './utils/splitter';\r\n *\r\n * const str = \"apple pear orange\";\r\n * splitter(str, item => window.console.log(item)); // Logs \"apple\", \"pear\", \"orange\" into the console. Returns [\"apple\",\"pear\",\"orange\"].\r\n */\r\n\r\nimport { isArray } from \"./typeCheckers\";\r\n\r\n/**\r\n * Split a string into an array.\r\n *\r\n * @param {string|Array} input - String containing one or more items, separated by space/comma, or an array of entries.\r\n * @param {function} [callback] - Optional callback to run for each entry in the given array.\r\n * @returns {Array} The processed data in the form of an array.\r\n */\r\nexport function splitter(input, callback) {\r\n const inputArray =\r\n typeof input === \"string\"\r\n ? input\r\n .replace(/,/gm, \" \") // First, replace commas with spaces\r\n .replace(/[\\s]{2,}/gm, \" \") // Then, replace two or more spaces with just one.\r\n .trim() // Remove leading/trailing whitespace and similar crap\r\n .split(\" \")\r\n : isArray(input)\r\n ? input\r\n : [];\r\n\r\n if (typeof callback === \"function\") {\r\n inputArray.forEach(inputEntry => {\r\n if (inputEntry !== undefined) {\r\n callback(inputEntry);\r\n }\r\n });\r\n }\r\n\r\n return inputArray;\r\n}\r\n","/**\r\n * **Iterate over just about any iterable object type** - primarily for node lists, arrays and objects, but will also\r\n * yield results for single elements such as elements (nodes), strings or numbers.\r\n *\r\n * @module utils/forEach\r\n * @author Anders Gissel \r\n *\r\n * @example Iterating through an array:\r\n * import { forEach } from './utils/forEach';\r\n * forEach([value1, value2, value3], (value, index) => {\r\n * // Loop through the values in the array\r\n * });\r\n *\r\n *\r\n * @example Iterating through an object:\r\n * import { forEach } from './utils/forEach';\r\n * forEach({\"key1\": value1, \"key2\": value2}, (value, key) => {\r\n * // Loop through the values in the object\r\n * });\r\n *\r\n *\r\n * @example Iterating through a DOM-collection:\r\n * import { forEach } from './utils/forEach';\r\n *\r\n * const collection = document.querySelectorAll(\"div\");\r\n * forEach(collection, element => {\r\n * // \"element\" is a reference to the current DOM-element.\r\n * });\r\n *\r\n */\r\n\r\nimport { isArray } from \"./typeCheckers\";\r\n\r\n/**\r\n *\r\n * @param {Node|NodeList|Window|Document|Array|object|*} collection - Collection to iterate over. Can be a single element, too.\r\n * @param {function} iterator - Callback function for iterator. Will be called with (value, key) as arguments.\r\n * @param {boolean} [allowNullValues=false] Whether or not to allow the iterator to run if null/undefined is given as a collection.\r\n */\r\nexport function forEach(collection, iterator, allowNullValues = false) {\r\n // ** NODE LISTS\r\n // If we're dealing with a node list (see document.querySelectorAll()), we'll iterate through\r\n // it the old fashioned way.\r\n if (collection instanceof NodeList) {\r\n for (let i = 0; i < collection.length; i += 1) {\r\n iterator(collection.item(i), i);\r\n }\r\n }\r\n\r\n // ** ARRAYS\r\n // Regular arrays are, you know, completely easy.\r\n else if (isArray(collection)) {\r\n // Why not use `Array.prototype.forEach()`? Because for all the optimizations behind\r\n // the scenes, it's still much slower than a simple for-loop.\r\n for (let i = 0; i < collection.length; i += 1) {\r\n iterator(collection[i], i);\r\n }\r\n }\r\n\r\n // ** ITERATORS\r\n // If we have an iterator object we'll use the \"for ... of\" method of iterating through it.\r\n else if (collection && collection.constructor.name === \"Iterator\") {\r\n let index = 0;\r\n for (const item of collection) {\r\n iterator(item, index);\r\n index += 1;\r\n }\r\n }\r\n\r\n // ** REGULAR OBJECTS\r\n // Objects that are *NOT* HTML-elements of some kind get special treatment.\r\n else if (\r\n collection &&\r\n typeof collection === \"object\" &&\r\n !(\r\n collection instanceof Node ||\r\n collection instanceof Window ||\r\n collection instanceof Document\r\n )\r\n ) {\r\n forEach(Object.keys(collection), key => {\r\n // We only want to deal with properties that exist on the object itself,\r\n // not some prototyped stuff.\r\n // eslint-disable-next-line no-prototype-builtins\r\n if (collection.hasOwnProperty(key)) {\r\n iterator(collection[key], key);\r\n }\r\n });\r\n }\r\n\r\n // ** SINGLE NODES OR ELEMENTS\r\n // Anything that doesn't fit in the cases above will be handled here. We'll just fire the iterator once with the\r\n // given collection argument, and 0 as the key, and hope that is enough for the use case.\r\n else {\r\n if (collection || allowNullValues) {\r\n iterator(collection, 0);\r\n }\r\n }\r\n}\r\n","/**\r\n * Class bootstrapper.\r\n *\r\n * @module utils/bootstrapper\r\n * @author Anders Gissel \r\n *\r\n * @example\r\n * \r\n * The bootstrapper is used to instantiate a class or constructor and tie it to a DOM element automatically.\r\n *\r\n * Given two DOM elements like this:\r\n * \r\n * {@lang html}\r\n *
\r\n *
\r\n *\r\n * @example\r\n * You would use the bootstrapper like so:\r\n * import { bootstrapper } from './utils/bootstrapper';\r\n * import { WhateverConstructorYouWant } from './modules/someFile';\r\n * import { AnotherConstructor } from './modules/someOtherFile';\r\n *\r\n * bootstrapper({\r\n * 'someExample': WhateverConstructorYouWant,\r\n * 'someOtherExample': AnotherConstructor\r\n * });\r\n *\r\n * @example\r\n * \r\n * Every time you run the bootstrapper it performs a very wide DOM lookup, so you should only run it once\r\n * per page load, and gather up all your references in one block like you see above. Anything else can\r\n * get expensive, depending on the browser's lookup engine.\r\n *\r\n * The bootstrapper will attach an event (defined in \"destroyEventName\") to the DOM-container. When triggered,\r\n * it will attempt to run the `destroy()` method on the object, if it exists, and then destroy the instantiation\r\n * completely in an attempt to clean up after itself. However, removing event listeners and DOM references set\r\n * by the module is your own responsibility.\r\n *\r\n * If you don't want to use the automatic lookup, but want to use the bootstrapper manually, use the helper\r\n * function **bootstrapConstructorOnElement()** instead, like so:\r\n * \r\n *\r\n * import { bootstrapConstructorOnElement } from './utils/bootstrapper';\r\n * import { WhateverConstructorYouWant } from './modules/someFile';\r\n *\r\n * let element = document.querySelector('.class');\r\n * bootstrapConstructorOnElement(element, WhateverConstructorYouWant, 'name-of-module');\r\n */\r\n\r\n/*\r\n Class bootstrapper\r\n\r\n Author: Anders Gissel \r\n ************************************************************************************************************\r\n\r\n The bootstrapper is used to instantiate a class or constructor and tie it to a DOM element automatically.\r\n Given two DOM elements like this:\r\n\r\n
\r\n
\r\n\r\n You would use the bootstrapper like so:\r\n\r\n import { bootstrapper } from './utils/bootstrapper';\r\n import { WhateverConstructorYouWant } from './modules/someFile';\r\n import { AnotherConstructor } from './modules/someOtherFile';\r\n\r\n bootstrapper({\r\n 'someExample': WhateverConstructorYouWant,\r\n 'someOtherExample': AnotherConstructor\r\n });\r\n\r\n\r\n Every time you run the bootstrapper it performs a very wide DOM lookup, so you should only run it once\r\n per page load, and gather up all your references in one block like you see above. Anything else can\r\n get expensive, depending on the browser's lookup engine.\r\n\r\n The bootstrapper will attach an event (defined in \"destroyEventName\") to the DOM-container. When triggered,\r\n it will attempt to run the destroy() method on the object, if it exists, and then destroy the instantiation\r\n completely in an attempt to clean up after itself. However, removing event listeners and DOM references set\r\n by the module is your own responsibility.\r\n\r\n If you don't want to use the automatic lookup, but want to use the bootstrapper manually, use the helper\r\n function bootstrapConstructorOnElement() instead, like so:\r\n\r\n import { bootstrapConstructorOnElement } from './utils/bootstrapper';\r\n import { WhateverConstructorYouWant } from './modules/someFile';\r\n\r\n let element = document.querySelector('.class');\r\n bootstrapConstructorOnElement(element, WhateverConstructorYouWant, 'name-of-module');\r\n\r\n */\r\n\r\nimport { triggerCustomEvent } from \"./events/triggerCustomEvent\";\r\nimport { splitter } from \"./helpers/splitter\";\r\nimport { forEach } from \"./helpers/forEach\";\r\nimport { addClass, hasClass, removeClass } from \"./dom/classList\";\r\n\r\n/**\r\n * The event name that will kill any given instantiation. Can be customized to your liking, but only before you start\r\n * using the bootstrapper.\r\n *\r\n * @type {string}\r\n */\r\nexport const destroyEventName = \"akqa.bootstrapper:destroyInstance\";\r\n\r\n/**\r\n * Once a constructor is initialized, this string will be appended to the active module name and added as a class.\r\n * @type {string}\r\n */\r\nexport const initializedAppendClass = \"--initialized\";\r\n\r\n/**\r\n * The DOM property used for the node lookups. The default is \"data-module\", which makes the script look for\r\n * something like:\r\n *\r\n * ``\r\n *\r\n * You can change this property name to your liking, but please use a data-attribute, and remember to do it\r\n * before you actually start bootstrapping modules, or there may be unexpected side effects.\r\n *\r\n * @type {string}\r\n */\r\nexport const moduleLookupPropertyName = \"data-module\";\r\n\r\n/**\r\n * Saves instances in an object to later get the same instances\r\n *\r\n * @type {{[moduleName: string]: any}}\r\n */\r\nexport const bootstrappedInstances = {};\r\n\r\nexport let counts = {};\r\n\r\n/**\r\n * Create a callback function to kill the given instantiation.\r\n *\r\n * @private\r\n * @param {Object} instance - The instantiation we'll be trying to kill.\r\n * @param {HTMLElement} domObject - The DOM reference we'll be working with.\r\n * @param {string} initializedTargetClass - The class previously added to the element, which should be removed upon destruction.\r\n * @returns {(this: HTMLElement, ev: any) => any}\r\n */\r\nfunction createInstanceKillerCallback(\r\n instance,\r\n domObject,\r\n initializedTargetClass\r\n) {\r\n // Allocate a name for the return function so we can refer to it when we remove the event listener again.\r\n let handlerFunction;\r\n\r\n handlerFunction = function(event) {\r\n // eslint-disable-line prefer-const\r\n\r\n // Make sure the event doesn't travel up the DOM tree and destroy something we'd need for later.\r\n event.stopPropagation();\r\n\r\n // If we have an instance, and it contains the \"destroy\" function, run it now.\r\n if (instance && typeof instance.destroy === \"function\") {\r\n instance.destroy();\r\n }\r\n\r\n // Try recovering the allocated memory from the instance.\r\n instance = null; // eslint-disable-line no-param-reassign\r\n\r\n // Remove the \"initiated\" class\r\n removeClass(domObject, initializedTargetClass);\r\n\r\n // ... and then remove the event handler pointing to... well, this function.\r\n domObject.removeEventListener(destroyEventName, handlerFunction);\r\n\r\n // Only continue with the next bit if we haven't explicitly been told NOT to.\r\n if (\r\n typeof event.detail !== \"object\" ||\r\n event.detail.doNotPropagateDown !== true\r\n ) {\r\n // Fire the destruction event on every single data-module that might exist inside the current container.\r\n // The destruction event is assumed to be fired prior to a DOM removal and/or cleanup, so we'll make sure\r\n // everything below this node is cleaned up as well. The rest is up to the instantiations running on the\r\n // DOM nodes we find, but we can't be responsible for those here.\r\n\r\n const childElements = domObject.querySelectorAll(\r\n `[${moduleLookupPropertyName}]`\r\n );\r\n\r\n // Trigger the destruction event on the subnodes we've found. By sending along \"doNotPropagateDown\", we\r\n // are ensuring that the subnodes will not do the same. The first top-level call will find and target all\r\n // instantiations, so once is enough.\r\n forEach(childElements, currentElement =>\r\n triggerCustomEvent(currentElement, destroyEventName, {\r\n doNotPropagateDown: true\r\n })\r\n );\r\n }\r\n };\r\n\r\n return handlerFunction;\r\n}\r\n\r\n/**\r\n * Spawn a constructor for the given DOM element.\r\n *\r\n * @private\r\n * @param {string} moduleName\r\n * @param {HTMLElement} domObject\r\n * @param {any} ConstructorReference\r\n * @param {string} initializedTargetClass\r\n * @returns {object}\r\n */\r\nfunction spawnInstance(\r\n moduleName,\r\n domObject,\r\n ConstructorReference,\r\n initializedTargetClass\r\n) {\r\n // Only continue if an instantiation hasn't been set up before.\r\n if (!hasClass(domObject, initializedTargetClass)) {\r\n // Add the \"initialized\"-class, just because.\r\n addClass(domObject, initializedTargetClass);\r\n\r\n if (!ConstructorReference) {\r\n window.console.warn(\r\n `ConstructorReference is undefined while bootstrapping '${moduleName}'`\r\n );\r\n }\r\n\r\n // Create the new instantiation right away.\r\n const instance = new ConstructorReference(domObject);\r\n\r\n // Create an event handler for\r\n const killEventHandler = createInstanceKillerCallback(\r\n instance,\r\n domObject,\r\n initializedTargetClass\r\n );\r\n\r\n // Set up an event listener looking for the destroy-event, which will destroy the instantiation\r\n // if fired. This can help us clean up our memory allocations (allowing the browser to run garbage\r\n // collection) when we're using SPA's or similar.\r\n domObject.addEventListener(destroyEventName, killEventHandler);\r\n\r\n if (bootstrappedInstances[moduleName]) {\r\n if (!counts[moduleName]) {\r\n counts[moduleName] = 1;\r\n } else {\r\n counts[moduleName] = counts[moduleName] + 1;\r\n }\r\n bootstrappedInstances[\r\n `${moduleName}-${counts[moduleName]}`\r\n ] = instance;\r\n } else {\r\n bootstrappedInstances[moduleName] = instance;\r\n }\r\n\r\n return instance;\r\n }\r\n}\r\n\r\n/**\r\n * Find all DOM-elements matching the given module names, and start the associated constructors for each of them.\r\n *\r\n * @private\r\n * @param {object} objectData - An associative array. Key must be the module name, and value must be the constructor to look for.\r\n * @param {boolean} [treatConstructorsAsAsyncLoaders=false] Treat the constructors not as classes but as async-loaders that should be resolved before spawning them.\r\n */\r\nfunction spawnInstancesFromObject(\r\n objectData,\r\n treatConstructorsAsAsyncLoaders = false,\r\n container\r\n) {\r\n const domElements = container.querySelectorAll(\r\n `[${moduleLookupPropertyName}]`\r\n );\r\n forEach(domElements, currentElement => {\r\n const moduleNames = currentElement.getAttribute(\r\n moduleLookupPropertyName\r\n );\r\n splitter(moduleNames, moduleName => {\r\n if (moduleName) {\r\n const ConstructorReference = objectData[moduleName];\r\n\r\n if (ConstructorReference) {\r\n const constructorType = typeof ConstructorReference;\r\n\r\n if (treatConstructorsAsAsyncLoaders) {\r\n // Using the objectData-reference to avoid trouble with ESLint. But it's the same as\r\n // using ConstructorReference.\r\n objectData[moduleName]().then(ResolvedConstructor =>\r\n spawnInstance(\r\n moduleName,\r\n currentElement,\r\n ResolvedConstructor,\r\n moduleName + initializedAppendClass\r\n )\r\n );\r\n } else {\r\n // Stop right now if the given reference isn't actually a function.\r\n if (constructorType === \"function\") {\r\n spawnInstance(\r\n moduleName,\r\n currentElement,\r\n ConstructorReference,\r\n moduleName + initializedAppendClass\r\n );\r\n } else {\r\n window.console.error(\r\n `ConstructorReference (for '${moduleName}') is not a function, but a ${constructorType}. The bootstrapper needs a constructor function to work with.`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n });\r\n });\r\n}\r\n\r\nexport function killInstancesFromObject() {\r\n forEach(bootstrappedInstances, (currentInstance, instanceName) => {\r\n if (counts[instanceName]) {\r\n counts[instanceName] = undefined;\r\n delete counts[instanceName];\r\n }\r\n\r\n if (currentInstance.kill) {\r\n currentInstance.kill();\r\n }\r\n\r\n triggerCustomEvent(currentInstance.dom.container, destroyEventName);\r\n bootstrappedInstances[instanceName] = undefined;\r\n delete bootstrappedInstances[instanceName];\r\n });\r\n}\r\n\r\n/**\r\n * Bootstrap the given HTML element with the given constructor reference. Module name will be inferred from element\r\n * if none is given.\r\n *\r\n * @param {HTMLElement} domReference\r\n * @param {Function} ConstructorReference\r\n * @param {string} [moduleName]\r\n * @returns {object}\r\n */\r\nexport function bootstrapConstructorOnElement(\r\n domReference,\r\n ConstructorReference,\r\n moduleName\r\n) {\r\n const usedModuleName =\r\n moduleName || domReference.getAttribute(moduleLookupPropertyName);\r\n return spawnInstance(\r\n moduleName,\r\n domReference,\r\n ConstructorReference,\r\n usedModuleName + initializedAppendClass\r\n );\r\n}\r\n\r\n/**\r\n * Bootstrap any module on the page that match the given name, using the constructor passed along.\r\n * Or, in plain English: spawn a javascript function for each HTML-tag that match this format:\r\n *\r\n * ``\r\n *\r\n * You can change the lookup property by changing \"moduleLookupPropertyName\" to something else. See\r\n * the documentation near the top of this file.\r\n *\r\n * @param {string|object} target - When defined as a string: the name of the module; used for looking up DOM-elements that match. When defined as an object: key defines name, value is used as the ConstructorReference.\r\n * @param {function} [ConstructorReference] - The constructor to instantiate.\r\n */\r\nexport function bootstrapper(\r\n target,\r\n ConstructorReference,\r\n container = document\r\n) {\r\n if (typeof target === \"string\") {\r\n spawnInstancesFromObject(\r\n {\r\n [target]: ConstructorReference\r\n },\r\n false,\r\n container\r\n );\r\n } else if (typeof target === \"object\") {\r\n spawnInstancesFromObject(target, false, container);\r\n } else {\r\n // eslint-disable-next-line no-throw-literal\r\n throw \"First argument to bootstrapper must be a string or an object!\";\r\n }\r\n}\r\n\r\n/**\r\n * Bootstrap any module on the page that match the given name, like the `bootstrapper()`, but instead\r\n * of passing a statically loaded constructor, you must feed it functions that return promises\r\n * generated by `import()` statements instead. See the example for an explanation.\r\n *\r\n * If you have a LOT of modules, and not all of them are included on every page, this MIGHT\r\n * be the way to go to get a faster page load. Please make sure you're using HTTP/2, or\r\n * the resulting load could potentially create a whole bunch of HTTP-requests that might\r\n * choke a mobile device.\r\n *\r\n * This technique is best suited for modules that MIGHT show up on the page,\r\n * but for modules that are GUARANTEED to show up everywhere, you should probably\r\n * use the regular bootstrapper - or, if there's only a single usage (like a navigation menu\r\n * or similar), just turn it into a singleton instead. The `asyncBootstrapper` is for\r\n * hardcore code splitting.\r\n *\r\n *\r\n * @param {string|object} target - When defined as a string: the name of the module; used for looking up DOM-elements that match. When defined as an object: key defines name, value is used as the moduleResolverPromise.\r\n * @param {function} [moduleResolverPromise] - The import-promise that loads the constructor to instantiate.\r\n *\r\n * @example Lazy-load and spawn any and all of these modules when encountered on the page:\r\n * asyncBootstrapper({\r\n * 'example': () => import('./modules/example').then(module => module.Example),\r\n * 'example2': () => import('./modules/example2').then(module => module.SomeOtherConstructor),\r\n * 'otherModule': () => import('./modules/otherModule').then(module => module.YetAnotherConstructor),\r\n * 'krombopulosMichael': () => import('./modules/krombopulosMichael').then(module => module.OohBoyHereIGoKillingAgain)\r\n * };\r\n */\r\nexport function asyncBootstrapper(\r\n target,\r\n moduleResolverPromise,\r\n container = document\r\n) {\r\n if (typeof target === \"string\") {\r\n spawnInstancesFromObject(\r\n {\r\n [target]: moduleResolverPromise\r\n },\r\n true,\r\n container\r\n );\r\n } else if (typeof target === \"object\") {\r\n spawnInstancesFromObject(target, true, container);\r\n } else {\r\n // eslint-disable-next-line no-throw-literal\r\n throw \"First argument to asyncBootstrapper must be a string or an object!\";\r\n }\r\n}\r\n","// If you want to use React instead of vanilla modules, use the reactBootstrapper,\r\n// the same rules and guidelines apply for this bootstrapper as they do for the bootstrapper and asyncBootstrapper (split your code responsibly).\r\n// The reactBootstrapper supports both static and dynamic imports - which is why there is no asyncReactBootstrapper\r\n// import { reactBootstrapper } from \"./utils/react/reactBootstrapper\";\r\n\r\nimport \"./utils/globals\";\r\nimport { onReady } from \"./utils/events/onReady\";\r\nimport {\r\n onWindowResize,\r\n currentBreakpoint,\r\n breakpointIndex\r\n} from \"./utils/events/onWindowResize\";\r\nimport { enableScrollLock } from \"./utils/dom/scrollLock\";\r\nimport {\r\n getScrollBarWidth,\r\n getNavHeight,\r\n getInPageNavigationHeight,\r\n getInPageNavigationOffset,\r\n getInPageNavigationScrollHeight\r\n} from \"./utils/dom/cssProps\";\r\nimport { isElementInViewport } from \"./utils/dom/elementProperties\";\r\nimport { lazyLoad } from \"./utils/dom/lazyLoad\";\r\nimport { Navigation } from \"./components/navigation/navigation\";\r\nimport { Modal } from \"./components/modal/modal\";\r\nimport { ExternalLink } from \"./components/external-link/external-link\";\r\nimport { Accordion } from \"./components/accordion/accordion\";\r\nimport { References } from \"./components/references/references\";\r\nimport { RibbonImage } from \"./components/ribbon-image/ribbon-image\";\r\nimport { Hero } from \"./components/hero/hero\";\r\nimport { Overlay } from \"./components/overlay/overlay\";\r\nimport { InformationModal } from \"./components/information-modal/information-modal\";\r\nimport { StaticIframe } from \"./components/static-iframe/static-iframe\";\r\nimport { Carousel } from \"./components/multi-column-carousel/multi-column-carousel\";\r\nimport { CarouselVideo } from \"./components/multi-column-carousel/multi-column-carousel-video\";\r\nimport { Video } from \"./components/video/video\";\r\nimport { ScrollTop } from \"./components/scroll-top/scroll-top\";\r\nimport { InPageNavigation } from \"./components/in-page-navigation/in-page-navigation\";\r\nimport { GatedContent } from \"./components/gated-content/gated-content\";\r\nimport { RccCalculator } from \"./components/rcc-calculator/rcc-calculator\";\r\nimport { bootstrapper } from \"./utils/bootstrapper\";\r\nimport { throttle } from \"./utils/dom/throttle\";\r\nimport { scrollDirection } from \"./utils/events/scrollDirection\";\r\nimport { ThreeQ } from \"./components/threeq/3q\";\r\n\r\nexport const modules = {\r\n modal: Modal,\r\n \"external-link\": ExternalLink,\r\n navigation: Navigation,\r\n accordion: Accordion,\r\n references: References,\r\n \"ribbon-image\": RibbonImage,\r\n hero: Hero,\r\n video: Video,\r\n overlay: Overlay,\r\n \"scroll-top\": ScrollTop,\r\n \"in-page-navigation\": InPageNavigation,\r\n \"gated-content\": GatedContent,\r\n carousel: Carousel,\r\n \"carousel-video\": CarouselVideo,\r\n \"information-modal\": InformationModal,\r\n \"static-iframe\": StaticIframe,\r\n \"rcc-calculator\": RccCalculator,\r\n threeq: ThreeQ\r\n};\r\n\r\nbootstrapper(modules);\r\n\r\n// You can use the following code to listen for when the styles on the page are lazy-loaded. This is cool for waiting for\r\n// styles to be rendered and ready (if you need them for calculating sizes and similar), but since everything is loaded\r\n// asynchronously, you can't know the load order, so the CSS might be loaded before the JS is. Your code MUST assume that\r\n// the CSS has *already* been loaded once the JS runs.\r\n// This function is especially helpful for slow browsers (IE) and slow/unstable connections.\r\n//\r\n// window.akqa = window.akqa || {};\r\n// window.akqa.stylesRendered = () => {\r\n// // Run your repaint callbacks here. Consider using a throttle/debounce, and\r\n// // remember to run the function at load-time if the code here is important\r\n// // for your layout (pro-tip: it probably shouldn't be).\r\n// };\r\n\r\nonReady(() => {\r\n // init css Props\r\n getScrollBarWidth();\r\n getNavHeight();\r\n getInPageNavigationHeight();\r\n getInPageNavigationOffset();\r\n getInPageNavigationScrollHeight();\r\n\r\n onWindowResize(getNavHeight);\r\n onWindowResize(getInPageNavigationHeight);\r\n onWindowResize(getInPageNavigationOffset);\r\n\r\n /* remove js class dymamically */\r\n (() => {\r\n document.documentElement.classList.remove(\"no-js\");\r\n })();\r\n\r\n /* gated content */\r\n const gatedContent = document.querySelectorAll(\".gated-content\");\r\n if (gatedContent && gatedContent.length) {\r\n enableScrollLock();\r\n }\r\n\r\n /* lazyload images */\r\n (() => {\r\n lazyLoad(\".lazy\");\r\n const attachScrollLoadEvent = () => {\r\n const lazyLoadBackgroundImage = document.querySelectorAll(\r\n `[data-src]`\r\n );\r\n if (lazyLoadBackgroundImage.length) {\r\n lazyLoadBackgroundImage.forEach(item => {\r\n if (isElementInViewport(item)) {\r\n const src = item.dataset.src;\r\n item.classList.add(\"background-image-loaded\");\r\n item.setAttribute(\r\n \"style\",\r\n 'background-image: url(\"' + src + '\")'\r\n );\r\n }\r\n });\r\n }\r\n };\r\n attachScrollLoadEvent();\r\n document.addEventListener(\"scroll\", () => {\r\n attachScrollLoadEvent();\r\n });\r\n })();\r\n\r\n /* scroll events */\r\n (() => {\r\n const elem = document.body;\r\n const scrollClass = \"scroll--active\";\r\n const scrollUpClass = \"scroll--up\";\r\n const scrollDownClass = \"scroll--down\";\r\n const inPageNavigationClass = \"in-page-navigation--active\";\r\n const interval = 3000;\r\n const scrollYOffset = 200;\r\n const inPageNavigation = document.querySelector(`.in-page-navigation`);\r\n const inPageNavigationInner = document.querySelector(\r\n `.in-page-navigation__inner`\r\n );\r\n const inPageNavigationOffsetTop = inPageNavigation?.offsetTop;\r\n const isMobile = currentBreakpoint < breakpointIndex.lg;\r\n if (window.scrollY > scrollYOffset) {\r\n elem.classList.add(scrollClass);\r\n }\r\n document.addEventListener(\"scroll\", () => {\r\n if (\r\n inPageNavigation &&\r\n window.scrollY > inPageNavigationOffsetTop &&\r\n inPageNavigationInner?.offsetHeight\r\n ) {\r\n throttle(elem.classList.add(inPageNavigationClass), interval);\r\n } else {\r\n throttle(\r\n elem.classList.remove(inPageNavigationClass),\r\n interval\r\n );\r\n }\r\n if (window.scrollY > scrollYOffset) {\r\n throttle(elem.classList.add(scrollClass), interval);\r\n } else {\r\n throttle(elem.classList.remove(scrollClass), interval);\r\n }\r\n if (isMobile) {\r\n getInPageNavigationScrollHeight();\r\n }\r\n });\r\n scrollDirection((scrollPos, previousScrollPos) => {\r\n if (previousScrollPos > scrollPos) {\r\n elem.classList.remove(scrollDownClass);\r\n elem.classList.add(scrollUpClass);\r\n } else {\r\n elem.classList.remove(scrollUpClass);\r\n elem.classList.add(scrollDownClass);\r\n }\r\n });\r\n })();\r\n\r\n /* set alt text */\r\n (() => {\r\n const images = document.querySelectorAll(\"img\");\r\n images.forEach(item => {\r\n const altText = item.getAttribute(\"alt\");\r\n if (!altText) {\r\n item.setAttribute(\"alt\", \"Eisai Pro\");\r\n }\r\n });\r\n })();\r\n}, 150);\r\n","import { addEvent, addEventOnce, removeEvent } from \"../../utils/events/events\";\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport {\r\n disableScrollLock,\r\n enableScrollLock\r\n} from \"../../utils/dom/scrollLock\";\r\nimport {\r\n currentBreakpoint,\r\n breakpointIndex\r\n} from \"../../utils/events/onWindowResize\";\r\nimport { hasClass } from \"../../utils/dom/classList\";\r\n\r\nexport class Modal {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference, modalId) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n modal: \"modal\",\r\n modalActive: \"modal--active\",\r\n backdrop: \"modal-backdrop\",\r\n newsletterSignup: \"newsletter-signup\",\r\n newsletterSignupInput: \"pre-email\",\r\n preventKeyEventsClass: \"modal__prevent-key-events\",\r\n hiddenClass: \"hidden\",\r\n navigationWrapper: \"navigation__list-wrapper\",\r\n navigationWrapperOpen: \"navigation__list-wrapper--open\"\r\n };\r\n\r\n onReady(() => this.init(domReference, modalId));\r\n }\r\n\r\n backdrop = document.querySelector(`.modal-backdrop`);\r\n\r\n openModal(event, modalId) {\r\n event.preventDefault();\r\n const modal = this.dom.container.querySelector(\r\n `.modal[data-modal-id='${modalId}']`\r\n );\r\n const newsletterSignupInput = this.dom.container.querySelector(\r\n `#${this.dom.classList.newsletterSignupInput}`\r\n );\r\n const emailInput = this.dom.container.querySelector(\r\n `.${this.dom.classList.newsletterSignup} #email`\r\n );\r\n\r\n if (modalId === this.dom.classList.newsletterSignup) {\r\n emailInput.value = newsletterSignupInput.value;\r\n }\r\n\r\n if (modal) {\r\n modal.classList.add(`${this.dom.classList.modalActive}`);\r\n this.backdrop.classList.add(\r\n `${this.dom.classList.backdrop}--active`\r\n );\r\n }\r\n\r\n if (modalId === \"search\") {\r\n modal.querySelector(\".search__input\").focus();\r\n }\r\n\r\n enableScrollLock();\r\n }\r\n\r\n closeModal() {\r\n const modals = document.querySelectorAll(\r\n `.modal:not(.${this.dom.classList.preventKeyEventsClass})`\r\n );\r\n modals.forEach(item => {\r\n item.classList.remove(`${this.dom.classList.modalActive}`);\r\n if (hasClass(item, \"modal__newsletter-signup\")) {\r\n const preEmail = document.querySelector(\"#pre-email\");\r\n preEmail.value = \"\";\r\n }\r\n });\r\n\r\n if (this.backdrop) {\r\n this.backdrop.classList.remove(\r\n `${this.dom.classList.backdrop}--active`\r\n );\r\n }\r\n\r\n const isMobile = currentBreakpoint < breakpointIndex.lg;\r\n const navigation = document.querySelector(\r\n `.${this.dom.classList.navigationWrapper}`\r\n );\r\n const isNavOpen = hasClass(\r\n navigation,\r\n this.dom.classList.navigationWrapperOpen\r\n );\r\n\r\n if (isMobile && isNavOpen) {\r\n return;\r\n } else {\r\n disableScrollLock();\r\n }\r\n }\r\n\r\n handleKeyEvent() {\r\n removeEvent(window, \"keydown\");\r\n window.addEventListener(\"keydown\", event => {\r\n if (event.key === \"Escape\") {\r\n this.closeModal();\r\n }\r\n });\r\n }\r\n\r\n handleClickOpenEvent() {\r\n const newsletterSignupInput = this.dom.container.querySelector(\r\n `#${this.dom.classList.newsletterSignupInput}`\r\n );\r\n const trigger = document.querySelector(\r\n `[data-modal-trigger=\"${this.dom.classList.newsletterSignup}\"]`\r\n );\r\n removeEvent(window, \"keydown\");\r\n window.addEventListener(\"keydown\", event => {\r\n if (\r\n newsletterSignupInput &&\r\n newsletterSignupInput.value.length &&\r\n newsletterSignupInput === document.activeElement &&\r\n event.key === \"Enter\"\r\n ) {\r\n trigger.click();\r\n }\r\n });\r\n }\r\n\r\n handleClickOutsideEvent() {\r\n if (this.backdrop !== null) {\r\n removeEvent(this.backdrop, \"click\");\r\n this.backdrop.addEventListener(\"click\", () => {\r\n this.closeModal();\r\n });\r\n }\r\n }\r\n\r\n init() {\r\n const hrefs = document.querySelectorAll(\r\n \"a, button, div[data-modal-trigger]\"\r\n );\r\n const close = document.querySelectorAll(\".modal__close\");\r\n\r\n addEventOnce(hrefs, \"click\", event => {\r\n const target =\r\n event.currentTarget.dataset.modalTrigger ||\r\n event.currentTarget.parentNode.dataset.modalTrigger;\r\n if (target) {\r\n this.openModal(event, target);\r\n }\r\n });\r\n\r\n addEvent(close, \"click\", () => this.closeModal());\r\n\r\n this.handleKeyEvent();\r\n this.handleClickOpenEvent();\r\n this.handleClickOutsideEvent();\r\n }\r\n}\r\n","/* global eisai */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport { addEvent, removeEvent } from \"../../utils/events/events\";\r\n\r\nexport class ExternalLink {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.externalLinkSetter = null;\r\n this.dom.classList = {\r\n modal: \"modal__external-link\",\r\n modalSiteSwitch: \"modal__site-switch\",\r\n modalCloseButton: \"modal__close-button\",\r\n modalTargetLink: \"button--icon-cta\",\r\n modalCancelButton: \"button--icon-arrow-back\",\r\n modalBackdrop: \"modal-backdrop\",\r\n gatedContent: \"gated-content\",\r\n gatedContentButton: \"button--secondary\",\r\n overlayTrigger: \"overlay-trigger\",\r\n navigationLink: \"navigation__list\"\r\n };\r\n this.whitelistUrls = eisai.whitelistUrls || [];\r\n this.triggerList = eisai.triggerList || [];\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n currentHost(linkElement) {\r\n return linkElement.host === window.location.host;\r\n }\r\n\r\n externalLink(linkElement) {\r\n if (\r\n this.whitelistUrls.length &&\r\n this.whitelistUrls.includes(linkElement)\r\n ) {\r\n return true;\r\n }\r\n }\r\n\r\n siteSwitchLink(linkElement) {\r\n if (\r\n this.triggerList.length &&\r\n this.triggerList.includes(linkElement.hostname)\r\n ) {\r\n return true;\r\n }\r\n }\r\n\r\n attachAllLinkProperties() {\r\n const hrefs = document.querySelectorAll(\r\n `a:not(.${this.dom.classList.modal} .${this.dom.classList.modalTargetLink}):not(.${this.dom.classList.gatedContent} .${this.dom.classList.gatedContentButton}):not(.${this.dom.classList.overlayTrigger})`\r\n );\r\n\r\n hrefs.forEach(item => {\r\n const href = item.getAttribute(\"href\");\r\n let url = href;\r\n if (url && (url.startsWith(\"mailto:\") || url.startsWith(\"tel:\"))) {\r\n return;\r\n }\r\n if (url) {\r\n url = url.charAt(0);\r\n if (this.currentHost(item)) {\r\n return;\r\n }\r\n\r\n if (!this.externalLink(href) && url !== \"/\" && url !== \"#\") {\r\n item.setAttribute(\"data-modal-trigger\", \"external-link\");\r\n }\r\n\r\n if (this.siteSwitchLink(item)) {\r\n item.setAttribute(\"data-modal-trigger\", \"site-switch\");\r\n if (\r\n document.querySelector(\r\n `.${this.dom.classList.modalSiteSwitch}`\r\n ) === null\r\n ) {\r\n item.setAttribute(\"target\", \"_blank\");\r\n item.removeAttribute(\r\n \"data-modal-trigger\",\r\n \"external-link\"\r\n );\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n onAttachExternalLinkClickEvent(event) {\r\n event.preventDefault();\r\n const href =\r\n event.currentTarget.getAttribute(\"href\") ||\r\n event.currentTarget.parentNode.getAttribute(\"href\");\r\n const targetLink = document.querySelector(\r\n `.${this.dom.classList.modal} .${this.dom.classList.modalTargetLink}`\r\n );\r\n targetLink.setAttribute(\"href\", href);\r\n\r\n removeEvent(window, \"keydown\");\r\n window.addEventListener(\"keydown\", event => {\r\n if (event.key === \"Escape\") {\r\n this.resetLinkProperties();\r\n }\r\n });\r\n }\r\n\r\n onAttachSiteSwitchLinkClickEvent(event) {\r\n event.preventDefault();\r\n const href =\r\n event.currentTarget.getAttribute(\"href\") ||\r\n event.currentTarget.parentNode.getAttribute(\"href\");\r\n const targetLink = document.querySelector(\r\n `.${this.dom.classList.modalSiteSwitch} .${this.dom.classList.modalTargetLink}`\r\n );\r\n targetLink.setAttribute(\"data-href\", href);\r\n\r\n removeEvent(window, \"keydown\");\r\n window.addEventListener(\"keydown\", event => {\r\n if (event.key === \"Escape\") {\r\n this.resetLinkProperties();\r\n }\r\n });\r\n }\r\n\r\n attachExternalSiteSwitchEvent() {\r\n const targetLink = document.querySelector(\r\n `.${this.dom.classList.modalSiteSwitch} .${this.dom.classList.modalTargetLink}`\r\n );\r\n const link = targetLink.getAttribute(\"data-href\");\r\n window.open(link, \"_blank\");\r\n window.location.reload();\r\n }\r\n\r\n resetLinkProperties() {\r\n const targetLinkExternal = document.querySelector(\r\n `.${this.dom.classList.modal} .${this.dom.classList.modalTargetLink}`\r\n );\r\n const targetLinkSiteSwitch = document.querySelector(\r\n `.${this.dom.classList.modalSiteSwitch} .${this.dom.classList.modalTargetLink}`\r\n );\r\n if (targetLinkExternal !== null) {\r\n targetLinkExternal.setAttribute(\"href\", \"\");\r\n }\r\n if (targetLinkSiteSwitch !== null) {\r\n targetLinkSiteSwitch.setAttribute(\"data-href\", \"\");\r\n }\r\n }\r\n\r\n /**\r\n * Bind events we need to the DOM-elements.\r\n */\r\n bindEvents() {\r\n addEvent(\r\n this.dom.externalLinkSetter,\r\n \"click\",\r\n this.onAttachExternalLinkClickEvent.bind(this)\r\n );\r\n addEvent(\r\n this.dom.siteSwitchLinkSetter,\r\n \"click\",\r\n this.onAttachSiteSwitchLinkClickEvent.bind(this)\r\n );\r\n addEvent(\r\n this.dom.siteSwitchExternalLink,\r\n \"click\",\r\n this.attachExternalSiteSwitchEvent.bind(this)\r\n );\r\n addEvent(\r\n this.dom.cancelTrigger,\r\n \"click\",\r\n this.resetLinkProperties.bind(this)\r\n );\r\n }\r\n\r\n init() {\r\n this.attachAllLinkProperties();\r\n this.dom.externalLinkSetter = document.querySelectorAll(\r\n `[data-modal-trigger='external-link']`\r\n );\r\n this.dom.siteSwitchLinkSetter = document.querySelectorAll(\r\n `[data-modal-trigger=\"site-switch\"]`\r\n );\r\n this.dom.siteSwitchExternalLink = document.querySelectorAll(\r\n `.${this.dom.classList.modalSiteSwitch} .${this.dom.classList.modalTargetLink}`\r\n );\r\n this.dom.cancelTrigger = document.querySelectorAll(\r\n `.${this.dom.classList.modal} .${this.dom.classList.modalCloseButton},\r\n .${this.dom.classList.modal} .${this.dom.classList.modalCancelButton},\r\n .${this.dom.classList.modalSiteSwitch} .${this.dom.classList.modalCloseButton},\r\n .${this.dom.classList.modalSiteSwitch} .${this.dom.classList.modalCancelButton},\r\n .${this.dom.classList.modalBackdrop}`\r\n );\r\n this.bindEvents();\r\n }\r\n}\r\n","/* global eisai */\r\n\r\nimport { addEvent, addEventOnce, removeEvent } from \"../../utils/events/events\";\r\nimport {\r\n onClickOutside,\r\n removeOnClickOutside\r\n} from \"../../utils/events/onClickOutside\";\r\nimport {\r\n disableScrollLock,\r\n enableScrollLock\r\n} from \"../../utils/dom/scrollLock\";\r\nimport {\r\n currentBreakpoint,\r\n breakpointIndex,\r\n onWindowResize\r\n} from \"../../utils/events/onWindowResize\";\r\nimport { scrollTo } from \"../../utils/dom/scrollTo\";\r\nimport { getSiblings } from \"../../utils/dom/siblings\";\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport { hasClass } from \"../../utils/dom/classList\";\r\n\r\nexport class Navigation {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.hash = window.location.hash;\r\n this.dom.pathname = window.location.pathname;\r\n this.dom.navHeight = document.querySelector(\"header\")?.clientHeight;\r\n this.dom.classList = {\r\n navigationWrapper: \"navigation__wrapper\",\r\n navigationWrapperOpen: \"navigation__wrapper-open\",\r\n navigationListWrapper: \"navigation__list-wrapper\",\r\n navigationListWrapperOpen: \"navigation__list-wrapper--open\",\r\n navigationList: \"navigation__list\",\r\n navigationBackTop: \"navigation__back\",\r\n navigationListOpen: \"navigation__list--open\",\r\n navigationButton: \"navigation__list-button\",\r\n navigationMenu: \"navigation__list__menu\",\r\n navigationClose: \"navigation__list__close\",\r\n navigationBack: \"navigation__list__back\",\r\n navigationPanel: \"navigation__list-panel\",\r\n navigationPanelOpen: \"navigation__list-panel--open\",\r\n subNavigationList: \"navigation__subnavigation-list\",\r\n subNavigationWrapper: \"navigation__subnavigation-wrapper\",\r\n subNavigationTrigger: \"navigation__subnavigation-trigger\",\r\n subNavigationBack: \"navigation__subnavigation-back\",\r\n subNavigationOpen: \"navigation__subnavigation-list--open\",\r\n subNavigationActive: \"navigation__subnavigation-list--active\",\r\n mobileNavigationTrigger: \"navigation__trigger\",\r\n samePageNavigationLink: \"navigation__same-page-navigation\"\r\n };\r\n this.triggerList = eisai.triggerList || [];\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n siteSwitchLink(linkElement) {\r\n if (\r\n this.triggerList.length &&\r\n this.triggerList.includes(linkElement.hostname)\r\n ) {\r\n return true;\r\n }\r\n }\r\n\r\n // mobile and desktop\r\n togglePanel({ target }) {\r\n this.resetSubNavigation();\r\n\r\n const navigationWrapper = document.querySelector(\r\n `.${this.dom.classList.navigationWrapper}`\r\n );\r\n const expanded = target.getAttribute(\"aria-expanded\") === \"true\";\r\n const navigations = document.querySelectorAll(`[role='navigation']`);\r\n const currentNavigation = document.querySelector(\r\n `[aria-labelledby=${target.id}]`\r\n );\r\n\r\n removeEvent(currentNavigation, \"transitionend\");\r\n addEventOnce(\r\n currentNavigation,\r\n \"transitionend\",\r\n () => this.handleAnimation(currentNavigation, expanded),\r\n false\r\n );\r\n\r\n navigations.forEach(nav => {\r\n if (expanded) {\r\n nav.classList.remove(this.dom.classList.navigationPanelOpen);\r\n navigationWrapper.classList.remove(\r\n this.dom.classList.navigationWrapperOpen\r\n );\r\n } else {\r\n nav.classList.add(this.dom.classList.navigationPanelOpen);\r\n navigationWrapper.classList.add(\r\n this.dom.classList.navigationWrapperOpen\r\n );\r\n }\r\n });\r\n\r\n if (!expanded) {\r\n const active = [...navigations].filter(nav =>\r\n nav.classList.contains(this.dom.classList.navigationPanelOpen)\r\n );\r\n active.forEach(nav => {\r\n nav.classList.remove(this.dom.classList.navigationPanelOpen);\r\n });\r\n\r\n this.resetMainNavigation();\r\n currentNavigation.classList.add(\r\n this.dom.classList.navigationPanelOpen\r\n );\r\n }\r\n\r\n target.setAttribute(\"aria-expanded\", !expanded);\r\n\r\n onClickOutside(currentNavigation, ({ target }) => {\r\n const wrapper = !target.closest(\".navigation\");\r\n if (wrapper) {\r\n this.handleAnimation(currentNavigation, true);\r\n this.resetMainNavigation();\r\n this.resetSubNavigation();\r\n navigationWrapper.classList.remove(\r\n this.dom.classList.navigationWrapperOpen\r\n );\r\n disableScrollLock();\r\n }\r\n removeOnClickOutside(currentNavigation, this);\r\n });\r\n\r\n removeEvent(window, \"keydown\");\r\n window.addEventListener(\"keydown\", event => {\r\n if (event.key === \"Escape\") {\r\n this.handleAnimation(currentNavigation, true);\r\n this.resetMainNavigation();\r\n this.resetSubNavigation();\r\n navigationWrapper.classList.remove(\r\n this.dom.classList.navigationWrapperOpen\r\n );\r\n disableScrollLock();\r\n }\r\n });\r\n\r\n expanded ? disableScrollLock() : enableScrollLock();\r\n }\r\n\r\n toggleMobileNavigation(event, elem, className) {\r\n if (hasClass(elem, className)) {\r\n elem.classList.remove(className);\r\n disableScrollLock();\r\n this.resetMainNavigation();\r\n this.resetSubNavigation();\r\n } else if (event.target.classList.length === 0) {\r\n return true;\r\n } else {\r\n elem.classList.add(className);\r\n enableScrollLock();\r\n }\r\n }\r\n\r\n handleAnimation(currentNavigation, expanded) {\r\n if (expanded) {\r\n currentNavigation.classList.remove(\r\n this.dom.classList.navigationPanelOpen\r\n );\r\n }\r\n }\r\n\r\n resetMainNavigation() {\r\n const buttons = document.querySelectorAll(\r\n `.${this.dom.classList.navigationButton}`\r\n );\r\n const navigations = document.querySelectorAll(`[role='navigation']`);\r\n navigations.forEach(nav => {\r\n nav.setAttribute(\"aria-expanded\", false);\r\n nav.classList.remove(`.${this.dom.classList.navigationPanelOpen}`);\r\n });\r\n buttons.forEach(button => {\r\n button.setAttribute(\"aria-expanded\", false);\r\n });\r\n }\r\n\r\n resetSubNavigation() {\r\n const subNavigationList = document.querySelectorAll(\r\n `.${this.dom.classList.subNavigationList}`\r\n );\r\n const subNavigationTrigger = document.querySelectorAll(\r\n `.${this.dom.classList.subNavigationTrigger}`\r\n );\r\n const navigationPanel = document.querySelectorAll(\r\n `.${this.dom.classList.navigationPanel}`\r\n );\r\n navigationPanel.forEach(item => {\r\n item.classList.remove(this.dom.classList.navigationPanelOpen);\r\n });\r\n subNavigationList.forEach(item => {\r\n item.removeAttribute(\"style\");\r\n item.classList.remove(this.dom.classList.subNavigationOpen);\r\n });\r\n subNavigationTrigger.forEach(item => {\r\n item.classList.remove(this.dom.classList.subNavigationActive);\r\n });\r\n }\r\n\r\n attachScrollEvent() {\r\n const navigationList = this.dom.container.querySelector(\r\n `.${this.dom.classList.navigationList}`\r\n );\r\n const navigationClose = this.dom.container.querySelector(\r\n `.${this.dom.classList.mobileNavigationTrigger}-close`\r\n );\r\n const navigationCloseActive = `${this.dom.classList.mobileNavigationTrigger}-close--active`;\r\n\r\n navigationList.addEventListener(\"scroll\", () => {\r\n if (navigationList.scrollTop >= 100) {\r\n navigationClose.classList.add(navigationCloseActive);\r\n } else {\r\n navigationClose.classList.remove(navigationCloseActive);\r\n }\r\n });\r\n }\r\n\r\n handleSamePageNavitation() {\r\n const navigationList = this.dom.container.querySelector(\r\n `.${this.dom.classList.navigationList}`\r\n );\r\n const page = this.dom.pathname.split(\"/\").slice(-1)[0];\r\n const links = navigationList.querySelectorAll(\"a\");\r\n links.forEach(item => {\r\n const currentPage = item\r\n .getAttribute(\"href\")\r\n .split(\"/\")\r\n .slice(-1)[0];\r\n if (currentPage.match(\"#\")) {\r\n const url = currentPage.split(\"#\");\r\n if (url[0] === page) {\r\n item.classList.add(\r\n `${this.dom.classList.samePageNavigationLink}`\r\n );\r\n }\r\n }\r\n });\r\n }\r\n\r\n handleExternalLinkEvent() {\r\n const externalLink = this.dom.container\r\n .querySelector(`.${this.dom.classList.navigationList}`)\r\n .querySelectorAll(\"a\");\r\n externalLink.forEach(item => {\r\n if (this.siteSwitchLink(item)) {\r\n item.classList.add(\r\n \"button\",\r\n \"button--tertiary\",\r\n \"button--icon-external-link\",\r\n \"navigation__external-link\"\r\n );\r\n }\r\n });\r\n }\r\n\r\n init(domReference) {\r\n const self = this;\r\n const navigationList = domReference.querySelector(\r\n `.${self.dom.classList.navigationList}`\r\n );\r\n if (navigationList == null) {\r\n return;\r\n }\r\n self.handleSamePageNavitation();\r\n const mainNavigationTrigger = domReference.querySelectorAll(\r\n `.${self.dom.classList.navigationButton}`\r\n );\r\n const mobileNavigationTrigger = domReference.querySelectorAll(\r\n `.${self.dom.classList.mobileNavigationTrigger}`\r\n );\r\n const mainNavigationList = domReference.querySelector(\r\n `.${self.dom.classList.navigationListWrapper}`\r\n );\r\n const subNavigationWrapper = domReference.querySelectorAll(\r\n `.${self.dom.classList.subNavigationWrapper}`\r\n );\r\n const navigationBackTop = domReference.querySelectorAll(\r\n `.${self.dom.classList.navigationBackTop}`\r\n );\r\n const samePageNavigationLinks = navigationList.querySelectorAll(\r\n `.${self.dom.classList.samePageNavigationLink}`\r\n );\r\n\r\n function prepareNav(nav) {\r\n const navBar = nav.querySelector(\"ul\");\r\n const navElems = nav.querySelectorAll(\"li[data-level] > ul\");\r\n navBar.style.left = \"0%\";\r\n nav.onclick = e => {\r\n e.stopPropagation();\r\n startNav(e, navBar, navElems);\r\n };\r\n }\r\n\r\n function startNav(e, navBar, navElems) {\r\n const trigger = domReference.querySelectorAll(\r\n `.${self.dom.classList.subNavigationTrigger}`\r\n );\r\n if (e.target.dataset && e.target.dataset.level) {\r\n if (currentBreakpoint < breakpointIndex.lg) {\r\n navBar.style.left = -(e.target.dataset.level * 100) + \"%\";\r\n } else {\r\n navBar.style.left = \"0%\";\r\n }\r\n [].forEach.call(navElems, function(item) {\r\n item.classList.remove(self.dom.classList.subNavigationOpen);\r\n });\r\n trigger.forEach(item => {\r\n const siblings = getSiblings(e.target, true);\r\n const dataLevel = parseInt(item.getAttribute(\"data-level\"));\r\n const subNavigationItems = item\r\n .closest(\"ul\")\r\n .querySelectorAll(`[data-level=\"${dataLevel + 1}\"]`);\r\n siblings.forEach(subItem =>\r\n subItem.classList.remove(\r\n self.dom.classList.subNavigationActive\r\n )\r\n );\r\n subNavigationItems.forEach(subItem =>\r\n subItem.classList.remove(\r\n self.dom.classList.subNavigationActive\r\n )\r\n );\r\n });\r\n e.target.classList.add(self.dom.classList.subNavigationActive);\r\n e.target\r\n .closest(\"ul\")\r\n .classList.add(self.dom.classList.subNavigationOpen);\r\n const subNavList = e.target.querySelector(\"ul\");\r\n subNavList.classList.add(self.dom.classList.subNavigationOpen);\r\n }\r\n if (e.target.className === self.dom.classList.subNavigationBack) {\r\n const leftPos = parseInt(navBar.style.left);\r\n navBar.style.left = leftPos + 100 + \"%\";\r\n }\r\n }\r\n\r\n function resizeEvent() {\r\n if (currentBreakpoint >= breakpointIndex.lg) {\r\n document\r\n .querySelector(\r\n `.${self.dom.classList.navigationListWrapper}`\r\n )\r\n .classList.remove(\r\n self.dom.classList.navigationListWrapperOpen\r\n );\r\n }\r\n }\r\n\r\n addEvent(mainNavigationTrigger, \"click\", event =>\r\n self.togglePanel(event)\r\n );\r\n\r\n addEvent(mobileNavigationTrigger, \"click\", event =>\r\n self.toggleMobileNavigation(\r\n event,\r\n mainNavigationList,\r\n self.dom.classList.navigationListWrapperOpen\r\n )\r\n );\r\n\r\n addEvent(navigationBackTop, \"click\", () => {\r\n self.resetSubNavigation();\r\n self.resetMainNavigation();\r\n });\r\n\r\n onWindowResize(resizeEvent);\r\n\r\n if (subNavigationWrapper) {\r\n Array.from(subNavigationWrapper).forEach(item => {\r\n prepareNav(item);\r\n });\r\n }\r\n\r\n if (navigationList !== null) {\r\n self.attachScrollEvent();\r\n self.handleExternalLinkEvent();\r\n }\r\n\r\n addEvent(samePageNavigationLinks, \"click\", event => {\r\n event.preventDefault();\r\n const navigationWrapper = document.querySelector(\r\n `.${self.dom.classList.navigationWrapper}`\r\n );\r\n const navigationListWrapper = document.querySelector(\r\n `.${self.dom.classList.navigationListWrapper}`\r\n );\r\n const samePageLink = event.target.href.split(\"#\")[1];\r\n const section = document.querySelector(`[id=${samePageLink}]`);\r\n self.resetSubNavigation();\r\n self.resetMainNavigation();\r\n navigationWrapper.classList.remove(\r\n self.dom.classList.navigationWrapperOpen\r\n );\r\n navigationListWrapper.classList.remove(\r\n self.dom.classList.navigationListWrapperOpen\r\n );\r\n disableScrollLock();\r\n scrollTo(section, 600, window, [0, -self.dom.navHeight + 1]).then(\r\n () => {\r\n const newLoc = (self.dom.hash = `#${samePageLink}`);\r\n window.history.replaceState(null, null, newLoc);\r\n }\r\n );\r\n });\r\n }\r\n}\r\n","import { onReady } from \"../../utils/events/onReady\";\r\nimport { addEvent } from \"../../utils/events/events\";\r\n\r\nexport class Accordion {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n openClass: \"accordion__list--open\"\r\n };\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n onAccordionClickEvent(event) {\r\n event.preventDefault();\r\n const elem = event.currentTarget;\r\n if (elem.classList.contains(this.dom.classList.openClass)) {\r\n elem.classList.remove(this.dom.classList.openClass);\r\n elem.setAttribute(\"aria-expanded\", false);\r\n } else {\r\n elem.classList.add(this.dom.classList.openClass);\r\n elem.setAttribute(\"aria-expanded\", true);\r\n }\r\n }\r\n\r\n /**\r\n * Bind events we need to the DOM-elements.\r\n */\r\n bindEvents() {\r\n addEvent(\r\n this.dom.accordionTrigger,\r\n \"click\",\r\n this.onAccordionClickEvent.bind(this)\r\n );\r\n }\r\n\r\n init(domReference) {\r\n this.dom.accordionTrigger = this.dom.container.querySelectorAll(\r\n \".accordion__list > li > a\"\r\n );\r\n this.bindEvents();\r\n }\r\n}\r\n","import { onReady } from \"../../utils/events/onReady\";\r\nimport { addEvent } from \"../../utils/events/events\";\r\n\r\nexport class References {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n openWrapperClass: \"references--open\",\r\n openListClass: \"references__list--open\"\r\n };\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n onReferencesClickEvent(event) {\r\n event.preventDefault();\r\n const elem = event.currentTarget;\r\n const parent = elem.closest(\"ul\");\r\n if (elem.classList.contains(this.dom.classList.openListClass)) {\r\n elem.classList.remove(this.dom.classList.openListClass);\r\n parent.classList.remove(this.dom.classList.openWrapperClass);\r\n elem.setAttribute(\"aria-expanded\", false);\r\n } else {\r\n elem.classList.add(this.dom.classList.openListClass);\r\n parent.classList.add(this.dom.classList.openWrapperClass);\r\n elem.setAttribute(\"aria-expanded\", true);\r\n }\r\n }\r\n\r\n /**\r\n * Bind events we need to the DOM-elements.\r\n */\r\n bindEvents() {\r\n addEvent(\r\n this.dom.referencesTrigger,\r\n \"click\",\r\n this.onReferencesClickEvent.bind(this)\r\n );\r\n }\r\n\r\n init(domReference) {\r\n this.dom.referencesTrigger = domReference.querySelectorAll(\r\n \".references__list .grid > a\"\r\n );\r\n this.bindEvents();\r\n }\r\n}\r\n","import { addEvent } from \"../../utils/events/events\";\r\nimport { onReady } from \"../../utils/events/onReady\";\r\n\r\nexport class RibbonImage {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n container: \"ribbon-image\"\r\n };\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n init(domReference) {\r\n const button = domReference.querySelector(\r\n \".ribbon-image__expand .button\"\r\n );\r\n addEvent(button, \"click\", () =>\r\n domReference.classList.add(\r\n `${this.dom.classList.container}__expanded`\r\n )\r\n );\r\n }\r\n}\r\n","/* global eisai */\r\n/* global js3q */\r\n/* global UC_UI */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\n\r\nexport class Hero {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n videoPlayer = \"\";\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n hiddenClass: \"hidden\"\r\n };\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n cookieConsent() {\r\n let consent = false;\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n });\r\n } else if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n return consent;\r\n }\r\n\r\n onHeroVideoLoadEvent() {\r\n const videoElem = this.dom.container.querySelector(\r\n \"[data-video-id-hero]\"\r\n );\r\n if (videoElem && typeof js3q !== \"undefined\") {\r\n const videoId = videoElem.getAttribute(\"data-video-id-hero\");\r\n const id = videoElem.getAttribute(\"id\");\r\n const js3qVideoPlayer = new js3q({\r\n dataid: videoId,\r\n container: id,\r\n autoplay: true,\r\n allowmutedautoplay: true,\r\n loop: true,\r\n muted: true,\r\n controls: false,\r\n width: \"100%\",\r\n height: \"100%\"\r\n });\r\n js3qVideoPlayer.once(\"media.ready\", () => {\r\n videoElem.classList.remove(this.dom.classList.hiddenClass);\r\n });\r\n this.videoPlayer = js3qVideoPlayer;\r\n }\r\n }\r\n handleConsentEvent(consentType, hasConsent) {\r\n if (\r\n consentType === \"ACCEPT_ALL\" ||\r\n (consentType === \"SAVE\" && hasConsent)\r\n ) {\r\n this.onHeroVideoLoadEvent();\r\n } else if (\r\n consentType === \"DENY_ALL\" ||\r\n (consentType === \"SAVE\" && !hasConsent)\r\n ) {\r\n if (this.videoPlayer) {\r\n this.videoPlayer.destroy();\r\n }\r\n }\r\n }\r\n init() {\r\n window.addEventListener(\"UC_UI_CMP_EVENT\", data => {\r\n const consentType = data.detail.type;\r\n const hasConsent = UC_UI.getServicesBaseInfo().some(\r\n service =>\r\n service.id === eisai.threeQVideoServiceId &&\r\n service.consent.status\r\n );\r\n this.handleConsentEvent(consentType, hasConsent);\r\n });\r\n setTimeout(() => {\r\n if (this.cookieConsent() !== false) {\r\n this.onHeroVideoLoadEvent();\r\n }\r\n }, 500);\r\n }\r\n}\r\n","/* global eisai */\r\n/* global js3q */\r\n/* global UC_UI */\r\n/* global dataLayer */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\n\r\nexport class Video {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n observer = null;\r\n videoPlayer = \"\";\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n\r\n this.dom.classList = {\r\n hiddenClass: \"hidden\"\r\n };\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n cookieConsent() {\r\n let consent = false;\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n });\r\n } else if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n return consent;\r\n }\r\n // Method to check if autoplay is enabled\r\n isAutoplayEnabled(videoPlayer) {\r\n return videoPlayer.configLoader.MainStage.config.autoplay === true;\r\n }\r\n onHeroVideoLoadEvent() {\r\n const videoElem = this.dom.container.querySelector(\r\n \".article-body-text__video-wrapper\"\r\n );\r\n if (videoElem && typeof js3q !== \"undefined\") {\r\n const videoId = videoElem.getAttribute(\"data-video-id\");\r\n const id = videoElem.getAttribute(\"id\");\r\n const js3qVideoPlayer = new js3q({\r\n dataid: videoId,\r\n container: id,\r\n width: \"100%\",\r\n height: \"100%\"\r\n });\r\n js3qVideoPlayer.once(\"media.ready\", () => {\r\n videoElem.classList.remove(this.dom.classList.hiddenClass);\r\n // Check if autoplay is enabled in the video configuration\r\n const autoplayEnabled = this.isAutoplayEnabled(js3qVideoPlayer);\r\n\r\n if (autoplayEnabled) {\r\n // Intersection Observer to manage autoplay\r\n this.observer = new IntersectionObserver(entries => {\r\n entries.forEach(entry => {\r\n if (entry.isIntersecting) {\r\n js3qVideoPlayer.play(); // Play video when in view\r\n } else {\r\n js3qVideoPlayer.pause(); // Pause video when out of view\r\n }\r\n });\r\n });\r\n\r\n this.observer.observe(videoElem); // Start observing the video element\r\n }\r\n });\r\n //event tracking\r\n js3qVideoPlayer.on(\"media.autoplay\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"media.autoplay\"\r\n });\r\n });\r\n js3qVideoPlayer.on(\"player.playRequest\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"player.playRequest\"\r\n });\r\n });\r\n js3qVideoPlayer.on(\"player.pauseRequest\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"player.pauseRequest\"\r\n });\r\n });\r\n\r\n // media.timeChange event fires every 250ms\r\n let timeValue = 0;\r\n js3qVideoPlayer.on(\"media.timeChange\", function(data) {\r\n timeValue = data;\r\n });\r\n //check every 5 seconds if media.timeChange event is fired then push timeValue to dataLayer\r\n setInterval(() => {\r\n if (timeValue) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n js3qVideoPlayer.configLoader.MainStage.config\r\n .metadata.Title || videoId,\r\n type: \"media.timeChange\",\r\n value: timeValue,\r\n length:\r\n js3qVideoPlayer.configLoader.originalProcessedConfig\r\n .vlength\r\n });\r\n timeValue = 0;\r\n }\r\n }, 5000);\r\n\r\n js3qVideoPlayer.on(\"media.complete\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"media.complete\"\r\n });\r\n });\r\n (() => {\r\n const findImagePoster = setInterval(() => {\r\n const elem = this.dom.container.querySelector(\"video\");\r\n const param = elem?.getAttribute(\"poster\");\r\n if (elem && param?.includes(\"?\")) {\r\n const newSrc = param.split(\"?\")[0];\r\n elem.setAttribute(\"poster\", newSrc);\r\n clearInterval(findImagePoster);\r\n }\r\n }, 1000);\r\n })();\r\n this.videoPlayer = js3qVideoPlayer;\r\n }\r\n }\r\n\r\n onCookieConsentEvent(cookieStatus) {\r\n const consentWrapper = this.dom.container.querySelector(\r\n \".article-body-text__video-consent\"\r\n );\r\n const videoElem = this.dom.container.querySelector(\r\n \".article-body-text__video-wrapper\"\r\n );\r\n if (cookieStatus) {\r\n this.onHeroVideoLoadEvent();\r\n consentWrapper.classList.add(this.dom.classList.hiddenClass);\r\n } else {\r\n consentWrapper.classList.remove(this.dom.classList.hiddenClass);\r\n videoElem.classList.add(this.dom.classList.hiddenClass);\r\n }\r\n }\r\n handleConsentEvent(consentType, hasConsent) {\r\n if (\r\n consentType === \"ACCEPT_ALL\" ||\r\n (consentType === \"SAVE\" && hasConsent)\r\n ) {\r\n this.onCookieConsentEvent(true);\r\n } else if (\r\n consentType === \"DENY_ALL\" ||\r\n (consentType === \"SAVE\" && !hasConsent)\r\n ) {\r\n this.onCookieConsentEvent(false);\r\n if (this.videoPlayer) {\r\n this.videoPlayer.destroy();\r\n }\r\n if (this.observer) {\r\n this.observer.disconnect();\r\n this.observer = null;\r\n }\r\n }\r\n }\r\n\r\n init() {\r\n window.addEventListener(\"UC_UI_CMP_EVENT\", data => {\r\n const consentType = data.detail.type;\r\n const hasConsent = UC_UI.getServicesBaseInfo().some(\r\n service =>\r\n service.id === eisai.threeQVideoServiceId &&\r\n service.consent.status\r\n );\r\n this.handleConsentEvent(consentType, hasConsent);\r\n });\r\n\r\n setTimeout(() => {\r\n if (this.cookieConsent() !== false) {\r\n this.onHeroVideoLoadEvent();\r\n } else {\r\n this.onCookieConsentEvent(false);\r\n }\r\n }, 500);\r\n }\r\n}\r\n","/* global eisai */\r\n/* global js3q */\r\n/* global UC_UI */\r\n/* global dataLayer */\r\n/* global AdobeDC */\r\n\r\nimport { addEvent, addEventOnce, removeEvent } from \"../../utils/events/events\";\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport {\r\n disableScrollLock,\r\n enableScrollLock\r\n} from \"../../utils/dom/scrollLock\";\r\nimport { hasClass } from \"../../utils/dom/classList\";\r\n\r\nexport class Overlay {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference, overlayId) {\r\n this.dom.container = domReference;\r\n this.dom.objJs3qVideoPlayer = \"js3qVideoPlayer\";\r\n this.dom.classList = {\r\n hiddenClass: \"hidden\",\r\n overlay: \"overlay\",\r\n overlayActive: \"overlay--active\",\r\n overlayClose: \"overlay__close\",\r\n audioTrigger: \"button--icon-audio\",\r\n overlayVideo: \"overlay__video\",\r\n overlayAudio: \"overlay__audio\",\r\n overlayPdf: \"overlay__pdf\",\r\n overlayImage: \"overlay__image\"\r\n };\r\n onReady(() => this.init(domReference, overlayId));\r\n }\r\n\r\n openOverlay(event, overlayId) {\r\n event.preventDefault();\r\n this.closeOverlay(event);\r\n let overlay = this.dom.container.querySelector(\r\n `.overlay[data-overlay-id='${overlayId}']`\r\n );\r\n if (overlayId === \"overlay-pdf\" || overlayId === \"overlay-image\") {\r\n overlay = document.querySelector(\r\n `.overlay[data-overlay-id='${overlayId}']`\r\n );\r\n }\r\n if (overlay) {\r\n overlay.classList.add(this.dom.classList.overlayActive);\r\n }\r\n if (\r\n !event.currentTarget.classList.contains(\r\n `${this.dom.classList.audioTrigger}`\r\n )\r\n ) {\r\n enableScrollLock();\r\n }\r\n }\r\n\r\n onPdfLoadEvent(pdfId) {\r\n if (AdobeDC) {\r\n var dataId = document\r\n .querySelector(\".overlay__pdf .content-wrapper\")\r\n .getAttribute(\"data-viewer-id\");\r\n var adobeDCView = new AdobeDC.View({\r\n clientId: dataId,\r\n divId: \"adobe-dc-view\"\r\n });\r\n adobeDCView.previewFile({\r\n content: { location: { url: pdfId } },\r\n metaData: { fileName: \"pdf\" }\r\n });\r\n }\r\n }\r\n\r\n onImageLoadEvent(imgSrc) {\r\n const overlayImage = document.querySelector(\r\n `.${this.dom.classList.overlayImage} img`\r\n );\r\n overlayImage.src = imgSrc;\r\n }\r\n\r\n resetPdfOverlay() {\r\n const pdfIframe = document.querySelector(\r\n `.${this.dom.classList.overlayPdf} iframe`\r\n );\r\n pdfIframe.src = \"\";\r\n }\r\n\r\n resetImageOverlay() {\r\n const imgSrc = document.querySelector(\r\n `.${this.dom.classList.overlayImage} img`\r\n );\r\n imgSrc.src = \"\";\r\n }\r\n\r\n cookieConsent() {\r\n let consent = false;\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n });\r\n } else if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n return consent;\r\n }\r\n mediaTracking(media, id, name) {\r\n // event tracking\r\n media.on(\"media.autoplay\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: name,\r\n id: this.configLoader.MainStage.config.metadata.Title || id,\r\n type: \"media.autoplay\"\r\n });\r\n });\r\n media.on(\"player.playRequest\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: name,\r\n id: this.configLoader.MainStage.config.metadata.Title || id,\r\n type: \"player.playRequest\"\r\n });\r\n });\r\n\r\n media.on(\"player.pauseRequest\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: name,\r\n id: this.configLoader.MainStage.config.metadata.Title || id,\r\n type: \"player.pauseRequest\"\r\n });\r\n });\r\n // media.timeChange event fires every 250ms\r\n let timeValue = 0;\r\n media.on(\"media.timeChange\", function(data) {\r\n timeValue = data;\r\n });\r\n //check every 5 seconds if media.timeChange event is fired then push timeValue to dataLayer\r\n setInterval(() => {\r\n if (timeValue) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: name,\r\n id:\r\n media.configLoader.MainStage.config.metadata.Title ||\r\n id,\r\n type: \"media.timeChange\",\r\n value: timeValue,\r\n length: media.configLoader.originalProcessedConfig.vlength\r\n });\r\n timeValue = 0;\r\n }\r\n }, 5000);\r\n\r\n media.on(\"media.complete\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: name,\r\n id: this.configLoader.MainStage.config.metadata.Title || id,\r\n type: \"media.complete\"\r\n });\r\n });\r\n }\r\n onVideoLoadEvent(videoId, destroyVideo) {\r\n const videoElem = this.dom.container.querySelector(\r\n `.${this.dom.classList.overlayActive} [data-video-id]`\r\n );\r\n let id;\r\n if (typeof js3q !== \"undefined\") {\r\n if (\r\n destroyVideo &&\r\n typeof this.dom.objJs3qVideoPlayer !== \"string\"\r\n ) {\r\n id = \"\";\r\n this.dom.objJs3qVideoPlayer.pause();\r\n this.dom.objJs3qVideoPlayer.destroy();\r\n } else if (videoElem) {\r\n id = videoElem.getAttribute(\"id\");\r\n this.dom.objJs3qVideoPlayer = new js3q({\r\n dataid: videoId,\r\n container: id,\r\n layout: \"default\",\r\n width: \"100%\",\r\n height: \"100%\",\r\n autoplay: true\r\n });\r\n this.dom.objJs3qVideoPlayer.once(\"media.ready\", () => {\r\n videoElem.classList.remove(this.dom.classList.hiddenClass);\r\n });\r\n this.mediaTracking(\r\n this.dom.objJs3qVideoPlayer,\r\n videoId,\r\n \"3q_video\"\r\n );\r\n } else {\r\n return;\r\n }\r\n }\r\n }\r\n\r\n onAudioLoadEvent(audioId, destroyAudio) {\r\n const audioElem = this.dom.container.querySelector(\r\n `.${this.dom.classList.overlayActive} [data-audio-id]`\r\n );\r\n let id;\r\n if (typeof js3q !== \"undefined\") {\r\n if (\r\n destroyAudio &&\r\n typeof this.dom.objJs3qVideoPlayer !== \"string\"\r\n ) {\r\n id = \"\";\r\n this.dom.objJs3qVideoPlayer.pause();\r\n this.dom.objJs3qVideoPlayer.destroy();\r\n } else if (audioElem) {\r\n id = audioElem.getAttribute(\"id\");\r\n this.dom.objJs3qVideoPlayer = new js3q({\r\n dataid: audioId,\r\n container: id,\r\n layout: \"fixed\",\r\n width: \"100%\",\r\n height: \"100%\",\r\n autoplay: true\r\n });\r\n this.mediaTracking(\r\n this.dom.objJs3qVideoPlayer,\r\n audioId,\r\n \"3q_audio\"\r\n );\r\n } else {\r\n return;\r\n }\r\n }\r\n }\r\n\r\n handleOverlayReset() {\r\n const overlayActive = document.querySelector(\r\n `.${this.dom.classList.overlayActive}`\r\n );\r\n if (overlayActive) {\r\n const overlayClose = overlayActive.querySelector(\r\n `.${this.dom.classList.overlayClose}`\r\n );\r\n overlayClose.click();\r\n }\r\n }\r\n\r\n closeOverlay(event) {\r\n event.preventDefault();\r\n const overlays = document.querySelectorAll(\".overlay\");\r\n overlays.forEach(item => {\r\n item.classList.remove(this.dom.classList.overlayActive);\r\n });\r\n disableScrollLock();\r\n }\r\n\r\n handleKeyEvent() {\r\n const videoWrapper = document.querySelectorAll(\r\n `.${this.dom.classList.overlayVideo}`\r\n );\r\n const audioWrapper = document.querySelectorAll(\r\n `.${this.dom.classList.overlayAudio}`\r\n );\r\n let isVideo;\r\n let isAudio;\r\n\r\n removeEvent(window, \"keydown\");\r\n window.addEventListener(\"keydown\", event => {\r\n videoWrapper.forEach(item => {\r\n hasClass(item, this.dom.classList.overlayActive);\r\n isVideo = true;\r\n });\r\n audioWrapper.forEach(item => {\r\n hasClass(item, this.dom.classList.overlayActive);\r\n isAudio = true;\r\n });\r\n\r\n if (event.key === \"Escape\") {\r\n if (isVideo) {\r\n this.onVideoLoadEvent(event, true);\r\n } else if (isAudio) {\r\n this.onAudioLoadEvent(event, true);\r\n }\r\n this.closeOverlay(event);\r\n }\r\n });\r\n }\r\n\r\n init(domReference) {\r\n const self = this;\r\n const hrefs = domReference.querySelectorAll(\"a, button\");\r\n const close = document.querySelectorAll(\r\n `.${self.dom.classList.overlayClose}`\r\n );\r\n const pdfClose = document.querySelector(\r\n `.overlay__pdf .${self.dom.classList.overlayClose}`\r\n );\r\n const imgClose = document.querySelector(\r\n `.overlay__image .${self.dom.classList.overlayClose}`\r\n );\r\n\r\n addEventOnce(hrefs, \"click\", event => {\r\n this.handleOverlayReset();\r\n const isImage =\r\n event.currentTarget.dataset.imageTriggerId ||\r\n event.currentTarget.parentNode.dataset.imageTriggerId;\r\n const isPDF =\r\n event.currentTarget.dataset.pdfTriggerId ||\r\n event.currentTarget.parentNode.dataset.pdfTriggerId;\r\n const isVideo =\r\n event.currentTarget.dataset.videoTriggerId ||\r\n event.currentTarget.parentNode.dataset.videoTriggerId;\r\n const isAudio =\r\n event.currentTarget.dataset.audioTriggerId ||\r\n event.currentTarget.parentNode.dataset.audioTriggerId;\r\n let target;\r\n if ((isVideo || isAudio) && self.cookieConsent() === false) {\r\n target = \"overlay-consent\";\r\n } else {\r\n target =\r\n event.currentTarget.dataset.overlayTrigger ||\r\n event.currentTarget.parentNode.dataset.overlayTrigger;\r\n }\r\n if (target && isImage) {\r\n this.openOverlay(event, target);\r\n this.onImageLoadEvent(\r\n event.currentTarget.dataset.imageTriggerId ||\r\n event.currentTarget.parentNode.dataset.imageTriggerId\r\n );\r\n } else if (target && isPDF) {\r\n this.openOverlay(event, target);\r\n this.onPdfLoadEvent(\r\n event.currentTarget.dataset.pdfTriggerId ||\r\n event.currentTarget.parentNode.dataset.pdfTriggerId\r\n );\r\n } else if (target && isVideo) {\r\n this.openOverlay(event, target);\r\n if (self.cookieConsent() !== false) {\r\n this.onVideoLoadEvent(\r\n event.currentTarget.dataset.videoTriggerId ||\r\n event.currentTarget.parentNode.dataset\r\n .videoTriggerId\r\n );\r\n }\r\n } else if (target && isAudio) {\r\n this.openOverlay(event, target);\r\n if (self.cookieConsent() !== false) {\r\n this.onAudioLoadEvent(\r\n event.currentTarget.dataset.audioTriggerId ||\r\n event.currentTarget.parentNode.dataset\r\n .audioTriggerId\r\n );\r\n }\r\n } else {\r\n return;\r\n }\r\n });\r\n\r\n addEventOnce(close, \"click\", event => {\r\n const videoWrapper = document.querySelectorAll(\".overlay__video\");\r\n const audioWrapper = document.querySelectorAll(\".overlay__audio\");\r\n let isVideo;\r\n let isAudio;\r\n videoWrapper.forEach(item => {\r\n hasClass(item, this.dom.classList.overlayActive);\r\n isVideo = true;\r\n });\r\n audioWrapper.forEach(item => {\r\n hasClass(item, this.dom.classList.overlayActive);\r\n isAudio = true;\r\n });\r\n if (isVideo) {\r\n this.onVideoLoadEvent(event, true);\r\n } else if (isAudio) {\r\n this.onAudioLoadEvent(event, true);\r\n }\r\n this.closeOverlay(event);\r\n });\r\n\r\n addEvent(pdfClose, \"click\", event => {\r\n this.closeOverlay(event);\r\n this.resetPdfOverlay();\r\n });\r\n\r\n addEvent(imgClose, \"click\", event => {\r\n this.closeOverlay(event);\r\n this.resetImageOverlay();\r\n });\r\n\r\n this.handleKeyEvent();\r\n }\r\n}\r\n","import { onReady } from \"../../utils/events/onReady\";\r\nimport { addEvent } from \"../../utils/events/events\";\r\nimport { scrollTo } from \"../../utils/dom/scrollTo\";\r\n\r\nexport class ScrollTop {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n onScrollTopClickEvent(event) {\r\n event.preventDefault();\r\n scrollTo(0, 600);\r\n }\r\n\r\n /**\r\n * Bind events we need to the DOM-elements.\r\n */\r\n bindEvents() {\r\n addEvent(\r\n this.dom.container,\r\n \"click\",\r\n this.onScrollTopClickEvent.bind(this)\r\n );\r\n }\r\n\r\n init() {\r\n this.bindEvents();\r\n }\r\n}\r\n","import { onReady } from \"../../utils/events/onReady\";\r\nimport { throttle } from \"../../utils/dom/throttle\";\r\nimport { bindScrollToElement } from \"../../utils/events/bindScrollToElement\";\r\nimport {\r\n currentBreakpoint,\r\n breakpointIndex\r\n} from \"../../utils/events/onWindowResize\";\r\n\r\nexport class InPageNavigation {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.hash = window.location.hash;\r\n this.dom.pathname = window.location.pathname;\r\n this.dom.interval = 1000;\r\n this.dom.transition = 600;\r\n this.dom.navHeight = document.querySelector(\"header\")?.clientHeight;\r\n this.dom.classList = {\r\n activeClass: \"active\",\r\n hiddenClass: \"hidden\"\r\n };\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n onInPageNavigationLoad() {\r\n const inPageNavigation = this.dom.container.firstElementChild;\r\n const section = document.querySelectorAll(\"[data-in-page-navigation]\");\r\n if (section && section.length) {\r\n section[0].classList.add(\"component__first-item\");\r\n section.forEach(item => {\r\n if (item.dataset.inPageNavigation) {\r\n const template = `
  • ${item.dataset.inPageNavigation}
  • `;\r\n inPageNavigation.insertAdjacentHTML(\"beforeend\", template);\r\n }\r\n });\r\n }\r\n }\r\n\r\n onInPageNavigationScroll() {\r\n const inPageNavigation = this.dom.container;\r\n const links = inPageNavigation.querySelectorAll(\"a\");\r\n const section = document.querySelectorAll(\"[data-in-page-navigation]\");\r\n if (section && section.length) {\r\n section.forEach(item => {\r\n const id = item.getAttribute(\"id\");\r\n if (item.dataset.inPageNavigation) {\r\n const sectionTop = item.offsetTop - this.dom.navHeight;\r\n if (window.scrollY >= sectionTop) {\r\n links.forEach(item =>\r\n item.classList.remove(\r\n this.dom.classList.activeClass\r\n )\r\n );\r\n const currentLink = inPageNavigation.querySelector(\r\n `a[href=\"#${id}\"]`\r\n );\r\n currentLink.classList.add(\r\n this.dom.classList.activeClass\r\n );\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n onInPageNavigationClick() {\r\n const inPageNavigation = this.dom.container;\r\n const links = inPageNavigation.querySelectorAll(\"a\");\r\n links.forEach(item => {\r\n item.addEventListener(\"click\", event => {\r\n event.preventDefault();\r\n const href = item.getAttribute(\"href\");\r\n const section = document.querySelector(`${href}`);\r\n section.scrollIntoView({});\r\n let lastPos = null;\r\n requestAnimationFrame(checkPos);\r\n function checkPos() {\r\n const newPos = section.getBoundingClientRect().top;\r\n if (newPos !== lastPos) {\r\n lastPos = newPos;\r\n requestAnimationFrame(checkPos);\r\n window.history.replaceState(null, null, href);\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n init(domReference) {\r\n const isMobile = currentBreakpoint < breakpointIndex.lg;\r\n const inPageNavigation = domReference;\r\n const inPageNavigationInner = inPageNavigation.querySelector(\r\n \".in-page-navigation__inner\"\r\n );\r\n const section = document.querySelectorAll(\"[data-in-page-navigation]\");\r\n let sections = [...section].filter(\r\n item => item.getAttribute(\"data-in-page-navigation\") !== \"\"\r\n );\r\n if (sections.length) {\r\n this.onInPageNavigationLoad();\r\n this.onInPageNavigationScroll();\r\n this.onInPageNavigationClick();\r\n\r\n document.addEventListener(\"scroll\", () => {\r\n throttle(this.onInPageNavigationScroll(), this.dom.interval);\r\n });\r\n inPageNavigation.classList.remove(this.dom.classList.hiddenClass);\r\n if (isMobile) {\r\n bindScrollToElement(document.body, inPageNavigationInner, 40);\r\n }\r\n } else {\r\n inPageNavigation.classList.add(this.dom.classList.hiddenClass);\r\n }\r\n }\r\n}\r\n","/* Bind vertical scrolling from one element to horiziontak scrolling in another\r\n * import { bindScrollToElement } from \"./utils/events/bindScrollToElement\";\r\n * bindScrollToElement( div1, div2 );\r\n */\r\n\r\nexport function bindScrollToElement(elem1, elem2, buffer = 0) {\r\n elem1.onscroll = function() {\r\n const elem1Height = elem1.scrollHeight;\r\n const elem1Offset = window.scrollY / elem1Height;\r\n const elem2Offset = elem2.scrollWidth - elem2.offsetWidth + buffer;\r\n elem2.scrollLeft = elem2Offset * elem1Offset;\r\n };\r\n}\r\n","import { onReady } from \"../../utils/events/onReady\";\r\n\r\nexport class GatedContent {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.hash = window.location.hash;\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n attachGatedContentProperties(target) {\r\n const link = this.dom.hash.split(\"#\")[1];\r\n if (link) {\r\n const href = target.getAttribute(\"href\");\r\n target.setAttribute(\"href\", href + \"?hash=\" + link);\r\n }\r\n }\r\n\r\n init(domReference) {\r\n const target = domReference.querySelector(\".button--icon-cta\");\r\n this.attachGatedContentProperties(target);\r\n }\r\n}\r\n","import { onReady } from \"../../utils/events/onReady\";\r\nimport {\r\n currentWindowWidth,\r\n onWindowResize\r\n} from \"../../utils/events/onWindowResize\";\r\nimport { debounce } from \"../../utils/dom/debounce\";\r\n\r\nexport class Carousel {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.currentItem = 0;\r\n this.dom.lastWidth = window.innerWidth;\r\n this.dom.carouselItemWrapper = domReference.querySelector(\r\n \".carousel__item-wrapper\"\r\n );\r\n this.dom.carouselLeftButton = domReference.querySelector(\r\n \".carousel__arrow--left\"\r\n );\r\n this.dom.carouselRightButton = domReference.querySelector(\r\n \".carousel__arrow--right\"\r\n );\r\n this.dom.carouselItem = domReference.querySelector(\".carousel__item\");\r\n this.dom.carouselCircleWrapper = domReference.querySelector(\r\n \".carousel__circle-wrapper\"\r\n );\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n setColumns() {\r\n const carousel = this.dom.container;\r\n if (carousel.dataset.carouselEnable === \"true\") {\r\n if (carousel.dataset.carouselColumns === \"4\") {\r\n this.dom.carouselItemWrapper\r\n .querySelectorAll(\".carousel__item\")\r\n .forEach(item =>\r\n item.classList.add(\r\n `col--md-6`,\r\n `col--lg-${12 / carousel.dataset.carouselColumns}`\r\n )\r\n );\r\n } else {\r\n this.dom.carouselItemWrapper\r\n .querySelectorAll(\".carousel__item\")\r\n .forEach(item =>\r\n item.classList.add(\r\n `col--md-${12 / carousel.dataset.carouselColumns}`\r\n )\r\n );\r\n }\r\n if (\r\n carousel.dataset.carouselColumns >=\r\n this.dom.carouselItemWrapper.childElementCount\r\n ) {\r\n this.dom.carouselRightButton.classList.add(\r\n \"carousel__arrow--right--hidden\"\r\n );\r\n }\r\n } else {\r\n this.dom.carouselItemWrapper.classList.add(\r\n `carousel__item-wrapper--col-${carousel.dataset.carouselColumns}`\r\n );\r\n this.dom.carouselItemWrapper\r\n .querySelectorAll(\".carousel__item\")\r\n .forEach(item => (item.ariaHidden = false));\r\n }\r\n }\r\n setActiveAttributes() {\r\n const carouselCircles = this.dom.container.querySelectorAll(\r\n \".carousel__circle\"\r\n );\r\n carouselCircles.forEach(item => {\r\n item.classList.remove(\"carousel__circle--active\");\r\n });\r\n this.dom.carouselItemWrapper\r\n .querySelectorAll(\".carousel__item\")\r\n .forEach(item => (item.ariaHidden = true));\r\n this.dom.carouselItemWrapper\r\n .querySelectorAll(\"a\")\r\n .forEach(link => link.setAttribute(\"tabindex\", \"-1\"));\r\n let items =\r\n this.dom.carouselItemWrapper.childElementCount <\r\n this.dom.container.dataset.carouselColumns\r\n ? this.dom.carouselItemWrapper.childElementCount\r\n : this.dom.container.dataset.carouselColumns;\r\n if (window.innerWidth > 992) {\r\n for (let i = 0; i < items; i++) {\r\n carouselCircles[this.dom.currentItem + i].classList.add(\r\n \"carousel__circle--active\"\r\n );\r\n this.dom.carouselItemWrapper.children[\r\n this.dom.currentItem + i\r\n ].ariaHidden = false;\r\n this.dom.carouselItemWrapper.children[this.dom.currentItem + i]\r\n .querySelector(\"a\")\r\n ?.removeAttribute(\"tabindex\");\r\n }\r\n }\r\n }\r\n resetCarousel() {\r\n if (this.dom.lastWidth !== currentWindowWidth) {\r\n if (currentWindowWidth >= 992) {\r\n this.dom.carouselItemWrapper.style.transform = ``;\r\n this.dom.carouselRightButton.classList.remove(\r\n \"carousel__arrow--right--hidden\"\r\n );\r\n this.dom.carouselLeftButton.classList.add(\r\n \"carousel__arrow--left--hidden\"\r\n );\r\n this.dom.currentItem = 0;\r\n this.setActiveAttributes();\r\n } else {\r\n this.dom.carouselItemWrapper.style.transform = ``;\r\n this.setSelected();\r\n }\r\n this.dom.lastWidth = currentWindowWidth;\r\n }\r\n }\r\n previousItem() {\r\n //show right button\r\n this.dom.carouselRightButton.classList.remove(\r\n \"carousel__arrow--right--hidden\"\r\n );\r\n const slideWidth = this.dom.carouselItem.clientWidth;\r\n //if reached first item, hide left button\r\n\r\n if (this.dom.currentItem === 1) {\r\n this.dom.carouselLeftButton.classList.add(\r\n \"carousel__arrow--left--hidden\"\r\n );\r\n }\r\n if (this.dom.currentItem !== 0) {\r\n this.dom.currentItem -= 1;\r\n }\r\n this.dom.carouselItemWrapper.style.transform = `translateX(-${(slideWidth +\r\n 32) *\r\n this.dom.currentItem}px)`;\r\n this.setActiveAttributes();\r\n }\r\n\r\n nextItem() {\r\n //show the left button + remove margin-left\r\n this.dom.carouselLeftButton.classList.remove(\r\n \"carousel__arrow--left--hidden\"\r\n );\r\n //slide the carousel\r\n const slideWidth = this.dom.carouselItem.clientWidth;\r\n if (\r\n this.dom.currentItem !==\r\n this.dom.carouselItemWrapper.childElementCount - 1\r\n ) {\r\n this.dom.currentItem += 1;\r\n }\r\n this.dom.carouselItemWrapper.style.transform = `translateX(-${(slideWidth +\r\n 32) *\r\n this.dom.currentItem}px)`;\r\n //if reached last item, hide the right button\r\n if (\r\n this.dom.currentItem +\r\n Number(this.dom.container.dataset.carouselColumns) ===\r\n this.dom.carouselItemWrapper.childElementCount\r\n ) {\r\n this.dom.carouselRightButton.classList.add(\r\n \"carousel__arrow--right--hidden\"\r\n );\r\n }\r\n this.setActiveAttributes();\r\n }\r\n\r\n generateCarouselCircle() {\r\n for (\r\n let i = 0;\r\n i < this.dom.carouselItemWrapper.childElementCount;\r\n i++\r\n ) {\r\n const circle = document.createElement(\"div\");\r\n circle.classList.add(\"carousel__circle\");\r\n this.dom.carouselCircleWrapper?.appendChild(circle);\r\n }\r\n this.dom.carouselCircleWrapper?.classList.add(\r\n \"carousel__circle-wrapper--show\"\r\n );\r\n }\r\n\r\n // using overflow-x:scroll, scroll-snap css properties and setSelected function to achieve smooth scroll on mobile devices\r\n setSelected() {\r\n const circles = this.dom.carouselCircleWrapper.querySelectorAll(\r\n \".carousel__circle\"\r\n );\r\n circles.forEach(circle => {\r\n circle.classList.remove(\"carousel__circle--active\");\r\n });\r\n this.dom.carouselItemWrapper\r\n .querySelectorAll(\".carousel__item\")\r\n .forEach(item => {\r\n item.classList.remove(\"selected\");\r\n item.ariaHidden = true;\r\n item.querySelector(\"a\")?.setAttribute(\"tabindex\", \"-1\");\r\n });\r\n const scrolllength = this.dom.carouselItemWrapper.querySelectorAll(\r\n \".carousel__item\"\r\n )[1]?.offsetLeft;\r\n const nthchild = Math.round(\r\n this.dom.carouselItemWrapper.scrollLeft / scrolllength + 1\r\n );\r\n this.dom.carouselCircleWrapper\r\n .querySelector(`div:nth-child(${nthchild})`)\r\n .classList.add(\"carousel__circle--active\");\r\n this.dom.carouselItemWrapper\r\n .querySelector(`li:nth-child(${nthchild})`)\r\n .classList.add(\"selected\");\r\n\r\n this.dom.carouselItemWrapper.children[nthchild - 1].ariaHidden = false;\r\n this.dom.carouselItemWrapper.children[nthchild - 1]\r\n .querySelector(\"a\")\r\n ?.removeAttribute(\"tabindex\");\r\n }\r\n init(domReference) {\r\n const carousel = domReference;\r\n this.setColumns();\r\n\r\n if (carousel.dataset.carouselEnable === \"true\") {\r\n carousel.classList.add(\"carousel--enabled\");\r\n this.dom.carouselLeftButton.addEventListener(\"click\", () =>\r\n this.previousItem()\r\n );\r\n this.dom.carouselRightButton.addEventListener(\"click\", () =>\r\n this.nextItem()\r\n );\r\n this.generateCarouselCircle();\r\n this.setActiveAttributes();\r\n this.setSelected();\r\n onWindowResize(() => this.resetCarousel());\r\n this.dom.carouselItemWrapper.addEventListener(\r\n \"scroll\",\r\n debounce(() => this.setSelected())\r\n );\r\n }\r\n }\r\n}\r\n","/* global eisai */\r\n/* global js3q */\r\n/* global UC_UI */\r\n/*global dataLayer */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport { onWindowResize } from \"../../utils/events/onWindowResize\";\r\n\r\nexport class CarouselVideo {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n videoPlayers = [];\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n hiddenClass: \"hidden\"\r\n };\r\n onReady(() => this.init(domReference));\r\n }\r\n cookieConsent() {\r\n let consent = false;\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n });\r\n } else if (\r\n UC_UI.getServicesBaseInfo().find(\r\n data => data.id === eisai.threeQVideoServiceId\r\n ).consent.status\r\n ) {\r\n consent = true;\r\n }\r\n return consent;\r\n }\r\n onCookieConsentEvent(cookieStatus) {\r\n const consentWrappers = this.dom.container.querySelectorAll(\r\n \".carousel__item-video-consent\"\r\n );\r\n const videoElements = this.dom.container.querySelectorAll(\r\n \".carousel__item-video-wrapper\"\r\n );\r\n if (cookieStatus) {\r\n consentWrappers.forEach(consentWrapper =>\r\n consentWrapper.classList.add(this.dom.classList.hiddenClass)\r\n );\r\n } else {\r\n consentWrappers.forEach(consentWrapper =>\r\n consentWrapper.classList.remove(this.dom.classList.hiddenClass)\r\n );\r\n videoElements.forEach(videoElement =>\r\n videoElement.classList.add(this.dom.classList.hiddenClass)\r\n );\r\n }\r\n }\r\n onCarouselVideoLoadEvent() {\r\n const videos = this.dom.container.querySelectorAll(\r\n \".carousel__item-video-wrapper\"\r\n );\r\n videos.forEach(videoElem => {\r\n if (videoElem && typeof js3q !== \"undefined\") {\r\n const videoId = videoElem.getAttribute(\"data-video-id\");\r\n const id = videoElem.getAttribute(\"id\");\r\n const js3qVideoPlayer = new js3q({\r\n dataid: videoId,\r\n container: id,\r\n width: \"100%\",\r\n height: \"100%\"\r\n });\r\n js3qVideoPlayer.once(\"media.ready\", () => {\r\n videoElem.classList.remove(this.dom.classList.hiddenClass);\r\n });\r\n //event tracking\r\n js3qVideoPlayer.on(\"media.autoplay\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"media.autoplay\"\r\n });\r\n });\r\n js3qVideoPlayer.on(\"player.playRequest\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"player.playRequest\"\r\n });\r\n });\r\n js3qVideoPlayer.on(\"player.pauseRequest\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"player.pauseRequest\"\r\n });\r\n });\r\n\r\n // media.timeChange event fires every 250ms\r\n let timeValue = 0;\r\n js3qVideoPlayer.on(\"media.timeChange\", function(data) {\r\n timeValue = data;\r\n });\r\n //check every 5 seconds if media.timeChange event is fired then push timeValue to dataLayer\r\n setInterval(() => {\r\n if (timeValue) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n js3qVideoPlayer.configLoader.MainStage.config\r\n .metadata.Title || videoId,\r\n type: \"media.timeChange\",\r\n value: timeValue,\r\n length:\r\n js3qVideoPlayer.configLoader\r\n .originalProcessedConfig.vlength\r\n });\r\n timeValue = 0;\r\n }\r\n }, 5000);\r\n\r\n js3qVideoPlayer.on(\"media.complete\", function(data) {\r\n dataLayer.push({\r\n event: \"gtm_event\",\r\n category: \"3q_video\",\r\n id:\r\n this.configLoader.MainStage.config.metadata.Title ||\r\n videoId,\r\n type: \"media.complete\"\r\n });\r\n });\r\n (() => {\r\n const findImagePoster = setInterval(() => {\r\n const elem = this.dom.container.querySelector(\"video\");\r\n const param = elem?.getAttribute(\"poster\");\r\n if (elem && param?.includes(\"?\")) {\r\n const newSrc = param.split(\"?\")[0];\r\n elem.setAttribute(\"poster\", newSrc);\r\n clearInterval(findImagePoster);\r\n }\r\n }, 1000);\r\n })();\r\n this.videoPlayers.push(js3qVideoPlayer);\r\n }\r\n });\r\n }\r\n handleConsentEvent(consentType, hasConsent) {\r\n if (\r\n consentType === \"ACCEPT_ALL\" ||\r\n (consentType === \"SAVE\" && hasConsent)\r\n ) {\r\n this.onCarouselVideoLoadEvent();\r\n this.onCookieConsentEvent(true);\r\n } else if (\r\n consentType === \"DENY_ALL\" ||\r\n (consentType === \"SAVE\" && !hasConsent)\r\n ) {\r\n this.onCookieConsentEvent(false);\r\n const consentWrappers = this.dom.container.querySelectorAll(\r\n \".carousel__item-video-consent\"\r\n );\r\n const img = this.dom.container.querySelector(\"img\");\r\n consentWrappers.forEach(consentWrapper => {\r\n consentWrapper.style.height = img?.clientHeight + \"px\";\r\n });\r\n\r\n if (this.videoPlayers) {\r\n this.videoPlayers.forEach(videoPlayers =>\r\n videoPlayers.destroy()\r\n );\r\n this.videoPlayers = [];\r\n }\r\n }\r\n }\r\n\r\n init(domReference) {\r\n function cookieConsentHeight() {\r\n const consentWrappers = domReference.querySelectorAll(\r\n \".carousel__item-video-consent\"\r\n );\r\n const img = domReference.querySelector(\"img\");\r\n consentWrappers.forEach(consentWrapper => {\r\n consentWrapper.style.height = img?.clientHeight + \"px\";\r\n });\r\n }\r\n\r\n window.addEventListener(\"UC_UI_CMP_EVENT\", data => {\r\n const consentType = data.detail.type;\r\n const hasConsent = UC_UI.getServicesBaseInfo().some(\r\n service =>\r\n service.id === eisai.threeQVideoServiceId &&\r\n service.consent.status\r\n );\r\n this.handleConsentEvent(consentType, hasConsent);\r\n });\r\n\r\n setTimeout(() => {\r\n if (this.cookieConsent() !== false) {\r\n this.onCarouselVideoLoadEvent();\r\n } else {\r\n this.onCookieConsentEvent(false);\r\n cookieConsentHeight();\r\n }\r\n }, 500);\r\n onWindowResize(cookieConsentHeight);\r\n }\r\n}\r\n","/* global UC_UI */\r\n\r\nimport { addEventOnce } from \"../../utils/events/events\";\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport {\r\n disableScrollLock,\r\n enableScrollLock\r\n} from \"../../utils/dom/scrollLock\";\r\n\r\nexport class InformationModal {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.loader = document.querySelector(\".loading-screen\");\r\n this.dom.classList = {\r\n hiddenClass: \"hidden\",\r\n informationModal: \"information-modal\",\r\n InformationModalActive: \"information-modal--active\",\r\n InformationModalClose: \"information-modal__close\"\r\n };\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n setCookie(name) {\r\n const date = new Date();\r\n date.setTime(date.getTime() + 1 * 3600 * 1000); // 1 hour\r\n let expires = \"expires=\" + date.toUTCString();\r\n document.cookie = name + \"=true;\" + expires + \";path=/\"; //set cookie for 1 hour\r\n }\r\n getCookie(name) {\r\n const match = document.cookie.match(\r\n new RegExp(\"(^| )\" + name + \"=([^;]+)\")\r\n );\r\n if (match) return match[2];\r\n }\r\n showInformationModal() {\r\n this.dom.container.classList.add(\r\n this.dom.classList.InformationModalActive\r\n );\r\n this.dom.loader.classList.add(this.dom.classList.hiddenClass);\r\n\r\n enableScrollLock();\r\n }\r\n hideInformationModal(name) {\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n if (UC_UI.areAllConsentsAccepted()) {\r\n this.setCookie(name);\r\n }\r\n });\r\n } else if (UC_UI.areAllConsentsAccepted()) {\r\n this.setCookie(name);\r\n }\r\n this.dom.container.classList.remove(\r\n this.dom.classList.InformationModalActive\r\n );\r\n disableScrollLock();\r\n }\r\n init(domReference) {\r\n const self = this;\r\n const close = document.querySelector(\r\n `.${self.dom.classList.InformationModalClose}`\r\n );\r\n const cookieName = domReference.dataset.id;\r\n\r\n if (cookieName) {\r\n //check if there isn't a cookie to show the popup\r\n let iscookieExists = this.getCookie(cookieName);\r\n\r\n if (!iscookieExists) {\r\n this.showInformationModal();\r\n }\r\n this.dom.loader.classList.add(this.dom.classList.hiddenClass);\r\n }\r\n addEventOnce(close, \"click\", () => {\r\n this.hideInformationModal(cookieName);\r\n });\r\n }\r\n}\r\n","/* global UC_UI */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\n\r\nexport class StaticIframe {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n this.dom.classList = {\r\n hiddenClass: \"hidden\"\r\n };\r\n onReady(() => this.init(domReference));\r\n }\r\n cookieConsent(id) {\r\n let consent = false;\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n if (\r\n UC_UI.getServicesBaseInfo()?.find(data => data.id === id)\r\n ?.consent.status\r\n ) {\r\n consent = true;\r\n }\r\n });\r\n } else if (\r\n UC_UI.getServicesBaseInfo()?.find(data => data.id === id)?.consent\r\n .status\r\n ) {\r\n consent = true;\r\n }\r\n return consent;\r\n }\r\n\r\n onCookieConsentEvent() {\r\n const iframe = this.dom.container.querySelector(\"iframe\");\r\n const consentWrapper = this.dom.container.querySelector(\r\n \".static-iframe__consent\"\r\n );\r\n if (iframe.dataset.usercentricsId) {\r\n if (this.cookieConsent(iframe.dataset.usercentricsId) !== false) {\r\n iframe.src = iframe.dataset.src;\r\n consentWrapper.classList.add(this.dom.classList.hiddenClass);\r\n iframe.classList.remove(this.dom.classList.hiddenClass);\r\n } else {\r\n consentWrapper.classList.remove(this.dom.classList.hiddenClass);\r\n iframe.classList.add(this.dom.classList.hiddenClass);\r\n iframe.src = \"\";\r\n }\r\n } else {\r\n iframe.src = iframe.dataset.src;\r\n }\r\n }\r\n\r\n init() {\r\n setTimeout(() => {\r\n this.onCookieConsentEvent();\r\n }, 500);\r\n if (!window.UC_UI || !UC_UI.isInitialized()) {\r\n window.addEventListener(\"UC_UI_INITIALIZED\", () => {\r\n window.addEventListener(\"ucEvent\", () => {\r\n this.onCookieConsentEvent();\r\n });\r\n });\r\n } else {\r\n window.addEventListener(\"ucEvent\", () => {\r\n this.onCookieConsentEvent();\r\n });\r\n }\r\n }\r\n}\r\n","/* global Chart */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\nimport chartData from \"../../../.storybook/rcc-data.json\";\r\nexport class RccCalculator {\r\n constructor(domReference) {\r\n this.dom = {\r\n container: domReference,\r\n classList: { hiddenClass: \"hidden\" }\r\n };\r\n\r\n onReady(() => this.init());\r\n }\r\n async init() {\r\n await this.initCharts();\r\n }\r\n async initCharts() {\r\n const initialDataId = this.dom.container.querySelector(\r\n \".rcc__dropdown option:first-child\"\r\n ).value;\r\n const json = chartData[initialDataId];\r\n const barChart = new Chart(\"bar-chart\", {\r\n type: \"bar\",\r\n options: this.getChartOptions(),\r\n data: json?.leftGraphJson.barchart\r\n });\r\n\r\n this.updateTableContent(json);\r\n this.updateContainers(json);\r\n const doughnutChart = new Chart(\"doughnut-chart\", {\r\n type: \"doughnut\",\r\n data: json?.rightGraphJson.circlediagram[0],\r\n options: this.getDoughnutChartOptions(\r\n \"Lenvatinib and pembrolizumab\"\r\n ),\r\n plugins: [\r\n this.getDoughnutLabel(\r\n json?.rightGraphJson.circlediagram[0].datasets[1]\r\n .backgroundColor[0]\r\n )\r\n ]\r\n });\r\n const doughnutChart2 = new Chart(\"doughnut-chart-2\", {\r\n type: \"doughnut\",\r\n data: json?.rightGraphJson.circlediagram[1],\r\n options: this.getDoughnutChartOptions(\"Sunitinib\"),\r\n plugins: [\r\n this.getDoughnutLabel(\r\n json?.rightGraphJson.circlediagram[1].datasets[1]\r\n .backgroundColor[0]\r\n )\r\n ]\r\n });\r\n this.setupDropdown(barChart, doughnutChart, doughnutChart2);\r\n }\r\n\r\n getChartOptions() {\r\n return {\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n plugins: {\r\n legend: {\r\n position: \"bottom\",\r\n labels: { usePointStyle: true, color: \"black\" }\r\n }\r\n },\r\n scales: {\r\n y: {\r\n grid: { display: true },\r\n max: 80,\r\n min: 0,\r\n ticks: {\r\n stepSize: 10,\r\n textStrokeColor: \"#cccccc\",\r\n color: \"#000\"\r\n },\r\n title: {\r\n display: true,\r\n text: \"Amount of months\"\r\n }\r\n },\r\n x: {\r\n grid: { display: true },\r\n stacked: false\r\n }\r\n }\r\n };\r\n }\r\n\r\n getDoughnutChartOptions(title) {\r\n return {\r\n responsive: false,\r\n cutout: \"70%\",\r\n plugins: {\r\n legend: {\r\n position: \"bottom\",\r\n labels: {\r\n usePointStyle: true,\r\n color: \"black\",\r\n generateLabels: chart => {\r\n const originalLabels = Chart.overrides.doughnut.plugins.legend.labels.generateLabels(\r\n chart\r\n );\r\n return originalLabels.slice(\r\n 0,\r\n originalLabels.length - 2\r\n );\r\n }\r\n }\r\n },\r\n title: {\r\n display: true,\r\n text: title,\r\n color: \"black\",\r\n font: {\r\n weight: 400\r\n }\r\n }\r\n }\r\n };\r\n }\r\n\r\n getDoughnutLabel(dotColor) {\r\n return {\r\n id: \"doughnutLabel\",\r\n beforeDatasetsDraw: chart => {\r\n const { ctx, data } = chart;\r\n ctx.save();\r\n const { x, y } = chart.getDatasetMeta(0).data[0];\r\n // Draw a circle above the text\r\n const circleRadius = 7;\r\n ctx.beginPath();\r\n ctx.arc(x, y - 35, circleRadius, 0, Math.PI * 2);\r\n ctx.fillStyle = dotColor; // Circle color\r\n ctx.fill();\r\n ctx.closePath();\r\n // Draw the text\r\n ctx.font = \"bold 24px sans-serif\";\r\n ctx.fillStyle = \"#202020\";\r\n ctx.textAlign = \"center\";\r\n ctx.textBaseline = \"bottom\";\r\n ctx.fillText(data.labels[data.labels.length - 2], x, y);\r\n ctx.textBaseline = \"top\";\r\n ctx.fillText(\r\n `${\r\n data.datasets[1].data[data.datasets[1].data.length - 2]\r\n }%`,\r\n x,\r\n y\r\n );\r\n ctx.restore();\r\n }\r\n };\r\n }\r\n\r\n updateTableContent(json) {\r\n const mobileTable = this.dom.container.querySelector(\r\n \".rcc__table--mobile\"\r\n );\r\n const desktopTable = this.dom.container.querySelector(\r\n \".rcc__table--desktop\"\r\n );\r\n const tableFooter = this.dom.container.querySelector(\r\n \".rcc__table-footer\"\r\n );\r\n\r\n mobileTable.innerHTML = json.mobileTable;\r\n desktopTable.innerHTML = json.desktopTable;\r\n tableFooter.innerHTML = json.tableDescriptionText;\r\n }\r\n\r\n updateContainers(json) {\r\n const leftContainer = this.dom.container.querySelector(\r\n \".rcc__container-left\"\r\n );\r\n const rightContainer = this.dom.container.querySelector(\r\n \".rcc__container-right\"\r\n );\r\n\r\n this.updateContainerData(\r\n leftContainer,\r\n json.leftGraphBottomDescription,\r\n json.leftGraphTitle,\r\n json.leftGraphDescription\r\n );\r\n this.updateContainerData(\r\n rightContainer,\r\n json.rightGraphBottomDescription,\r\n json.rightGraphTitle,\r\n json.rightGraphDescription\r\n );\r\n }\r\n\r\n updateContainerData(container, captionText, titleText, descriptionText) {\r\n const caption = container.querySelector(\".rcc__container-caption\");\r\n const title = container.querySelector(\".rcc__container-title\");\r\n const description = container.querySelector(\r\n \".rcc__container-description\"\r\n );\r\n\r\n caption.innerHTML = captionText;\r\n title.innerHTML = titleText;\r\n description.innerHTML = descriptionText;\r\n }\r\n\r\n setupDropdown(barChart, doughnutChart, doughnutChart2) {\r\n const dropdown = this.dom.container.querySelector(\".rcc__dropdown\");\r\n const disclaimer = this.dom.container.querySelector(\".rcc__disclaimer\");\r\n\r\n dropdown.addEventListener(\"change\", async e => {\r\n disclaimer.innerHTML = chartData[e.target.value].disclaimerText;\r\n\r\n const barData =\r\n chartData[e.target.value].leftGraphJson.barchart.datasets;\r\n const doughnutData =\r\n chartData[e.target.value].rightGraphJson.circlediagram[0]\r\n .datasets;\r\n const doughnutData2 =\r\n chartData[e.target.value].rightGraphJson.circlediagram[1]\r\n .datasets;\r\n barChart.config.data.datasets.forEach((dataset, index) => {\r\n dataset.data = barData[index].data;\r\n });\r\n barChart.update();\r\n doughnutChart.config.data.labels =\r\n chartData[\r\n e.target.value\r\n ].rightGraphJson.circlediagram[0].labels;\r\n doughnutChart.config.data.datasets.forEach((dataset, index) => {\r\n dataset.data = doughnutData[index].data;\r\n });\r\n doughnutChart.update();\r\n doughnutChart2.config.data.labels =\r\n chartData[\r\n e.target.value\r\n ].rightGraphJson.circlediagram[1].labels;\r\n doughnutChart2.config.data.datasets.forEach((dataset, index) => {\r\n dataset.data = doughnutData2[index].data;\r\n });\r\n doughnutChart2.update();\r\n\r\n this.updateTableContent(chartData[e.target.value]);\r\n this.updateContainers(chartData[e.target.value]);\r\n });\r\n }\r\n}\r\n","/* global eisai */\r\n\r\nimport { onReady } from \"../../utils/events/onReady\";\r\n\r\nexport class ThreeQ {\r\n /**\r\n * Internal placeholder for DOM-objects\r\n *\r\n * @type {object}\r\n * @ignore\r\n */\r\n dom = {\r\n container: undefined\r\n };\r\n\r\n /**\r\n *\r\n * @param {Element} domReference - The element to work from\r\n */\r\n constructor(domReference) {\r\n this.dom.container = domReference;\r\n\r\n onReady(() => this.init(domReference));\r\n }\r\n\r\n onThreeQLoadEvent() {\r\n const baseURL = eisai.threeQBaseURL;\r\n const path = eisai.threeQPath;\r\n const apiKey = eisai.threeQAPIKey;\r\n const region = this.dom.container.parentElement.className;\r\n fetch(`${baseURL}${path}/projects`, {\r\n method: \"GET\",\r\n headers: {\r\n \"X-AUTH-APIKEY\": apiKey\r\n }\r\n })\r\n .then(res => {\r\n if (res.status === 200) {\r\n return res.json();\r\n }\r\n })\r\n .then(data => {\r\n if (region !== \"undefined\") {\r\n data = data.Projects.filter(\r\n item => item.Label === `EISAI (${region})`\r\n );\r\n this.dom.container.innerHTML = `
  • ${JSON.stringify(\r\n data,\r\n null,\r\n 4\r\n )}
  • `;\r\n } else {\r\n this.dom.container.innerHTML = `
  • ${JSON.stringify(\r\n data,\r\n null,\r\n 4\r\n )}
  • `;\r\n }\r\n });\r\n }\r\n\r\n init() {\r\n this.onThreeQLoadEvent();\r\n }\r\n}\r\n","/* detect scroll direction\r\n * import { scrollDirection } from \"./utils/events/scrollDirection\";\r\n * scrollDirection((scrollPos, previousScrollPos) => {\r\n * if (previousScrollPos > scrollPos) {\r\n * // scrolling up\r\n * } else {\r\n * // scrolling down\r\n * }\r\n *});\r\n */\r\n\r\nexport function scrollDirection(fn) {\r\n let last_known_scroll_position = 0;\r\n let ticking = false;\r\n window.addEventListener(\"scroll\", function() {\r\n let previous_known_scroll_position = last_known_scroll_position;\r\n last_known_scroll_position = window.scrollY;\r\n if (!ticking) {\r\n window.requestAnimationFrame(function() {\r\n fn(last_known_scroll_position, previous_known_scroll_position);\r\n ticking = false;\r\n });\r\n ticking = true;\r\n }\r\n });\r\n}\r\n"],"sourceRoot":""}