{"version":3,"file":"main.min.js","sources":["../../../Frontend/js/utils/windowResize.js","../../../Frontend/js/utils/scroll.js","../../../Frontend/js/utils/onReady.js","../../../Frontend/js/utils/elementProperties.js","../../../Frontend/js/utils/scrollLock.js","../../../Frontend/js/components/nav.js","../../../Frontend/js/utils/stickyNavOnScroll.js","../../../Frontend/js/utils/lazyImage.js","../../../Frontend/js/utils/helpers.js","../../../Frontend/js/utils/scrollTo.js","../../../Frontend/js/components/video.js","../../../Frontend/js/main.js","../../../Frontend/js/components/eventticker.js"],"sourcesContent":["import settings from '../../settings.json';\n\nexport const breakpoints = settings.breakpoints;\nexport const breakpointKeys = Object.keys(breakpoints);\nexport let currentWindowWidth = window.innerWidth;\nexport let currentWindowHeight = window.innerHeight;\nexport let currentBreakpoint;\nexport let currentBreakpointIndex = 0;\nlet resizeTimer;\n\nconst resizeFunctions = [];\n\n/**\n * Get various window sizes - width, height etc.\n * This function is fired automatically upon page load. and run each time the window changes size.\n *\n */\nfunction getWindowSizes() {\n currentWindowWidth = window.innerWidth;\n currentWindowHeight = window.innerHeight;\n\n // Calculate which breakpoint is currently active, based on the screen width compared to the breakpoint definitions.\n\n let lastFoundWidth = 0;\n\n breakpointKeys.forEach((key, index) => {\n const width = breakpoints[key];\n if (currentWindowWidth >= width && width > lastFoundWidth) {\n lastFoundWidth = width;\n currentBreakpoint = key;\n currentBreakpointIndex = index;\n }\n });\n}\n\nfunction resizeHandler() {\n clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => {\n getWindowSizes();\n resizeFunctions.forEach(funcRef => funcRef());\n }, 100);\n}\n\nexport function onWindowResize(handler) {\n if (!currentBreakpoint) {\n initWindowResize();\n }\n\n resizeFunctions.push(handler);\n}\n\nexport function initWindowResize() { \n getWindowSizes();\n window.addEventListener('resize', resizeHandler);\n window.addEventListener('orientationchange', resizeHandler);\n}\n","export let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;\n\nlet ticking = false;\nconst scrollFunctions = [];\n\nfunction animate() {\n scrollFunctions.forEach(funcRef => funcRef());\n\n ticking = false;\n}\n\nfunction requestTick() {\n if (!ticking) {\n requestAnimationFrame(animate);\n ticking = true;\n }\n}\n\nfunction scrollHandler() {\n scrollTop = document.documentElement.scrollTop || document.body.scrollTop;\n requestTick();\n}\n/**\n * Adds a function to a function array, executed on a single scroll-event set on window.\n * This avoids the memory load and possible hickups of setting multiple eventlisteners for the same event.\n * Also this optimizes rendering by utilising the requestAnimationFrame for these scroll-events.\n * \n * @param {Function} handler - function to be called on scroll \n * @param {boolean} triggerNow - Should the function be called at once\n */\nexport function onScroll(handler, triggerNow = false) {\n // if first call: setup eventlistener on window\n !scrollFunctions.length ? initScroll() : null;\n\n // Trigger function\n triggerNow ? handler() : null;\n\n scrollFunctions.push(handler); \n}\n\nexport function initScroll() {\n window.addEventListener('scroll', scrollHandler);\n}\n","/**\n * Handler to trigger callbacks once the browser is ready for them.\n *\n * You can keep adding references using onReady() even after the page is loaded. In that case they will be\n * run at once.\n *\n * @example\n * import { onReady } from './utils/events/onReady';\n *\n * onReady(yourFunctionHere);\n *\n */\n\nlet functionReferences = [];\n\n// Set the initial readyState based on the browser's current state. If the script has been loaded\n// asynchronously, the DOM might be ready for us already, in which case there's no reason to delay\n// any further processing. The following will evaluate as true if the DOM is ready, or the page is\n// complete.\nlet readyState = document.readyState === 'interactive' || document.readyState === 'complete';\n\n// Defines whether or not the window.onReady event has been bound, so we won't do it twice. That\n// would just be stupid.\nlet readyEventBound = false;\n\n/**\n * Run the given array of callback functions.\n *\n * @private\n * @param {Array} funcArray\n */\nfunction runFunctionArray(funcArray) {\n funcArray.forEach(funcRef => funcRef());\n}\n\n/**\n * Empty the callback arrays\n *\n * @private\n */\nfunction emptyCallbackArrays() {\n // Keep iterating through the function references until there are none left.\n while (functionReferences.length) {\n // Set up a temporary array that mirrors the list of callbacks, and empty the real one.\n const tempArray = functionReferences.slice(0);\n functionReferences = [];\n\n // Run the callbacks. The callbacks themselves may set up more callbacks, which\n // is why we keep looping the array until we're done.\n runFunctionArray(tempArray);\n }\n\n // At this point we'll assume we're ready for anything!\n readyState = true;\n}\n\n/**\n * Make sure the \"ready\"-event is set.\n *\n * @private\n */\nfunction bindReadyEvent() {\n if (!readyEventBound) {\n if (document.readyState === 'loading') {\n // loading yet, wait for the event\n document.addEventListener('DOMContentLoaded', emptyCallbackArrays);\n } else {\n // DOM is ready!\n emptyCallbackArrays();\n }\n\n readyEventBound = true;\n }\n}\n\n/**\n * Register a function to run when the page is ready.\n *\n * @param {Function} functionReference - The function you want to run.\n */\nexport function onReady(functionReference) {\n if (typeof functionReference === 'function') {\n if (readyState) {\n functionReference();\n } else {\n bindReadyEvent();\n\n functionReferences.push(functionReference);\n }\n }\n}\n","/**\n * Utilities for checking properties and states of elements.\n */\n\n/**\n * Check if an element is empty.\n *\n * @param {Node} element - Check if this element is empty.\n * @param {boolean} [strict=true] - Set this to **false** to ignore nodes with whitespace.\n * @returns {boolean} **True** if the element is empty.\n */\nexport function elementIsEmpty(element, strict = true) {\n return strict ? !element.childNodes.length : !element.innerHTML.trim().length;\n}\n\n/**\n * Check if an element is hidden in the DOM with `display: none;`\n *\n * @param {HTMLElement} element - The element to check.\n * @returns {boolean} **True** if element is hidden, otherwise **false**.\n */\nexport function elementIsHidden(element) {\n return element.offsetParent === null;\n}\n\n/**\n * Check if an element is in the viewport\n * \n * @param {HTMLElement} elem - The element to check \n */\nexport function isVisible(elem) {\n return !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length);\n}\n\n/**\n * Find out whether or not the given argument is an element that would react somewhat normally to DOM-manipulations.\n *\n * @param {*} element - The element to check.\n * @returns {boolean} `true` if the given argument is an element (or document, or window), and `false` otherwise.\n */\nexport function isElement(element) {\n return element instanceof Element || element instanceof Document || element instanceof Window;\n}\n\n/**\n * Return the position of an element\n *\n * @param {Element|String} element - The HTML element to work with or its ID\n * @param {Element|String|Window} [relativeTo=window] - The HTML element to return the position relative to or its ID\n * @returns {{top: Number, left: Number}} An object with top and left positions in pixels\n *\n *\n * @example Basic usage:\n * import { getElementPosition } from './utils/dom/elementProperties';\n *\n * const element = document.querySelector('.anElement');\n * getElementPosition(element);\n *\n *\n * @example Perform a search for an element with an ID equal to the string, i.e. 'elementId', and get the position of that:\n * import { getElementPosition } from './utils/dom/elementProperties';\n *\n * getElementPosition('elementId');\n */\nexport function getElementPosition(element, relativeTo = window) {\n const useElement = typeof element === 'string' ? document.getElementById(element) : element;\n\n // Throw error if element wasn't found\n if (!useElement) {\n throw 'getElementPosition did not find an element.';\n }\n\n const useRelativeTo = typeof relativeTo === 'string' ? document.getElementById(relativeTo) : relativeTo;\n\n // Throw error if relative element wasn't found\n if (!useRelativeTo) {\n throw 'getElementPosition did not find an element to show the position relative to.';\n }\n\n if (relativeTo === window) {\n // Return position relative to window\n const rect = useElement.getBoundingClientRect();\n return {\n top: rect.top + (window.pageYOffset || document.documentElement.scrollTop),\n left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft)\n };\n } else {\n // Return position relative to declared element\n return {\n top: useElement.offsetTop - relativeTo.offsetTop,\n left: useElement.offsetLeft - relativeTo.offsetLeft\n };\n }\n}\n\n/**\n * Get the current scroll values of the given element (or window). Will return an object containing\n * \"left\" and \"top\" properties, which are set to the scroll values, or false if no compatible element\n * was given.\n *\n * @param {Element|Window} [element=window]\n * @returns {{ left: number, top: number } | boolean}\n */\nexport function getElementScroll(element = window) {\n if (isElement(element)) {\n if (element instanceof Window) {\n return {\n left: element.pageXOffset || document.documentElement.scrollLeft,\n top: element.pageYOffset || document.documentElement.scrollTop\n };\n } else {\n return {\n left: element.scrollX || element.scrollLeft,\n top: element.scrollY || element.scrollTop\n };\n }\n } else {\n console.warn('Can\\'t get scroll-position or given argument type.');\n return false;\n }\n}\n\n/**\n * Get both width and height of element\n *\n * @param {Element} element - The HTML element to work with\n * @param {Object} [options={}] - Object of options\n * @param {boolean} [options.includePadding=false] - Get size including padding (defaults to true)\n * @param {boolean} [options.includeBorder=false] - Get size including border (defaults to true)\n * @param {boolean} [options.includeMargin=true] - Get size including margin (defaults to false)\n * @param {null|':before'|':after'} [options.pseudoElement=null] - Get size of pseudo element ':before' or ':after'\n * @returns {{width: number, height: number}} An object with the width and height as numbers\n */\nexport function getElementSize(element, options = {}) {\n // Get styles\n const elementStyle = window.getComputedStyle(element, options.pseudoElement);\n\n return {\n width: getElementWidth(element, options, elementStyle),\n height: getElementHeight(element, options, elementStyle)\n };\n}\n\n/**\n * Get width of element\n *\n * @param {Element} element - The HTML element to work with\n * @param {Object} [options={}] - Object of options\n * @param {boolean} [options.includeMargin=false] - Get width including margin (defaults to false)\n * @param {boolean} [options.includeBorder=true] - Get width including border (defaults to true)\n * @param {boolean} [options.includePadding=true] - Get width including padding (defaults to true)\n * @param {null|':before'|':after'} [options.pseudoElement=null] - Get width of pseudo element ':before' or ':after'\n * @param {CSSStyleDeclaration} [elementStyle] - Style declaration of element (in case you already have called .getComputedStyle(), pass its returned value here)\n * @returns {number} The width as a number\n */\nexport function getElementWidth(element, options = {}, elementStyle = null) {\n // Keep supplied values or set to defaults\n options.includeMargin = options.includeMargin === true;\n options.includeBorder = options.includeBorder !== false;\n options.includePadding = options.includePadding !== false;\n\n // Get styles\n const style = elementStyle || window.getComputedStyle(element, options.pseudoElement);\n\n // Get width including border and padding\n let width = element.offsetWidth;\n\n // Calculate width with margin\n if (options.includeMargin) {\n width += parseFloat(style.marginLeft) + parseFloat(style.marginRight);\n }\n\n // Calculate width without border\n if (!options.includeBorder) {\n width -= parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth);\n }\n\n // Calculate width without padding\n if (!options.includePadding) {\n width -= parseFloat(style.paddingLeft) + parseFloat(style.paddingRight);\n }\n\n return width;\n}\n\n/**\n * Get height of element\n *\n * @param {Element} element - The HTML element to work with\n * @param {Object} [options={}] - Object of options\n * @param {boolean} [options.includeMargin=false] - Get height including margin (defaults to false)\n * @param {boolean} [options.includeBorder=true] - Get height including border (defaults to true)\n * @param {boolean} [options.includePadding=true] - Get height including padding (defaults to true)\n * @param {null|':before'|':after'} [options.pseudoElement=null] - Get height of pseudo element ':before' or ':after'\n * @param {CSSStyleDeclaration} [elementStyle] - Style declaration of element (in case you already have called .getComputedStyle(), pass its returned value here)\n * @returns {number} The height as a number\n */\nexport function getElementHeight(element, options = {}, elementStyle = null) {\n // Keep supplied values or set to defaults\n options.includeMargin = options.includeMargin === true;\n options.includeBorder = options.includeBorder !== false;\n options.includePadding = options.includePadding !== false;\n\n // Get styles\n const style = elementStyle || window.getComputedStyle(element, options.pseudoElement);\n\n // Get height including border and padding\n let height = element.offsetHeight;\n\n // Calculate height with margin\n if (options.includeMargin) {\n height += parseFloat(style.marginTop) + parseFloat(style.marginBottom);\n }\n\n // Calculate height without border\n if (!options.includeBorder) {\n height -= parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);\n }\n\n // Calculate height without padding\n if (!options.includePadding) {\n height -= parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);\n }\n\n return height;\n}\n","/**\n * A utility to **lock the viewport** at the current position in order to **stop scrolling**.\n *\n * @example Basic usage\n * import { enableScrollLock, disableScrollLock } from './utils/dom/scrollLock';\n *\n * enableScrollLock();\n * window.setTimeout(disableScrollLock, 3000);\n */\n\nimport { getElementScroll } from './elementProperties';\n\nconst className = 'scroll-lock';\nlet scrollTop = 0;\n\n/**\n * Get the current state of the scroll lock. `true` if the scroll lock is enabled, otherwise `false`.\n *\n * @type {boolean}\n */\nexport let scrollLocked = false;\n\n/**\n * Enable the scroll lock.\n */\nexport function enableScrollLock() {\n if (!scrollLocked) {\n // Get scroll position\n const scrollPosition = getElementScroll();\n\n // Reset scroll position\n window.scrollTo(scrollPosition.left, 0);\n\n const htmlTag = document.documentElement;\n htmlTag.classList.add(className);\n htmlTag.style.marginTop = `${-scrollPosition.top}px`;\n htmlTag.style.position = 'fixed';\n htmlTag.style.overflow = 'hidden';\n htmlTag.style.width = '100%';\n document.body.style.overflowY = 'scroll';\n\n // Remember state\n scrollLocked = true;\n scrollTop = scrollPosition.top;\n }\n}\n\n/**\n * @type {function}\n * @ignore\n */\nexport const enable = enableScrollLock;\n\n/**\n * Disable the scroll lock\n */\nexport function disableScrollLock() {\n if (scrollLocked) {\n const scrollPosition = getElementScroll();\n\n const htmlTag = document.documentElement;\n htmlTag.classList.remove(className);\n htmlTag.style.marginTop = '';\n htmlTag.style.position = '';\n htmlTag.style.overflow = '';\n htmlTag.style.width = '';\n document.body.removeAttribute('style');\n // Set the scroll position to what it was before\n window.scrollTo(scrollPosition.left, scrollTop);\n\n // Remember state\n scrollLocked = false;\n }\n}\n\n/**\n * @type {function}\n * @ignore\n */\nexport const disable = disableScrollLock;\n\n/**\n * Toggle the scroll lock between on and off\n */\nexport function toggleScrollLock() {\n if (scrollLocked) {\n disableScrollLock();\n } else {\n enableScrollLock();\n }\n}\n\n/**\n * @type {function}\n * @ignore\n */\nexport const toggle = toggleScrollLock;\n\nexport default {\n enable,\n disable,\n toggle\n};\n","import { stickyNavOnScroll } from '../utils/stickyNavOnScroll';\r\nimport { enableScrollLock, disableScrollLock } from '../utils/scrollLock';\r\n\r\nexport let nav;\r\n\r\nexport function toggleMenuOpen() {\r\n if (nav.classList.contains('nav--open')) {\r\n disableScrollLock();\r\n nav.classList.remove('nav--open');\r\n\r\n if (window.pageYOffset > 50) {\r\n setTimeout(() => nav.classList.add('going-up'), 40);\r\n }\r\n\r\n } else {\r\n enableScrollLock();\r\n nav.classList.add('nav--open');\r\n }\r\n}\r\n\r\nfunction clickCreateUser(e) {\r\n const target = e.currentTarget.closest('.nav__create-user');\r\n\r\n if (target) {\r\n if (target.classList.contains('js-show')) {\r\n target.classList.remove('js-show');\r\n } else {\r\n target.classList.add('js-show');\r\n }\r\n }\r\n}\r\n\r\nexport function setupNav(selector = '.nav', sticky = true) {\r\n nav = document.body.querySelector(selector);\r\n\r\n if (nav) {\r\n const navBtn = nav.querySelector('.nav__btn');\r\n\r\n navBtn.addEventListener('click', toggleMenuOpen);\r\n\r\n if (sticky) {\r\n stickyNavOnScroll(nav, 'nav--sticky', 30, 'going-up');\r\n }\r\n\r\n const navCreateUser = nav.querySelector('.nav__create-user > svg');\r\n\r\n if (navCreateUser) {\r\n navCreateUser.addEventListener('click',clickCreateUser);\r\n }\r\n }\r\n}\r\n","import { getElementScroll } from './elementProperties';\nimport { scrollLocked } from './scrollLock';\nimport { onScroll } from './scroll';\n\n/**\n * \n * @param {HTMLElement} element - element to add sticky class to\n * @param {string} className - sticky class name to add on scroll\n * @param {number} scrollInPixels - number of pixels before activating scroll\n * @param {string} goingUpClass - class added when scrolling up\n */\nexport function stickyNavOnScroll(element, className = 'nav--sticky', scrollInPixels = 30, goingUpClass = 'nav--going-up') {\n let scrollTimer;\n let lastScrollPosition;\n\n const scrollHandler = () => {\n\n clearTimeout(scrollTimer);\n\n if (!scrollLocked) {\n scrollTimer = setTimeout(() => {\n const windowScroll = getElementScroll();\n \n if (windowScroll.top > scrollInPixels) {\n element.classList.add(className);\n \n if (lastScrollPosition > windowScroll.top) {\n element.classList.add(goingUpClass);\n } else {\n element.classList.remove(goingUpClass);\n }\n \n lastScrollPosition = windowScroll.top;\n } else {\n element.classList.remove(className);\n element.classList.remove(goingUpClass);\n }\n }, 30);\n }\n\n };\n\n onScroll(scrollHandler, true);\n}\n","import { breakpointKeys, currentBreakpointIndex } from '../utils/windowResize';\nimport { onWindowResize } from './windowResize';\nimport { onScroll } from './scroll';\n//import \"objectFitPolyfill\";\n\nexport const isBot = (!('onscroll' in window)) || (typeof navigator !== 'undefined' && /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent));\n\nlet lastUsedScreenWidth;\nlet lazyArray = [];\n\nlet options = {\n className: 'lazy',\n loadedClass: 'lazy--loaded',\n loadClass: 'lazy--loading',\n decodeImg: true, // This option requires promises support (incl. via polyfill.io)\n oldIe11Fit: false, // This option requires objectFit support\n offset: 0\n};\n\nexport function setupLazyLoading(customOptions = {}) {\n lastUsedScreenWidth = -1;\n options = { ...options, ...customOptions };\n lazyArray = document.body.getElementsByClassName(options.className);\n\n // onWindowsResize set before first lazyLoad, to insure currentBreakPoint is set\n onWindowResize(lazyLoad);\n\n onScroll(lazyLoad, true);\n}\n\nfunction lazyLoad() {\n // If our current screen mode does not match the one we used the last time we made an image lookup,\n // perform a new one now. Otherwise, what would be the point?\n\n if (isBot || lastUsedScreenWidth < currentBreakpointIndex) {\n\n for (let i = 0; i < lazyArray.length; i++) {\n const lazyElem = lazyArray[i];\n\n if (isBot || isInViewport(lazyElem)) {\n lazyElem.classList.add(options.loadClass);\n if (lazyElem.classList.contains('lazy--bg')) {\n loadBgImage(lazyElem);\n } else {\n loadLazyImage(lazyElem);\n }\n }\n }\n\n cleanLazy();\n }\n}\n\nfunction cleanLazy() {\n lazyArray = Array.prototype.filter.call(lazyArray, l => !l.classList.contains(options.loadClass));\n}\n\nfunction isInViewport(el) {\n const rect = el.getBoundingClientRect();\n\n return (\n rect.bottom >= 0 &&\n rect.right >= 0 &&\n rect.top - options.offset <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.left - options.offset <= (window.innerWidth || document.documentElement.clientWidth)\n );\n}\n\n/**\n * This function gets the image wrapper data attributes src and alt text\n * and creates an new image tag to download the image.\n * It then uses the src as a background-image.\n *\n * @param {HTMLElement} bgContainer - Image wrapper element\n */\nexport function loadBgImage(bgContainer) {\n const src = getImageSrc(bgContainer);\n const handleLoadedBg = () => {\n bgContainer.style.backgroundImage = formattedSrc;\n bgContainer.classList.add(options.loadedClass);\n bgContainer.classList.remove(options.loadClass);\n };\n\n // If no usable source was returned, abort at once.\n if (!src) {\n return;\n }\n\n const formattedSrc = `url(${src})`;\n\n if (bgContainer.style.backgroundImage === formattedSrc) {\n return;\n }\n\n if (options.decodeImg) {\n // Start loading the new image.\n loadImage(src).then(handleLoadedBg);\n } else {\n handleLoadedBg();\n }\n}\n\n/**\n * This function gets the container data attributes src.\n * If the container is an image it sets the src of it.\n * If the container is not an image it creates a new image tag and inserts it into the given container.\n *\n * @param {HTMLElement} container - Image wrapper element\n */\nexport function loadLazyImage(container) {\n const src = getImageSrc(container);\n\n // If no usable source was returned, abort mission.\n if (!src) {\n return;\n }\n\n if (options.decodeImg) {\n // We don't want to start processing if the new URL matches the old one.\n const oldImage = container.querySelector('img');\n if (oldImage && container.classList.contains(options.loadedClass)) {\n if (oldImage.getAttribute('src') === src) {\n if (options.oldIe11Fit) {\n window.objectFitPolyfill(oldImage);\n }\n return;\n } else {\n container.removeChild(oldImage);\n }\n }\n\n // Start loading the new image.\n loadImage(src).then(newImageTag => {\n // Set src and ALT text if defined.\n if (container.tagName === 'IMG') {\n container.src = src;\n } else {\n const altText = container.getAttribute('data-alt') || '';\n newImageTag.setAttribute('alt', altText);\n\n container.appendChild(newImageTag);\n }\n\n container.classList.add(options.loadedClass);\n container.classList.remove(options.loadClass);\n\n // oldIE object-fit polyfill placed here to take resize into account\n if (options.oldIe11Fit) {\n window.objectFitPolyfill(newImageTag);\n }\n });\n } else {\n container.src = src;\n container.classList.add(options.loadedClass);\n container.classList.remove(options.loadClass);\n }\n}\n\n/**\n * Try to decode the image, after it's loaded, and resolve the Promise.\n *\n * @param {Element} newImage\n * @returns {Promise}\n */\nfunction decodeImage(newImage) {\n return 'decode' in newImage ? newImage.decode().then(() => newImage) : Promise.resolve(newImage);\n}\n\n/**\n * Load an image, and return a Promise that resolves once the image is loaded.\n *\n * @param {string} path\n * @returns {Promise} Promise that will resolve with the loaded image once it's ready.\n */\nexport function loadImage(path) {\n const newImage = new Image();\n\n return new Promise(resolve => {\n newImage.addEventListener('load', () => decodeImage(newImage).then(image => resolve(image)), false);\n newImage.src = path;\n });\n}\n\n/**\n * This function gets the data-src from the image wrapper, based on width of the browser window.\n *\n * @param {HTMLElement} container - Image wrapper element\n * @returns {string}\n */\nfunction getImageSrc(container) {\n let src = '';\n let largestBreakpointFound = 0;\n\n if (container.getAttribute('data-src')) {\n src = container.getAttribute('data-src');\n container.removeAttribute('data-src');\n } else {\n breakpointKeys.forEach((breakpointName, index) => {\n if (currentBreakpointIndex >= index) {\n if (index === 0 || index > largestBreakpointFound) {\n const srcAttribute = `data-src-${breakpointName}`;\n src = container.getAttribute(srcAttribute) || src;\n\n container.removeAttribute(srcAttribute);\n\n // Make sure we won't set the size to a smaller breakpoint later, in case they're not properly ordered.\n largestBreakpointFound = index;\n }\n }\n });\n }\n\n return src;\n}\n","export const body = document.body;\r\nexport const qs = (s, o = body) => o.querySelector(s);\r\nexport const qsa = (s, o = body) => o.querySelectorAll(s);\r\n\r\nexport const allowStatCookies = window.CookieInformation && CookieInformation.getConsentGivenFor('cookie_cat_statistic');\r\n\r\n/**\r\n * Sets a custom CSS variable to ensure precise vh unit mesuarment\r\n *\r\n */\r\n\r\nexport function setVhProp() {\r\n // First we get the viewport height and we multiple it by 1% to get a value for a vh unit\r\n const vh = window.innerHeight * 0.01;\r\n // Then we set the value in the --vh custom property to the root of the document\r\n document.documentElement.style.setProperty('--vh', `${vh}px`);\r\n}\r\n\r\nexport function initVhUnitOverwrite() {\r\n setVhProp();\r\n //window.addEventListener('resize', setVhProp);\r\n}\r\n\r\nexport function canUseWebP() {\r\n const elem = document.createElement('canvas');\r\n\r\n if (elem.getContext && elem.getContext('2d')) {\r\n // was able or not to get WebP representation\r\n return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;\r\n }\r\n\r\n // very old browser like IE 8, canvas not supported\r\n return false;\r\n}\r\n\r\n/**\r\n * Add a to the head\r\n */\r\nexport function addPrefetch(kind, url, as) {\r\n const linkElem = document.createElement('link');\r\n linkElem.rel = kind;\r\n linkElem.href = url;\r\n if (as) {\r\n linkElem.as = as;\r\n }\r\n linkElem.crossorigin = true;\r\n document.head.append(linkElem);\r\n}\r\n\r\n/**\r\n * Format number sparated with commas per thousand.\r\n *\r\n * @param {Number} num - Number you want to format\r\n *\r\n * @returns {string} - Returns the number formatet with commas\r\n *\r\n * @example:\r\n * console.info(formatNumber(2665)) // 2,665\r\n * console.info(formatNumber(102665)) // 102,665\r\n * console.info(formatNumber(1240.5)) // 1,240.5\r\n */\r\n\r\nexport function formatNumber(num, seperator = '.') {\r\n return num.toString().replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, `$1${seperator}`);\r\n}\r\n\r\n/**\r\n * Prevent function from being executed as long as it is invoked, while given delay hasn't passed.\r\n *\r\n * @param {Function} callback Callback\r\n * @param {String} delay Delay\r\n * @return {Function} Callback\r\n */\r\nexport function debounce(callback, delay) {\r\n let timer = null;\r\n\r\n return function () {\r\n const context = this,\r\n args = arguments;\r\n\r\n clearTimeout(timer);\r\n\r\n timer = setTimeout(function () {\r\n callback.apply(context, args);\r\n }, delay);\r\n };\r\n}\r\n\r\n/*\r\n* Load JavsScript asynchronously when needed\r\n* @param {String} source The path to the file\r\n* @param {Function} callback The callback to excecute upon load\r\n* @return {Element} Element to attach\r\n*/\r\nexport function loadJS (source, callback) {\r\n const reference = document.getElementsByTagName('script')[0];\r\n const script = document.createElement('script');\r\n\r\n script.src = source;\r\n script.async = true;\r\n reference.parentNode.insertBefore(script, reference);\r\n\r\n if (callback && typeof(callback) === 'function') {\r\n script.onload = callback;\r\n }\r\n\r\n return script;\r\n}\r\n\r\n/**\r\n * Get the thumbnail dimensions to use for a given player size.\r\n *\r\n * @param {Object} options\r\n * @param {number} options.width The width of the player\r\n * @param {number} options.height The height of the player\r\n * @return {Object} The width and height\r\n */\r\nexport function getRoundedDimensions({ width, height }) {\r\n let roundedWidth = width;\r\n let roundedHeight = height;\r\n\r\n // If the original width is a multiple of 320 then we should\r\n // not round up. This is to keep the native image dimensions\r\n // so that they match up with the actual frames from the video.\r\n //\r\n // For example 640x360, 960x540, 1280x720, 1920x1080\r\n //\r\n // Round up to nearest 100 px to improve cacheability at the\r\n // CDN. For example, any width between 601 pixels and 699\r\n // pixels will render the thumbnail at 700 pixels width.\r\n if (roundedWidth % 320 !== 0) {\r\n roundedWidth = Math.ceil(width / 100) * 100;\r\n roundedHeight = Math.round((roundedWidth / width) * height);\r\n }\r\n\r\n return {\r\n width: roundedWidth,\r\n height: roundedHeight\r\n };\r\n}\r\n\r\n/**\r\n * Detect if a device as touch support\r\n *\r\n * 'ontouchstart' in window - works on most browsers\r\n * navigator.maxTouchPoints - works on IE10/11 and Surface\r\n */\r\nexport function isTouchDevice() {\r\n return !!('ontouchstart' in window || navigator.maxTouchPoints);\r\n}\r\n\r\nexport const isIE11 = !!window.MSInputMethodContext && !!document.documentMode;","import { getElementPosition } from './elementProperties';\n\nconst easeInOutQuad = function(currentTime, start, change, duration) {\n let time = currentTime;\n time /= duration / 2;\n if (time < 1) {\n return (change / 2) * time * time + start;\n }\n time--;\n return (-change / 2) * (time * (time - 2) - 1) + start;\n};\n\nconst easeInOutQuintic = function(currentTime, start, change, duration) {\n let time = currentTime;\n const ts = (time /= duration) * time,\n tc = ts * time;\n return start + change * (6 * tc * ts + -15 * ts * ts + 10 * tc);\n};\n\nexport function scrollTo(to, duration = 750, callback) {\n function move(amount) {\n if (document.scrollingElement) {\n document.scrollingElement.scrollTop = amount;\n } else {\n document.documentElement.scrollTop = amount;\n document.body.parentNode.scrollTop = amount;\n document.body.scrollTop = amount;\n }\n }\n function position() {\n return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;\n }\n\n const start = position(),\n change = to instanceof Element ? getElementPosition(to).top - start : to - start,\n increment = 20;\n\n\n let currentTime = 0;\n\n const animate = function() {\n // increment the time\n currentTime += increment;\n // find the value with the quadratic in-out easing function\n const val = easeInOutQuintic(currentTime, start, change, duration);\n // move the document.body\n move(val);\n // do the animation unless its over\n if (currentTime < duration) {\n requestAnimationFrame(animate);\n } else {\n if (callback && typeof callback === 'function') {\n // the animation is done so lets callback\n if (typeof callback === 'function') {\n callback();\n }\n }\n }\n };\n animate();\n}\n","import { addPrefetch, canUseWebP, getRoundedDimensions, allowStatCookies } from '../utils/helpers';\nimport { scrollTo } from '../utils/scrollTo';\n\n/**\n * Combined lightweight vimeo/youtube embed code.\n *\n * Ported from https://github.com/paulirish/lite-youtube-embed by Paul Irish\n * and https://github.com/luwes/lite-vimeo-embed by Wesley Luyten\n *\n * @param {HTMLElement} container - Element in which you want the video inserted\n */\nclass Video {\n constructor(container) {\n this.container = container;\n this.id = container.getAttribute('data-video-id');\n this.bg = container.getAttribute('data-video-bg') || 0;\n this.byline = container.getAttribute('data-video-byline') || 0;\n this.color = container.getAttribute('data-video-color') || 0;\n this.controls = container.getAttribute('data-video-controls') || 1;\n this.ytUrl = allowStatCookies ? 'https://www.youtube.com' : 'https://www.youtube-nocookie.com';\n\n if (!this.id) {\n this.videoLink = container.getAttribute('data-video-link');\n if (this.videoLink) {\n this.id = extractVideoIdFromUrl(this.videoLink);\n } else {\n console.warn('Video missing video-id / data-video-link');\n return;\n }\n\n if (this.id.indexOf('/') > -1) {\n this.id = this.id.slice(0, this.id.indexOf('/'));\n this.isPrivate = true;\n }\n }\n\n this.isVimeo = container.getAttribute('data-action') === 'video-vimeo' || this.videoLink && this.videoLink.indexOf('vimeo') > -1;\n this.poster = container.getAttribute('data-poster') || container.getAttribute('data-src');\n\n if (!this.poster) {\n if (this.isVimeo) {\n if (this.isPrivate) {\n this.container.classList.add('placeholder');\n } else {\n let { width, height } = getRoundedDimensions(container.getBoundingClientRect());\n const devicePixelRatio = window.devicePixelRatio || 1;\n width *= devicePixelRatio;\n height *= devicePixelRatio;\n /**\n * To get the vimeo poster image, we have to use the Vimeo API.\n */\n this.poster = `https://lite-vimeo-embed.now.sh/thumb/${this.id}`;\n this.poster += `.${canUseWebP() ? 'webp' : 'jpg'}`;\n this.poster += `?mw=${width}&mh=${height}&q=${devicePixelRatio > 1 ? 70 : 85}`;\n }\n\n } else {\n /**\n * Comment about the thumbnail, by original author: Paul Irish\n * Lo, the youtube placeholder image! (aka the thumbnail, poster image, etc)\n * There is much internet debate on the reliability of thumbnail URLs. Weak consensus is that you\n * cannot rely on anything and have to use the YouTube Data API.\n *\n * amp-youtube also eschews using the API, so they just try sddefault with a hqdefault fallback:\n * https://github.com/ampproject/amphtml/blob/6039a6317325a8589586e72e4f98c047dbcbf7ba/extensions/amp-youtube/0.1/amp-youtube.js#L498-L537\n * For now I'm gonna go with this confident (lol) assertion: https://stackoverflow.com/a/20542029, though I'll use `i.ytimg` to optimize for origin reuse.\n *\n * Worth noting that sddefault is _higher_ resolution than hqdefault. Naming is hard. ;)\n * From my own testing, it appears that hqdefault is ALWAYS there sddefault is missing for ~10% of videos*/\n\n this.poster = `https://i.ytimg.com/vi/${this.id}/sddefault.jpg`;\n }\n }\n\n if (this.poster && !this.container.classList.contains('lazy')) {\n this.container.style.backgroundImage = `url(\"${this.poster}\")`;\n }\n\n // On hover (or tap), warm up the TCP connections we're (likely) about to use.\n this.container.addEventListener('pointerover', Video.warmConnections, { once: true });\n\n // Once the user clicks, add the real iframe and drop our play button\n // TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time\n // We'd want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003\n this.container.addEventListener('click', () => this.addIframe());\n }\n\n /**\n * Begin pre-connecting to warm up the iframe load\n * Since the embed's network requests load within its iframe,\n * preload/prefetch'ing them outside the iframe will only cause double-downloads.\n * So, the best we can do is warm up a few connections to origins that are in the critical path.\n *\n * Maybe `` would work, but it's unsupported: http://crbug.com/593267\n * But TBH, I don't think it'll happen soon with Site Isolation and split caches adding serious complexity.\n */\n static warmConnections() {\n if (Video.preconnected) return;\n\n if (this.isVimeo) {\n // The iframe document and most of its subresources come right off player.vimeo.com\n addPrefetch('preconnect', 'https://player.vimeo.com');\n // Images\n addPrefetch('preconnect', 'https://i.vimeocdn.com');\n // Files .js, .css\n addPrefetch('preconnect', 'https://f.vimeocdn.com');\n // Metrics\n addPrefetch('preconnect', 'https://fresnel.vimeocdn.com');\n } else {\n // The iframe document and most of its subresources come right off youtube.com\n addPrefetch('preconnect', this.ytUrl);\n // The botguard script is fetched off from google.com\n addPrefetch('preconnect', 'https://www.google.com');\n // Not certain if these ad related domains are in the critical path. Could verify with domain-specific throttling.\n addPrefetch('preconnect', 'https://googleads.g.doubleclick.net');\n addPrefetch('preconnect', 'https://static.doubleclick.net');\n }\n\n Video.preconnected = true;\n }\n\n addIframe() {\n const videoService = this.isVimeo ? 'https://player.vimeo.com/video' : `${this.ytUrl}/embed`;\n let videoUrl = `${videoService}/${this.id}?autoplay=1&rel=0`;\n const iframe = document.createElement('iframe');\n iframe.setAttribute('frameborder', 0);\n iframe.setAttribute('allowtransparency', 'true');\n iframe.setAttribute('playsinline', 'true');\n iframe.setAttribute('tabindex', '-1');\n iframe.setAttribute('allow', 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture; autoplay');\n iframe.addEventListener('load', () => {\n // Timeout is set to prevent paint-lag when iframe is inserted\n setTimeout(() => {\n this.container.classList.add('video--loaded');\n this.container.classList.remove('loading');\n\n if (this.container.getAttribute('data-scroll-to')) {\n scrollTo(this.container, 1000);\n }\n }, 300);\n });\n\n videoUrl += `&controls=${this.controls}&byline=${this.byline}&background=${this.bg}&mute=${this.bg}`;\n if (this.color) videoUrl += `&color=${this.color}`;\n\n iframe.src = videoUrl;\n\n this.container.classList.add('loading');\n this.container.appendChild(iframe);\n }\n}\n\n\nfunction extractVideoIdFromUrl(url) {\n const videoIdRegExp = /^.*((youtu.be\\/|vimeo.com\\/)|(v\\/)|(\\/u\\/\\w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#&?]*).*/;\n const match = url.match(videoIdRegExp);\n\n if (match && match[7]) {\n return match[7];\n } else {\n console.warn(url, 'Invalid Video URL');\n }\n}\n\n/**\n * Initialise video embeds with this function\n * Will only run if given selector elements are found in DOM\n *\n * @param {string} selector - element selector string\n */\n\nexport function setupVideos(selector = '[data-action^=\"video\"]') {\n const videos = document.body.querySelectorAll(selector);\n\n for (let i = 0; i < videos.length; i++) {\n void new Video(videos[i]);\n }\n}\n","import { onWindowResize, currentBreakpoint, currentBreakpointIndex } from './utils/windowResize';\r\nimport { onScroll, scrollTop } from './utils/scroll';\r\nimport { onReady } from './utils/onReady';\r\nimport { setupNav } from './components/nav';\r\nimport { setupLazyLoading } from './utils/lazyImage';\r\nimport { initVhUnitOverwrite, isTouchDevice, isIE11 } from './utils/helpers';\r\nimport { setupEventtickers } from './components/eventticker';\r\n//import { setupAccordions } from './components/accordion';\r\nimport { setupVideos } from './components/video';\r\n//import { setupGalleries } from './components/gallery';\r\n//import { version } from '../../package.json';\r\n//import { setupAnchorLinkScroll } from './components/anchors';\r\n//import { setupFilters } from './components/filter';\r\n//import { setupOverlay } from './components/overlay';\r\n//import { setupTabs } from './components/tabs';\r\n//import { setupYTVideos } from './components/video-yt';\r\n//import { setupSliders } from './components/slider';\r\n//import { watchFormFields } from './components/form';\r\n\r\n// Below are example of how to use import libraries installed via npm.\r\n// import sal from 'sal.js';\r\n\r\nfunction init() {\r\n document.body.classList.remove('standby');\r\n\r\n if (isTouchDevice()) {\r\n document.body.classList.add('js-is-touch');\r\n }\r\n\r\n if (isIE11) {\r\n document.body.classList.add('js-ie-11');\r\n }\r\n\r\n //setupAnchorLinkScroll();\r\n\r\n setupNav('.nav');\r\n\r\n onReady(() => {\r\n initVhUnitOverwrite();\r\n\r\n setupLazyLoading();\r\n\r\n setupEventtickers();\r\n\r\n //setupAccordions();\r\n\r\n //setupFilters();\r\n\r\n //setupOverlay();\r\n\r\n setupVideos();\r\n\r\n //setupGalleries();\r\n\r\n //setupYTVideos();\r\n\r\n //setupTabs();\r\n\r\n //setupSliders();\r\n\r\n //watchFormFields();\r\n });\r\n\r\n // Simulated CookieBot function-call via GTM\r\n //window.showCookieBanner();\r\n\r\n // onWindowResize event demo\r\n // I recommend you remove this before going live ;)\r\n onWindowResize(() => {\r\n //window.console.log('Resize Event (throuttled)', {currentBreakpoint, currentBreakpointIndex});\r\n });\r\n\r\n // onScroll event demo\r\n // Remove when you get tired of the console spam\r\n let prevScroll = 0;\r\n const header = document.querySelector('.header');\r\n\r\n if (header) {\r\n onScroll(() => {\r\n if (scrollTop > prevScroll && scrollTop > header.offsetHeight) {\r\n document.body.classList.add('js-scrolled');\r\n } else {\r\n document.body.classList.remove('js-scrolled');\r\n }\r\n\r\n prevScroll = scrollTop;\r\n });\r\n }\r\n\r\n //console.info(`fong kører - nedkogt til version ${version}`);\r\n\r\n window.addEventListener('load', () => {\r\n // Polyfill for using svg spritesheet in oldIE\r\n svg4everybody();\r\n });\r\n}\r\n\r\ninit();\r\n","export function setupEventtickers() {\r\n const newsTickers = document.querySelectorAll('.event-ticker');\r\n\r\n Array.from(newsTickers).forEach(newsTicker => {\r\n const items = Array.from(newsTicker.querySelectorAll('li'));\r\n let hover = false;\r\n\r\n function itemAnimationEnd(e) {\r\n const item = e.currentTarget;\r\n\r\n item.classList.remove('js-active');\r\n item.classList.remove('js-hide');\r\n item.removeEventListener('transitionend', itemAnimationEnd);\r\n }\r\n\r\n setInterval(function () {\r\n const _items = arguments[0];\r\n const _hover = arguments[1];\r\n const activeItem = _items.filter(x => x.classList.contains('js-active'))[0];\r\n const activeIndex = _items.findIndex(x => x == activeItem);\r\n let newActiveIndex = -1;\r\n\r\n if (!hover) {\r\n if (activeIndex + 1 < items.length) {\r\n newActiveIndex = activeIndex + 1;\r\n } else {\r\n newActiveIndex = 0;\r\n }\r\n\r\n activeItem.classList.add('js-hide');\r\n activeItem.addEventListener('transitionend',itemAnimationEnd);\r\n\r\n items[newActiveIndex].classList.add('js-active');\r\n }\r\n }.bind(this,items,hover), 5000);\r\n\r\n function enterNewsTicker() {\r\n hover = true;\r\n }\r\n\r\n function leaveNewsTicker() {\r\n hover = false;\r\n }\r\n\r\n newsTicker.addEventListener('mouseenter', enterNewsTicker);\r\n newsTicker.addEventListener('mouseleave', leaveNewsTicker);\r\n });\r\n}"],"names":["currentBreakpoint","resizeTimer","breakpoints","breakpointKeys","Object","keys","currentWindowWidth","window","innerWidth","currentBreakpointIndex","resizeFunctions","getWindowSizes","lastFoundWidth","forEach","key","index","width","resizeHandler","clearTimeout","setTimeout","funcRef","onWindowResize","handler","addEventListener","push","scrollTop","document","documentElement","body","ticking","scrollFunctions","animate","scrollHandler","requestAnimationFrame","onScroll","triggerNow","length","functionReferences","readyState","readyEventBound","emptyCallbackArrays","tempArray","slice","onReady","functionReference","getElementScroll","element","Element","Document","Window","left","pageXOffset","scrollLeft","top","pageYOffset","scrollX","scrollY","console","warn","nav","className","scrollLocked","toggleMenuOpen","scrollPosition","htmlTag","classList","contains","remove","style","marginTop","position","overflow","removeAttribute","scrollTo","add","overflowY","clickCreateUser","e","target","currentTarget","closest","setupNav","selector","sticky","querySelector","scrollTimer","lastScrollPosition","scrollInPixels","goingUpClass","windowScroll","stickyNavOnScroll","navCreateUser","lastUsedScreenWidth","isBot","navigator","test","userAgent","lazyArray","options","loadedClass","loadClass","decodeImg","oldIe11Fit","offset","lazyLoad","i","lazyElem","el","rect","getBoundingClientRect","bottom","right","innerHeight","clientHeight","clientWidth","isInViewport","bgContainer","handleLoadedBg","backgroundImage","formattedSrc","src","getImageSrc","loadImage","then","container","oldImage","getAttribute","objectFitPolyfill","removeChild","newImageTag","altText","tagName","setAttribute","appendChild","Array","prototype","filter","call","l","path","newImage","Image","Promise","resolve","decode","image","largestBreakpointFound","breakpointName","srcAttribute","allowStatCookies","CookieInformation","getConsentGivenFor","initVhUnitOverwrite","vh","setProperty","addPrefetch","kind","url","as","linkElem","createElement","rel","href","crossorigin","head","append","isIE11","MSInputMethodContext","documentMode","to","duration","callback","start","parentNode","change","relativeTo","useElement","getElementById","offsetTop","offsetLeft","getElementPosition","currentTime","val","ts","time","tc","easeInOutQuintic","amount","scrollingElement","Video","height","id","bg","byline","color","controls","ytUrl","this","videoLink","match","extractVideoIdFromUrl","indexOf","isPrivate","isVimeo","poster","roundedHeight","roundedWidth","Math","ceil","round","devicePixelRatio","elem","getContext","toDataURL","warmConnections","once","_this","addIframe","preconnected","videoService","videoUrl","iframe","_this2","maxTouchPoints","customOptions","getElementsByClassName","setupLazyLoading","newsTickers","querySelectorAll","from","newsTicker","items","hover","itemAnimationEnd","item","removeEventListener","setInterval","_items","arguments","activeItem","x","activeIndex","findIndex","newActiveIndex","bind","setupEventtickers","videos","setupVideos","prevScroll","header","offsetHeight","svg4everybody","init"],"mappings":"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"}