/** * JS helpers for image handling */ /* eslint-disable no-unused-vars */ document.addEventListener('DOMContentLoaded', event => { // Add class to loaded images to apply opacity animation var lazyImages = document.querySelectorAll('.image-attachment .image'); lazyImages.forEach((lazyImage) => { if (lazyImage.complete) { imageLoaded(lazyImage); } else { lazyImage.addEventListener('load', imageLoaded.bind(null, lazyImage)); } function imageLoaded(lazyImage) { if( '' === lazyImage || !lazyImage ) return; lazyImage.classList.add('lazy-image-loaded'); lazyImage.parentElement.classList.add('no-background-color'); } }); }, false); /* eslint-enable no-unused-vars */ ; !function () { //=NS FP.Utils = FP.Utils || {}; FP.Utils.trapFocus = { /** * @summary Trap keyboard focus in DOM elements * * @description Traps focus in expanded nav, modals, etc. * * @param {array} containerElements Array of DOM elements from document.querySelectorAll() * @param {obj} DOM element from document.querySelector() to return focus to after closing trap element * * @return {void} */ init: function(containerElements, returnFocusToElement = false) { // do not continue if there are no container DOM elements passed if (containerElements.length < 1) return; // key codes for keyboard nav const KEYCODE_TAB = 9; const KEYCODE_ESC = 27; // iterate throgh container DOM elements containerElements.forEach((containerElement) => { // get all focusable elements var focusableEls = this.getfocusableEls(containerElement); // get first focusable element var firstFocusableEl = focusableEls[0]; // get last focusable element var lastFocusableEl = focusableEls[focusableEls.length - 1]; // add listener to container DOM elements containerElement.addEventListener('keydown', function(e) { // determine whether user pressed the escape key var isEscapePressed = (e.key === 'Esc' || e.keyCode === KEYCODE_ESC); // determine whether user pressed the tab key var isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB); // only evaluate escape and tab keydown if (!isEscapePressed && !isTabPressed) return; // escape key pressed if ( isEscapePressed ) { // assuming the close button is the first item // // TO-DO - make this more dynamic to accommodate other elements by class, id, etc.? // firstFocusableEl.click(); if( returnFocusToElement ) { returnFocusToElement.focus(); } // shift + tab keys pressed } else if ( e.shiftKey ) { // if user is on the first focusable element... if (document.activeElement === firstFocusableEl) { // ...move focus to last focusable element lastFocusableEl.focus(); e.preventDefault(); } // tab key pressed } else { // if user is on the last focusable element... if (document.activeElement === lastFocusableEl) { firstFocusableEl.focus(); // ...move focus to first focusable element e.preventDefault(); } } }); }); }, /** * @summary Get array of focusable elements in container * * @description Get all focusable elements using the query selector options defined in the function * * @param {array} containerElement DOM element that (may) contains focusable elements * * @return {array} focusable DOM elements */ getfocusableEls: function(containerElement) { return containerElement.querySelectorAll('iframe:not([disabled]), a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="search"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])'); }, /** * @summary Toggle inert attribute on elements that should be hidden when a modal is displayed * * @description Get all elements with data-inert-when-modal="true" and toggle "inert" and "aria-hidden" attributes * * @param {bool} enable Whether to enable or disable the "inert" and "aria-hidden" attributes * * @return {void} */ toggleInertAttribute: function(enable = true) { document.querySelectorAll('[data-inert-when-modal="true"]').forEach(element => { if(enable) { element.setAttribute('inert', ''); element.setAttribute('aria-hidden', 'true'); } else { element.removeAttribute('inert'); element.removeAttribute('aria-hidden'); } }); }, }; }(); ; (()=>{"use strict";var __webpack_modules__={"../assets/src/scripts/components/navigation/navigation.js"(__unused_webpack_module,__webpack_exports__,__webpack_require__){eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ \"./node_modules/@babel/runtime/helpers/esm/classCallCheck.js\");\n/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ \"./node_modules/@babel/runtime/helpers/esm/createClass.js\");\n\n\nvar FPNav = /*#__PURE__*/function () {\n function FPNav() {\n (0,_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(this, FPNav);\n // define constants\n // key codes for keyboard nav\n this.KEYCODE_TAB = 9;\n this.KEYCODE_ESC = 27;\n\n // get DOM elements needed throughout the code\n this.siteHeader = document.querySelector('.site-header');\n this.headerElement = document.querySelector('header');\n\n // define config for header components and CSS classes for display toggling\n this.nav = document.querySelector('#navigation');\n this.headerNavWrapper = document.querySelector('.header-nav-wrapper');\n this.headerNavDrawerOpen = 'drawer--open';\n this.headerNavParentScrolled = 'nav-menu-scrolled-true--parent';\n this.headerNavParentNotScrolled = 'nav-menu-scrolled-false--parent';\n this.headerNavScrolled = 'nav-menu-scrolled-true';\n this.headerNavNotScrolled = 'nav-menu-scrolled-false';\n\n // define config for user menu elements\n this.userIcon = document.querySelector('.js-site-nav-user-icon-navbar');\n this.userMenu = document.querySelector('.site-nav-usermenu-nav-navbar');\n this.userIconFullMenu = document.querySelector('.js-site-nav-user-icon-full-menu');\n this.userMenuFullMenu = document.querySelector('.site-nav-usermenu-nav-full-menu');\n\n // define config for search menu elements\n this.searchDrawerCloseButton = document.querySelector('#searchform-site-nav-drawer-close-btn');\n this.searchDrawerInputField = document.querySelector('#searchform-site-nav-drawer .searchfield-site-nav');\n\n // define config for mobile drawer buttons\n this.mobileDrawerButtons = document.querySelectorAll('.js-drawer-mobile-button');\n this.mobileDrawerClosed = 'drawer-mobile-button--closed';\n this.mobileDrawerOpen = 'drawer-mobile-button--open';\n\n // define config for full nav menu\n this.hamburgerButtons = document.querySelectorAll('.nav-modal-open');\n this.closeButtons = document.querySelectorAll('.nav-full-menu__close');\n this.desktopMenu = document.querySelector('.nav-full-menu');\n this.desktopMenuClosed = 'nav-full-menu--closed';\n this.desktopMenuOpen = 'nav-full-menu--open';\n\n // track height of open drawers in desktop nav\n // use as padding below\n this.openDrawerHeight = 0;\n\n // define config for drawers and supporting interactive elements \n // and CSS classes for display toggling\n this.drawers = {\n regions: {\n button: document.querySelector('.js-drawer-regions-button'),\n buttonClosed: 'drawer-regions-button--closed',\n buttonOpen: 'drawer-regions-button--open',\n drawer: document.querySelector('.nav-drawer__regions'),\n drawerClosed: 'drawer-regions--closed',\n drawerOpen: 'drawer-regions--open'\n },\n newsletters: {\n button: document.querySelector('.js-drawer-newsletters-button'),\n buttonClosed: 'drawer-newsletters-button--closed',\n buttonOpen: 'drawer-newsletters-button--open',\n drawer: document.querySelector('.nav-drawer__newsletters'),\n drawerClosed: 'drawer-newsletters--closed',\n drawerOpen: 'drawer-newsletters--open'\n },\n search: {\n button: document.querySelector('.js-drawer-search-button'),\n buttonClosed: 'drawer-search-button--closed',\n buttonOpen: 'drawer-search-button--open',\n drawer: document.querySelector('.nav-drawer__search'),\n drawerClosed: 'drawer-search--closed',\n drawerOpen: 'drawer-search--open'\n }\n };\n }\n return (0,_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(FPNav, [{\n key: \"init\",\n value: function init() {\n var self = this;\n\n // Sticky main nav, content toggle on scroll\n self.navAppearanceOnScroll();\n document.addEventListener('DOMContentLoaded', function () {\n // user menus\n self.userMenuInteractivity(self.userIcon, self.userMenu);\n self.userMenuInteractivity(self.userIconFullMenu, self.userMenuFullMenu);\n self.keyboardCloseExpandedDrawerContent(document.querySelectorAll('.site-nav-usermenu-nav'));\n\n // drawers\n self.drawerInteractivity();\n self.keyboardCloseExpandedDrawerContent(document.querySelectorAll('.nav-drawer-wrapper'));\n self.mobileDrawerInteractivity();\n\n // full menu\n self.fullMenuInteractivity();\n\n // focus trap\n self.trapFocusInteractivity();\n });\n\n // Piano iframes\n self.observePianoIframes();\n }\n\n /**\n * @summary Add scroll listener for navigation appearance based on scroll depth\n * \n * @return {void}\n */\n }, {\n key: \"navAppearanceOnScroll\",\n value: function navAppearanceOnScroll() {\n var self = this;\n\n // scroll listener to toggle classes between: \n // - main nav static\n // - main nav scrolled\n window.addEventListener('scroll', function () {\n var mainElement = document.querySelector('main');\n\n // main nav static\n // user has not scrolled to a depth less than the siteHeader height\n // or has scolled back to the top of the page\n if (window.scrollY > self.siteHeader.offsetHeight) {\n self.toggleElementClasses(self.siteHeader,\n // target DOM element\n self.headerNavParentScrolled,\n // class to add\n self.headerNavParentNotScrolled // class to remove\n );\n self.toggleElementClasses(self.headerNavWrapper, self.headerNavScrolled, self.headerNavNotScrolled);\n self.toggleElementClasses(self.nav, self.headerNavScrolled, self.headerNavNotScrolled);\n if (self.openDrawerHeight > 0) {\n // add 80 below to account for .header-nav-wrapper height and bottom margin\n mainElement.style.paddingTop = self.openDrawerHeight + 80 + 'px';\n }\n // main nav scrolled\n // user has scrolled to a depth equal to or greater than the siteHeader height\n } else {\n self.toggleElementClasses(self.siteHeader,\n // target DOM element\n self.headerNavParentNotScrolled,\n // class to add\n self.headerNavParentScrolled // class to remove\n );\n self.toggleElementClasses(self.headerNavWrapper, self.headerNavNotScrolled, self.headerNavScrolled);\n self.toggleElementClasses(self.nav, self.headerNavNotScrolled, self.headerNavScrolled);\n mainElement.style.paddingTop = '';\n }\n });\n }\n\n /**\n * @summary Add listeners for drawer interactivity\n * \n * @return {void}\n */\n }, {\n key: \"drawerInteractivity\",\n value: function drawerInteractivity() {\n var self = this;\n\n // Handling for drawer display toggle buttons\n var _loop = function _loop(drawerName) {\n if (!self.drawers[drawerName].button) return 1; // continue\n\n // Handles click and enter keydown\n self.drawers[drawerName].button.addEventListener('click', function (event) {\n event.preventDefault();\n self.toggleDrawer(drawerName, event);\n });\n };\n for (var drawerName in self.drawers) {\n if (_loop(drawerName)) continue;\n }\n\n // Handling for search close button\n if (self.searchDrawerCloseButton) {\n self.searchDrawerCloseButton.addEventListener('click', function () {\n var searchDrawerConfig = self.drawers.search;\n if (searchDrawerConfig.drawer.classList.contains(searchDrawerConfig.drawerOpen)) {\n self.toggleElementClasses(searchDrawerConfig.drawer,\n // target DOM element\n searchDrawerConfig.drawerClosed,\n // class to add\n searchDrawerConfig.drawerOpen // class to remove\n );\n self.toggleElementClasses(searchDrawerConfig.button, searchDrawerConfig.buttonClosed, searchDrawerConfig.buttonOpen);\n if (!self.drawers.regions.drawer.classList.contains(self.drawers.regions.drawerOpen) && !self.drawers.newsletters.drawer.classList.contains(self.drawers.newsletters.drawerOpen)) {\n self.headerNavWrapper.classList.remove(self.headerNavDrawerOpen);\n document.querySelector('.site-nav-search #search').setAttribute('aria-expanded', 'false');\n document.querySelector('.site-nav-search #search').focus();\n\n // Remove padding from
\n self.headerElement.style.paddingBottom = '';\n }\n }\n });\n }\n }\n\n /**\n * @summary Drawer display toggling functionality\n * \n * @description Traps focus in expanded nav, modals, etc.\n * \n * @param {string} currentDrawer Name of current drawer\n * @param {object} event DOM event\n *\n * @return {void}\n */\n }, {\n key: \"toggleDrawer\",\n value: function toggleDrawer(currentDrawer, event) {\n var _activeDrawer$drawer$;\n var self = this;\n\n // Check if other drawers are open and close them if they are\n for (var drawerName in self.drawers) {\n if (drawerName !== currentDrawer) {\n var drawerObj = self.drawers[drawerName];\n if (drawerObj.drawer && drawerObj.drawer.classList && drawerObj.drawer.classList.contains(drawerObj.drawerOpen)) {\n self.toggleElementClasses(drawerObj.drawer,\n // target DOM element\n drawerObj.drawerClosed,\n // class to add\n drawerObj.drawerOpen // class to remove\n );\n self.toggleElementClasses(drawerObj.button, drawerObj.buttonClosed, drawerObj.buttonOpen);\n }\n }\n }\n var activeDrawer = self.drawers[currentDrawer];\n if (activeDrawer.drawer.classList.contains(activeDrawer.drawerOpen)) {\n self.toggleElementClasses(activeDrawer.button,\n // target DOM element\n activeDrawer.buttonClosed,\n // class to add\n activeDrawer.buttonOpen // class to remove\n );\n self.toggleElementClasses(activeDrawer.drawer, activeDrawer.drawerClosed, activeDrawer.drawerOpen);\n self.headerNavWrapper.classList.remove(self.headerNavDrawerOpen);\n } else {\n self.toggleElementClasses(activeDrawer.button, activeDrawer.buttonOpen, activeDrawer.buttonClosed);\n self.toggleElementClasses(activeDrawer.drawer, activeDrawer.drawerOpen, activeDrawer.drawerClosed);\n self.headerNavWrapper.classList.add(self.headerNavDrawerOpen);\n }\n var isExpanded = false;\n if (activeDrawer.drawer.classList.contains(activeDrawer.drawerOpen)) isExpanded = true;\n if (isExpanded) {\n // set aria-expanded attribute to true for parent tag\n activeDrawer.button.setAttribute('aria-expanded', 'true');\n } else {\n // set aria-expanded attribute to false for parent tag\n activeDrawer.button.setAttribute('aria-expanded', 'false');\n }\n\n // set padding to
to push content down when drawer is open\n self.openDrawerHeight = (_activeDrawer$drawer$ = activeDrawer.drawer.offsetHeight) !== null && _activeDrawer$drawer$ !== void 0 ? _activeDrawer$drawer$ : 0;\n self.headerElement.style.paddingBottom = self.openDrawerHeight + 'px';\n\n // set focus and CSS classes for drawers\n switch (currentDrawer) {\n case 'search':\n activeDrawer.drawer.setAttribute('aria-hidden', 'false');\n self.searchDrawerInputField.focus();\n // only apply focus outline style if user navigated via keyboard\n if ('Enter' !== event.key) {\n self.searchDrawerInputField.classList.add('no-focus-outline');\n } else {\n self.searchDrawerInputField.classList.remove('no-focus-outline');\n }\n break;\n default:\n if (isExpanded) {\n // set aria-hidden attribute to false\n activeDrawer.drawer.setAttribute('aria-hidden', 'false');\n } else {\n // set aria-hidden attribute to false\n activeDrawer.drawer.setAttribute('aria-hidden', 'true');\n }\n break;\n }\n }\n\n /**\n * @summary Mobile drawer display toggling functionality\n * \n * @return {void}\n */\n }, {\n key: \"mobileDrawerInteractivity\",\n value: function mobileDrawerInteractivity() {\n var self = this;\n\n // Handling for mobileDrawerButton\n self.mobileDrawerButtons.forEach(function (mobileDrawerButton) {\n mobileDrawerButton.addEventListener('click', function (e) {\n if (window.innerWidth > 979) return;\n e.preventDefault();\n mobileDrawerButton.classList.toggle(self.mobileDrawerOpen);\n mobileDrawerButton.classList.toggle(self.mobileDrawerClosed);\n if (!mobileDrawerButton.classList.contains(self.mobileDrawerOpen)) {\n self.headerNavWrapper.classList.remove(self.headerNavDrawerOpen);\n }\n });\n });\n }\n\n /**\n * @summary Full menu display toggling functionality\n * \n * @return {void}\n */\n }, {\n key: \"fullMenuInteractivity\",\n value: function fullMenuInteractivity() {\n var self = this;\n self.hamburgerButtons.forEach(function (hamburgerButton) {\n hamburgerButton.addEventListener('click', function () {\n hamburgerButton.setAttribute('aria-expanded', 'true');\n self.toggleElementClasses(self.desktopMenu, self.desktopMenuOpen, self.desktopMenuClosed);\n self.desktopMenu.setAttribute('aria-expanded', 'true');\n self.desktopMenu.setAttribute('aria-hidden', 'false');\n setTimeout(function () {\n self.closeButtons[0].focus();\n }, 100);\n document.querySelector('.nav-full-menu').scrollTop = 0;\n document.body.classList.add('overlay-no-scroll');\n });\n });\n self.closeButtons.forEach(function (closeButton) {\n closeButton.addEventListener('click', function () {\n self.toggleElementClasses(self.desktopMenu, self.desktopMenuClosed, self.desktopMenuOpen);\n self.desktopMenu.setAttribute('aria-expanded', 'false');\n self.desktopMenu.setAttribute('aria-hidden', 'true');\n self.hamburgerButtons.forEach(function (hamburgerButton) {\n hamburgerButton.setAttribute('aria-expanded', 'false');\n });\n self.hamburgerButtons[0].focus();\n document.body.classList.remove('overlay-no-scroll');\n });\n });\n }\n\n /**\n * @summary Add listeners for user menu interactivity\n *\n * @param {object} userIcon user icon DOM element object\n * @param {object} userMenu user menuu DOM element object\n * \n * @return {void}\n */\n }, {\n key: \"userMenuInteractivity\",\n value: function userMenuInteractivity(userIcon, userMenu) {\n if (!userIcon) return;\n userIcon.addEventListener('click', function (event) {\n event.preventDefault();\n if (userMenu.style.display !== 'block') {\n userIcon.setAttribute('aria-expanded', 'true');\n userMenu.style.display = 'block';\n } else {\n userIcon.setAttribute('aria-expanded', 'false');\n userMenu.style.display = 'none';\n }\n });\n userIcon.addEventListener('mouseenter', function () {\n userIcon.setAttribute('aria-expanded', 'true');\n userMenu.style.display = 'block';\n });\n userMenu.addEventListener('mouseleave', function () {\n userIcon.setAttribute('aria-expanded', 'false');\n userMenu.style.display = 'none';\n });\n }\n\n /**\n * @summary Trap focus functionality in expanded menu items and expanded nav\n * \n * @return {void}\n */\n }, {\n key: \"trapFocusInteractivity\",\n value: function trapFocusInteractivity() {\n FP.Utils.trapFocus.init(document.querySelectorAll('#expanded-navigation'));\n }\n\n /**\n * @summary Helper to close all drawers on desktop\n * \n * @return {void}\n */\n }, {\n key: \"closeAllDrawers\",\n value: function closeAllDrawers() {\n var self = this;\n for (var drawerName in self.drawers) {\n var drawerObj = self.drawers[drawerName];\n self.toggleElementClasses(drawerObj.drawer, drawerObj.drawerClosed, drawerObj.drawerOpen);\n self.toggleElementClasses(drawerObj.button, drawerObj.buttonClosed, drawerObj.buttonOpen);\n drawerObj.button.setAttribute('aria-expanded', 'false');\n }\n\n // update header elements\n self.headerNavWrapper.classList.remove(self.headerNavDrawerOpen);\n self.headerElement.style.paddingBottom = '';\n\n // reset open drawer height to 0\n self.openDrawerHeight = 0;\n\n // update main element\n var mainElement = document.querySelector('main');\n mainElement.style.paddingTop = '';\n\n // close user menus\n self.userMenu.style.display = 'none';\n self.userMenuFullMenu.style.display = 'none';\n self.userIcon.setAttribute('aria-expanded', 'false');\n self.userIconFullMenu.setAttribute('aria-expanded', 'false');\n }\n\n /**\n * @summary Helper to focus on parent element after closing drawers\n *\n * @param {object} containerElement DOM element object\n * \n * @return {void}\n */\n }, {\n key: \"focusOnParent\",\n value: function focusOnParent(containerElement) {\n // TO-DO - make this more flexible, not only searching for an tag\n var focusEl = containerElement.parentNode.querySelector('a');\n if (focusEl) {\n focusEl.setAttribute('aria-expanded', 'false');\n focusEl.focus();\n }\n }\n\n /**\n * @summary Helper to handle full nav closure with keyboard input\n *\n * @description Allow expanded nav to be closed when:\n * - the user presses the Escape key\n * - the user shift + tabs back past the first item in the drawer\n * - the user tabs past the last item in the drawer\n *\n * @param {array} containerElements Array of DOM elements from document.querySelectorAll()\n * \n * @return {void}\n */\n }, {\n key: \"keyboardCloseExpandedDrawerContent\",\n value: function keyboardCloseExpandedDrawerContent(containerElements) {\n var self = this;\n containerElements.forEach(function (containerElement) {\n var focusableEls = FP.Utils.trapFocus.getfocusableEls(containerElement);\n var firstFocusableEl = focusableEls[0];\n var lastFocusableEl = focusableEls[focusableEls.length - 1];\n containerElement.addEventListener('keydown', function (e) {\n var isEscapePressed = e.key === 'Esc' || e.keyCode === self.KEYCODE_ESC;\n var isTabPressed = e.key === 'Tab' || e.keyCode === self.KEYCODE_TAB;\n if (!isEscapePressed && !isTabPressed) {\n return;\n }\n var processAction = false;\n var changeFocus = false;\n\n // esc pressed\n if (isEscapePressed) {\n processAction = true;\n changeFocus = true;\n // shift + tab pressed\n } else if (e.shiftKey) {\n // if user is on the first focusable element in the drawer\n if (document.activeElement === firstFocusableEl) {\n processAction = true;\n }\n // tab pressed\n } else {\n // if user is on the last focusable element in the drawer\n if (document.activeElement === lastFocusableEl) {\n processAction = true;\n changeFocus = true;\n }\n }\n\n // run additional code to close drawers or focus on parent element\n if (processAction) {\n // close all drawers\n self.closeAllDrawers();\n }\n if (changeFocus) {\n // focus on parent element\n self.focusOnParent(containerElement);\n }\n });\n });\n }\n\n /**\n * @summary Helper to remove and add a class\n *\n * @param {object} element DOM element\n * @param {string} addClass Class name to add to element\n * @param {string} removeClass Class name to remove from element\n * \n * @return {void}\n */\n }, {\n key: \"toggleElementClasses\",\n value: function toggleElementClasses(element, addClass, removeClass) {\n var _element$classList, _element$classList2;\n element === null || element === void 0 || (_element$classList = element.classList) === null || _element$classList === void 0 || _element$classList.remove(removeClass);\n element === null || element === void 0 || (_element$classList2 = element.classList) === null || _element$classList2 === void 0 || _element$classList2.add(addClass);\n }\n\n /**\n * @summary Helper to adjust focus with Piano iframes\n *\n * @description This is needed as a workaround for the iframe focus issue\n * \n * @return {void}\n */\n }, {\n key: \"observePianoIframes\",\n value: function observePianoIframes() {\n // Options for the observer (which mutations to observe)\n var config = {\n attributes: false,\n childList: true,\n subtree: true\n };\n\n // Callback function to execute when mutations are observed\n // eslint-disable-next-line no-unused-vars\n var observer = new MutationObserver(function (mutations) {\n mutations.forEach(function (mutation) {\n // Looping through all added nodes\n mutation.addedNodes.forEach(function (node) {\n if (node instanceof Element && node.matches('iframe')) {\n // If the added node matches the selector, execute the callback and disconnect the observer\n if (document.querySelector('.tp-close')) {\n document.querySelector('.tp-close').addEventListener('click', function () {\n setTimeout(function () {\n var loginElement = document.querySelector('.FP-paywall--login');\n if (loginElement) {\n loginElement.focus();\n }\n }, 750);\n });\n }\n //observer.disconnect();\n }\n });\n });\n });\n\n // Start observing the target node for configured mutations\n observer.observe(document, config);\n }\n }]);\n}();\nwindow.FPNav = new FPNav();\nwindow.FPNav.init();//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vYXNzZXRzL3NyYy9zY3JpcHRzL2NvbXBvbmVudHMvbmF2aWdhdGlvbi9uYXZpZ2F0aW9uLmpzIiwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBSUE7O0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUlBO0FBSUE7O0FBSUE7QUFDQTtBQUNBO0FBR0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUFBO0FBQUE7QUFNQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQU1BO0FBQ0E7QUFDQTtBQUNBOztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUFBO0FBQUE7QUFNQTs7QUFFQTtBQUFBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBVEE7QUFBQTtBQUNBOztBQVVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBSUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBVEE7QUFBQTtBQUFBO0FBVUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFLQTtBQU1BO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQUE7QUFBQTtBQU1BOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUFBO0FBQUE7QUFNQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBTUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBTUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVBBO0FBQUE7QUFBQTtBQVNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQUE7QUFBQTtBQU1BO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQUE7QUFBQTtBQU1BO0FBRUE7QUFDQTtBQUVBO0FBS0E7QUFNQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFOQTtBQUFBO0FBQUE7QUFRQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFYQTtBQUFBO0FBQUE7QUFhQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVJBO0FBQUE7QUFBQTtBQVNBO0FBQ0E7QUFDQTtBQUNBOztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTkE7QUFBQTtBQUFBO0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUlBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9mb3JlaWducG9saWN5LWJ1aWxkLy4uL2Fzc2V0cy9zcmMvc2NyaXB0cy9jb21wb25lbnRzL25hdmlnYXRpb24vbmF2aWdhdGlvbi5qcz82YjEwIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZQTmF2IHtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHQvLyBkZWZpbmUgY29uc3RhbnRzXG5cdFx0Ly8ga2V5IGNvZGVzIGZvciBrZXlib2FyZCBuYXZcblx0XHR0aGlzLktFWUNPREVfVEFCICAgICAgICAgICAgICAgID0gOTtcblx0XHR0aGlzLktFWUNPREVfRVNDICAgICAgICAgICAgICAgID0gMjc7XG5cblx0XHQvLyBnZXQgRE9NIGVsZW1lbnRzIG5lZWRlZCB0aHJvdWdob3V0IHRoZSBjb2RlXG5cdFx0dGhpcy5zaXRlSGVhZGVyICAgICAgICAgICAgICAgICA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5zaXRlLWhlYWRlcicpO1xuXHRcdHRoaXMuaGVhZGVyRWxlbWVudCAgICAgICAgICAgICAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdoZWFkZXInKTtcblxuXHRcdC8vIGRlZmluZSBjb25maWcgZm9yIGhlYWRlciBjb21wb25lbnRzIGFuZCBDU1MgY2xhc3NlcyBmb3IgZGlzcGxheSB0b2dnbGluZ1xuXHRcdHRoaXMubmF2ICAgICAgICAgICAgICAgICAgICAgICAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjbmF2aWdhdGlvbicpO1xuXHRcdHRoaXMuaGVhZGVyTmF2V3JhcHBlciAgICAgICAgICAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaGVhZGVyLW5hdi13cmFwcGVyJyk7XG5cdFx0dGhpcy5oZWFkZXJOYXZEcmF3ZXJPcGVuICAgICAgICA9ICdkcmF3ZXItLW9wZW4nO1xuXHRcdHRoaXMuaGVhZGVyTmF2UGFyZW50U2Nyb2xsZWQgICAgPSAnbmF2LW1lbnUtc2Nyb2xsZWQtdHJ1ZS0tcGFyZW50Jztcblx0XHR0aGlzLmhlYWRlck5hdlBhcmVudE5vdFNjcm9sbGVkID0gJ25hdi1tZW51LXNjcm9sbGVkLWZhbHNlLS1wYXJlbnQnO1xuXHRcdHRoaXMuaGVhZGVyTmF2U2Nyb2xsZWQgICAgICAgICAgPSAnbmF2LW1lbnUtc2Nyb2xsZWQtdHJ1ZSc7XG5cdFx0dGhpcy5oZWFkZXJOYXZOb3RTY3JvbGxlZCAgICAgICA9ICduYXYtbWVudS1zY3JvbGxlZC1mYWxzZSc7XG5cblx0XHQvLyBkZWZpbmUgY29uZmlnIGZvciB1c2VyIG1lbnUgZWxlbWVudHNcblx0XHR0aGlzLnVzZXJJY29uICAgICAgICAgICAgICAgICAgID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmpzLXNpdGUtbmF2LXVzZXItaWNvbi1uYXZiYXInKTtcblx0XHR0aGlzLnVzZXJNZW51ICAgICAgICAgICAgICAgICAgID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnNpdGUtbmF2LXVzZXJtZW51LW5hdi1uYXZiYXInKTtcblx0XHRcblx0XHR0aGlzLnVzZXJJY29uRnVsbE1lbnUgICAgICAgICAgID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmpzLXNpdGUtbmF2LXVzZXItaWNvbi1mdWxsLW1lbnUnKTtcblx0XHR0aGlzLnVzZXJNZW51RnVsbE1lbnUgICAgICAgICAgID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnNpdGUtbmF2LXVzZXJtZW51LW5hdi1mdWxsLW1lbnUnKTtcblx0XHRcblx0XHQvLyBkZWZpbmUgY29uZmlnIGZvciBzZWFyY2ggbWVudSBlbGVtZW50c1xuXHRcdHRoaXMuc2VhcmNoRHJhd2VyQ2xvc2VCdXR0b24gICAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjc2VhcmNoZm9ybS1zaXRlLW5hdi1kcmF3ZXItY2xvc2UtYnRuJyk7XG5cdFx0dGhpcy5zZWFyY2hEcmF3ZXJJbnB1dEZpZWxkICAgICA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNzZWFyY2hmb3JtLXNpdGUtbmF2LWRyYXdlciAuc2VhcmNoZmllbGQtc2l0ZS1uYXYnKTtcblxuXHRcdC8vIGRlZmluZSBjb25maWcgZm9yIG1vYmlsZSBkcmF3ZXIgYnV0dG9uc1xuXHRcdHRoaXMubW9iaWxlRHJhd2VyQnV0dG9ucyAgICAgICAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuanMtZHJhd2VyLW1vYmlsZS1idXR0b24nKTtcblx0XHR0aGlzLm1vYmlsZURyYXdlckNsb3NlZCAgICAgICAgID0gJ2RyYXdlci1tb2JpbGUtYnV0dG9uLS1jbG9zZWQnO1xuXHRcdHRoaXMubW9iaWxlRHJhd2VyT3BlbiAgICAgICAgICAgPSAnZHJhd2VyLW1vYmlsZS1idXR0b24tLW9wZW4nO1xuXG5cdFx0Ly8gZGVmaW5lIGNvbmZpZyBmb3IgZnVsbCBuYXYgbWVudVxuXHRcdHRoaXMuaGFtYnVyZ2VyQnV0dG9ucyAgICAgICAgICAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcubmF2LW1vZGFsLW9wZW4nKTtcblx0XHR0aGlzLmNsb3NlQnV0dG9ucyAgICAgICAgICAgICAgID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLm5hdi1mdWxsLW1lbnVfX2Nsb3NlJyk7XG5cdFx0dGhpcy5kZXNrdG9wTWVudSAgICAgICAgICAgICAgICA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5uYXYtZnVsbC1tZW51Jyk7XG5cdFx0dGhpcy5kZXNrdG9wTWVudUNsb3NlZCAgICAgICAgICA9ICduYXYtZnVsbC1tZW51LS1jbG9zZWQnO1xuXHRcdHRoaXMuZGVza3RvcE1lbnVPcGVuICAgICAgICAgICAgPSAnbmF2LWZ1bGwtbWVudS0tb3Blbic7XG5cblx0XHQvLyB0cmFjayBoZWlnaHQgb2Ygb3BlbiBkcmF3ZXJzIGluIGRlc2t0b3AgbmF2XG5cdFx0Ly8gdXNlIGFzIHBhZGRpbmcgYmVsb3dcblx0XHR0aGlzLm9wZW5EcmF3ZXJIZWlnaHQgICAgICAgICAgID0gMDtcblxuXHRcdC8vIGRlZmluZSBjb25maWcgZm9yIGRyYXdlcnMgYW5kIHN1cHBvcnRpbmcgaW50ZXJhY3RpdmUgZWxlbWVudHMgXG5cdFx0Ly8gYW5kIENTUyBjbGFzc2VzIGZvciBkaXNwbGF5IHRvZ2dsaW5nXG5cdFx0dGhpcy5kcmF3ZXJzID0ge1xuXHRcdFx0cmVnaW9uczoge1xuXHRcdFx0XHRidXR0b246ICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5qcy1kcmF3ZXItcmVnaW9ucy1idXR0b24nKSxcblx0XHRcdFx0YnV0dG9uQ2xvc2VkOiAnZHJhd2VyLXJlZ2lvbnMtYnV0dG9uLS1jbG9zZWQnLFxuXHRcdFx0XHRidXR0b25PcGVuOiAgICdkcmF3ZXItcmVnaW9ucy1idXR0b24tLW9wZW4nLFxuXHRcdFx0XHRkcmF3ZXI6ICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5uYXYtZHJhd2VyX19yZWdpb25zJyksXG5cdFx0XHRcdGRyYXdlckNsb3NlZDogJ2RyYXdlci1yZWdpb25zLS1jbG9zZWQnLFxuXHRcdFx0XHRkcmF3ZXJPcGVuOiAgICdkcmF3ZXItcmVnaW9ucy0tb3BlbicsXG5cdFx0XHR9LFxuXHRcdFx0bmV3c2xldHRlcnM6IHtcblx0XHRcdFx0YnV0dG9uOiAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuanMtZHJhd2VyLW5ld3NsZXR0ZXJzLWJ1dHRvbicpLFxuXHRcdFx0XHRidXR0b25DbG9zZWQ6ICdkcmF3ZXItbmV3c2xldHRlcnMtYnV0dG9uLS1jbG9zZWQnLFxuXHRcdFx0XHRidXR0b25PcGVuOiAgICdkcmF3ZXItbmV3c2xldHRlcnMtYnV0dG9uLS1vcGVuJyxcblx0XHRcdFx0ZHJhd2VyOiAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcubmF2LWRyYXdlcl9fbmV3c2xldHRlcnMnKSxcblx0XHRcdFx0ZHJhd2VyQ2xvc2VkOiAnZHJhd2VyLW5ld3NsZXR0ZXJzLS1jbG9zZWQnLFxuXHRcdFx0XHRkcmF3ZXJPcGVuOiAgICdkcmF3ZXItbmV3c2xldHRlcnMtLW9wZW4nLFxuXHRcdFx0fSxcblx0XHRcdHNlYXJjaDoge1xuXHRcdFx0XHRidXR0b246ICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5qcy1kcmF3ZXItc2VhcmNoLWJ1dHRvbicpLFxuXHRcdFx0XHRidXR0b25DbG9zZWQ6ICdkcmF3ZXItc2VhcmNoLWJ1dHRvbi0tY2xvc2VkJyxcblx0XHRcdFx0YnV0dG9uT3BlbjogICAnZHJhd2VyLXNlYXJjaC1idXR0b24tLW9wZW4nLFxuXHRcdFx0XHRkcmF3ZXI6ICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5uYXYtZHJhd2VyX19zZWFyY2gnKSxcblx0XHRcdFx0ZHJhd2VyQ2xvc2VkOiAnZHJhd2VyLXNlYXJjaC0tY2xvc2VkJyxcblx0XHRcdFx0ZHJhd2VyT3BlbjogICAnZHJhd2VyLXNlYXJjaC0tb3BlbicsXG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXG5cblx0aW5pdCgpIHtcblx0XHRjb25zdCBzZWxmID0gdGhpcztcblxuXHRcdC8vIFN0aWNreSBtYWluIG5hdiwgY29udGVudCB0b2dnbGUgb24gc2Nyb2xsXG5cdFx0c2VsZi5uYXZBcHBlYXJhbmNlT25TY3JvbGwoKTtcblxuXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCAoKSA9PiB7XG5cdFx0XHQvLyB1c2VyIG1lbnVzXG5cdFx0XHRzZWxmLnVzZXJNZW51SW50ZXJhY3Rpdml0eShcblx0XHRcdFx0c2VsZi51c2VySWNvbixcblx0XHRcdFx0c2VsZi51c2VyTWVudVxuXHRcdFx0KTtcblx0XHRcdHNlbGYudXNlck1lbnVJbnRlcmFjdGl2aXR5KFxuXHRcdFx0XHRzZWxmLnVzZXJJY29uRnVsbE1lbnUsXG5cdFx0XHRcdHNlbGYudXNlck1lbnVGdWxsTWVudVxuXHRcdFx0KTtcblx0XHRcdHNlbGYua2V5Ym9hcmRDbG9zZUV4cGFuZGVkRHJhd2VyQ29udGVudChcblx0XHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnNpdGUtbmF2LXVzZXJtZW51LW5hdicpXG5cdFx0XHQpO1xuXHRcdFx0XG5cdFx0XHQvLyBkcmF3ZXJzXG5cdFx0XHRzZWxmLmRyYXdlckludGVyYWN0aXZpdHkoKTtcblx0XHRcdHNlbGYua2V5Ym9hcmRDbG9zZUV4cGFuZGVkRHJhd2VyQ29udGVudChcblx0XHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLm5hdi1kcmF3ZXItd3JhcHBlcicpXG5cdFx0XHQpO1xuXHRcdFx0c2VsZi5tb2JpbGVEcmF3ZXJJbnRlcmFjdGl2aXR5KCk7XG5cdFx0XHRcblx0XHRcdC8vIGZ1bGwgbWVudVxuXHRcdFx0c2VsZi5mdWxsTWVudUludGVyYWN0aXZpdHkoKTtcblxuXHRcdFx0Ly8gZm9jdXMgdHJhcFxuXHRcdFx0c2VsZi50cmFwRm9jdXNJbnRlcmFjdGl2aXR5KCk7XG5cdFx0fSk7XG5cblx0XHQvLyBQaWFubyBpZnJhbWVzXG5cdFx0c2VsZi5vYnNlcnZlUGlhbm9JZnJhbWVzKCk7XG5cdH1cblxuXHQvKipcblx0ICogQHN1bW1hcnkgQWRkIHNjcm9sbCBsaXN0ZW5lciBmb3IgbmF2aWdhdGlvbiBhcHBlYXJhbmNlIGJhc2VkIG9uIHNjcm9sbCBkZXB0aFxuXHQgKiBcblx0ICogQHJldHVybiB7dm9pZH1cblx0ICovXG5cdG5hdkFwcGVhcmFuY2VPblNjcm9sbCgpIHtcblx0XHRjb25zdCBzZWxmID0gdGhpcztcblxuXHRcdC8vIHNjcm9sbCBsaXN0ZW5lciB0byB0b2dnbGUgY2xhc3NlcyBiZXR3ZWVuOiBcblx0XHQvLyAtIG1haW4gbmF2IHN0YXRpY1xuXHRcdC8vIC0gbWFpbiBuYXYgc2Nyb2xsZWRcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29uc3QgbWFpbkVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtYWluJyk7XG5cblx0XHRcdC8vIG1haW4gbmF2IHN0YXRpY1xuXHRcdFx0Ly8gdXNlciBoYXMgbm90IHNjcm9sbGVkIHRvIGEgZGVwdGggbGVzcyB0aGFuIHRoZSBzaXRlSGVhZGVyIGhlaWdodFxuXHRcdFx0Ly8gb3IgaGFzIHNjb2xsZWQgYmFjayB0byB0aGUgdG9wIG9mIHRoZSBwYWdlXG5cdFx0XHRpZiAod2luZG93LnNjcm9sbFkgPiBzZWxmLnNpdGVIZWFkZXIub2Zmc2V0SGVpZ2h0KSB7XG5cdFx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdFx0c2VsZi5zaXRlSGVhZGVyLCAgICAgICAgICAgICAgICAvLyB0YXJnZXQgRE9NIGVsZW1lbnRcblx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdlBhcmVudFNjcm9sbGVkLCAgIC8vIGNsYXNzIHRvIGFkZFxuXHRcdFx0XHRcdHNlbGYuaGVhZGVyTmF2UGFyZW50Tm90U2Nyb2xsZWQgLy8gY2xhc3MgdG8gcmVtb3ZlXG5cdFx0XHRcdCk7XG5cdFx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdFx0c2VsZi5oZWFkZXJOYXZXcmFwcGVyLCBcblx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdlNjcm9sbGVkLCBcblx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdk5vdFNjcm9sbGVkXG5cdFx0XHRcdCk7XG5cdFx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdFx0c2VsZi5uYXYsIFxuXHRcdFx0XHRcdHNlbGYuaGVhZGVyTmF2U2Nyb2xsZWQsIFxuXHRcdFx0XHRcdHNlbGYuaGVhZGVyTmF2Tm90U2Nyb2xsZWRcblx0XHRcdFx0KTtcblxuXHRcdFx0XHRpZiggc2VsZi5vcGVuRHJhd2VySGVpZ2h0ID4gMCApIHtcblx0XHRcdFx0XHQvLyBhZGQgODAgYmVsb3cgdG8gYWNjb3VudCBmb3IgLmhlYWRlci1uYXYtd3JhcHBlciBoZWlnaHQgYW5kIGJvdHRvbSBtYXJnaW5cblx0XHRcdFx0XHRtYWluRWxlbWVudC5zdHlsZS5wYWRkaW5nVG9wID0gc2VsZi5vcGVuRHJhd2VySGVpZ2h0ICsgODAgKyAncHgnOyBcblx0XHRcdFx0fVxuXHRcdFx0Ly8gbWFpbiBuYXYgc2Nyb2xsZWRcblx0XHRcdC8vIHVzZXIgaGFzIHNjcm9sbGVkIHRvIGEgZGVwdGggZXF1YWwgdG8gb3IgZ3JlYXRlciB0aGFuIHRoZSBzaXRlSGVhZGVyIGhlaWdodFxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VsZi50b2dnbGVFbGVtZW50Q2xhc3Nlcyhcblx0XHRcdFx0XHRzZWxmLnNpdGVIZWFkZXIsICAgICAgICAgICAgICAgICAvLyB0YXJnZXQgRE9NIGVsZW1lbnRcblx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdlBhcmVudE5vdFNjcm9sbGVkLCAvLyBjbGFzcyB0byBhZGRcblx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdlBhcmVudFNjcm9sbGVkICAgICAvLyBjbGFzcyB0byByZW1vdmVcblx0XHRcdFx0KTtcblx0XHRcdFx0c2VsZi50b2dnbGVFbGVtZW50Q2xhc3Nlcyhcblx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdldyYXBwZXIsIFxuXHRcdFx0XHRcdHNlbGYuaGVhZGVyTmF2Tm90U2Nyb2xsZWQsIFxuXHRcdFx0XHRcdHNlbGYuaGVhZGVyTmF2U2Nyb2xsZWRcblx0XHRcdFx0KTtcblx0XHRcdFx0c2VsZi50b2dnbGVFbGVtZW50Q2xhc3Nlcyhcblx0XHRcdFx0XHRzZWxmLm5hdiwgXG5cdFx0XHRcdFx0c2VsZi5oZWFkZXJOYXZOb3RTY3JvbGxlZCwgXG5cdFx0XHRcdFx0c2VsZi5oZWFkZXJOYXZTY3JvbGxlZFxuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdG1haW5FbGVtZW50LnN0eWxlLnBhZGRpbmdUb3AgPSAnJztcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cblx0LyoqXG5cdCAqIEBzdW1tYXJ5IEFkZCBsaXN0ZW5lcnMgZm9yIGRyYXdlciBpbnRlcmFjdGl2aXR5XG5cdCAqIFxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0ZHJhd2VySW50ZXJhY3Rpdml0eSgpIHtcblx0XHRjb25zdCBzZWxmID0gdGhpcztcblxuXHRcdC8vIEhhbmRsaW5nIGZvciBkcmF3ZXIgZGlzcGxheSB0b2dnbGUgYnV0dG9uc1xuXHRcdGZvciAoY29uc3QgZHJhd2VyTmFtZSBpbiBzZWxmLmRyYXdlcnMpIHtcblx0XHRcdGlmKCAhc2VsZi5kcmF3ZXJzW2RyYXdlck5hbWVdLmJ1dHRvbiApIGNvbnRpbnVlO1xuXG5cdFx0XHQvLyBIYW5kbGVzIGNsaWNrIGFuZCBlbnRlciBrZXlkb3duXG5cdFx0XHRzZWxmLmRyYXdlcnNbZHJhd2VyTmFtZV0uYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGV2ZW50KSA9PiB7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdHNlbGYudG9nZ2xlRHJhd2VyKGRyYXdlck5hbWUsIGV2ZW50KTtcblx0XHRcdH0pO1xuXG5cdFx0fVxuXG5cdFx0Ly8gSGFuZGxpbmcgZm9yIHNlYXJjaCBjbG9zZSBidXR0b25cblx0XHRpZiggc2VsZi5zZWFyY2hEcmF3ZXJDbG9zZUJ1dHRvbiApIHtcblx0XHRcdFxuXHRcdFx0c2VsZi5zZWFyY2hEcmF3ZXJDbG9zZUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcblx0XHRcdFx0Y29uc3Qgc2VhcmNoRHJhd2VyQ29uZmlnID0gc2VsZi5kcmF3ZXJzLnNlYXJjaDtcblx0XHRcdFx0aWYgKHNlYXJjaERyYXdlckNvbmZpZy5kcmF3ZXIuY2xhc3NMaXN0LmNvbnRhaW5zKHNlYXJjaERyYXdlckNvbmZpZy5kcmF3ZXJPcGVuKSkge1xuXHRcdFx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdFx0XHRzZWFyY2hEcmF3ZXJDb25maWcuZHJhd2VyLCAgICAgICAvLyB0YXJnZXQgRE9NIGVsZW1lbnRcblx0XHRcdFx0XHRcdHNlYXJjaERyYXdlckNvbmZpZy5kcmF3ZXJDbG9zZWQsIC8vIGNsYXNzIHRvIGFkZFxuXHRcdFx0XHRcdFx0c2VhcmNoRHJhd2VyQ29uZmlnLmRyYXdlck9wZW4gICAgLy8gY2xhc3MgdG8gcmVtb3ZlXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRzZWxmLnRvZ2dsZUVsZW1lbnRDbGFzc2VzKFxuXHRcdFx0XHRcdFx0c2VhcmNoRHJhd2VyQ29uZmlnLmJ1dHRvbiwgICAgICAgXG5cdFx0XHRcdFx0XHRzZWFyY2hEcmF3ZXJDb25maWcuYnV0dG9uQ2xvc2VkLCBcblx0XHRcdFx0XHRcdHNlYXJjaERyYXdlckNvbmZpZy5idXR0b25PcGVuICAgIFxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XG5cdFx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdFx0IXNlbGYuZHJhd2Vycy5yZWdpb25zLmRyYXdlci5jbGFzc0xpc3QuY29udGFpbnMoc2VsZi5kcmF3ZXJzLnJlZ2lvbnMuZHJhd2VyT3BlbikgXG5cdFx0XHRcdFx0XHQmJiAhc2VsZi5kcmF3ZXJzLm5ld3NsZXR0ZXJzLmRyYXdlci5jbGFzc0xpc3QuY29udGFpbnMoc2VsZi5kcmF3ZXJzLm5ld3NsZXR0ZXJzLmRyYXdlck9wZW4pXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRzZWxmLmhlYWRlck5hdldyYXBwZXIuY2xhc3NMaXN0LnJlbW92ZShzZWxmLmhlYWRlck5hdkRyYXdlck9wZW4pO1xuXHRcdFx0XHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnNpdGUtbmF2LXNlYXJjaCAjc2VhcmNoJykuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ2ZhbHNlJyk7XG5cdFx0XHRcdFx0XHRkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuc2l0ZS1uYXYtc2VhcmNoICNzZWFyY2gnKS5mb2N1cygpO1xuXG5cdFx0XHRcdFx0XHQvLyBSZW1vdmUgcGFkZGluZyBmcm9tIDxoZWFkZXI+XG5cdFx0XHRcdFx0XHRzZWxmLmhlYWRlckVsZW1lbnQuc3R5bGUucGFkZGluZ0JvdHRvbSA9ICcnO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblxuXHQvKipcblx0ICogQHN1bW1hcnkgRHJhd2VyIGRpc3BsYXkgdG9nZ2xpbmcgZnVuY3Rpb25hbGl0eVxuXHQgKiBcblx0ICogQGRlc2NyaXB0aW9uIFRyYXBzIGZvY3VzIGluIGV4cGFuZGVkIG5hdiwgbW9kYWxzLCBldGMuXG5cdCAqIFxuXHQgKiBAcGFyYW0gIHtzdHJpbmd9IGN1cnJlbnREcmF3ZXIgTmFtZSBvZiBjdXJyZW50IGRyYXdlclxuXHQgKiBAcGFyYW0gIHtvYmplY3R9IGV2ZW50IERPTSBldmVudFxuXHQgKlxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0dG9nZ2xlRHJhd2VyKGN1cnJlbnREcmF3ZXIsIGV2ZW50KSB7XG5cdFx0Y29uc3Qgc2VsZiA9IHRoaXM7XG5cblx0XHQvLyBDaGVjayBpZiBvdGhlciBkcmF3ZXJzIGFyZSBvcGVuIGFuZCBjbG9zZSB0aGVtIGlmIHRoZXkgYXJlXG5cdFx0Zm9yIChsZXQgZHJhd2VyTmFtZSBpbiBzZWxmLmRyYXdlcnMpIHtcblx0XHRcdGlmIChkcmF3ZXJOYW1lICE9PSBjdXJyZW50RHJhd2VyKSB7XG5cdFx0XHRcdGNvbnN0IGRyYXdlck9iaiA9IHNlbGYuZHJhd2Vyc1tkcmF3ZXJOYW1lXTtcblx0XHRcdFx0aWYgKFxuXHRcdFx0XHRcdGRyYXdlck9iai5kcmF3ZXIgXG5cdFx0XHRcdFx0JiYgZHJhd2VyT2JqLmRyYXdlci5jbGFzc0xpc3QgXG5cdFx0XHRcdFx0JiYgZHJhd2VyT2JqLmRyYXdlci5jbGFzc0xpc3QuY29udGFpbnMoZHJhd2VyT2JqLmRyYXdlck9wZW4pXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdFx0XHRkcmF3ZXJPYmouZHJhd2VyLCAgICAgICAvLyB0YXJnZXQgRE9NIGVsZW1lbnRcblx0XHRcdFx0XHRcdGRyYXdlck9iai5kcmF3ZXJDbG9zZWQsIC8vIGNsYXNzIHRvIGFkZFxuXHRcdFx0XHRcdFx0ZHJhd2VyT2JqLmRyYXdlck9wZW4gICAgLy8gY2xhc3MgdG8gcmVtb3ZlXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRzZWxmLnRvZ2dsZUVsZW1lbnRDbGFzc2VzKFxuXHRcdFx0XHRcdFx0ZHJhd2VyT2JqLmJ1dHRvbixcblx0XHRcdFx0XHRcdGRyYXdlck9iai5idXR0b25DbG9zZWQsXG5cdFx0XHRcdFx0XHRkcmF3ZXJPYmouYnV0dG9uT3BlblxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRjb25zdCBhY3RpdmVEcmF3ZXIgPSBzZWxmLmRyYXdlcnNbY3VycmVudERyYXdlcl07XG5cblx0XHRpZiAoYWN0aXZlRHJhd2VyLmRyYXdlci5jbGFzc0xpc3QuY29udGFpbnMoYWN0aXZlRHJhd2VyLmRyYXdlck9wZW4pKSB7XG5cdFx0XHRzZWxmLnRvZ2dsZUVsZW1lbnRDbGFzc2VzKFxuXHRcdFx0XHRhY3RpdmVEcmF3ZXIuYnV0dG9uLCAgICAgICAvLyB0YXJnZXQgRE9NIGVsZW1lbnRcblx0XHRcdFx0YWN0aXZlRHJhd2VyLmJ1dHRvbkNsb3NlZCwgLy8gY2xhc3MgdG8gYWRkXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5idXR0b25PcGVuICAgIC8vIGNsYXNzIHRvIHJlbW92ZVxuXHRcdFx0KTtcblx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXIsXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXJDbG9zZWQsXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXJPcGVuXG5cdFx0XHQpO1xuXHRcdFx0XG5cdFx0XHRzZWxmLmhlYWRlck5hdldyYXBwZXIuY2xhc3NMaXN0LnJlbW92ZShzZWxmLmhlYWRlck5hdkRyYXdlck9wZW4pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZWxmLnRvZ2dsZUVsZW1lbnRDbGFzc2VzKFxuXHRcdFx0XHRhY3RpdmVEcmF3ZXIuYnV0dG9uLFxuXHRcdFx0XHRhY3RpdmVEcmF3ZXIuYnV0dG9uT3Blbixcblx0XHRcdFx0YWN0aXZlRHJhd2VyLmJ1dHRvbkNsb3NlZFxuXHRcdFx0KTtcblx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXIsXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXJPcGVuLFxuXHRcdFx0XHRhY3RpdmVEcmF3ZXIuZHJhd2VyQ2xvc2VkXG5cdFx0XHQpO1xuXHRcdFx0XG5cdFx0XHRzZWxmLmhlYWRlck5hdldyYXBwZXIuY2xhc3NMaXN0LmFkZChzZWxmLmhlYWRlck5hdkRyYXdlck9wZW4pO1xuXHRcdH1cblxuXHRcdGxldCBpc0V4cGFuZGVkID0gZmFsc2U7XG5cdFx0aWYgKGFjdGl2ZURyYXdlci5kcmF3ZXIuY2xhc3NMaXN0LmNvbnRhaW5zKGFjdGl2ZURyYXdlci5kcmF3ZXJPcGVuKSkgaXNFeHBhbmRlZCA9IHRydWU7XG5cdFx0aWYgKGlzRXhwYW5kZWQpIHtcblx0XHRcdC8vIHNldCBhcmlhLWV4cGFuZGVkIGF0dHJpYnV0ZSB0byB0cnVlIGZvciBwYXJlbnQgPGE+IHRhZ1xuXHRcdFx0YWN0aXZlRHJhd2VyLmJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAndHJ1ZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBzZXQgYXJpYS1leHBhbmRlZCBhdHRyaWJ1dGUgdG8gZmFsc2UgZm9yIHBhcmVudCA8YT4gdGFnXG5cdFx0XHRhY3RpdmVEcmF3ZXIuYnV0dG9uLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuXHRcdH1cbiBcblx0XHQvLyBzZXQgcGFkZGluZyB0byA8aGVhZGVyPiB0byBwdXNoIGNvbnRlbnQgZG93biB3aGVuIGRyYXdlciBpcyBvcGVuXG5cdFx0c2VsZi5vcGVuRHJhd2VySGVpZ2h0ID0gYWN0aXZlRHJhd2VyLmRyYXdlci5vZmZzZXRIZWlnaHQgPz8gMDtcblx0XHRzZWxmLmhlYWRlckVsZW1lbnQuc3R5bGUucGFkZGluZ0JvdHRvbSA9IHNlbGYub3BlbkRyYXdlckhlaWdodCArICdweCc7XG5cblx0XHQvLyBzZXQgZm9jdXMgYW5kIENTUyBjbGFzc2VzIGZvciBkcmF3ZXJzXG5cdFx0c3dpdGNoIChjdXJyZW50RHJhd2VyKSB7XG5cdFx0Y2FzZSAnc2VhcmNoJzpcblx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXIuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICdmYWxzZScpO1xuXHRcdFx0c2VsZi5zZWFyY2hEcmF3ZXJJbnB1dEZpZWxkLmZvY3VzKCk7XG5cdFx0XHQvLyBvbmx5IGFwcGx5IGZvY3VzIG91dGxpbmUgc3R5bGUgaWYgdXNlciBuYXZpZ2F0ZWQgdmlhIGtleWJvYXJkXG5cdFx0XHRpZiAoJ0VudGVyJyAhPT0gZXZlbnQua2V5KSB7XG5cdFx0XHRcdHNlbGYuc2VhcmNoRHJhd2VySW5wdXRGaWVsZC5jbGFzc0xpc3QuYWRkKCduby1mb2N1cy1vdXRsaW5lJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZWxmLnNlYXJjaERyYXdlcklucHV0RmllbGQuY2xhc3NMaXN0LnJlbW92ZSgnbm8tZm9jdXMtb3V0bGluZScpO1xuXHRcdFx0fVxuXHRcdFx0YnJlYWs7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdGlmIChpc0V4cGFuZGVkKSB7XG5cdFx0XHRcdC8vIHNldCBhcmlhLWhpZGRlbiBhdHRyaWJ1dGUgdG8gZmFsc2Vcblx0XHRcdFx0YWN0aXZlRHJhd2VyLmRyYXdlci5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgJ2ZhbHNlJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBzZXQgYXJpYS1oaWRkZW4gYXR0cmlidXRlIHRvIGZhbHNlXG5cdFx0XHRcdGFjdGl2ZURyYXdlci5kcmF3ZXIuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG5cdFx0XHR9XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRcblx0LyoqXG5cdCAqIEBzdW1tYXJ5IE1vYmlsZSBkcmF3ZXIgZGlzcGxheSB0b2dnbGluZyBmdW5jdGlvbmFsaXR5XG5cdCAqIFxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0bW9iaWxlRHJhd2VySW50ZXJhY3Rpdml0eSgpIHtcblx0XHRjb25zdCBzZWxmID0gdGhpcztcblxuXHRcdC8vIEhhbmRsaW5nIGZvciBtb2JpbGVEcmF3ZXJCdXR0b25cblx0XHRzZWxmLm1vYmlsZURyYXdlckJ1dHRvbnMuZm9yRWFjaCgobW9iaWxlRHJhd2VyQnV0dG9uKSA9PiB7XG5cdFx0XHRtb2JpbGVEcmF3ZXJCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZSkgPT4ge1xuXHRcdFx0XHRpZiAod2luZG93LmlubmVyV2lkdGggPiA5NzkpIHJldHVybjtcblxuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdFx0bW9iaWxlRHJhd2VyQnV0dG9uLmNsYXNzTGlzdC50b2dnbGUoc2VsZi5tb2JpbGVEcmF3ZXJPcGVuKTtcblx0XHRcdFx0bW9iaWxlRHJhd2VyQnV0dG9uLmNsYXNzTGlzdC50b2dnbGUoc2VsZi5tb2JpbGVEcmF3ZXJDbG9zZWQpO1xuXG5cdFx0XHRcdGlmICghbW9iaWxlRHJhd2VyQnV0dG9uLmNsYXNzTGlzdC5jb250YWlucyhzZWxmLm1vYmlsZURyYXdlck9wZW4pKSB7XG5cdFx0XHRcdFx0c2VsZi5oZWFkZXJOYXZXcmFwcGVyLmNsYXNzTGlzdC5yZW1vdmUoc2VsZi5oZWFkZXJOYXZEcmF3ZXJPcGVuKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cblxuXG5cdC8qKlxuXHQgKiBAc3VtbWFyeSBGdWxsIG1lbnUgZGlzcGxheSB0b2dnbGluZyBmdW5jdGlvbmFsaXR5XG5cdCAqIFxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0ZnVsbE1lbnVJbnRlcmFjdGl2aXR5KCkge1xuXHRcdGNvbnN0IHNlbGYgPSB0aGlzO1xuXG5cdFx0c2VsZi5oYW1idXJnZXJCdXR0b25zLmZvckVhY2goKGhhbWJ1cmdlckJ1dHRvbikgPT4ge1xuXHRcdFx0aGFtYnVyZ2VyQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRoYW1idXJnZXJCdXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ3RydWUnKTtcblx0XHRcdFx0XG5cdFx0XHRcdHNlbGYudG9nZ2xlRWxlbWVudENsYXNzZXMoXG5cdFx0XHRcdFx0c2VsZi5kZXNrdG9wTWVudSxcblx0XHRcdFx0XHRzZWxmLmRlc2t0b3BNZW51T3Blbixcblx0XHRcdFx0XHRzZWxmLmRlc2t0b3BNZW51Q2xvc2VkXG5cdFx0XHRcdCk7XG5cdFx0XHRcdFxuXHRcdFx0XHRzZWxmLmRlc2t0b3BNZW51LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICd0cnVlJyk7XG5cdFx0XHRcdHNlbGYuZGVza3RvcE1lbnUuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICdmYWxzZScpO1xuXHRcdFx0XHRcblx0XHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0c2VsZi5jbG9zZUJ1dHRvbnNbMF0uZm9jdXMoKTtcblx0XHRcdFx0fSwgMTAwKTtcblx0XHRcdFx0XG5cdFx0XHRcdGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5uYXYtZnVsbC1tZW51Jykuc2Nyb2xsVG9wID0gMDtcblx0XHRcdFx0XG5cdFx0XHRcdGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgnb3ZlcmxheS1uby1zY3JvbGwnKTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXG5cdFx0c2VsZi5jbG9zZUJ1dHRvbnMuZm9yRWFjaCgoY2xvc2VCdXR0b24pID0+IHtcblx0XHRcdGNsb3NlQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRzZWxmLnRvZ2dsZUVsZW1lbnRDbGFzc2VzKFxuXHRcdFx0XHRcdHNlbGYuZGVza3RvcE1lbnUsXG5cdFx0XHRcdFx0c2VsZi5kZXNrdG9wTWVudUNsb3NlZCxcblx0XHRcdFx0XHRzZWxmLmRlc2t0b3BNZW51T3BlblxuXHRcdFx0XHQpO1xuXHRcdFx0XHRcblx0XHRcdFx0c2VsZi5kZXNrdG9wTWVudS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcblx0XHRcdFx0c2VsZi5kZXNrdG9wTWVudS5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgJ3RydWUnKTtcblxuXHRcdFx0XHRzZWxmLmhhbWJ1cmdlckJ1dHRvbnMuZm9yRWFjaCgoaGFtYnVyZ2VyQnV0dG9uKSA9PiB7XG5cdFx0XHRcdFx0aGFtYnVyZ2VyQnV0dG9uLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRzZWxmLmhhbWJ1cmdlckJ1dHRvbnNbMF0uZm9jdXMoKTtcblxuXHRcdFx0XHRkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ292ZXJsYXktbm8tc2Nyb2xsJyk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cblx0LyoqXG5cdCAqIEBzdW1tYXJ5IEFkZCBsaXN0ZW5lcnMgZm9yIHVzZXIgbWVudSBpbnRlcmFjdGl2aXR5XG5cdCAqXG5cdCAqIEBwYXJhbSAge29iamVjdH0gdXNlckljb24gdXNlciBpY29uIERPTSBlbGVtZW50IG9iamVjdFxuXHQgKiBAcGFyYW0gIHtvYmplY3R9IHVzZXJNZW51IHVzZXIgbWVudXUgRE9NIGVsZW1lbnQgb2JqZWN0XG5cdCAqIFxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0dXNlck1lbnVJbnRlcmFjdGl2aXR5KHVzZXJJY29uLCB1c2VyTWVudSkge1xuXHRcdGlmKCAhdXNlckljb24gKSByZXR1cm47XG5cblx0XHR1c2VySWNvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uIChldmVudCkge1xuXHRcdFx0XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRpZiAodXNlck1lbnUuc3R5bGUuZGlzcGxheSAhPT0gJ2Jsb2NrJykge1xuXHRcdFx0XHR1c2VySWNvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAndHJ1ZScpO1xuXHRcdFx0XHR1c2VyTWVudS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHVzZXJJY29uLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuXHRcdFx0XHR1c2VyTWVudS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dXNlckljb24uYWRkRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIGZ1bmN0aW9uICgpIHtcblx0XHRcdHVzZXJJY29uLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICd0cnVlJyk7XG5cdFx0XHR1c2VyTWVudS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblx0XHR9KTtcblxuXHRcdHVzZXJNZW51LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHR1c2VySWNvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcblx0XHRcdHVzZXJNZW51LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0fSk7XG5cdH1cblxuXG5cdC8qKlxuXHQgKiBAc3VtbWFyeSBUcmFwIGZvY3VzIGZ1bmN0aW9uYWxpdHkgaW4gZXhwYW5kZWQgbWVudSBpdGVtcyBhbmQgZXhwYW5kZWQgbmF2XG5cdCAqIFxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0dHJhcEZvY3VzSW50ZXJhY3Rpdml0eSgpIHtcblx0XHRGUC5VdGlscy50cmFwRm9jdXMuaW5pdChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcjZXhwYW5kZWQtbmF2aWdhdGlvbicpKTtcblx0fVxuXG5cblx0LyoqXG5cdCAqIEBzdW1tYXJ5IEhlbHBlciB0byBjbG9zZSBhbGwgZHJhd2VycyBvbiBkZXNrdG9wXG5cdCAqIFxuXHQgKiBAcmV0dXJuIHt2b2lkfVxuXHQgKi9cblx0Y2xvc2VBbGxEcmF3ZXJzKCkge1xuXHRcdGNvbnN0IHNlbGYgPSB0aGlzO1xuXG5cdFx0Zm9yIChsZXQgZHJhd2VyTmFtZSBpbiBzZWxmLmRyYXdlcnMpIHtcblx0XHRcdGNvbnN0IGRyYXdlck9iaiA9IHNlbGYuZHJhd2Vyc1tkcmF3ZXJOYW1lXTtcblx0XHRcdFxuXHRcdFx0c2VsZi50b2dnbGVFbGVtZW50Q2xhc3Nlcyhcblx0XHRcdFx0ZHJhd2VyT2JqLmRyYXdlcixcblx0XHRcdFx0ZHJhd2VyT2JqLmRyYXdlckNsb3NlZCxcblx0XHRcdFx0ZHJhd2VyT2JqLmRyYXdlck9wZW5cblx0XHRcdCk7XG5cdFx0XHRzZWxmLnRvZ2dsZUVsZW1lbnRDbGFzc2VzKFxuXHRcdFx0XHRkcmF3ZXJPYmouYnV0dG9uLFxuXHRcdFx0XHRkcmF3ZXJPYmouYnV0dG9uQ2xvc2VkLFxuXHRcdFx0XHRkcmF3ZXJPYmouYnV0dG9uT3BlblxuXHRcdFx0KTtcblxuXHRcdFx0ZHJhd2VyT2JqLmJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcblx0XHR9XG5cblx0XHQvLyB1cGRhdGUgaGVhZGVyIGVsZW1lbnRzXG5cdFx0c2VsZi5oZWFkZXJOYXZXcmFwcGVyLmNsYXNzTGlzdC5yZW1vdmUoc2VsZi5oZWFkZXJOYXZEcmF3ZXJPcGVuKTtcblx0XHRzZWxmLmhlYWRlckVsZW1lbnQuc3R5bGUucGFkZGluZ0JvdHRvbSA9ICcnO1xuXG5cdFx0Ly8gcmVzZXQgb3BlbiBkcmF3ZXIgaGVpZ2h0IHRvIDBcblx0XHRzZWxmLm9wZW5EcmF3ZXJIZWlnaHQgPSAwO1xuXG5cdFx0Ly8gdXBkYXRlIG1haW4gZWxlbWVudFxuXHRcdGNvbnN0IG1haW5FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignbWFpbicpO1xuXHRcdG1haW5FbGVtZW50LnN0eWxlLnBhZGRpbmdUb3AgPSAnJztcblxuXHRcdC8vIGNsb3NlIHVzZXIgbWVudXNcblx0XHRzZWxmLnVzZXJNZW51LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0c2VsZi51c2VyTWVudUZ1bGxNZW51LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdFx0c2VsZi51c2VySWNvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcblx0XHRzZWxmLnVzZXJJY29uRnVsbE1lbnUuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ2ZhbHNlJyk7XG5cdH1cblxuXHRcblx0LyoqXG5cdCAqIEBzdW1tYXJ5IEhlbHBlciB0byBmb2N1cyBvbiBwYXJlbnQgZWxlbWVudCBhZnRlciBjbG9zaW5nIGRyYXdlcnNcblx0ICpcblx0ICogQHBhcmFtICB7b2JqZWN0fSBjb250YWluZXJFbGVtZW50IERPTSBlbGVtZW50IG9iamVjdFxuXHQgKiBcblx0ICogQHJldHVybiB7dm9pZH1cblx0ICovXG5cdGZvY3VzT25QYXJlbnQoY29udGFpbmVyRWxlbWVudCkge1xuXHRcdC8vIFRPLURPIC0gbWFrZSB0aGlzIG1vcmUgZmxleGlibGUsIG5vdCBvbmx5IHNlYXJjaGluZyBmb3IgYW4gPGE+IHRhZ1xuXHRcdHZhciBmb2N1c0VsID0gY29udGFpbmVyRWxlbWVudC5wYXJlbnROb2RlLnF1ZXJ5U2VsZWN0b3IoJ2EnKTtcblxuXHRcdGlmKCBmb2N1c0VsICkge1xuXHRcdFx0Zm9jdXNFbC5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcblx0XHRcdGZvY3VzRWwuZm9jdXMoKTtcblx0XHR9XG5cdH1cblxuXG5cdC8qKlxuXHQgKiBAc3VtbWFyeSBIZWxwZXIgdG8gaGFuZGxlIGZ1bGwgbmF2IGNsb3N1cmUgd2l0aCBrZXlib2FyZCBpbnB1dFxuXHQgKlxuXHQgKiBAZGVzY3JpcHRpb24gQWxsb3cgZXhwYW5kZWQgbmF2IHRvIGJlIGNsb3NlZCB3aGVuOlxuXHQgKiAgICAgIC0gdGhlIHVzZXIgcHJlc3NlcyB0aGUgRXNjYXBlIGtleVxuXHQgKiAgICAgIC0gdGhlIHVzZXIgc2hpZnQgKyB0YWJzIGJhY2sgcGFzdCB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgZHJhd2VyXG5cdCAqICAgICAgLSB0aGUgdXNlciB0YWJzIHBhc3QgdGhlIGxhc3QgaXRlbSBpbiB0aGUgZHJhd2VyXG5cdCAqXG5cdCAqIEBwYXJhbSAge2FycmF5fSBjb250YWluZXJFbGVtZW50cyBBcnJheSBvZiBET00gZWxlbWVudHMgZnJvbSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKClcblx0ICogXG5cdCAqIEByZXR1cm4ge3ZvaWR9XG5cdCAqL1xuXHRrZXlib2FyZENsb3NlRXhwYW5kZWREcmF3ZXJDb250ZW50KGNvbnRhaW5lckVsZW1lbnRzKSB7XG5cdFx0Y29uc3Qgc2VsZiA9IHRoaXM7XG5cblx0XHRjb250YWluZXJFbGVtZW50cy5mb3JFYWNoKChjb250YWluZXJFbGVtZW50KSA9PiB7XG5cdFx0XHR2YXIgZm9jdXNhYmxlRWxzID0gRlAuVXRpbHMudHJhcEZvY3VzLmdldGZvY3VzYWJsZUVscyhjb250YWluZXJFbGVtZW50KTtcblx0XHRcdHZhciBmaXJzdEZvY3VzYWJsZUVsID0gZm9jdXNhYmxlRWxzWzBdOyAgXG5cdFx0XHR2YXIgbGFzdEZvY3VzYWJsZUVsID0gZm9jdXNhYmxlRWxzW2ZvY3VzYWJsZUVscy5sZW5ndGggLSAxXTtcblxuXHRcdFx0Y29udGFpbmVyRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuXHRcdFx0XHR2YXIgaXNFc2NhcGVQcmVzc2VkID0gKGUua2V5ID09PSAnRXNjJyB8fCBlLmtleUNvZGUgPT09IHNlbGYuS0VZQ09ERV9FU0MpO1xuXHRcdFx0XHR2YXIgaXNUYWJQcmVzc2VkID0gKGUua2V5ID09PSAnVGFiJyB8fCBlLmtleUNvZGUgPT09IHNlbGYuS0VZQ09ERV9UQUIpO1xuXG5cdFx0XHRcdGlmICghaXNFc2NhcGVQcmVzc2VkICYmICFpc1RhYlByZXNzZWQpIHsgXG5cdFx0XHRcdFx0cmV0dXJuOyBcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciBwcm9jZXNzQWN0aW9uID0gZmFsc2U7XG5cdFx0XHRcdHZhciBjaGFuZ2VGb2N1cyA9IGZhbHNlO1xuXG5cdFx0XHRcdC8vIGVzYyBwcmVzc2VkXG5cdFx0XHRcdGlmICggaXNFc2NhcGVQcmVzc2VkICkge1xuXHRcdFx0XHRcdHByb2Nlc3NBY3Rpb24gPSB0cnVlO1xuXHRcdFx0XHRcdGNoYW5nZUZvY3VzID0gdHJ1ZTtcblx0XHRcdFx0Ly8gc2hpZnQgKyB0YWIgcHJlc3NlZFxuXHRcdFx0XHR9IGVsc2UgaWYgKCBlLnNoaWZ0S2V5ICkge1xuXHRcdFx0XHRcdC8vIGlmIHVzZXIgaXMgb24gdGhlIGZpcnN0IGZvY3VzYWJsZSBlbGVtZW50IGluIHRoZSBkcmF3ZXJcblx0XHRcdFx0XHRpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZmlyc3RGb2N1c2FibGVFbCkge1xuXHRcdFx0XHRcdFx0cHJvY2Vzc0FjdGlvbiA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHQvLyB0YWIgcHJlc3NlZFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIGlmIHVzZXIgaXMgb24gdGhlIGxhc3QgZm9jdXNhYmxlIGVsZW1lbnQgaW4gdGhlIGRyYXdlclxuXHRcdFx0XHRcdGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSBsYXN0Rm9jdXNhYmxlRWwpIHtcblx0XHRcdFx0XHRcdHByb2Nlc3NBY3Rpb24gPSB0cnVlO1xuXHRcdFx0XHRcdFx0Y2hhbmdlRm9jdXMgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIHJ1biBhZGRpdGlvbmFsIGNvZGUgdG8gY2xvc2UgZHJhd2VycyBvciBmb2N1cyBvbiBwYXJlbnQgZWxlbWVudFxuXHRcdFx0XHRpZiAoIHByb2Nlc3NBY3Rpb24gKSB7XG5cdFx0XHRcdFx0Ly8gY2xvc2UgYWxsIGRyYXdlcnNcblx0XHRcdFx0XHRzZWxmLmNsb3NlQWxsRHJhd2VycygpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggY2hhbmdlRm9jdXMgKSB7XG5cdFx0XHRcdFx0Ly8gZm9jdXMgb24gcGFyZW50IGVsZW1lbnRcblx0XHRcdFx0XHRzZWxmLmZvY3VzT25QYXJlbnQoY29udGFpbmVyRWxlbWVudCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG5cblxuXHQvKipcblx0ICogQHN1bW1hcnkgSGVscGVyIHRvIHJlbW92ZSBhbmQgYWRkIGEgY2xhc3Ncblx0ICpcblx0ICogQHBhcmFtICB7b2JqZWN0fSBlbGVtZW50ICAgICBET00gZWxlbWVudFxuXHQgKiBAcGFyYW0gIHtzdHJpbmd9IGFkZENsYXNzICAgIENsYXNzIG5hbWUgdG8gYWRkIHRvIGVsZW1lbnRcblx0ICogQHBhcmFtICB7c3RyaW5nfSByZW1vdmVDbGFzcyBDbGFzcyBuYW1lIHRvIHJlbW92ZSBmcm9tIGVsZW1lbnRcblx0ICogXG5cdCAqIEByZXR1cm4ge3ZvaWR9XG5cdCAqL1xuXHR0b2dnbGVFbGVtZW50Q2xhc3NlcyhlbGVtZW50LCBhZGRDbGFzcywgcmVtb3ZlQ2xhc3MpIHtcblx0XHRlbGVtZW50Py5jbGFzc0xpc3Q/LnJlbW92ZShyZW1vdmVDbGFzcyk7XG5cdFx0ZWxlbWVudD8uY2xhc3NMaXN0Py5hZGQoYWRkQ2xhc3MpO1xuXHR9XG5cblxuXHQvKipcblx0ICogQHN1bW1hcnkgSGVscGVyIHRvIGFkanVzdCBmb2N1cyB3aXRoIFBpYW5vIGlmcmFtZXNcblx0ICpcblx0ICogQGRlc2NyaXB0aW9uIFRoaXMgaXMgbmVlZGVkIGFzIGEgd29ya2Fyb3VuZCBmb3IgdGhlIGlmcmFtZSBmb2N1cyBpc3N1ZVxuXHQgKiBcblx0ICogQHJldHVybiB7dm9pZH1cblx0ICovXG5cdG9ic2VydmVQaWFub0lmcmFtZXMoKSB7XG5cdFx0Ly8gT3B0aW9ucyBmb3IgdGhlIG9ic2VydmVyICh3aGljaCBtdXRhdGlvbnMgdG8gb2JzZXJ2ZSlcblx0XHRjb25zdCBjb25maWcgPSB7XG5cdFx0XHRhdHRyaWJ1dGVzOiBmYWxzZSxcblx0XHRcdGNoaWxkTGlzdDogdHJ1ZSxcblx0XHRcdHN1YnRyZWU6IHRydWVcblx0XHR9O1xuXG5cdFx0Ly8gQ2FsbGJhY2sgZnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIG11dGF0aW9ucyBhcmUgb2JzZXJ2ZWRcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcblx0XHRjb25zdCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKG11dGF0aW9ucyA9PiB7XG5cdFx0XHRtdXRhdGlvbnMuZm9yRWFjaChtdXRhdGlvbiA9PiB7XG5cdFx0XHRcdC8vIExvb3BpbmcgdGhyb3VnaCBhbGwgYWRkZWQgbm9kZXNcblx0XHRcdFx0bXV0YXRpb24uYWRkZWROb2Rlcy5mb3JFYWNoKG5vZGUgPT4ge1xuXHRcdFx0XHRcdGlmIChub2RlIGluc3RhbmNlb2YgRWxlbWVudCAmJiBub2RlLm1hdGNoZXMoJ2lmcmFtZScpKSB7XG5cdFx0XHRcdFx0XHQvLyBJZiB0aGUgYWRkZWQgbm9kZSBtYXRjaGVzIHRoZSBzZWxlY3RvciwgZXhlY3V0ZSB0aGUgY2FsbGJhY2sgYW5kIGRpc2Nvbm5lY3QgdGhlIG9ic2VydmVyXG5cdFx0XHRcdFx0XHRpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnRwLWNsb3NlJykpIHtcblx0XHRcdFx0XHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnRwLWNsb3NlJykuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRsZXQgbG9naW5FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLkZQLXBheXdhbGwtLWxvZ2luJyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAobG9naW5FbGVtZW50KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGxvZ2luRWxlbWVudC5mb2N1cygpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0sIDc1MCk7XG5cdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Ly9vYnNlcnZlci5kaXNjb25uZWN0KCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXG5cdFx0Ly8gU3RhcnQgb2JzZXJ2aW5nIHRoZSB0YXJnZXQgbm9kZSBmb3IgY29uZmlndXJlZCBtdXRhdGlvbnNcblx0XHRvYnNlcnZlci5vYnNlcnZlKGRvY3VtZW50LCBjb25maWcpO1xuXHR9XG5cbn1cblxud2luZG93LkZQTmF2ID0gbmV3IEZQTmF2KCk7XG53aW5kb3cuRlBOYXYuaW5pdCgpO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///../assets/src/scripts/components/navigation/navigation.js\n\n}")},"./node_modules/@babel/runtime/helpers/esm/classCallCheck.js"(__unused_webpack___webpack_module__,__webpack_exports__,__webpack_require__){eval('{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ _classCallCheck)\n/* harmony export */ });\nfunction _classCallCheck(a, n) {\n if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY2xhc3NDYWxsQ2hlY2suanMiLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2ZvcmVpZ25wb2xpY3ktYnVpbGQvLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY2xhc3NDYWxsQ2hlY2suanM/Njk1MiJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soYSwgbikge1xuICBpZiAoIShhIGluc3RhbmNlb2YgbikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7XG59XG5leHBvcnQgeyBfY2xhc3NDYWxsQ2hlY2sgYXMgZGVmYXVsdCB9OyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/classCallCheck.js\n\n}')},"./node_modules/@babel/runtime/helpers/esm/createClass.js"(__unused_webpack___webpack_module__,__webpack_exports__,__webpack_require__){eval('{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ _createClass)\n/* harmony export */ });\n/* harmony import */ var _toPropertyKey_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./toPropertyKey.js */ "./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js");\n\nfunction _defineProperties(e, r) {\n for (var t = 0; t < r.length; t++) {\n var o = r[t];\n o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, (0,_toPropertyKey_js__WEBPACK_IMPORTED_MODULE_0__["default"])(o.key), o);\n }\n}\nfunction _createClass(e, r, t) {\n return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {\n writable: !1\n }), e;\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY3JlYXRlQ2xhc3MuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9mb3JlaWducG9saWN5LWJ1aWxkLy4vbm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvZXNtL2NyZWF0ZUNsYXNzLmpzPzlhMzYiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRvUHJvcGVydHlLZXkgZnJvbSBcIi4vdG9Qcm9wZXJ0eUtleS5qc1wiO1xuZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMoZSwgcikge1xuICBmb3IgKHZhciB0ID0gMDsgdCA8IHIubGVuZ3RoOyB0KyspIHtcbiAgICB2YXIgbyA9IHJbdF07XG4gICAgby5lbnVtZXJhYmxlID0gby5lbnVtZXJhYmxlIHx8ICExLCBvLmNvbmZpZ3VyYWJsZSA9ICEwLCBcInZhbHVlXCIgaW4gbyAmJiAoby53cml0YWJsZSA9ICEwKSwgT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsIHRvUHJvcGVydHlLZXkoby5rZXkpLCBvKTtcbiAgfVxufVxuZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKGUsIHIsIHQpIHtcbiAgcmV0dXJuIHIgJiYgX2RlZmluZVByb3BlcnRpZXMoZS5wcm90b3R5cGUsIHIpLCB0ICYmIF9kZWZpbmVQcm9wZXJ0aWVzKGUsIHQpLCBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgXCJwcm90b3R5cGVcIiwge1xuICAgIHdyaXRhYmxlOiAhMVxuICB9KSwgZTtcbn1cbmV4cG9ydCB7IF9jcmVhdGVDbGFzcyBhcyBkZWZhdWx0IH07Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/createClass.js\n\n}')},"./node_modules/@babel/runtime/helpers/esm/toPrimitive.js"(__unused_webpack___webpack_module__,__webpack_exports__,__webpack_require__){eval('{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ toPrimitive)\n/* harmony export */ });\n/* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js");\n\nfunction toPrimitive(t, r) {\n if ("object" != (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(t) || !t) return t;\n var e = t[Symbol.toPrimitive];\n if (void 0 !== e) {\n var i = e.call(t, r || "default");\n if ("object" != (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i)) return i;\n throw new TypeError("@@toPrimitive must return a primitive value.");\n }\n return ("string" === r ? String : Number)(t);\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vdG9QcmltaXRpdmUuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vZm9yZWlnbnBvbGljeS1idWlsZC8uL25vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL2VzbS90b1ByaW1pdGl2ZS5qcz9lNWEzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfdHlwZW9mIGZyb20gXCIuL3R5cGVvZi5qc1wiO1xuZnVuY3Rpb24gdG9QcmltaXRpdmUodCwgcikge1xuICBpZiAoXCJvYmplY3RcIiAhPSBfdHlwZW9mKHQpIHx8ICF0KSByZXR1cm4gdDtcbiAgdmFyIGUgPSB0W1N5bWJvbC50b1ByaW1pdGl2ZV07XG4gIGlmICh2b2lkIDAgIT09IGUpIHtcbiAgICB2YXIgaSA9IGUuY2FsbCh0LCByIHx8IFwiZGVmYXVsdFwiKTtcbiAgICBpZiAoXCJvYmplY3RcIiAhPSBfdHlwZW9mKGkpKSByZXR1cm4gaTtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQEB0b1ByaW1pdGl2ZSBtdXN0IHJldHVybiBhIHByaW1pdGl2ZSB2YWx1ZS5cIik7XG4gIH1cbiAgcmV0dXJuIChcInN0cmluZ1wiID09PSByID8gU3RyaW5nIDogTnVtYmVyKSh0KTtcbn1cbmV4cG9ydCB7IHRvUHJpbWl0aXZlIGFzIGRlZmF1bHQgfTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/toPrimitive.js\n\n}')},"./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js"(__unused_webpack___webpack_module__,__webpack_exports__,__webpack_require__){eval('{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ toPropertyKey)\n/* harmony export */ });\n/* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js");\n/* harmony import */ var _toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./toPrimitive.js */ "./node_modules/@babel/runtime/helpers/esm/toPrimitive.js");\n\n\nfunction toPropertyKey(t) {\n var i = (0,_toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__["default"])(t, "string");\n return "symbol" == (0,_typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i) ? i : i + "";\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vdG9Qcm9wZXJ0eUtleS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9mb3JlaWducG9saWN5LWJ1aWxkLy4vbm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvZXNtL3RvUHJvcGVydHlLZXkuanM/NGEyZCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgX3R5cGVvZiBmcm9tIFwiLi90eXBlb2YuanNcIjtcbmltcG9ydCB0b1ByaW1pdGl2ZSBmcm9tIFwiLi90b1ByaW1pdGl2ZS5qc1wiO1xuZnVuY3Rpb24gdG9Qcm9wZXJ0eUtleSh0KSB7XG4gIHZhciBpID0gdG9QcmltaXRpdmUodCwgXCJzdHJpbmdcIik7XG4gIHJldHVybiBcInN5bWJvbFwiID09IF90eXBlb2YoaSkgPyBpIDogaSArIFwiXCI7XG59XG5leHBvcnQgeyB0b1Byb3BlcnR5S2V5IGFzIGRlZmF1bHQgfTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/toPropertyKey.js\n\n}')},"./node_modules/@babel/runtime/helpers/esm/typeof.js"(__unused_webpack___webpack_module__,__webpack_exports__,__webpack_require__){eval('{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ _typeof)\n/* harmony export */ });\nfunction _typeof(o) {\n "@babel/helpers - typeof";\n\n return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;\n }, _typeof(o);\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vdHlwZW9mLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9mb3JlaWducG9saWN5LWJ1aWxkLy4vbm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvZXNtL3R5cGVvZi5qcz80YmY1Il0sInNvdXJjZXNDb250ZW50IjpbImZ1bmN0aW9uIF90eXBlb2Yobykge1xuICBcIkBiYWJlbC9oZWxwZXJzIC0gdHlwZW9mXCI7XG5cbiAgcmV0dXJuIF90eXBlb2YgPSBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBcInN5bWJvbFwiID09IHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPyBmdW5jdGlvbiAobykge1xuICAgIHJldHVybiB0eXBlb2YgbztcbiAgfSA6IGZ1bmN0aW9uIChvKSB7XG4gICAgcmV0dXJuIG8gJiYgXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgby5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG8gIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG87XG4gIH0sIF90eXBlb2Yobyk7XG59XG5leHBvcnQgeyBfdHlwZW9mIGFzIGRlZmF1bHQgfTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/typeof.js\n\n}')}},__webpack_module_cache__={};function __webpack_require__(e){var c=__webpack_module_cache__[e];if(void 0!==c)return c.exports;var n=__webpack_module_cache__[e]={exports:{}};if(!(e in __webpack_modules__)){delete __webpack_module_cache__[e];var d=new Error("Cannot find module '"+e+"'");throw d.code="MODULE_NOT_FOUND",d}return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,c)=>{for(var n in c)__webpack_require__.o(c,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:c[n]})},__webpack_require__.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("../assets/src/scripts/components/navigation/navigation.js")})();; (()=>{var __webpack_modules__={"../assets/src/scripts/components/navigation/navigation-skip-links.js"(){eval("{/**\n * Helper function to check if a given element is focusable.\n * @param {Element} el - The element to check for focusability.\n * @returns {boolean} - Returns true if the element is focusable, false otherwise.\n */\nvar isFocusable = function isFocusable(el) {\n // Get the tag name of the element and convert it to lowercase\n var tagName = el.tagName.toLowerCase();\n // Check if the tag name is one of the focusable elements\n return /^(a|input|select|textarea|button|object)$/.test(tagName) || el.hasAttribute('tabindex');\n};\n\n// Scroll to an element on the page and focus on it if it's focusable\n/**\n * Smoothly scroll to a target element on the page and set focus to it if it's focusable.\n * @param {string} element - The selector of the target element to scroll to.\n * @param {number} [duration=200] - The duration of the scroll animation in milliseconds.\n */\nfunction scrollToFocus(element) {\n var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;\n // Find the target element using the given selector\n var target = document.querySelector(element);\n\n // Check if the target element is focusable\n var focusableElement = isFocusable(target);\n\n // Handle search input as a target differently for mobile and desktop\n if (element === '#search') {\n target = window.innerWidth < 980 ? document.querySelector('#searchform-site-nav-menu-search-input') : document.querySelector('a.site-nav-search-button.icon.js-drawer-search-button');\n }\n if (element === '#navigation' && window.innerWidth < 980) {\n target = document.querySelector('.nav-full-menu__content');\n }\n var startPosition = window.pageYOffset;\n var targetPosition = target.getBoundingClientRect().top - 100;\n var startTime = performance.now();\n\n // Scroll the window smoothly to the target position\n var _scroll = function scroll(currentTime) {\n var elapsedTime = currentTime - startTime;\n var easing = easeInOutQuad(elapsedTime, startPosition, targetPosition, duration);\n window.scrollTo(0, easing);\n if (elapsedTime < duration) {\n requestAnimationFrame(_scroll);\n }\n };\n\n // Easing function for smooth scrolling\n function easeInOutQuad(t, b, c, d) {\n t /= d / 2;\n if (t < 1) return c / 2 * t * t + b;\n t--;\n return -c / 2 * (t * (t - 2) - 1) + b;\n }\n requestAnimationFrame(_scroll);\n\n // Make the target element focusable and set focus to it\n if (!focusableElement) {\n target.setAttribute('tabindex', '-1');\n target.addEventListener('onfocusout', function () {\n target.removeAttribute('tabindex');\n });\n }\n setTimeout(function () {\n target.focus();\n // if (!focusableElement) {\n // \ttarget.removeAttribute('tabindex');\n // \ttarget.blur();\n // }\n }, duration);\n}\n\n// Handle skip link events\nvar skipLinkEvent = function skipLinkEvent(event) {\n event.preventDefault();\n var targetId = event.currentTarget.getAttribute('href');\n\n // If the target is the search or navigation element, trigger the hamburger button click for mobile\n if (targetId === '#search' && window.innerWidth < 980 || targetId === '#navigation' && window.innerWidth < 980) {\n document.querySelector('.navbar-hamburger-button').click();\n }\n\n // Show the close menu button and add an event listener to it\n var closeMenuButton = document.querySelector('.close-menu-button');\n if (closeMenuButton) {\n closeMenuButton.style.display = 'block';\n closeMenuButton.style.zIndex = '999999';\n closeMenuButton.addEventListener('click', function () {\n closeMenuButton.style.display = 'none';\n closeMenuButton.style.zIndex = '-1';\n closeMenu();\n });\n }\n\n // Smooth scroll to the target element\n scrollToFocus(targetId);\n};\n\n// Close the menu and reset its elements\nvar closeMenu = function closeMenu() {\n var headerNavWrapper = document.querySelector('.header-nav-wrapper');\n if (headerNavWrapper.style.display === 'none' || headerNavWrapper.style.visibility === 'hidden') return;\n var hamburgerButton = document.querySelector('.hamburger-button');\n var elsNoScroll = document.querySelectorAll('.post-content, .grid--container');\n var headerNav = document.querySelector('.header-nav');\n //const headerNavNestedMenu = document.querySelector('.header-nav-nested-menu');\n var closeNav = document.querySelector('.close-menu-button');\n headerNavWrapper.style.display = 'none';\n hamburgerButton.classList.remove('mobile-nav-open');\n document.querySelectorAll('.header-subnav-wrapper').forEach(function (el) {\n return el.style.display = 'block';\n });\n document.querySelectorAll('.nav-menu__item').forEach(function (el) {\n return el.classList.remove('open');\n });\n //headerNavNestedMenu.style.display = 'none';\n headerNav.style.display = '';\n closeNav.style.display = 'none';\n document.body.classList.remove('overlay-no-scroll');\n elsNoScroll.forEach(function (el) {\n el.classList.remove('overlay-no-scroll');\n el.removeAttribute('style');\n });\n};\n// Add event listeners to skip links\ndocument.addEventListener('DOMContentLoaded', function () {\n var skipLinks = document.querySelectorAll('.skip-link');\n skipLinks.forEach(function (skipLink) {\n skipLink.addEventListener('focus', function () {\n this.style.opacity = '1';\n this.style.zIndex = '999999999';\n });\n skipLink.addEventListener('blur', function () {\n this.style.opacity = '0';\n this.style.zIndex = '-1';\n });\n skipLink.addEventListener('click', function (event) {\n return skipLinkEvent(event);\n });\n skipLink.addEventListener('keydown', function (event) {\n // Check if the key pressed is the Enter key.\n if (event.key === 'Enter') {\n skipLinkEvent(event);\n }\n });\n });\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vYXNzZXRzL3NyYy9zY3JpcHRzL2NvbXBvbmVudHMvbmF2aWdhdGlvbi9uYXZpZ2F0aW9uLXNraXAtbGlua3MuanMiLCJuYW1lcyI6WyJpc0ZvY3VzYWJsZSIsImVsIiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwidGVzdCIsImhhc0F0dHJpYnV0ZSIsInNjcm9sbFRvRm9jdXMiLCJlbGVtZW50IiwiZHVyYXRpb24iLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJ1bmRlZmluZWQiLCJ0YXJnZXQiLCJkb2N1bWVudCIsInF1ZXJ5U2VsZWN0b3IiLCJmb2N1c2FibGVFbGVtZW50Iiwid2luZG93IiwiaW5uZXJXaWR0aCIsInN0YXJ0UG9zaXRpb24iLCJwYWdlWU9mZnNldCIsInRhcmdldFBvc2l0aW9uIiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwidG9wIiwic3RhcnRUaW1lIiwicGVyZm9ybWFuY2UiLCJub3ciLCJzY3JvbGwiLCJjdXJyZW50VGltZSIsImVsYXBzZWRUaW1lIiwiZWFzaW5nIiwiZWFzZUluT3V0UXVhZCIsInNjcm9sbFRvIiwicmVxdWVzdEFuaW1hdGlvbkZyYW1lIiwidCIsImIiLCJjIiwiZCIsInNldEF0dHJpYnV0ZSIsImFkZEV2ZW50TGlzdGVuZXIiLCJyZW1vdmVBdHRyaWJ1dGUiLCJzZXRUaW1lb3V0IiwiZm9jdXMiLCJza2lwTGlua0V2ZW50IiwiZXZlbnQiLCJwcmV2ZW50RGVmYXVsdCIsInRhcmdldElkIiwiY3VycmVudFRhcmdldCIsImdldEF0dHJpYnV0ZSIsImNsaWNrIiwiY2xvc2VNZW51QnV0dG9uIiwic3R5bGUiLCJkaXNwbGF5IiwiekluZGV4IiwiY2xvc2VNZW51IiwiaGVhZGVyTmF2V3JhcHBlciIsInZpc2liaWxpdHkiLCJoYW1idXJnZXJCdXR0b24iLCJlbHNOb1Njcm9sbCIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJoZWFkZXJOYXYiLCJjbG9zZU5hdiIsImNsYXNzTGlzdCIsInJlbW92ZSIsImZvckVhY2giLCJib2R5Iiwic2tpcExpbmtzIiwic2tpcExpbmsiLCJvcGFjaXR5Iiwia2V5Il0sInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9mb3JlaWducG9saWN5LWJ1aWxkLy4uL2Fzc2V0cy9zcmMvc2NyaXB0cy9jb21wb25lbnRzL25hdmlnYXRpb24vbmF2aWdhdGlvbi1za2lwLWxpbmtzLmpzPzAzODYiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgaWYgYSBnaXZlbiBlbGVtZW50IGlzIGZvY3VzYWJsZS5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWwgLSBUaGUgZWxlbWVudCB0byBjaGVjayBmb3IgZm9jdXNhYmlsaXR5LlxuICogQHJldHVybnMge2Jvb2xlYW59IC0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IGlzIGZvY3VzYWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5jb25zdCBpc0ZvY3VzYWJsZSA9IChlbCkgPT4ge1xuXHQvLyBHZXQgdGhlIHRhZyBuYW1lIG9mIHRoZSBlbGVtZW50IGFuZCBjb252ZXJ0IGl0IHRvIGxvd2VyY2FzZVxuXHRjb25zdCB0YWdOYW1lID0gZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHQvLyBDaGVjayBpZiB0aGUgdGFnIG5hbWUgaXMgb25lIG9mIHRoZSBmb2N1c2FibGUgZWxlbWVudHNcblx0cmV0dXJuIC9eKGF8aW5wdXR8c2VsZWN0fHRleHRhcmVhfGJ1dHRvbnxvYmplY3QpJC8udGVzdCh0YWdOYW1lKSB8fCBlbC5oYXNBdHRyaWJ1dGUoJ3RhYmluZGV4Jyk7XG59O1xuXG4vLyBTY3JvbGwgdG8gYW4gZWxlbWVudCBvbiB0aGUgcGFnZSBhbmQgZm9jdXMgb24gaXQgaWYgaXQncyBmb2N1c2FibGVcbi8qKlxuICogU21vb3RobHkgc2Nyb2xsIHRvIGEgdGFyZ2V0IGVsZW1lbnQgb24gdGhlIHBhZ2UgYW5kIHNldCBmb2N1cyB0byBpdCBpZiBpdCdzIGZvY3VzYWJsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBlbGVtZW50IC0gVGhlIHNlbGVjdG9yIG9mIHRoZSB0YXJnZXQgZWxlbWVudCB0byBzY3JvbGwgdG8uXG4gKiBAcGFyYW0ge251bWJlcn0gW2R1cmF0aW9uPTIwMF0gLSBUaGUgZHVyYXRpb24gb2YgdGhlIHNjcm9sbCBhbmltYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICovXG5mdW5jdGlvbiBzY3JvbGxUb0ZvY3VzKGVsZW1lbnQsIGR1cmF0aW9uID0gMjAwKSB7XG5cdC8vIEZpbmQgdGhlIHRhcmdldCBlbGVtZW50IHVzaW5nIHRoZSBnaXZlbiBzZWxlY3RvclxuXHRsZXQgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihlbGVtZW50KTtcblxuXHQvLyBDaGVjayBpZiB0aGUgdGFyZ2V0IGVsZW1lbnQgaXMgZm9jdXNhYmxlXG5cdGNvbnN0IGZvY3VzYWJsZUVsZW1lbnQgPSBpc0ZvY3VzYWJsZSh0YXJnZXQpO1xuXG5cdC8vIEhhbmRsZSBzZWFyY2ggaW5wdXQgYXMgYSB0YXJnZXQgZGlmZmVyZW50bHkgZm9yIG1vYmlsZSBhbmQgZGVza3RvcFxuXHRpZiAoZWxlbWVudCA9PT0gJyNzZWFyY2gnKSB7XG5cdFx0dGFyZ2V0ID0gd2luZG93LmlubmVyV2lkdGggPCA5ODAgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjc2VhcmNoZm9ybS1zaXRlLW5hdi1tZW51LXNlYXJjaC1pbnB1dCcpIDogZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYS5zaXRlLW5hdi1zZWFyY2gtYnV0dG9uLmljb24uanMtZHJhd2VyLXNlYXJjaC1idXR0b24nKTtcblx0fVxuXG5cdGlmIChlbGVtZW50ID09PSAnI25hdmlnYXRpb24nICYmIHdpbmRvdy5pbm5lcldpZHRoIDwgOTgwKSB7XG5cdFx0dGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm5hdi1mdWxsLW1lbnVfX2NvbnRlbnQnKTtcblx0fVxuXG5cdGNvbnN0IHN0YXJ0UG9zaXRpb24gPSB3aW5kb3cucGFnZVlPZmZzZXQ7XG5cdGNvbnN0IHRhcmdldFBvc2l0aW9uID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtIDEwMDtcblx0Y29uc3Qgc3RhcnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG5cblx0Ly8gU2Nyb2xsIHRoZSB3aW5kb3cgc21vb3RobHkgdG8gdGhlIHRhcmdldCBwb3NpdGlvblxuXHRjb25zdCBzY3JvbGwgPSBjdXJyZW50VGltZSA9PiB7XG5cdFx0Y29uc3QgZWxhcHNlZFRpbWUgPSBjdXJyZW50VGltZSAtIHN0YXJ0VGltZTtcblx0XHRjb25zdCBlYXNpbmcgPSBlYXNlSW5PdXRRdWFkKGVsYXBzZWRUaW1lLCBzdGFydFBvc2l0aW9uLCB0YXJnZXRQb3NpdGlvbiwgZHVyYXRpb24pO1xuXG5cdFx0d2luZG93LnNjcm9sbFRvKDAsIGVhc2luZyk7XG5cblx0XHRpZiAoZWxhcHNlZFRpbWUgPCBkdXJhdGlvbikge1xuXHRcdFx0cmVxdWVzdEFuaW1hdGlvbkZyYW1lKHNjcm9sbCk7XG5cdFx0fVxuXHR9O1xuXG5cdC8vIEVhc2luZyBmdW5jdGlvbiBmb3Igc21vb3RoIHNjcm9sbGluZ1xuXHRmdW5jdGlvbiBlYXNlSW5PdXRRdWFkKHQsIGIsIGMsIGQpIHtcblx0XHR0IC89IGQgLyAyO1xuXHRcdGlmICh0IDwgMSkgcmV0dXJuIChjIC8gMikgKiB0ICogdCArIGI7XG5cdFx0dC0tO1xuXHRcdHJldHVybiAoLWMgLyAyKSAqICh0ICogKHQgLSAyKSAtIDEpICsgYjtcblx0fVxuXHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc2Nyb2xsKTtcblxuXHQvLyBNYWtlIHRoZSB0YXJnZXQgZWxlbWVudCBmb2N1c2FibGUgYW5kIHNldCBmb2N1cyB0byBpdFxuXHRpZiAoIWZvY3VzYWJsZUVsZW1lbnQpIHtcblx0XHR0YXJnZXQuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICctMScpO1xuXHRcdHRhcmdldC5hZGRFdmVudExpc3RlbmVyKCdvbmZvY3Vzb3V0JywgKCkgPT4ge1xuXHRcdFx0dGFyZ2V0LnJlbW92ZUF0dHJpYnV0ZSgndGFiaW5kZXgnKTtcblx0XHR9KTtcblx0fVxuXG5cdHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdHRhcmdldC5mb2N1cygpO1xuXHRcdC8vIGlmICghZm9jdXNhYmxlRWxlbWVudCkge1xuXHRcdC8vIFx0dGFyZ2V0LnJlbW92ZUF0dHJpYnV0ZSgndGFiaW5kZXgnKTtcblx0XHQvLyBcdHRhcmdldC5ibHVyKCk7XG5cdFx0Ly8gfVxuXHR9LCBkdXJhdGlvbik7XG59XG5cbi8vIEhhbmRsZSBza2lwIGxpbmsgZXZlbnRzXG5jb25zdCBza2lwTGlua0V2ZW50ID0gKGV2ZW50KSA9PiB7XG5cdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdGNvbnN0IHRhcmdldElkID0gZXZlbnQuY3VycmVudFRhcmdldC5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTtcblxuXHQvLyBJZiB0aGUgdGFyZ2V0IGlzIHRoZSBzZWFyY2ggb3IgbmF2aWdhdGlvbiBlbGVtZW50LCB0cmlnZ2VyIHRoZSBoYW1idXJnZXIgYnV0dG9uIGNsaWNrIGZvciBtb2JpbGVcblx0aWYgKCh0YXJnZXRJZCA9PT0gJyNzZWFyY2gnICYmIHdpbmRvdy5pbm5lcldpZHRoIDwgOTgwKSB8fCAodGFyZ2V0SWQgPT09ICcjbmF2aWdhdGlvbicgJiYgd2luZG93LmlubmVyV2lkdGggPCA5ODApKSB7XG5cdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm5hdmJhci1oYW1idXJnZXItYnV0dG9uJykuY2xpY2soKTtcblx0fVxuXG5cdC8vIFNob3cgdGhlIGNsb3NlIG1lbnUgYnV0dG9uIGFuZCBhZGQgYW4gZXZlbnQgbGlzdGVuZXIgdG8gaXRcblx0Y29uc3QgY2xvc2VNZW51QnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmNsb3NlLW1lbnUtYnV0dG9uJyk7XG5cdGlmIChjbG9zZU1lbnVCdXR0b24pIHtcblx0XHRjbG9zZU1lbnVCdXR0b24uc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG5cdFx0Y2xvc2VNZW51QnV0dG9uLnN0eWxlLnpJbmRleCA9ICc5OTk5OTknO1xuXHRcdGNsb3NlTWVudUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcblx0XHRcdGNsb3NlTWVudUJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXHRcdFx0Y2xvc2VNZW51QnV0dG9uLnN0eWxlLnpJbmRleCA9ICctMSc7XG5cdFx0XHRjbG9zZU1lbnUoKTtcblx0XHR9KTtcblx0fVxuXG5cdC8vIFNtb290aCBzY3JvbGwgdG8gdGhlIHRhcmdldCBlbGVtZW50XG5cdHNjcm9sbFRvRm9jdXModGFyZ2V0SWQpO1xufTtcblxuLy8gQ2xvc2UgdGhlIG1lbnUgYW5kIHJlc2V0IGl0cyBlbGVtZW50c1xuY29uc3QgY2xvc2VNZW51ID0gKCkgPT4ge1xuXHRjb25zdCBoZWFkZXJOYXZXcmFwcGVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmhlYWRlci1uYXYtd3JhcHBlcicpO1xuXHRpZiAoaGVhZGVyTmF2V3JhcHBlci5zdHlsZS5kaXNwbGF5ID09PSAnbm9uZScgfHwgaGVhZGVyTmF2V3JhcHBlci5zdHlsZS52aXNpYmlsaXR5ID09PSAnaGlkZGVuJykgcmV0dXJuO1xuXG5cdGNvbnN0IGhhbWJ1cmdlckJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5oYW1idXJnZXItYnV0dG9uJyk7XG5cdGNvbnN0IGVsc05vU2Nyb2xsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnBvc3QtY29udGVudCwgLmdyaWQtLWNvbnRhaW5lcicpO1xuXHRjb25zdCBoZWFkZXJOYXYgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaGVhZGVyLW5hdicpO1xuXHQvL2NvbnN0IGhlYWRlck5hdk5lc3RlZE1lbnUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaGVhZGVyLW5hdi1uZXN0ZWQtbWVudScpO1xuXHRjb25zdCBjbG9zZU5hdiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5jbG9zZS1tZW51LWJ1dHRvbicpO1xuXG5cdGhlYWRlck5hdldyYXBwZXIuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblx0aGFtYnVyZ2VyQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoJ21vYmlsZS1uYXYtb3BlbicpO1xuXHRkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuaGVhZGVyLXN1Ym5hdi13cmFwcGVyJykuZm9yRWFjaChlbCA9PiBlbC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJyk7XG5cdGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5uYXYtbWVudV9faXRlbScpLmZvckVhY2goZWwgPT4gZWwuY2xhc3NMaXN0LnJlbW92ZSgnb3BlbicpKTtcblx0Ly9oZWFkZXJOYXZOZXN0ZWRNZW51LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdGhlYWRlck5hdi5zdHlsZS5kaXNwbGF5ID0gJyc7XG5cdGNsb3NlTmF2LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cdGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnb3ZlcmxheS1uby1zY3JvbGwnKTtcblx0ZWxzTm9TY3JvbGwuZm9yRWFjaChlbCA9PiB7XG5cdFx0ZWwuY2xhc3NMaXN0LnJlbW92ZSgnb3ZlcmxheS1uby1zY3JvbGwnKTtcblx0XHRlbC5yZW1vdmVBdHRyaWJ1dGUoJ3N0eWxlJyk7XG5cdH0pO1xufTtcbi8vIEFkZCBldmVudCBsaXN0ZW5lcnMgdG8gc2tpcCBsaW5rc1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uICgpIHtcblxuXHRjb25zdCBza2lwTGlua3MgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuc2tpcC1saW5rJyk7XG5cblx0c2tpcExpbmtzLmZvckVhY2goc2tpcExpbmsgPT4ge1xuXHRcdHNraXBMaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0dGhpcy5zdHlsZS5vcGFjaXR5ID0gJzEnO1xuXHRcdFx0dGhpcy5zdHlsZS56SW5kZXggPSAnOTk5OTk5OTk5Jztcblx0XHR9KTtcblxuXHRcdHNraXBMaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHR0aGlzLnN0eWxlLm9wYWNpdHkgPSAnMCc7XG5cdFx0XHR0aGlzLnN0eWxlLnpJbmRleCA9ICctMSc7XG5cdFx0fSk7XG5cblx0XHRza2lwTGluay5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChldmVudCkgPT4gc2tpcExpbmtFdmVudChldmVudCkpO1xuXHRcdHNraXBMaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCAoZXZlbnQpID0+IHtcblx0XHRcdC8vIENoZWNrIGlmIHRoZSBrZXkgcHJlc3NlZCBpcyB0aGUgRW50ZXIga2V5LlxuXHRcdFx0aWYgKGV2ZW50LmtleSA9PT0gJ0VudGVyJykge1xuXHRcdFx0XHRza2lwTGlua0V2ZW50KGV2ZW50KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG59KTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQU1BLFdBQVcsR0FBRyxTQUFkQSxXQUFXQSxDQUFJQyxFQUFFLEVBQUs7RUFDM0I7RUFDQSxJQUFNQyxPQUFPLEdBQUdELEVBQUUsQ0FBQ0MsT0FBTyxDQUFDQyxXQUFXLENBQUMsQ0FBQztFQUN4QztFQUNBLE9BQU8sMkNBQTJDLENBQUNDLElBQUksQ0FBQ0YsT0FBTyxDQUFDLElBQUlELEVBQUUsQ0FBQ0ksWUFBWSxDQUFDLFVBQVUsQ0FBQztBQUNoRyxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNDLGFBQWFBLENBQUNDLE9BQU8sRUFBa0I7RUFBQSxJQUFoQkMsUUFBUSxHQUFBQyxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxHQUFHO0VBQzdDO0VBQ0EsSUFBSUcsTUFBTSxHQUFHQyxRQUFRLENBQUNDLGFBQWEsQ0FB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\n//# sourceURL=webpack-internal:///../assets/src/scripts/components/navigation/navigation-skip-links.js\n\n}")}},__webpack_exports__={};__webpack_modules__["../assets/src/scripts/components/navigation/navigation-skip-links.js"]()})();; (()=>{var __webpack_modules__={"../assets/src/scripts/components/navigation/navigation-subscribe-takeover.js"(){eval("{var _subscribeButtonClasses = '.site-header .subscribe-prompt, .subscribe-load-takeover, .fp-live__subscribe-trigger-modal';\nvar _subscribeTakeover = document.querySelector('#subscribe-takeover');\nvar _subscribeTakeoverIframe = document.querySelector('#subscribe-takeover-iframe');\nvar _subscribeTakeoverClose = document.querySelectorAll('.subscribe-takeover-close');\n\n/**\n * When clicking the Subscribe button in the top nav, suppress navigation link and\n * show full-screen overlay instead. \n */\nvar handleClick = function handleClick(e) {\n var _e$target$getAttribut;\n e.preventDefault();\n\n // Get iframe src and data-src values\n var iframeSrc = _subscribeTakeoverIframe.getAttribute('src');\n var dataSrc = (_e$target$getAttribut = e.target.getAttribute('data-modal-iframe-url')) !== null && _e$target$getAttribut !== void 0 ? _e$target$getAttribut : _subscribeTakeoverIframe.getAttribute('data-src');\n\n // Set iframe src if not already set or if it has changed \n // since the iframe was last displayed\n if (!iframeSrc || iframeSrc === 'data:text/html;charset=utf-8,' || iframeSrc !== dataSrc) {\n _subscribeTakeoverIframe.setAttribute('src', dataSrc);\n _subscribeTakeoverIframe.contentWindow.location.replace(dataSrc);\n }\n _subscribeTakeover.style.display = 'block';\n _subscribeTakeoverClose.forEach(function (button) {\n // Set close button as contentEditable to allow focus when tabbing\n button.contentEditable = true;\n });\n\n // Set focus to subscribe takeover\n _subscribeTakeover.focus();\n\n // set inert attribute\n FP.Utils.trapFocus.toggleInertAttribute(true);\n\n // close modal when user presses ESC key\n [_subscribeTakeoverIframe, _subscribeTakeover].forEach(function (element) {\n element.addEventListener('keydown', function (event) {\n if (event.key == 'Escape') {\n closeSubscribeModal();\n }\n });\n });\n\n // Take additional action once iframe has loaded\n _subscribeTakeoverIframe.addEventListener('load', function () {\n // Set focus to subscribe takeover\n _subscribeTakeover.focus();\n\n // Ensure subscribe takeover iframe is scrolled to top\n try {\n _subscribeTakeoverIframe.contentWindow.scrollTo({\n top: 0,\n left: 0,\n behavior: 'smooth'\n });\n\n // close modal when user presses ESC key\n _subscribeTakeoverIframe.contentWindow.document.addEventListener('keydown', function (event) {\n if (event.key == 'Escape') {\n closeSubscribeModal();\n }\n });\n } catch (error) {\n console.error(error);\n }\n });\n};\n\n// Hide the takeover on close button click/keydown\nfunction closeSubscribeModal() {\n // remove inert attribute\n FP.Utils.trapFocus.toggleInertAttribute(false);\n // hide takeover and set focus back to subscribe button\n _subscribeTakeover.style.display = 'none';\n\n // delay the following code to give the DOM time to update\n setTimeout(function () {\n // focus on parent window if focus is in iframe\n window.parent.focus();\n // set focus back to clicked button\n var expandedNavigationStyle = window.getComputedStyle(document.querySelector('#expanded-navigation'));\n if (expandedNavigationStyle && 'visible' === expandedNavigationStyle.visibility) {\n // if expanded nav is open, focus on the button in the expanded nav\n document.querySelectorAll('.site-header .subscribe-prompt')[1].focus();\n } else {\n // focus on the button in the sticky nav\n document.querySelectorAll('.site-header .subscribe-prompt')[0].focus();\n }\n }, 250);\n}\nfunction attachListeners() {\n // Attach event listener to each element matching the selector\n document.querySelectorAll(_subscribeButtonClasses).forEach(function (element) {\n // Remove any previously set event listeners\n element.removeEventListener('click', handleClick);\n\n // Add event listeners\n element.addEventListener('click', handleClick);\n element.addEventListener('keydown', function (event) {\n // Check if the key pressed is the Enter key.\n if (event.key === 'Enter') {\n handleClick(event);\n }\n });\n });\n}\nattachListeners();\nwindow.addEventListener('myfp:user-loaded', function () {\n // Listen for MyFP user loaded event\n // Give this an additional second to populate\n // the DOM with any subscribe prompts before\n // attaching new listeners\n setTimeout(function () {\n attachListeners();\n }, '1000');\n});\n\n// Attach event listener to close buttons\n_subscribeTakeoverClose.forEach(function (button) {\n button.addEventListener('click', function () {\n closeSubscribeModal();\n });\n button.addEventListener('keydown', function (event) {\n // Check if the key pressed is the Enter key.\n if (event.key === 'Enter') {\n closeSubscribeModal();\n }\n });\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vYXNzZXRzL3NyYy9zY3JpcHRzL2NvbXBvbmVudHMvbmF2aWdhdGlvbi9uYXZpZ2F0aW9uLXN1YnNjcmliZS10YWtlb3Zlci5qcyIsIm5hbWVzIjpbIl9zdWJzY3JpYmVCdXR0b25DbGFzc2VzIiwiX3N1YnNjcmliZVRha2VvdmVyIiwiZG9jdW1lbnQiLCJxdWVyeVNlbGVjdG9yIiwiX3N1YnNjcmliZVRha2VvdmVySWZyYW1lIiwiX3N1YnNjcmliZVRha2VvdmVyQ2xvc2UiLCJxdWVyeVNlbGVjdG9yQWxsIiwiaGFuZGxlQ2xpY2siLCJlIiwiX2UkdGFyZ2V0JGdldEF0dHJpYnV0IiwicHJldmVudERlZmF1bHQiLCJpZnJhbWVTcmMiLCJnZXRBdHRyaWJ1dGUiLCJkYXRhU3JjIiwidGFyZ2V0Iiwic2V0QXR0cmlidXRlIiwiY29udGVudFdpbmRvdyIsImxvY2F0aW9uIiwicmVwbGFjZSIsInN0eWxlIiwiZGlzcGxheSIsImZvckVhY2giLCJidXR0b24iLCJjb250ZW50RWRpdGFibGUiLCJmb2N1cyIsIkZQIiwiVXRpbHMiLCJ0cmFwRm9jdXMiLCJ0b2dnbGVJbmVydEF0dHJpYnV0ZSIsImVsZW1lbnQiLCJhZGRFdmVudExpc3RlbmVyIiwiZXZlbnQiLCJrZXkiLCJjbG9zZVN1YnNjcmliZU1vZGFsIiwic2Nyb2xsVG8iLCJ0b3AiLCJsZWZ0IiwiYmVoYXZpb3IiLCJlcnJvciIsImNvbnNvbGUiLCJzZXRUaW1lb3V0Iiwid2luZG93IiwicGFyZW50IiwiZXhwYW5kZWROYXZpZ2F0aW9uU3R5bGUiLCJnZXRDb21wdXRlZFN0eWxlIiwidmlzaWJpbGl0eSIsImF0dGFjaExpc3RlbmVycyIsInJlbW92ZUV2ZW50TGlzdGVuZXIiXSwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2VicGFjazovL2ZvcmVpZ25wb2xpY3ktYnVpbGQvLi4vYXNzZXRzL3NyYy9zY3JpcHRzL2NvbXBvbmVudHMvbmF2aWdhdGlvbi9uYXZpZ2F0aW9uLXN1YnNjcmliZS10YWtlb3Zlci5qcz8zZDlkIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IF9zdWJzY3JpYmVCdXR0b25DbGFzc2VzID0gJy5zaXRlLWhlYWRlciAuc3Vic2NyaWJlLXByb21wdCwgLnN1YnNjcmliZS1sb2FkLXRha2VvdmVyLCAuZnAtbGl2ZV9fc3Vic2NyaWJlLXRyaWdnZXItbW9kYWwnO1xuY29uc3QgX3N1YnNjcmliZVRha2VvdmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI3N1YnNjcmliZS10YWtlb3ZlcicpO1xuY29uc3QgX3N1YnNjcmliZVRha2VvdmVySWZyYW1lID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI3N1YnNjcmliZS10YWtlb3Zlci1pZnJhbWUnKTtcbmNvbnN0IF9zdWJzY3JpYmVUYWtlb3ZlckNsb3NlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnN1YnNjcmliZS10YWtlb3Zlci1jbG9zZScpO1xuXG4vKipcbiAqIFdoZW4gY2xpY2tpbmcgdGhlIFN1YnNjcmliZSBidXR0b24gaW4gdGhlIHRvcCBuYXYsIHN1cHByZXNzIG5hdmlnYXRpb24gbGluayBhbmRcbiAqIHNob3cgZnVsbC1zY3JlZW4gb3ZlcmxheSBpbnN0ZWFkLiBcbiAqL1xuY29uc3QgaGFuZGxlQ2xpY2sgPSBlID0+IHtcblx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcblx0Ly8gR2V0IGlmcmFtZSBzcmMgYW5kIGRhdGEtc3JjIHZhbHVlc1xuXHRsZXQgaWZyYW1lU3JjID0gX3N1YnNjcmliZVRha2VvdmVySWZyYW1lLmdldEF0dHJpYnV0ZSgnc3JjJyk7XG5cdGxldCBkYXRhU3JjID0gZS50YXJnZXQuZ2V0QXR0cmlidXRlKCdkYXRhLW1vZGFsLWlmcmFtZS11cmwnKSA/PyBfc3Vic2NyaWJlVGFrZW92ZXJJZnJhbWUuZ2V0QXR0cmlidXRlKCdkYXRhLXNyYycpO1xuXG5cdC8vIFNldCBpZnJhbWUgc3JjIGlmIG5vdCBhbHJlYWR5IHNldCBvciBpZiBpdCBoYXMgY2hhbmdlZCBcblx0Ly8gc2luY2UgdGhlIGlmcmFtZSB3YXMgbGFzdCBkaXNwbGF5ZWRcblx0aWYgKFxuXHRcdCFpZnJhbWVTcmMgXG5cdFx0fHwgaWZyYW1lU3JjID09PSAnZGF0YTp0ZXh0L2h0bWw7Y2hhcnNldD11dGYtOCwnIFxuXHRcdHx8IChpZnJhbWVTcmMgIT09IGRhdGFTcmMpXG5cdCkge1xuXHRcdF9zdWJzY3JpYmVUYWtlb3ZlcklmcmFtZS5zZXRBdHRyaWJ1dGUoJ3NyYycsIGRhdGFTcmMpO1xuXHRcdF9zdWJzY3JpYmVUYWtlb3ZlcklmcmFtZS5jb250ZW50V2luZG93LmxvY2F0aW9uLnJlcGxhY2UoZGF0YVNyYyk7XG5cdH1cblxuXHRfc3Vic2NyaWJlVGFrZW92ZXIuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG5cblx0X3N1YnNjcmliZVRha2VvdmVyQ2xvc2UuZm9yRWFjaChidXR0b24gPT4ge1xuXHRcdC8vIFNldCBjbG9zZSBidXR0b24gYXMgY29udGVudEVkaXRhYmxlIHRvIGFsbG93IGZvY3VzIHdoZW4gdGFiYmluZ1xuXHRcdGJ1dHRvbi5jb250ZW50RWRpdGFibGUgPSB0cnVlO1xuXHR9KTtcblxuXHQvLyBTZXQgZm9jdXMgdG8gc3Vic2NyaWJlIHRha2VvdmVyXG5cdF9zdWJzY3JpYmVUYWtlb3Zlci5mb2N1cygpO1xuXG5cdC8vIHNldCBpbmVydCBhdHRyaWJ1dGVcblx0RlAuVXRpbHMudHJhcEZvY3VzLnRvZ2dsZUluZXJ0QXR0cmlidXRlKHRydWUpO1xuXG5cdC8vIGNsb3NlIG1vZGFsIHdoZW4gdXNlciBwcmVzc2VzIEVTQyBrZXlcblx0W19zdWJzY3JpYmVUYWtlb3ZlcklmcmFtZSxfc3Vic2NyaWJlVGFrZW92ZXJdLmZvckVhY2goZWxlbWVudCA9PiB7XG5cdFx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRcdGlmIChldmVudC5rZXkgPT0gJ0VzY2FwZScpIHtcblx0XHRcdFx0Y2xvc2VTdWJzY3JpYmVNb2RhbCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcblx0XG5cdC8vIFRha2UgYWRkaXRpb25hbCBhY3Rpb24gb25jZSBpZnJhbWUgaGFzIGxvYWRlZFxuXHRfc3Vic2NyaWJlVGFrZW92ZXJJZnJhbWUuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGZ1bmN0aW9uKCkge1xuXHRcdC8vIFNldCBmb2N1cyB0byBzdWJzY3JpYmUgdGFrZW92ZXJcblx0XHRfc3Vic2NyaWJlVGFrZW92ZXIuZm9jdXMoKTtcblx0XHRcblx0XHQvLyBFbnN1cmUgc3Vic2NyaWJlIHRha2VvdmVyIGlmcmFtZSBpcyBzY3JvbGxlZCB0byB0b3Bcblx0XHR0cnkge1xuXHRcdFx0X3N1YnNjcmliZVRha2VvdmVySWZyYW1lLmNvbnRlbnRXaW5kb3cuc2Nyb2xsVG8oe1xuXHRcdFx0XHR0b3A6IDAsXG5cdFx0XHRcdGxlZnQ6IDAsXG5cdFx0XHRcdGJlaGF2aW9yOiAnc21vb3RoJ1xuXHRcdFx0fSk7XG5cblx0XHRcdC8vIGNsb3NlIG1vZGFsIHdoZW4gdXNlciBwcmVzc2VzIEVTQyBrZXlcblx0XHRcdF9zdWJzY3JpYmVUYWtlb3ZlcklmcmFtZS5jb250ZW50V2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRpZiAoZXZlbnQua2V5ID09ICdFc2NhcGUnKSB7XG5cdFx0XHRcdFx0Y2xvc2VTdWJzY3JpYmVNb2RhbCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0Y29uc29sZS5lcnJvcihlcnJvcik7XG5cdFx0fVxuXHR9KTtcbn07XG5cbi8vIEhpZGUgdGhlIHRha2VvdmVyIG9uIGNsb3NlIGJ1dHRvbiBjbGljay9rZXlkb3duXG5mdW5jdGlvbiBjbG9zZVN1YnNjcmliZU1vZGFsKCkge1xuXHQvLyByZW1vdmUgaW5lcnQgYXR0cmlidXRlXG5cdEZQLlV0aWxzLnRyYXBGb2N1cy50b2dnbGVJbmVydEF0dHJpYnV0ZShmYWxzZSk7XG5cdC8vIGhpZGUgdGFrZW92ZXIgYW5kIHNldCBmb2N1cyBiYWNrIHRvIHN1YnNjcmliZSBidXR0b25cblx0X3N1YnNjcmliZVRha2VvdmVyLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cblx0Ly8gZGVsYXkgdGhlIGZvbGxvd2luZyBjb2RlIHRvIGdpdmUgdGhlIERPTSB0aW1lIHRvIHVwZGF0ZVxuXHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHQvLyBmb2N1cyBvbiBwYXJlbnQgd2luZG93IGlmIGZvY3VzIGlzIGluIGlmcmFtZVxuXHRcdHdpbmRvdy5wYXJlbnQuZm9jdXMoKTtcblx0XHQvLyBzZXQgZm9jdXMgYmFjayB0byBjbGlja2VkIGJ1dHRvblxuXHRcdHZhciBleHBhbmRlZE5hdmlnYXRpb25TdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNleHBhbmRlZC1uYXZpZ2F0aW9uJykpO1xuXHRcdGlmKCBleHBhbmRlZE5hdmlnYXRpb25TdHlsZSAmJiAndmlzaWJsZScgPT09IGV4cGFuZGVkTmF2aWdhdGlvblN0eWxlLnZpc2liaWxpdHkgKSB7XG5cdFx0XHQvLyBpZiBleHBhbmRlZCBuYXYgaXMgb3BlbiwgZm9jdXMgb24gdGhlIGJ1dHRvbiBpbiB0aGUgZXhwYW5kZWQgbmF2XG5cdFx0XHRkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuc2l0ZS1oZWFkZXIgLnN1YnNjcmliZS1wcm9tcHQnKVsxXS5mb2N1cygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBmb2N1cyBvbiB0aGUgYnV0dG9uIGluIHRoZSBzdGlja3kgbmF2XG5cdFx0XHRkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuc2l0ZS1oZWFkZXIgLnN1YnNjcmliZS1wcm9tcHQnKVswXS5mb2N1cygpO1xuXHRcdH1cblx0fSwgMjUwKTtcbn1cblxuZnVuY3Rpb24gYXR0YWNoTGlzdGVuZXJzKCkge1xuXHQvLyBBdHRhY2ggZXZlbnQgbGlzdGVuZXIgdG8gZWFjaCBlbGVtZW50IG1hdGNoaW5nIHRoZSBzZWxlY3RvclxuXHRkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKF9zdWJzY3JpYmVCdXR0b25DbGFzc2VzKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuXHRcdC8vIFJlbW92ZSBhbnkgcHJldmlvdXNseSBzZXQgZXZlbnQgbGlzdGVuZXJzXG5cdFx0ZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIGhhbmRsZUNsaWNrKTtcblxuXHRcdC8vIEFkZCBldmVudCBsaXN0ZW5lcnNcblx0XHRlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgaGFuZGxlQ2xpY2spO1xuXG5cdFx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGV2ZW50KSA9PiB7XG5cdFx0XHQvLyBDaGVjayBpZiB0aGUga2V5IHByZXNzZWQgaXMgdGhlIEVudGVyIGtleS5cblx0XHRcdGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcblx0XHRcdFx0aGFuZGxlQ2xpY2soZXZlbnQpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cbmF0dGFjaExpc3RlbmVycygpO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbXlmcDp1c2VyLWxvYWRlZCcsICgpID0+IHtcblx0Ly8gTGlzdGVuIGZvciBNeUZQIHVzZXIgbG9hZGVkIGV2ZW50XG5cdC8vIEdpdmUgdGhpcyBhbiBhZGRpdGlvbmFsIHNlY29uZCB0byBwb3B1bGF0ZVxuXHQvLyB0aGUgRE9NIHdpdGggYW55IHN1YnNjcmliZSBwcm9tcHRzIGJlZm9yZVxuXHQvLyBhdHRhY2hpbmcgbmV3IGxpc3RlbmVyc1xuXHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRhdHRhY2hMaXN0ZW5lcnMoKTtcblx0fSwgJzEwMDAnKTtcbn0pO1xuXG4vLyBBdHRhY2ggZXZlbnQgbGlzdGVuZXIgdG8gY2xvc2UgYnV0dG9uc1xuX3N1YnNjcmliZVRha2VvdmVyQ2xvc2UuZm9yRWFjaChidXR0b24gPT4ge1xuXHRidXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG5cdFx0Y2xvc2VTdWJzY3JpYmVNb2RhbCgpO1xuXHR9KTtcblxuXHRidXR0b24uYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChldmVudCkgPT4ge1xuXHRcdC8vIENoZWNrIGlmIHRoZSBrZXkgcHJlc3NlZCBpcyB0aGUgRW50ZXIga2V5LlxuXHRcdGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcblx0XHRcdGNsb3NlU3Vic2NyaWJlTW9kYWwoKTtcblx0XHR9XG5cdH0pO1xufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBLElBQU1BLHVCQUF1QixHQUFHLDZGQUE2RjtBQUM3SCxJQUFNQyxrQkFBa0IsR0FBR0MsUUFBUSxDQUFDQyxhQUFhLENBQUMscUJBQXFCLENBQUM7QUFDeEUsSUFBTUMsd0JBQXdCLEdBQUdGLFFBQVEsQ0FBQ0MsYUFBYSxDQUFDLDRCQUE0QixDQUFDO0FBQ3JGLElBQU1FLHVCQUF1QixHQUFHSCxRQUFRLENBQUNJLGdCQUFnQixDQUFDLDJCQUEyQixDQUFDOztBQUV0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQU1DLFdBQVcsR0FBRyxTQUFkQSxXQUFXQSxDQUFHQyxDQUFDLEVBQUk7RUFBQSxJQUFBQyxxQkFBQTtFQUN4QkQsQ0FBQyxDQUFDRSxjQUFjLENBQUMsQ0FBQzs7RUFFbEI7RUFDQSxJQUFJQyxTQUFTLEdBQUdQLHdCQUF3QixDQUFDUSxZQUFZLENBQUMsS0FBSyxDQUFDO0VBQzVELElBQUlDLE9BQU8sSUFBQUoscUJBQUEsR0FBR0QsQ0FBQyxDQUFDTSxNQUFNLENBQUNGLFlBQVksQ0FBQyx1QkFBdUIsQ0FBQyxjQUFBSCxxQkFBQSxjQUFBQSxxQkFBQSxHQUFJTCx3QkFBd0IsQ0FBQ1EsWUFBWSxDQUFDLFVBQVUsQ0FBQzs7RUFFakg7RUFDQTtFQUNBLElBQ0MsQ0FBQ0QsU0FBUyxJQUNQQSxTQUFTLEtBQUssK0JBQStCLElBQzVDQSxTQUFTLEtBQUtFLE9BQVEsRUFDekI7SUFDRFQsd0JBQXdC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\n//# sourceURL=webpack-internal:///../assets/src/scripts/components/navigation/navigation-subscribe-takeover.js\n\n}")}},__webpack_exports__={};__webpack_modules__["../assets/src/scripts/components/navigation/navigation-subscribe-takeover.js"]()})();; !function ($) { // Remove the no-js class from html - testing if js is enabled $( 'html' ).removeClass( 'no-js' ); // Stop default behavior on specific links $( 'a.no-link' ).on( 'click', function( e ){ e.preventDefault(); }); // Track specific link clicks that have "track-download" class // e.g. link text $( 'a.track-download' ).on( 'click', function( e ){ var url_string = $(this).attr('href'); if(typeof url_string !== typeof undefined && url_string !== false) { var url_array = url_string.split('/'); var eLabel = url_array[ url_array.length - 1 ]; if(typeof zaraz !== 'undefined') { zaraz.track( 'dl_event', { category: 'download', action: 'click', label: eLabel, } ); } dataLayer.push({ 'event':'dl_event', 'event_category':'download', 'event_action':'click', 'event_label': eLabel, 'event_value':'' }); } }); }(jQuery); ; /** * Helpers for urls */ !function () { //=NS FP.Utils = FP.Utils || {}; FP.Utils.url = { /** * Helper to parse URL parameters * @param {string} sParam URL parameter to get * @param {bool} toLower * @returns string. */ getUrlParameter: function(sParam, toLower = true) { var sPageURL = window.location.search.substring(1); if (toLower) sPageURL = sPageURL.toLowerCase(); var sURLVariables = sPageURL.split("&"); var ret = "not found"; for (var i = 0; i < sURLVariables.length; i++) { var sParameterName = sURLVariables[i].split("="); if (sParameterName[0] == sParam) { ret = sParameterName[1]; } } return ret; }, /** * Helper to get URL slug. * @returns string. */ getUrlSlug: function() { var urlPath = window.location.pathname; urlPath = urlPath.replace(/^\/+/, ''); // remove leading slash urlPath = urlPath.replace(/\/+$/, ''); // remove trailing slash var urlPathArray = urlPath.split('/'); var urlSlug = urlPathArray[urlPathArray.length-1]; return urlSlug; }, /** * Get root domain (necessary for IP access clients with proxy URLs). * @param {string} hostname * @returns string. */ getRootDomain: function(hostname) { let parts = hostname.split("."); if (parts.length <= 2) { return hostname; } parts = parts.slice(-3); if (['co','com','edu'].indexOf(parts[1]) > -1) { return parts.join('.'); } return parts.slice(-2).join('.'); }, /** * Get UTM parameters from URL. All parameters are defined in the function. * @returns object. */ getUtmParameters: function() { let utmParamData = { utm_source: FP.Utils.url.getUrlParameter('utm_source'), utm_medium: FP.Utils.url.getUrlParameter('utm_medium'), utm_campaign: FP.Utils.url.getUrlParameter('utm_campaign'), utm_content: FP.Utils.url.getUrlParameter('utm_content'), utm_term: FP.Utils.url.getUrlParameter('utm_term'), }; // FP.Utils.url.getUrlParameter() returns a string "not found" if UTM param is not found // if this is the case, we just need to remove the key from the utmParamData object Object.keys(utmParamData).forEach(key => { if (utmParamData[key] === 'not found') { delete utmParamData[key]; } }); return utmParamData; }, /** * Check if string is valid base64 * (primarily for user email URL param - ?e=[base64-encoded-email]). * @param {string} base64 encoded string to check * @returns bool. */ isValidBase64: function(str) { const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/; return base64Regex.test(str); }, } }();; !function($){ //=NS FP.Utils = FP.Utils || {}; FP.Utils.forms = { recaptchaSiteKey: '6LdNhYkiAAAAAEo_IrOgwgJPQt4LnKpiSPXhUHxZ', recaptchaValidationURL: '/recaptcha-verify/?s=verify_recaptcha&__fp_endpoint_recaptcha_api=1&__fp_endpoint_recaptcha_api_token=', /** * @summary Helper utility for forms. * * @description Animated labels, recaptcha form validation, etc. * * @return {void} */ init: function() { FP.Utils.forms.animateLabels(); FP.Utils.forms.validateFormsWithRecaptcha(); FP.Utils.forms.validateHtmxFormsWithRecaptcha(); }, /** * @summary Animate labels on forms. * * @description Animate labels to appear above inputs when input is either in focus or populated. * * @return {void} */ animateLabels: function() { const animatedLabels = document.querySelectorAll('.animated-labels'); if ( animatedLabels.length > 0 ) { document.querySelectorAll('.animated-labels input, .animated-labels textarea').forEach( ( animatedLabelInput ) => { animatedLabelInput.addEventListener( 'focus', ( el ) => { const targetLabel = document.querySelector('label[for=\'' + el.target.id + '\']'); if( targetLabel ) { targetLabel.classList.add('active'); } } ); animatedLabelInput.addEventListener( 'blur', ( el ) => { const targetLabel = document.querySelector('label[for=\'' + el.target.id + '\']'); if( targetLabel && el.target.value === '' ) { targetLabel.classList.remove('active'); } } ); } ); } }, /** * @summary Handle recaptcha validation on forms. * * @description Add click events and form validation on forms that have recaptcha. * * @return {void} */ validateFormsWithRecaptcha: function() { // // Pages with form and recaptcha v3 // var formWithRecaptchaV3 = $('.salesforce-lead-form--with-recaptcha-v3'); if( formWithRecaptchaV3.length < 1 ) { return true; } $('.salesforce-lead-form--with-recaptcha-v3 input[type=submit]').on('click', function(e) { // leverage browser native validation primarily for screenreaders // browser native functionality will automatically focus on invalid fields if (!formWithRecaptchaV3[0].checkValidity()) { // Prevent form submission e.preventDefault(); // Show browser native validation errors formWithRecaptchaV3[0].reportValidity(); return; } var errorMessage = ''; var errorFields = ''; var errorMessageContainer = formWithRecaptchaV3.find('.form-feedback'); errorMessageContainer.html('').removeClass('show-error'); $('.form-feedback-error').remove(); // verify required fields are populated let requiredFieldsFilled = true; formWithRecaptchaV3.find('[required]').each( function() { if( '' === $(this).val() ) { errorFields = errorFields + '' + $(this).attr('data-field-name') + ', '; requiredFieldsFilled = false; var formFeedbackText = $(this).attr('data-field-error') ?? 'Enter a ' + $(this).attr('data-field-name'); $(this).before(''); } }); if( !requiredFieldsFilled ) { errorMessage = '

Please complete the following required fields: ' + errorFields.substring(0,errorFields.length-2) + '

'; } else { // prevent default form submission e.preventDefault(); // verify recaptcha var grecaptcha = window.grecaptcha; grecaptcha.ready(function() { grecaptcha.execute(FP.Utils.forms.recaptchaSiteKey, {action: 'submit'}).then(function(token) { $.ajax({ type: 'POST', url: FP.Utils.forms.recaptchaValidationURL + token, async: false, cache: false, }).then(function(resp) { // recaptcha verification successful if( resp.data.success === true && resp.data.score >= 0.7 ) { // continue processing form formWithRecaptchaV3.submit(); // recaptcha verification failed } else { // show error below errorMessage = '

There was an error processing your information. Please contact support@foreignpolicy.com for assistance.

'; FP.Utils.forms.showFormErrors(errorMessage, errorMessageContainer); console.log('validation score feedback: ' + resp.data.score); } }); }); }); } if( '' !== errorMessage ) { // prevent default form submission e.preventDefault(); // show error FP.Utils.forms.showFormErrors(errorMessage, errorMessageContainer); return false; } }); }, /** * @summary Handle recaptcha validation on HTMx forms. * * @description Add form validation on HTMx forms that have recaptcha. * * @return {void} */ validateHtmxFormsWithRecaptcha: function() { document.body.addEventListener('htmx:confirm', (evt) => { const element = evt.detail.elt; // Only target .htmx--recaptcha elements if( element.classList.contains('htmx--recaptcha') || element.closest('.htmx--recaptcha') ) { // Pauses the request until validation is complete evt.preventDefault(); // Validate recaptcha before processing the request FP.Utils.forms.validateRecaptcha() .then(function(resp) { // Check boolean resp.success return value if( typeof resp.success !== 'undefined' && resp.success ) { // Request met the minimum recaptcha score threshold // Allow form processing to continue evt.detail.issueRequest(); } }); } }); }, /** * @summary Returns whether or not the recaptcha has been verified. * * @description Primarily for SailThru sign up buttons, not tied to an actual form submission. * * @param {int} scoreThreshold - Recaptcha score threshold. * * @returns {Object} jQuery Promise. */ validateRecaptcha: function( scoreThreshold = 0.5 ) { // verify recaptcha let recaptchaStatus = function( deferred ) { var grecaptcha = window.grecaptcha; grecaptcha.ready(function() { grecaptcha.execute(FP.Utils.forms.recaptchaSiteKey, {action: 'submit'}).then(function(token) { $.ajax({ type: 'POST', url: FP.Utils.forms.recaptchaValidationURL + token, async: false, cache: false, }).then(function(resp) { // recaptcha verification successful if( resp.data.success === true && resp.data.score > scoreThreshold ) { deferred.resolve( { success: true, data: 1 } ); // recaptcha verification failed } else { deferred.resolve( { success: false, data: 0 } ); } }); }); }); }; return $.when( $.Deferred( recaptchaStatus ) ); }, /** * @summary Validate email address. * * @description Validate email address using regex. * * @param {string} email * * @returns {boolean} Is valid email string */ validateEmail: function( email ) { var emailReg = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(email); }, /** * @summary Handles showing error messages. * * @description Inject form errors into error container and display the container. * If a clicked element should revert to a previous state, update the element text. * * @param {string} errorMessage - HTML string of error message to show. * @param {Object} errorMessageContainer - jQuery object to show error * @param {Object} clickedElement - jQuery object that triggered the event. * * @returns {void} */ showFormErrors: function( errorMessage, errorMessageContainer, clickedElement = null ) { // show error errorMessageContainer.html(errorMessage).addClass('show-error'); // TO-DO - the .show-error class needs to be added to the NL HTML? errorMessageContainer.attr('tabindex','0'); // update clicked element if present if( clickedElement ) { clickedElement.removeClass('button-clicked'); } // take user to error window.scrollTo( { top: errorMessageContainer.offset().top - $('.site-header').outerHeight() - 50, left: 0, behavior: 'smooth' } ); errorMessageContainer.focus(); return; }, /** * @summary Error handling for account-related forms. * * @description Primarily used for newsletter account signup form error handling. * * @param {Object} $form - jQuery form object to validate * * @returns {bool} */ validateAccountForms: function($form) { // Clear any previous errors var $errorContainer = $form.find('.form-feedback'); $errorContainer.find('.error-message').remove(); var errors = []; // TO-DO - make this more dynamic for form fields? Look for a required attribute? var $email = $form.find('input[name="email"]'); var $password = $form.find('input[name="password"]'); var $firstname = $form.find('input[name="firstname"]'); var $lastname = $form.find('input[name="lastname"]'); var $optin = $form.find('input[name="optin"]'); // Every screen has an email field if (!FP.Utils.forms.validateEmail($email.val())) { errors.push('Email address is invalid'); } if ($password.length) { if ($password.val().length < 8) { errors.push('Password must be at least 8 characters'); } } [$firstname, $lastname].forEach(function($el) { if ($el.length) { if (!$el.val()) { errors.push($el.attr('placeholder') + ' is required'); } } }); if ($optin.length && !$optin.is(':checked')) { errors.push('Opt-in is required'); } if (errors) { FP.Utils.forms.showAccountFormErrors($form, errors); } return !errors.length; }, /** * @summary Show errors on account-related forms. * * @description Primarily used for newsletter account signup form error display. * * @param {Object} $form - jQuery object of form * * @param {array} errors - Array of errors to show * * @returns {void} */ showAccountFormErrors: function($form, errors) { var $errorContainer = $form.find('.form-feedback'); var error_list = errors.join('
'); if('' !== error_list){ FP.Utils.forms.showFormErrors( '' + errors.join('
') + '
', $errorContainer, null, null ); } }, }; }(jQuery); FP.Utils.forms.init(); ; //~ Hack for links the proxy does not adjust !function($){ $(document).on('pianoAccessCheckComplete', function () { tp = window.tp || []; //~ Data is not ready if(typeof FP.Singletons.UserAltAccess === 'undefined') { return } //~ Does not apply to normal proxy access if (!FP.Singletons.UserAltAccess.isIPAccess || 'proxy_hosts' !== FP.Singletons.UserAltAccess.ipAccessData.access_type) { return; } $(document).on('click', 'a', function(e){ var refLink = null; if (/^trc\.taboola\.com/) { var search = this.search.split('&'); for (var i = 0, len = search.length; i < len; i++) { var query = search[i]; if ('url=' === query.substr(0, 4)) { refLink = decodeURIComponent(query.substr(4)); break; } } } var a; if (null === refLink) { a = this; } else { a = document.createElement('a'); a.href = refLink; } //~ If it's not an internal link, not our problem if (!/^(www\.)?foreignpolicy.com$/.test(a.hostname)) { return; } //~ Stop the internal link e.preventDefault(); document.location = ( document.location.protocol + '//' + document.location.host + a.pathname + a.search + a.hash ); }); }); }(jQuery); ; /*! * jQuery Cookie Plugin v1.3.1 * https://github.com/carhartl/jquery-cookie * * Copyright 2013 Klaus Hartl * Released under the MIT license */ (function (factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as anonymous module. define(['jquery'], factory); } else { // Browser globals. factory(jQuery); } }(function ($) { var pluses = /\+/g; function decode(s) { if (config.raw) { return s; } try { // If we can't decode the cookie, ignore it, it's unusable. return decodeURIComponent(s.replace(pluses, ' ')); } catch(e) {} } function decodeAndParse(s) { if (s.indexOf('"') === 0) { // This is a quoted cookie as according to RFC2068, unescape... s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); } s = decode(s); try { // If we can't parse the cookie, ignore it, it's unusable. return config.json ? JSON.parse(s) : s; } catch(e) {} } var config = $.cookie = function (key, value, options) { // Write if (value !== undefined) { options = $.extend({}, config.defaults, options); if (typeof options.expires === 'number') { var days = options.expires, t = options.expires = new Date(); t.setDate(t.getDate() + days); } value = config.json ? JSON.stringify(value) : String(value); return (document.cookie = [ config.raw ? key : encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join('')); } // Read var result = key ? undefined : {}; // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. Also prevents odd result when // calling $.cookie(). var cookies = document.cookie ? document.cookie.split('; ') : []; for (var i = 0, l = cookies.length; i < l; i++) { var parts = cookies[i].split('='); var name = decode(parts.shift()); var cookie = parts.join('='); if (key && key === name) { result = decodeAndParse(cookie); break; } // Prevent storing a cookie that we couldn't decode. if (!key && (cookie = decodeAndParse(cookie)) !== undefined) { result[name] = cookie; } } return result; }; config.defaults = {}; $.removeCookie = function (key, options) { if ($.cookie(key) !== undefined) { // Must not alter options, thus extending a fresh object... $.cookie(key, '', $.extend({}, options, { expires: -1 })); return true; } return false; }; })); ; !function ($) { tp = window.tp || []; FP.Utils = FP.Utils || {}; FP.Utils.Piano = { /** * ------------------------------------------------------------------------ * Initialize utility helper * called in /assets/src/scripts/users/user-piano.js * ------------------------------------------------------------------------ */ init: function() { // Piano custom field form handling if ( $('.piano-custom-fields-form').length > 0 ) FP.Utils.Piano.updatePianoUserCustomFieldsFormHandling(); // Piano custom button/clickable element custom field handling if ( $('.piano-custom-fields-element').length > 0 ) FP.Utils.Piano.updatePianoUserCustomFieldsElementClickHandling(); // Initialize click listeners FP.Utils.Piano.initClickListeners(); // Ensure full article content displays in the in-app browser for non-Insider content if( FP.Utils.Piano.isUserFromApp() && !FP.Utils.Piano.isInsiderContent() ) { $( '.content-ungated' ).hide(); $( '.content-gated' ).show(); } $(document).on('pianoAccessCheckComplete', function () { if (window.location.pathname === '/' && !FP.Singletons.User.isIPAccess) { const cRegEx = /^(?:.*;)?\s*__utp\s*=\s*([^;]+)(?:.*)?$/ let existingToken = (document.cookie.match(cRegEx)||[,null])[1] // We've got an existing cookie use that. if(existingToken !== null) { FP.Utils.Piano.syncUserToST(existingToken); } } // Password reset page logic if ( $('#reset-password-page').length > 0 ) FP.Utils.Piano.initPasswordReset(); // Remove Piano auth cookies generated for IP access clients // accessing the PressReader print archive var pressreader_auth = $.cookie( '__utp_ipaccess' ); if ( pressreader_auth && FP.Singletons.User.isIPAccess && 'ipsubscriber@foreignpolicy.com' === FP.Singletons.User.userData.email ) { // get root domain (necessary for IP access clients with proxy URLs) var rootDomain = FP.Utils.url.getRootDomain(window.location.hostname); // remove cookies by setting expiration date in the past document.cookie = '__utp=0; expires=Thu, 01 Jan 1970 00:00:01 GMT;' + ' path=/; domain=.' + rootDomain + ';'; document.cookie = '__utp_ipaccess=false; expires=Thu, 01 Jan 1970 00:00:01 GMT;' + ' path=/; domain=.' + rootDomain + ';'; if( window.location.search !== '?ipaccess_reload=1' ) { // reload to register cookie removal // add URL parameter to avoid an infinite redirect loop window.location.href = window.location.href + '?ipaccess_reload=1'; } } }); }, performLogout(event) { // Remove cookies and local storage if(window?.rudderTools?.lib?.reset) { window.rudderTools.lib.reset(); } // Comments $.removeCookie('fp-coral-token', { path: '/' }); // VIP cache group $.removeCookie('vip-go-seg', { path: '/' }); // Piano user data $.removeCookie('fp-user-data', { path: '/' }); // Piano metering $.removeCookie('__utp_mec', { path: '/' }); // ST HID $.removeCookie('sailthru_hid', { path: '/' }); // Local ST $.removeCookie('__utp_fp_st', { path: '/' }); // FP Live window.localStorage.removeItem('fp-live-email-address'); window.localStorage.removeItem('fp-live-registered'); window.localStorage.removeItem('fp-live-attended'); window.localStorage.removeItem('fp-live-ondemand'); window.localStorage.removeItem('fp-live-optout'); window.localStorage.removeItem('fp-live-list-subs'); // Logout and refresh the page tp.pianoId.logout(); }, /** * ------------------------------------------------------------------------ * Initialize click listeners * ------------------------------------------------------------------------ */ initClickListeners: function() { // Trigger Piano login $(document).on('click', 'a.navlink.FP-paywall--login, .FP-paywall--login.FP-paywall--login--login, .FP-paywall--login--ip-access', function (event) { event.preventDefault(); // show login tp.pianoId.show({ displayMode: 'modal', screen: 'login', loggedIn: function(data) { FP.Utils.Piano.toggleHeaderContent(); }, loggedOut: function() { FP.Utils.Piano.toggleHeaderContent(); }, loginDisplayed: function() { $('.tp-modal').attr('role','modal'); $('.tp-modal').attr('title','Sign In to your account'); $('.tp-modal').attr('tabindex','0'); $('.tp-modal').focus(); $('.tp-modal iframe').attr('title','Sign In form'); $('.tp-modal iframe').attr('tabindex','0'); FP.Utils.trapFocus.init(document.querySelectorAll('.tp-modal')); FP.Utils.trapFocus.toggleInertAttribute(true); }, registerDisplayed: function() { $('.tp-modal').attr('role','modal'); $('.tp-modal').attr('title','Sign up for an account'); $('.tp-modal').attr('tabindex','0'); $('.tp-modal').focus(); $('.tp-modal iframe').attr('title','Sign up form'); $('.tp-modal iframe').attr('tabindex','0'); FP.Utils.trapFocus.init(document.querySelectorAll('.tp-modal')); FP.Utils.trapFocus.toggleInertAttribute(true); }, }); }); // Trigger Piano signup $(document).on('click', 'a.FP-paywall--login--signup', function (event) { event.preventDefault(); // show signup tp.pianoId.show({ displayMode: 'modal', screen: 'register', loggedIn: function(data) { FP.Utils.Piano.toggleHeaderContent(); }, loggedOut: function() { FP.Utils.Piano.toggleHeaderContent(); }, loginDisplayed: function() { $('.tp-modal iframe').attr('title','Login to your account'); FP.Utils.trapFocus.init(document.querySelectorAll('.tp-modal')); FP.Utils.trapFocus.toggleInertAttribute(true); }, registerDisplayed: function() { $('.tp-modal iframe').attr('title','Sign up for an account'); FP.Utils.trapFocus.init(document.querySelectorAll('.tp-modal')); FP.Utils.trapFocus.toggleInertAttribute(true); }, }); }); // Trigger Piano logout $(document).on('click', 'a.FP-paywall--logout', FP.Utils.Piano.performLogout); // HTMX Logout document.body.addEventListener('pianoLogout', FP.Utils.Piano.performLogout); // Trigger Piano login/sign up modal close $(document).on('click', '.tp-close', function () { FP.Utils.trapFocus.toggleInertAttribute(false); }); // Trigger offers on 2022 subscribe page sticky top nav $('.subscribe-link.subscribe-list__item').on('click', function(e) { e.preventDefault(); var termId = ''; if( $('.dropdown__list-item[data-selected="1"]').length > 0 ) { if( typeof $('.dropdown__list-item[data-selected="1"]').attr('data-term-id') !== 'undefined' ) { termId = $('.dropdown__list-item[data-selected="1"]').attr('data-term-id'); } } if( termId !== '' ) { tp.offer.show({ offerId: 'OFC557HUHRK2', templateId: 'OTSW23E1OBRE', termId: termId, }); } }); // Trigger offers on Group Subscriptions page const groupSubsButton = document.getElementById('group-subs-subscribe-button'); if (groupSubsButton) { groupSubsButton.addEventListener('click', function(e) { e.preventDefault(); const termId = this.dataset.selectedTermId; if( termId !== '' ) { tp.offer.show({ formNameByTermId: '{"'+termId+'":"group_subs"}', offerId: 'OFTA11MJ1YP0', termId: termId, displayMode: 'modal', }); } }); } }, /** * ------------------------------------------------------------------------ * Password reset page * ------------------------------------------------------------------------ */ initPasswordReset: function() { if ( tp.user.isUserValid() ) { // Password cannot be reset if user is logged in $('#reset-password-page').css('display','none'); $('#reset-password-page-logged-in-user').css('display','block'); } else { // Password can only be reset if user is anonymous $('#reset-password-page').css('display','block'); $('#reset-password-page-logged-in-user').css('display','none'); // If URL has reset_token parameter var tokenMatch = location.search.match(/reset_token=([A-Za-z0-9]+)/); if (tokenMatch) { // Get value of the token var token = tokenMatch[1]; // Present password reset form with the found token tp.pianoId.show({ 'resetPasswordToken': token, displayMode: 'inline', containerSelector: '#reset-password-page', loggedIn: function () { // Once user logs in - refresh the page location.reload(); } }); } } }, /** * @summary. Synchronizes user on login with ST * * @description. Validates the user token through our endpoint and * synchronizes the user in ST. We then take the returned cookie from ST and * apply it to a ssailthru_hid cookie. * * @param {string} token - The Piano token * * @return {void} */ syncUserToST: function(token) { const endpoint = '/wp-json/fp/sailthru-hid/'; fetch(endpoint, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type' : 'application/json', } }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok ' + response.statusText); } return response.json(); }) .then(data => { if (data.keys && typeof data.keys.cookie === 'string') { const cookieValue = data.keys.cookie; const expires = new Date( Date.now() + 30 * 24 * 60 * 60 * 1000 ).toUTCString(); document.cookie = `sailthru_hid=${cookieValue}; ` + `expires=${expires}; ` + `domain=${window.location.hostname}; ` + `path=/;`; } }) .catch(error => { console.error('Could not synchronize ST user', error); }); }, /** * ------------------------------------------------------------------------ * Toggle body class based on whether user is logged in/subscribed * ------------------------------------------------------------------------ */ toggleBodyClass: function() { // Check if user is logged in if( FP.Singletons.User.hasAccount || FP.Utils.Piano.isUserFromApp() ) { // Check if user is subscribed if( FP.Singletons.User.isSub ) { $( 'body' ).addClass( 'sub_user' ); } else { $( 'body' ).addClass( 'reg_user' ); } // Check if user is an insider if ( FP.Singletons.User.isInsider ) { $( 'body' ).addClass( 'insider_user' ); } // Check if user is IP access } else if( FP.Singletons.User.isIPAccess ) { $( 'body' ).addClass( 'ip_access_user' ); } else { $( 'body' ).addClass( 'anon_user' ); } }, /** * ------------------------------------------------------------------------ * Toggle header content based on whether user is logged in * ------------------------------------------------------------------------ */ toggleHeaderContent: function() { // If user is logged in if ( // If user is IP access and they are registered // Non-authenticated IP access users are pushed down to the // "If user is IP access client" condition below ( FP.Singletons.User.isIPAccess && FP.Singletons.User.hasAccount ) || // If user is not IP access, but is a sub or registered ( !FP.Singletons.User.isIPAccess && ( FP.Singletons.User.isSub || FP.Singletons.User.hasAccount ) ) ) { // Update header content to match logged in state $('.site-nav-user-button').show(); $('.header-nav-wrapper .login-ip-access, .nav-full-menu__header__tools .login-ip-access').hide(); $('.header-nav-wrapper .login-user, .nav-full-menu__header__tools .login-user').hide(); if ( FP.Singletons.User.isInsider ) { $('.header-nav-wrapper .subscribe-prompt, .nav-full-menu__header__tools .subscribe-prompt').hide(); $('.header-nav-wrapper .subscribe-link, .nav-full-menu__header__tools .subscribe-link').hide(); $('.header-nav-wrapper .gift-link, .nav-full-menu__header__tools .gift-link').show(); $('.header-nav-wrapper .upgrade-to-insider-prompt, .nav-full-menu__header__tools .upgrade-to-insider-prompt').hide(); } else if( FP.Singletons.User.isSub || FP.Singletons.User.isPrem ) { $('.header-nav-wrapper .subscribe-prompt, .nav-full-menu__header__tools .subscribe-prompt').hide(); $('.header-nav-wrapper .subscribe-link, .nav-full-menu__header__tools .subscribe-link').hide(); $('.header-nav-wrapper .gift-link, .nav-full-menu__header__tools .gift-link').hide(); $('.nav-menu__item.subscribe-link').css('display', 'block'); $('.header-nav-wrapper .upgrade-to-insider-prompt, .nav-full-menu__header__tools .upgrade-to-insider-prompt').show(); } else if( FP.Singletons.User.hasAccount && FP.Singletons.User.isIPAccess ) { $('.header-nav-wrapper .subscribe-prompt, .nav-full-menu__header__tools .subscribe-prompt').hide(); $('.header-nav-wrapper .gift-link, .nav-full-menu__header__tools .gift-link').hide(); $('.header-nav-wrapper .upgrade-to-insider-prompt, .nav-full-menu__header__tools .upgrade-to-insider-prompt').hide(); } else if( FP.Singletons.User.hasAccount ) { $('.nav-menu__item.subscribe-link').css('display', 'block'); $('.header-nav-wrapper .subscribe-prompt, .nav-full-menu__header__tools .subscribe-prompt').show(); $('.header-nav-wrapper .gift-link, .nav-full-menu__header__tools .gift-link').hide(); $('.header-nav-wrapper .upgrade-to-insider-prompt, .nav-full-menu__header__tools .upgrade-to-insider-prompt').hide(); } // If user is IP access client } else if( FP.Singletons.UserAltAccess && FP.Singletons.UserAltAccess.isIPAccess ) { // Update header content to match logged in state $('.site-nav-user-button').hide(); $('.login-ip-access--welcome > span') .text( FP.Singletons.UserAltAccess.ipAccessData.message ) .attr('href','#') .removeClass('FP-paywall--login'); $('.header-nav-wrapper .subscribe-link, .nav-full-menu__header__tools .subscribe-link').hide(); $('.header-nav-wrapper .gift-link, .nav-full-menu__header__tools .gift-link').hide(); $('.header-nav-wrapper .upgrade-to-insider-prompt, .nav-full-menu__header__tools .upgrade-to-insider-prompt').hide(); // Prompt IP access users to login $('.header-nav-wrapper .login-user, .nav-full-menu__header__tools .login-user').hide(); $('.header-nav-wrapper .login-ip-access, .nav-full-menu__header__tools .login-ip-access').show(); // If user is link access client } else if( FP.Singletons.UserAltAccess && FP.Singletons.UserAltAccess.isLinkAccess ) { // Update header content to match logged in state $('.site-nav-user-button').hide(); $('.header-nav-wrapper .login-user.FP-paywall--login') .text( FP.Singletons.UserAltAccess.linkAccessData.message ) .attr('href','#') .removeClass('FP-paywall--login'); $('.header-nav-wrapper .login-user').hide(); $('.header-nav-wrapper .subscribe-link').hide(); } else { // Update header content to match logged out state $('.site-nav-user-button').hide(); $('.nav-menu__item.subscribe-link').css('display', 'block'); $('.header-nav-wrapper .subscribe-prompt, .nav-full-menu__header__tools .subscribe-prompt').show(); $('.header-nav-wrapper .gift-link, .nav-full-menu__header__tools .gift-link').hide(); $('.header-nav-wrapper .upgrade-to-insider-prompt, .nav-full-menu__header__tools .upgrade-to-insider-prompt').hide(); $('.header-nav-wrapper .login-user, .nav-full-menu__header__tools .gift-link .login-user').show(); $('.header-nav-wrapper .login-ip-access, .nav-full-menu__header__tools .login-ip-access').hide(); } // Hide header for users viewing article in our app if( FP.Utils.Piano.isUserFromApp() ) { $('.site-header, .in-article-dynamic-ad, .ad-container, .ad-container--parent, .sidebar-big-box-ad, .home-ad-region-1, .home-ad-region-2, .channel-sidebar-big-box-ad, #mobile-adhesion-ad').hide(); $('body').css('padding-top','0').addClass('in-app'); } // Hide header for users viewing article from Facebook Instant Articles if( FP.Utils.Piano.isUserFromFBIA() ) { $('.header-nav-wrapper').hide(); $('.site-header .logo').removeAttr('href'); $('body').css('padding-top','0'); $('body').addClass('no-piano-modal-margin'); } }, /** * ------------------------------------------------------------------------ * Add titles to injected Piano iframes for accessibility * ------------------------------------------------------------------------ */ addTitlestoPianoIframes: function() { // FP containers that contain injected Piano content var targetNodes = document.querySelectorAll('.tp-container-inner'); for( let targetNode of targetNodes ) { // Add title attributes to iframes let pianoIframe = targetNode.querySelector('iframe'); if( pianoIframe ) pianoIframe.setAttribute('title', 'Subscription offer'); } }, /** * ------------------------------------------------------------------------ * Add the user's Piano id to the gifting link params if user is a sub * ------------------------------------------------------------------------ */ updateGiftingLink: function() { if( !FP.Singletons.User.isSub ) return; var pianoUid = FP.Singletons.User.userData.uid ?? ''; if( '' !== pianoUid && $('.gift-article__wrapper').length > 0 ) { $('.gift-article__wrapper .share-dropdown__option[data-url]').each(function() { $(this).attr('data-url', $(this).attr('data-url') + '&pid=' + pianoUid ); }); $('.gift-article__wrapper .share-dropdown__option[href]').each(function() { $(this).attr('href', $(this).attr('href') + '%26pid%3D' + pianoUid ); }); } }, /** * ------------------------------------------------------------------------ * Determine whether user is coming to the page from our app by * looking for ?app=true in the URL * ------------------------------------------------------------------------ */ isUserFromApp: function() { var isFromApp = ( 'true' === FP.Utils.url.getUrlParameter('app') ); return isFromApp; }, /** * ------------------------------------------------------------------------ * Determine whether user is coming to the page from Facebook * Instant Articles by looking for surface=meter_limit_reached in the URL * ------------------------------------------------------------------------ */ isUserFromFBIA: function() { var isFromFBIA = ( 'not found' !== FP.Utils.url.getUrlParameter('account_linking_token') ); return isFromFBIA; }, /** * ------------------------------------------------------------------------ * Track events in Facebook * ------------------------------------------------------------------------ */ sendSignedFbPixel: function( event_name, params ) { jQuery.ajax( { url: '/wp-json/fp/fb-pixel', data: { event_name: event_name, params: params }, type: 'GET', async: false, success: function ( response ) { var image = jQuery( '' ); image.attr( 'src', response.pixel_url ); jQuery( 'body' ).append( image ); }, error: function( request, error ) { console.error( error ); } } ); }, /** * ------------------------------------------------------------------------ * Update custom fields in Piano * ------------------------------------------------------------------------ */ updatePianoUserCustomFields: function( piano_form_id, custom_fields, email = '', uid = '' ) { var user_email = ( email ) ? email : FP.Singletons.User.userData.email; var user_uid = ( uid ) ? uid : FP.Singletons.User.userData.uid; return $.ajax({ url: '/piano-user-update/results/', data: { '__fp_endpoint_piano_ajax_update_user' : 1, '__fp_endpoint_piano_action_update_user': 'update_user_custom_fields', '__fp_endpoint_piano_user_email' : user_email, '__fp_endpoint_piano_user_uid' : user_uid, '__fp_endpoint_piano_user_form_id' : piano_form_id, '__fp_endpoint_piano_user_custom_fields': custom_fields, '__fp_endpoint_piano_user_nonce' : window.pianoData.cache_group_nonce || '', }, cache: true }); }, /** * ------------------------------------------------------------------------ * Piano custom field form handling * ------------------------------------------------------------------------ */ updatePianoUserCustomFieldsFormHandling: function() { $('.piano-custom-fields-form').on('submit', function(e) { e.preventDefault(); // Get Piano form id var piano_form_id = $(this).attr('data-piano-form-id') || ''; // Build array of custom fields var custom_fields = {}; $(this).find( '.custom_field' ).each(function() { if( 'checkbox' === $(this).attr('type') ) { if( $(this).is(':checked') ) { custom_fields[$(this).attr('name')] = $(this).val(); } } else { custom_fields[$(this).attr('name')] = $(this).val(); } }); custom_fields = Object.keys(custom_fields).map(function(k){return k+'=='+custom_fields[k];}).join('||'); // Send data to Piano return FP.Utils.Piano.updatePianoUserCustomFields( piano_form_id, custom_fields ); }); }, /** * ------------------------------------------------------------------------ * Piano custom button/clickable element custom field handling * ------------------------------------------------------------------------ */ updatePianoUserCustomFieldsElementClickHandling: function() { // Remove any existing click events on elements // to avoid running click events twice $('.piano-custom-fields-element').off('click'); // Add click events on elements $('.piano-custom-fields-element').on('click', function(e) { // Get Piano form id var piano_form_id = $(this).attr('data-piano-form-id') || ''; // Build array of custom fields var custom_fields = {}; custom_fields[$(this).attr('data-name')] = $(this).attr('data-value'); custom_fields = Object.keys(custom_fields).map(function(k){return k+'=='+custom_fields[k];}).join('||'); // Send data to Piano return FP.Utils.Piano.updatePianoUserCustomFields( piano_form_id, custom_fields ); }); }, /** * ------------------------------------------------------------------------ * User onboarding trigger * ------------------------------------------------------------------------ */ triggerUserOnboarding: function( conversionObject ) { // set custom field values to trigger onboarding flow display var custom_fields = {}; // toggle between 'onboarding_shown_regis' and 'onboarding_shown' // depending on Piano resource id (rid) if( conversionObject.rid && 'REGISTRATION' === conversionObject.rid ) { custom_fields['onboarding_shown_regis'] = '1'; } else { custom_fields['onboarding_shown'] = '1'; } custom_fields = Object.keys(custom_fields).map(function(k){return k+'=='+custom_fields[k];}).join('||'); // send data to Piano to trigger the display of the onboarding flow for the user FP.Utils.Piano.updatePianoUserCustomFields( '', custom_fields, conversionObject.email, conversionObject.uid ); }, /** * ------------------------------------------------------------------------ * Update "Last Purchase Source" custom field * ------------------------------------------------------------------------ */ updateLastPurchaseSource: function( userData ) { // set custom field value var custom_fields = {}; custom_fields['last_purchase_source'] = 'web'; custom_fields = Object.keys(custom_fields).map(function(k){return k+'=='+custom_fields[k];}).join('||'); // send data to Piano to update custom field FP.Utils.Piano.updatePianoUserCustomFields( '', custom_fields, userData.email, userData.uid ); }, /** * ------------------------------------------------------------------------ * Triggered by custom events from Piano experiences * ------------------------------------------------------------------------ */ onCustomEvent: function(event) { if (event && event.eventName === 'shared-subscription-redemption') { parent.location.reload(); } }, /** * ------------------------------------------------------------------------ * Triggered by upgrade purchase events from Piano * ------------------------------------------------------------------------ */ onCompleteUpgradePurchase: function(params) { /* Reset user cache group */ if( typeof tp.pianoId.getUser().uid !== 'undefined' ) { /* Update Last Purchase Source custom field */ if( tp.user.isUserValid() ) { FP.Utils.Piano.updateLastPurchaseSource( tp.pianoId.getUser() ); } /* Ensure we have the user id from Piano before resetting cache group */ FP.Singletons.User.setUserCacheGroup( tp.pianoId.getUser().uid ); } }, /** * ------------------------------------------------------------------------ * Triggered by checkout complete event from Piano * ------------------------------------------------------------------------ */ onCheckoutComplete: function(data) { FP.Utils.Piano.sendSignedFbPixel( 'Subscribe', { subscription_id: data.uid, offer_code: data.rid, value: data.chargeAmount, currency: data.chargeCurrency } ); /* Trigger onboarding flow */ FP.Utils.Piano.triggerUserOnboarding( data ); /* Update Last Purchase Source custom field */ if( tp.user.isUserValid() ) { FP.Utils.Piano.updateLastPurchaseSource( tp.pianoId.getUser() ); } /* Reset user cache group */ FP.Singletons.User.setUserCacheGroup( data.uid ); /* Push zaraz events */ if(typeof zaraz !== undefined && FP.Config.is_production) { zaraz.track('checkoutComplete', data); } }, /** * ------------------------------------------------------------------------ * Triggered by custom checkout event from Piano * ------------------------------------------------------------------------ */ onCheckoutExternalEvent: function(event) { switch( event.eventName ) { case 'show-insider-subscription-page': FP.Utils.Piano.showInsiderSubscriptionPage(); break; case 'hide-insider-subscription-page': FP.Utils.Piano.hideInsiderSubscriptionPage(); break; case 'cta-button': FP.Utils.Piano.toggleAutoRenew( true ); break; case 'ar-offer-cancel': FP.Utils.Piano.toggleAutoRenew( false ); break; case 'expand-offer-in-header': if( $(window).width() > 599 ) return; $( 'body' ).addClass( 'tp-modal-open' ); $( '.in-article-subscribe-expandable-container .tp-container-inner' ).addClass( 'tp-container-expanded' ); setTimeout(function() { // Give the DOM a little time to update $( '.in-article-subscribe-expandable-container .tp-container-inner' ).css({ 'min-height':$('.tp-container-expanded iframe').outerHeight()+200+'px' }); }, 500); break; case 'expand-benefits-offer-in-header': case 'close-benefits-offer-in-header': if( $(window).width() > 599 ) return; setTimeout(function() { // Give the DOM a little time to update $( '.in-article-subscribe-expandable-container .tp-container-inner' ).css({ 'min-height':$('.tp-container-expanded iframe').outerHeight()+200+'px' }); }, 500); break; case 'close-offer-in-header': if( $(window).width() > 599 ) return; $( 'body' ).removeClass( 'tp-modal-open' ); $( '.in-article-subscribe-expandable-container .tp-container-inner' ).removeClass( 'tp-container-expanded' ); $( '.in-article-subscribe-expandable-container .tp-container-inner' ).css({ 'min-height':'auto' }); break; } }, /** * ------------------------------------------------------------------------ * Triggered by checkout close event from Piano * ------------------------------------------------------------------------ */ onCheckoutClose: function(event) { /* Default behavior is to refresh the page on successful checkout */ if (event && event.state == 'checkoutCompleted') { // Redirect user to homepage if subscribed on /subscribe landing page if (window.location.pathname === '/subscribe/' || window.location.pathname === '/subscribe') { window.location.href = window.location.origin; // Redirect user to homepage if subscribed on /subscribe-offer landing page } else if (window.location.pathname === '/subscribe-offer/' || window.location.pathname === '/subscribe-offer') { window.location.href = window.location.origin; // Reload parent if user is on embedded /insider iframe } else if(window.location.search === '?subscribe-insider' && typeof parent.location !== 'undefined') { parent.location.reload(); // Reload parent if user is on embedded /subscribe iframe } else if(window.location.search === '?subscribe' && typeof parent.location !== 'undefined') { parent.location.reload(); } else if(window.location.search === '?subscribe&tpcc=navbar' && typeof parent.location !== 'undefined') { parent.location.reload(); } else if(window.location.search === '?subscribe-offer&tpcc=navbar' && typeof parent.location !== 'undefined') { parent.location.reload(); // Reload parent if user is on embedded /subscribe-offer iframe } else if(window.location.search === '?tpcc=navbar_presidentsday24' && typeof parent.location !== 'undefined') { // Reload parent if user is on embedded /subscribe-offer iframe } else if(window.location.search === '?utm_term=summer_sale_2024' && typeof parent.location !== 'undefined') { parent.location.reload(); // Reload page if on any other page } else { location.reload(); } } }, /** * ------------------------------------------------------------------------ * Triggered by checkout cancelled event from Piano * ------------------------------------------------------------------------ */ onCheckoutCancel: function() { }, /** * ------------------------------------------------------------------------ * Triggered by checkout error event from Piano * ------------------------------------------------------------------------ */ onCheckoutError: function() { }, /** * ------------------------------------------------------------------------ * Triggered by checkout payment submission event from Piano * ------------------------------------------------------------------------ */ onCheckoutSubmitPayment: function() { }, /** * ------------------------------------------------------------------------ * Triggered by checkout state change event from Piano * ------------------------------------------------------------------------ */ onCheckoutStateChange: function( stateView ) { let stateName = stateView.stateName; let offerId = stateView.offerId; if ( 'state1' === stateName || 'state2' === stateName ) { if ( window.fbq ) { fbq( 'track', 'InitiateCheckout', { offer_code: offerId } ); } } }, /** * ------------------------------------------------------------------------ * Triggered by offer displayed event from Piano * ------------------------------------------------------------------------ */ startCheckout: function( params ) { if('offerShow' === params.logType) { // Set accessibility attributes for checkout modal // that is triggered from within an experience // or from tp.offer.show() in our JS if('purchase' === params.offerType) { $('.tp-modal iframe').attr('title','Complete your purchase'); } else if( !tp.user.isUserValid() ) { $('.tp-modal iframe').attr('title','Sign up for an account or login to complete your purchase'); } else { $('.tp-modal iframe').attr('title','Subscription options'); } $('.tp-modal').attr('title','Subscription offer'); $('.tp-modal').attr('role','modal'); $('.tp-modal').attr('tabindex','0'); $('.tp-modal').focus(); $('.tp-modal iframe').attr('tabindex','0'); FP.Utils.trapFocus.init(document.querySelectorAll('.tp-modal')); FP.Utils.trapFocus.toggleInertAttribute(true); } }, /** * ------------------------------------------------------------------------ * Meter callback - fired when the meter has expired * ------------------------------------------------------------------------ */ onMeterExpired: function( data ) { // Only run the code below for one of the following: // - the default meter used for non-subs // - the regwall meter used for non-subs // - the gifting meter used for non-subs viewing gifted articles if( (typeof data.meterName !== 'undefined') && FP.Utils.Piano.getMeterNamesToTarget().includes(data.meterName) ) { if ( window.fbq ) { fbq( 'track', 'ViewPaywall', { surface: 'mWeb', meter_count: data.maxViews } ); } // The user's meter has expired. // Hide the full version of the article and show the truncated version. $( '.content-ungated' ).show(); $( '.content-gated' ).hide(); // Hide the author, tag, and alerts content that appears below the Piano offer $( '.bio-no-photo' ).hide(); $( '.the-tags' ).hide(); $( '.js-myfp-container' ).eq(1).hide().remove(); // Reduce min-height of sidebar sticky elements $( '.sidebar .sticky-container--delay' ).removeClass( 'sticky-container--delay' ); // Restructure sidebar $( '.hide-on-gated-post' ).remove(); // Hide read more unit with Insider companion article if present $( '.related-articles--insider' ).hide(); // Hide comment related content $( '.header-social-shares' ).hide(); // hide sidebar content on mobile $( '.post-content .sidebar' ).addClass('hide-mobile'); // hide mobile sticky ad and in-article ads on mobile $( 'body' ).addClass('hide-ads'); // hide the fixed/expandable Piano subscribe prompt template // show the takeover Piano subscribe prompt template $( '.in-article-subscribe-expandable-container' ).hide(); $( '.in-article-subscribe-takeover-container' ).show(); $( '.in-article-subscribe-takeover-other-options' ).show(); // add black background to first recirc unit $( '.post-content--after .post-content--after--recirc-units .posts-carousel' ).addClass( 'posts-carousel--black-bg' ); // move the disabled audio embed if present if ( $( '.fp-audio-embed--disabled' ).length > 0 ) { $( '.post-content-main' ).prepend( $( '.fp-audio-embed--disabled' ) ); // audio embed will appear in the same location as // the FP Live top promo, so it should be hidden $( '.fp-live-promo-top' ).hide(); // The My FP prompts should also be hidden $( '.js-myfp-container' ).hide().remove(); } // logging for troubleshooting console.log( 'PIANO LOG gating - onMeterExpired ' + data.meterName ); } }, /** * ------------------------------------------------------------------------ * Meter callback - fired when the meter is active (i.e. user is * not subscribed), but it has not expired yet * ------------------------------------------------------------------------ */ onMeterActive: function( data ) { // Only run the code below for one of the following: // - the default meter used for non-subs // - the regwall meter used for non-subs // - the gifting meter used for non-subs viewing gifted articles if( (typeof data.meterName !== 'undefined') && FP.Utils.Piano.getMeterNamesToTarget().includes(data.meterName) ) { // This is a free article for the non-subscribed user. // Hide the truncated version of the article and show the full version. $( '.content-ungated' ).hide(); $( '.content-gated' ).show( 1, // Show immediately FP.Utils.Piano.loadIframes() // Load iframes within gated content after the content is shown ); // Add class to adjust spacing on custom feature templates $( '.piano-gating-offer-container--in-feature' ).addClass( 'piano-gating-offer-container--tighter-space' ); // Update fixed subscribe prompt on Insider content offer template container for the gifting offer if( 'true' === FP.Utils.Piano.validateGiftingURL() && $('body.is-fp-insider').length > 0 ) { $('.insider-in-article-subscribe-container').addClass('insider-in-article-subscribe-container--fixed'); } // Add class to first article to toggle content within CSS $( '.post-content--after' ).addClass( 'hide-duplicate-content-on-mobile' ); // Do not show soft gating for registrants if( FP.Singletons.User.isReg ) { const onboardingContainer = document.querySelector('#new-subs-onboarding-screens'); if( onboardingContainer ) { $( '.in-article-subscribe-expandable-container' ).hide(); $( '.in-article-subscribe-takeover-container' ).hide(); $( '.in-article-subscribe-takeover-other-options' ).hide(); return; } } // Move gating for first article to top of the screen on mobile if( FP.Utils.Piano.getMeterNamesToTargetMobilePositioning().includes(data.meterName) ) { FP.Utils.Piano.positionArticleGating(); } // Show the fixed/expandable Piano subscribe prompt template // Hide the takeover Piano subscribe prompt template $( '.in-article-subscribe-expandable-container' ).show(); $( '.in-article-subscribe-takeover-container' ).hide(); $( '.in-article-subscribe-takeover-other-options' ).hide(); // logging for troubleshooting console.log( 'PIANO LOG gating - onMeterActive ' + data.meterName ); try { // Do we already have a cookie with articles. const pathname = window.location.pathname const cRegEx = /^(?:.*;)?\s*__utp_mec\s*=\s*([^;]+)(?:.*)?$/ const base64RegEx = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/ let existingCookie = (document.cookie.match(cRegEx)||[,null])[1] // Try parsing this cookie. if(existingCookie !== null && base64RegEx.test(base64RegEx)) { existingCookie = JSON.parse(atob(existingCookie)); } // Create the paths array and add this articles path there. data.paths = existingCookie?.paths ?? []; // Push this free article to array if not there. if(!data.paths.includes(pathname)) { data.paths.push(pathname); } // Update the metering cookie. let meterCookie = encodeURIComponent('__utp_mec') + '=' + btoa(JSON.stringify(data)) + '; max-age=2592000' + '; domain=' + window.location.hostname + '; path=/;' + '; secure'; document.cookie = meterCookie; } catch(e) { console.error(e) } } }, /** * ------------------------------------------------------------------------ * Define which meters to target in gating/paywall * ------------------------------------------------------------------------ */ getMeterNamesToTarget: function() { return [ 'DefaultMeter', 'Regwallmeter', 'GiftingMeter', 'RedditMeter', 'WhitelistMeter', ]; }, /** * ------------------------------------------------------------------------ * Define which meters to target in gating/paywall mobile positioning (first article) * ------------------------------------------------------------------------ */ getMeterNamesToTargetMobilePositioning: function() { return [ 'DefaultMeter', 'GiftingMeter', 'RedditMeter', 'WhitelistMeter', ] }, /** * ------------------------------------------------------------------------ * Gating logic for Insider content * ------------------------------------------------------------------------ */ gateInsiderContent: function() { // Return if insider gating container is not present // Output of the container is determined with PHP cache group check for Insider if( $( '.insider-in-article-subscribe-container' ).length < 1 ) return; // Reload the page for IP access Insiders that are being incorrectly gated // when the 'vip-go-seg' cookie is not available on page load if( 'Insider' === FP?.Singletons?.UserAltAccess?.ipAccessData?.access_level && !window.location.search.includes("ipaccess_reload") ) { // Reload page, add URL parameter to avoid an infinite redirect loop window.location.href = window.location.href + '?ipaccess_reload=1'; } // Hide the full version of the article and show the truncated version. $( '.content-ungated' ).show().css( 'display', 'block' ); $( '.content-gated' ).hide(); $( '.in-article-placement' ).hide(); // Hide related content block $( '.fp-related-wrapper' ).hide().remove(); $( '.related-articles--insider' ).hide().remove(); // Hide the author, tag, and alerts content that appears below the Piano offer $( '.bio-no-photo' ).hide(); $( '.the-tags' ).hide(); $( '.js-myfp-container' ).eq(1).hide().remove(); // if an audio embed is present, hide the My FP prompt as well if ( $( '.fp-audio-embed--disabled' ).length > 0 ) { $( '.js-myfp-container' ).hide().remove(); } // Reduce min-height of sidebar sticky elements $( '.sidebar .sticky-container--delay' ).removeClass('sticky-container--delay'); // Restructure sidebar $( '.hide-on-gated-post' ).remove(); // hide sidebar content on mobile $( '.post-content .sidebar' ).addClass( 'hide-mobile' ); // hide mobile sticky ad and in-article ads on mobile $( 'body' ).addClass( 'hide-ads' ); }, /** * ------------------------------------------------------------------------ * Triggered by login required event from Piano * ------------------------------------------------------------------------ */ onLoginRequired: function( params ) { if('purchase' === params.offerType && 'modal' === params.displayMode) { // Set accessibility attributes for sign up/login modal // that is triggered from within an experience $('.tp-modal').attr('role','modal'); $('.tp-modal').attr('title','Sign up for an account'); $('.tp-modal').attr('tabindex','0'); $('.tp-modal').focus(); $('.tp-modal iframe').attr('title','Sign Up form'); $('.tp-modal iframe').attr('tabindex','0'); FP.Utils.trapFocus.init(document.querySelectorAll('.tp-modal')); FP.Utils.trapFocus.toggleInertAttribute(true); } // this is a reference implementation only // your own custom login/registration implementation would // need to return the tinypass-compatible userRef inside the callback // mysite.showLoginRegistration(function (tinypassUserRef) // tp.push(["setUserRef", tinypassUserRef]); // tp.offer.startCheckout(params); // } // this will prevent the tinypass error screen from displaying return false; }, /** * ------------------------------------------------------------------------ * Triggered by login required event from Piano * The registrationSuccess event fires when a user completes the * registration process using Piano ID * ------------------------------------------------------------------------ */ onRegistrationSuccess: function(data) { if(typeof zaraz !== undefined && FP.Config.is_production) { zaraz.track('registrationSuccess', data); } }, /** * ------------------------------------------------------------------------ * Callback executed after an experience executed successfully * ------------------------------------------------------------------------ */ onExperienceExecute: function(event) { // Add titles to injected Piano iframes FP.Utils.Piano.addTitlestoPianoIframes(); // Subscribe page // Hide secondary subscription content if user is viewing // the B version of the A/B test /* 2/11/21 - Remove this toggle until another A/B test is enabled if( $('.subscribe').length > 0 ) { var abTestCookie = tp.util.findCookieByName('_pc_variant'); if( 'b' === abTestCookie ) { $('.subscribe .secondary-content').hide(); } }*/ }, /** * ------------------------------------------------------------------------ * Callback executed after a response variable is sent from the experience * ------------------------------------------------------------------------ */ onSetResponseVariable: function(eventParams){ var responseVariables = eventParams.responseVariables; if( typeof responseVariables.show_inline_sub_prompt !== 'undefined' ) { if( responseVariables.show_inline_sub_prompt ) { // Add in-article subscribe prompt after the truncated gated content } } if( typeof responseVariables.fire_ar_experience !== 'undefined' ) { if( responseVariables.fire_ar_experience ) { // Move gating for first article to top of the screen on mobile FP.Utils.Piano.positionArticleGating(); // Hide "Give a Gift" button $('.gift-prompt').hide(); // Hide upgrade prompt $('.upgrade-to-insider-prompt').hide(); // Show renew button on /manage page $('.fp-manage-page .renew-button').show(); $('.renew-button').on('click', function(){ $('.renew-button > span').text( 'Processing...' ); FP.Utils.Piano.toggleAutoRenew( true ); }); } } if( typeof responseVariables.fire_winback_experience !== 'undefined' ) { // Move gating for first article to top of the screen on mobile FP.Utils.Piano.positionArticleGating(); // Hide "Give a Gift" button $('.gift-prompt').hide(); } if( typeof responseVariables.fire_sale_ribbon !== 'undefined' ) { // Move gating for first article to top of the screen on mobile FP.Utils.Piano.positionArticleGating(); } if( typeof responseVariables.fire_top_ribbon !== 'undefined' ) { // Move gating for first article to top of the screen on mobile FP.Utils.Piano.positionArticleGating(); } if( typeof responseVariables.fire_giftpromo_experience !== 'undefined' || typeof responseVariables.fire_winback_experience !== 'undefined' || typeof responseVariables.fire_ribbon_experience !== 'undefined' ) { // Add new class to body to alter the header button styles? $('body').addClass('piano_ribbon_shown'); } if ( typeof responseVariables.fire_ribbon_experience !== 'undefined' ) { const rootElement = document.documentElement; rootElement.style.setProperty('--piano-ribbon-height', $('#piano-sticky-header').outerHeight() + 'px'); } if( typeof responseVariables.full_width_page !== 'undefined' ) { $('#subscribe-page-piano-top .tp-container-inner').addClass('full-width-piano-container'); } }, /** * ------------------------------------------------------------------------ * Callback executed if experience execution has been failed * ------------------------------------------------------------------------ */ onExperienceExecutionFailed: function(event) { }, /** * ------------------------------------------------------------------------ * Callback executed if external checkout has been completed successfully * ------------------------------------------------------------------------ */ onExternalCheckoutComplete: function(event) { /* Default behavior is to refresh the page on successful checkout */ location.reload(); }, /** * ------------------------------------------------------------------------ * Determine if content should not be free in the app * ------------------------------------------------------------------------ */ isInsiderContent: function() { return postDataPiano.includes('insider'); }, /** * ------------------------------------------------------------------------ * Mobile refinements for article gating position on first article * ------------------------------------------------------------------------ */ positionArticleGating: function() { if( $(window).width() < 600 && ( $('.site-header .in-article-subscribe-expandable-container').length < 1 || $('.site-header .insider-in-article-subscribe-container--fixed').length < 1 ) ) { // Standard gating if( $('.site-header .in-article-subscribe-expandable-container').length < 1 ) { $('.site-header').append($('.in-article-subscribe-expandable-container')); } // Insider gating (mainly for article gifting gating) if( $('body.is-fp-insider').length > 0 && $('.site-header .insider-in-article-subscribe-container--fixed').length < 1 ) { $('.site-header').append($('.insider-in-article-subscribe-container--fixed')); } // Listen for Piano content injection via mutation observer // Node that will be observed for mutations var targetNode = document.querySelector('.in-article-subscribe-expandable-container'); if( $('body.is-fp-insider').length > 0 ) { targetNode = document.querySelector('.insider-in-article-subscribe-container--fixed'); } // Options for the observer (which mutations to observe) const config = { attributes: true, childList: true, subtree: true }; // Callback function to execute when mutations are observed const callback = function(mutationsList, observer) { for(let mutation of mutationsList) { // CSS injection to account for dynamic height of Piano content injection if (mutation.attributeName === 'style' && mutation.type === 'attributes' && mutation.target.className === 'tp-container-inner') { var offsetHeight = $('.in-article-subscribe-expandable-container').outerHeight() + $('.header-nav-wrapper').outerHeight(); $('html > head').append( $('') ); $('html > head').append( $('') ); } } }; // Create an observer instance linked to the callback function const observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Stop observing after four seconds setTimeout(function() { observer.observe(targetNode, config); }, 4000); } }, /** * ------------------------------------------------------------------------ * Load iframes within gated content * This is needed for iframes that calculate their width/height dynamically when the iframe loads * ------------------------------------------------------------------------ */ loadIframes: function() { var iframeDefer = document.querySelectorAll('.content-gated iframe'); for (var i = 0; i < iframeDefer.length; i++) { if (iframeDefer[i].getAttribute('data-src')) { iframeDefer[i].setAttribute('src', iframeDefer[i].getAttribute('data-src')); } } }, /** * ------------------------------------------------------------------------ * Check for user visit to a gifted article link * get 'gifting_article' URL param value * return string version of boolean value for use in Piano experience and this file * ------------------------------------------------------------------------ */ validateGiftingURL: function() { var urlGiftingParamValue = FP.Utils.url.getUrlParameter('gifting_article', false); var isUrlValid = 'false'; // pass string instead of boolean for use in Piano // continue if URL param value was found if( 'not found' !== urlGiftingParamValue ) { // get URL slug var urlSlug = FP.Utils.url.getUrlSlug(); // PostUp occassionally replaces the final '=' // in a gifting URL with '%3D' // adding a checkpoint to fix that here urlGiftingParamValue = urlGiftingParamValue.replaceAll('%3D','='); try { // check URL slug against base64 decoded URL param value if( urlSlug === atob(urlGiftingParamValue) ) { isUrlValid = 'true'; // pass string instead of boolean for use in Piano } } catch (error) { // console.error(error); } } return isUrlValid; }, /** * Helper to show Insider subscription page content when user chooses to expand benefits * * @return {void} */ showInsiderSubscriptionPage: function() { return new Promise( function( resolve, reject ) { $.ajax({ type: 'GET', url: '/wp-json/fp/get-page-by-template/page-insider', data: { pageTitle: 'FP Insider', template: 'layouts/pages/page-insider', }, async: true, cache: true, }).then(function( response ) { // add Insider subscription page content to container $( '#subscribe-takeover--insider' ).html(response); // hide header offer template $('.insider-page-header').css('display', 'none'); $( '#insider-page-header-subscribe' ).css( 'display', 'none' ); // show Insider subscription page content $( '#subscribe-takeover--insider' ).show(); // add footer offer template if( $('#insider-page-footer-subscribe').length > 0 ) { tp.offer.show({ offerId: 'OFEYAKCMFC7N', templateId: 'OTJLYPYEOAKZ', displayMode: 'inline', containerSelector: '#insider-page-footer-subscribe', termIds: [ 'TMN7TTZYTVOH' ], }); } // initialize carousel if present for Insider posts list if ($( '.posts-carousel' ).length > 0) { // Initialize Swiper new Swiper('.posts-carousel__posts-swiper', { loop: true, breakpoints: { 200: { slidesPerView: 1, slidesPerGroup: 1, }, 600: { slidesPerView: 2, slidesPerGroup: 1, }, 980: { slidesPerView: 3, slidesPerGroup: 1, } }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, }); } // lazy load images in Insider subscription page content $(document.body).trigger('post-load'); $('article img').addClass('lazy-image-loaded'); $('article .image-attachment').addClass('no-background-color'); // scroll user to subscribe takeover content $('html, body').animate({ scrollTop: $( '#subscribe-takeover--insider' ).offset().top - $('header').outerHeight() - 60 }, 500); }); }); }, /** * Helper to hide Insider subscription page content when user chooses to expand benefits * * @return {void} */ hideInsiderSubscriptionPage: function() { $( '#subscribe-takeover--insider' ).hide(); }, /** * Helper to toggle auto renew * * @return {void} */ toggleAutoRenew: function ( enable = true ) { // Get user's subscription info FP.Singletons.User.getUserSubscriptionInfo() .then(function(resp) { var results = resp.data; if( ( !results || typeof results === 'undefined' ) || ( !results.user_subscription || typeof results.user_subscription === 'undefined' ) ) { // return if the necessary data is not available return; } // Iterate through user's subscriptions Object.keys(results.user_subscription.subscriptions).forEach(subscription => { var usersubscription = results.user_subscription.subscriptions[subscription]; if( ( !usersubscription || typeof usersubscription === 'undefined' ) || ( typeof usersubscription.auto_renew === 'undefined' ) || ( typeof usersubscription.status === 'undefined' ) || ( typeof usersubscription.subscription_id === 'undefined' ) ) { // return if the necessary data is not available return; } // handle enable vs disable state change if( enable ) { // Continue if auto-renew is disabled and the subscription is active if( !usersubscription.auto_renew && 'active' === usersubscription.status ) { var subscriptionId = usersubscription.subscription_id; if( !subscriptionId || typeof subscriptionId === 'undefined' ) { // return if the necessary data is not available return; } // update auto-renew value to 'true' FP.Singletons.User.updateUserAutoRenew( subscriptionId, true ) .then(function(resp) { var results = resp.data; // check results for successful code value of 0 if( 0 === results.code ) { // update renewal button text $('.renew-button > span').html( '✓  Confirmed' ); // Disable click for .renew-button $('.renew-button').prop('onclick', null).off('click'); // show success message $('#piano-sticky-header').html( '✓  Success! Your FP access will continue uninterrupted.' ).css({ 'background':'#5dae0e', 'padding':'10px 14px 11px', 'text-align':'center' }); } }); } } else { // Continue if auto-renew is enabled and the subscription is active if( usersubscription.auto_renew && 'active' === usersubscription.status ) { var subscriptionId = usersubscription.subscription_id; if( !subscriptionId || typeof subscriptionId === 'undefined' ) { // return if the necessary data is not available return; } // update auto-renew value to 'false' FP.Singletons.User.updateUserAutoRenew( subscriptionId, false ) .then(function(resp) { $('#piano-manage > iframe').attr('src', $('#piano-manage > iframe').attr('src')); }); } } }); }); }, /** * ------------------------------------------------------------------------ * Manage page * ------------------------------------------------------------------------ */ buildManagePage: function() { // Exit if user is not on Manage page if ( !$('.fp-manage-page') ) { return; } // Toggle display of FP manage content if ( FP.Singletons.User.hasAccount || FP.Singletons.User.isSub || FP.Singletons.User.isPrem ) { $('.fp-manage-anon').hide(); // $('.fp-manage-menu').show(); } if ( FP.Singletons.User.isIPAccess && !FP.Singletons.User.hasAccount ) { $('.fp-manage-reg').each(function() { $( this ).hide(); }); } if ( FP.Singletons.User.hasAccount && !FP.Singletons.User.isSub ) { $('.fp-manage-reg').each(function() { $( this ).show(); }); } if ( FP.Singletons.User.isSub || FP.Singletons.User.isPrem ) { $('.fp-manage-sub').each(function() { $( this ).show(); }); } if ( FP.Singletons.User.isPrem ) { $('.fp-manage-premium').each(function() { $( this ).show(); }); } // Show Piano manage content tp.myaccount.show({ displayMode: 'inline', containerSelector: '#piano-manage' }); }, /** * ------------------------------------------------------------------------ * Enable commenting * * Send a REST request with Piano UID, which will generate a JWT token * to pass to Coral, which will authenticate the user. * * Store the token in a cookie to avoid extra calls subsequent pageloads. * ------------------------------------------------------------------------ */ enableCommenting: function() { if ( tp.user.isUserValid() && FP.Singletons.User.isSub ) { if ( FP.Singletons.User.userData.customFields.comments_username ) { $( '.username-placeholder' ).html( FP.Singletons.User.userData.customFields.comments_username ); $( '.username-input' ).val( FP.Singletons.User.userData.customFields.comments_username ); } var coral_token = $.cookie( 'fp-coral-token' ); if ( coral_token && window.coral_embed ) { window.coral_embed.login( coral_token ); } else { jQuery.ajax( { url: '/wp-json/fp/coral-jwt', data: { uid: tp.pianoId.getUser().uid, username: FP.Singletons.User.userData.customFields.comments_username }, type: 'POST', async: true, success: function ( response ) { if ( response.token && window.coral_embed ) { $.cookie( 'fp-coral-token', response.token, { expires: 1, path: '/' } ); window.coral_embed.login( response.token ); } }, error: function( request, error ) { console.error( error ); } } ); } } }, /** * ------------------------------------------------------------------------ * Show browser compatibility error modal * * This primarily targets browsers that are blocking the * Piano JS from loading (Firefox is the main offender as of July 2024) * ------------------------------------------------------------------------ */ showBrowserCompatibilityErrorModal: function() { $('body').addClass('sticky_content_takeover_shown'); $('#browser-compatibility-error').removeAttr('aria-hidden'); $('#browser-compatibility-error').attr('tabindex','0'); $('#browser-compatibility-error').attr('aria-labelledby','browser-compatibility-error-message'); $('#browser-compatibility-error').focus(); $('.sticky_content_takeover--close, .sticky_content_takeover--close-text').click( function(){ $('body').removeClass('sticky_content_takeover_shown'); $('#browser-compatibility-error').attr('aria-hidden', 'true'); $('#browser-compatibility-error').removeAttr('tabindex'); }); }, }; }(jQuery); ; //~Singletons/User // // Helper funcs for interacting with identity provider !function ($) { var usePianoProduction = window.pianoData.use_piano_environment; if( 'production' === usePianoProduction ) { // Production var pianoAid = 'beVmoi3WRm'; var pianoAPIFile = '//pianocdn.foreignpolicy.com/api/tinypass.min.js'; } else { // Sandbox var pianoAid = 'Q0Q1FMiXiK'; var pianoAPIFile = '//pianocdn-sb.foreignpolicy.com/api/tinypass.min.js'; } window.dataLayer = window.dataLayer || []; /* Initialize Piano */ function initializePiano( postDataPianoFinal ){ tp = window.tp || []; /** * ------------------------------------------------------------------------ * Pass article tag data to Piano * ------------------------------------------------------------------------ */ function passDataToPiano( postDataPianoFinal ) { tp.push(["setTags", postDataPianoFinal]); } passDataToPiano( postDataPianoFinal ); /** * ------------------------------------------------------------------------ * Initialize Piano * ------------------------------------------------------------------------ */ // Initialize utility helper in /assets/src/scripts/utils/piano.js FP.Utils = FP.Utils || {}; FP.Utils.Piano.init(); // Initialize Piano ID tp.push(["setAid", pianoAid]); tp.push(["setCxenseSiteId", "1139724983415417198"]); /* domain whitelabeling - https://docs.piano.io/full-domain-whitelabeling/ */ if( "production" === usePianoProduction ) { tp.push(["setComposerHost","https://pianocomposer.foreignpolicy.com"]); tp.push(["setPianoIdUrl", "https://pianoauth.foreignpolicy.com"]); tp.push(["setEndpoint", "https://pianovx.foreignpolicy.com"]); tp.push(["setStaticDomain", "https://pianocdn.foreignpolicy.com"]); } else { tp.push(["setComposerHost","https://pianocomposer-sb.foreignpolicy.com"]); tp.push(["setPianoIdUrl", "https://pianoauth-sb.foreignpolicy.com"]); tp.push(["setEndpoint", "https://pianovx-sb.foreignpolicy.com"]); tp.push(["setStaticDomain", "https://pianocdn-sb.foreignpolicy.com"]); } /* do not use Piano Go/Tinypass Accounts legacy user management integration */ tp.push(["setUseTinypassAccounts", false]); /* use Piano id */ tp.push(["setUsePianoIdUserProvider", true]); /* set content created value from meta data if present */ if(document.querySelector('meta[name=content_created]')) { tp.push(["setContentCreated", document.querySelector('meta[name=content_created]').getAttribute('content')]); } /* Piano cookie setting - first party */ tp.push(["setCloudflareWorkerUrl", window.location.origin + "/endpoint/piano-cookies/?__fp_endpoint_piano_cookies=1"]); /* FB IA tracking (https://docs.piano.io/facebook-experiences/#IAscript) */ tp.push(["setFbPixelId", "203988873637408"]); /* checkout related events */ tp.push(["addHandler", "checkoutComplete", FP.Utils.Piano.onCheckoutComplete]); tp.push(["addHandler", "checkoutClose", FP.Utils.Piano.onCheckoutClose]); tp.push(["addHandler", "checkoutCustomEvent", FP.Utils.Piano.onCheckoutExternalEvent]); tp.push(["addHandler", "checkoutCancel", FP.Utils.Piano.onCheckoutCancel]); tp.push(["addHandler", "checkoutError", FP.Utils.Piano.onCheckoutError]); tp.push(["addHandler", "checkoutSubmitPayment", FP.Utils.Piano.onCheckoutSubmitPayment]); tp.push(["addHandler", "checkoutStateChange", FP.Utils.Piano.onCheckoutStateChange]); tp.push(["addHandler", "startCheckout", FP.Utils.Piano.startCheckout]); /* my account related events */ tp.push(['addHandler', 'customEvent', FP.Utils.Piano.onCustomEvent]); /* upgrade related events */ tp.push(["addHandler", "completeUpgradePurchase", FP.Utils.Piano.onCompleteUpgradePurchase]); /* user login events */ tp.push(["addHandler", "loginRequired", FP.Utils.Piano.onLoginRequired]); tp.push(["addHandler", "registrationSuccess", FP.Utils.Piano.onRegistrationSuccess]); /* content gating */ if ( postDataPianoFinal.includes('FP Insider') && 'false' === FP.Utils.Piano.validateGiftingURL() ) { /* handle Insider gating that is not accessed via article gifting URL */ FP.Utils.Piano.gateInsiderContent(); } else { /* meter related to standard content */ tp.push(["addHandler", "meterExpired", FP.Utils.Piano.onMeterExpired]); tp.push(["addHandler", "meterActive", FP.Utils.Piano.onMeterActive]); } tp.push(["addHandler", "experienceExecute", FP.Utils.Piano.onExperienceExecute]); tp.push(["addHandler", "experienceExecutionFailed", FP.Utils.Piano.onExperienceExecutionFailed]); /* get response variable from experience */ tp.push(["addHandler", "setResponseVariable", FP.Utils.Piano.onSetResponseVariable]); /* external checkout related events */ tp.push(["addHandler", "externalCheckoutComplete", FP.Utils.Piano.onExternalCheckoutComplete]); /* handle user login, signup and logout button clicks - callback executed after a tinypassAccounts login */ tp.push(["addHandler", "loginSuccess", function(data){ // Any logic required after a successful login if ( tp.user.isUserValid() ) { // Create or get Sailthru User FP.Utils.Piano.syncUserToST(data.user_token); FP.Utils.Piano.sendSignedFbPixel( 'LogIntoAccount', { subscription_id: data.params.uid, is_subscriber: true }); window.dispatchEvent(new CustomEvent('rudder:identify', { detail: { user_id: data.params.uid, traits: { first_name: data.params.firstName, last_name: data.params.lastName, email: data.params.email } } })); } // Toggle display of authenticated user content in header FP.Utils.Piano.toggleHeaderContent(); if( true === data.registration ) { // login came from registration } else if( "PIANOID" === data.source ) { // login came from standard login, not within an offer flow FP.Singletons.User.setUserCacheGroup( data.params.uid, true ); } }]); /** * ------------------------------------------------------------------------ * Load Piano API JS file * ------------------------------------------------------------------------ */ // Alert user if Piano script is blocked by their browser ((src) => { return new Promise( function(t,e) { let n = document.createElement("script"); n.src = src, n.type = "text/javascript", n.defer = "defer", n.onerror = (()=>e()), n.onload = ( () => { if("function" === typeof window.___tp) { ( tp=window.tp || [], tp.push(["init",function(){t()}]) ) } else { e(); } } ); let o = document.getElementsByTagName("script")[0]; o.parentNode.insertBefore(n,o); } ); })(pianoAPIFile).then( () => { // tinypass.min.js is loaded and initialized }, () => { // The tinypass.min.js script was blocked due to a browser content filter // Show error modal to user FP.Utils.Piano.showBrowserCompatibilityErrorModal(); } ) // Initialize Piano tp.push(["init", function() { // ensure cross domain tracking tp.enableGACrossDomainLinking('UA-6874192-41'); // Google Analytics 4 configuration tp.setGA4Config({ measurementId: 'G-T5CKP06L0Y', eventParameters: { send_page_view: false, } }); // If user is logged in if (tp.user.isUserValid()) { // Get the stored cookie value var paramsCookie = tp.util.findCookieByName('__pianoParams'); var params; try { // Try to parse stored JSON data params = JSON.parse(paramsCookie); // Remove the old cookie document.cookie = "__pianoParams=null; expires=-1;" + " path=/; domain=.foreignpolicy.com"; } catch (e) { params = false; } } // Check for gift URL parameters and validate if present // Send validation result to Piano as a custom variable // This must be performed before the `tp.experience.init()` below tp.setCustomVariable( "gift_url_validation", FP.Utils.Piano.validateGiftingURL() ); // Get meta page title for use in Piano experience text var pageTitle = document.querySelector(".article .hed-heading .hed"); if( pageTitle ) pageTitle = pageTitle.innerHTML; tp.setCustomVariable( "fp_page_title", pageTitle ); // Initialize Piano experience // unless user is viewing article in our app and the article is not insider only if( !FP.Utils.Piano.isUserFromApp() || ( FP.Utils.Piano.isUserFromApp() && FP.Utils.Piano.isInsiderContent() ) ) { tp.pianoId.init({ loggedOut: function() { // Reload the page after Piano has completed the logout process location.reload(); } }); tp.experience.init(); } /** * ------------------------------------------------------------------------ * Check user access * ------------------------------------------------------------------------ */ // Check for FP.Singletons instance FP.Singletons = FP.Singletons || {}; // Create User class FP.Singletons.User = { isInsider: false, isPrem: false, isSub: false, isISpyPlus: false, hasAccount: false, // has Piano account isReg: false, // has access to REGISTRATION Piano resource isIPAccess: false, isLinkAccess: false, userData: { uid: '', email: '', first_name: '', last_name: '', personal_name: '', customFields: {} }, ipAccessData: {}, /** * Listener for all subscription check events to finish */ accessCheckCompleteListener: function () { var that = this; // Listener var MyRequestsCompleted = (function() { var numRequestToComplete, requestsCompleted, callBacks, singleCallBack; return function(options) { if (!options) options = {}; numRequestToComplete = options.numRequest || 0; requestsCompleted = options.requestsCompleted || 0; callBacks = []; var fireCallbacks = function() { for (var i = 0; i < callBacks.length; i++) callBacks[i](); }; if (options.singleCallback) callBacks.push(options.singleCallback); this.addCallbackToQueue = function(isComplete, callback) { if (isComplete) requestsCompleted++; if (callback) callBacks.push(callback); if (requestsCompleted == numRequestToComplete) fireCallbacks(); }; this.requestComplete = function(isComplete) { if (isComplete) requestsCompleted++; if (requestsCompleted == numRequestToComplete) fireCallbacks(); }; this.setCallback = function(callback) { callBacks.push(callBack); }; }; })(); // Set number of events and callback for listener that.requestCallback = new MyRequestsCompleted({ numRequest: 2, singleCallback: function(){ FP.Utils.Piano.toggleBodyClass(); FP.Utils.Piano.toggleHeaderContent(); FP.Utils.Piano.updateGiftingLink(); FP.Utils.Piano.buildManagePage(); $.event.trigger('pianoAccessCheckComplete'); FP.Singletons.User.trackLoginData(); // Added to dispatch via vanilla JS const pianoEvt = new CustomEvent('accessPianoComplete'); window.dispatchEvent(pianoEvt, FP.Singletons.User); } }) }, /** * Helper that houses function calls to set user's access levels and Piano data * * @return {void} */ setAccess: function () { var that = this; that.accessCheckCompleteListener(); that.isPianoAccess(); that.isOtherAccess(); window.pianoReady = true; }, /** * Helper to evaluate user's Piano account access and * set data accordingly in the FP.Singletons.User object * * @return {void} */ isPianoAccess: function() { var that = this; // Process the user access info that came from the server-side // via Foreignpolicy_User_Cache_Group_Helper::get_user_access_levels if ( window.pianoData.userLevels && tp.user.isUserValid() ) { var userLevels = window.pianoData.userLevels; that.setUserSubLevels( userLevels ); if ( $.cookie( 'fp-user-data' ) ) { that.userData = JSON.parse( $.cookie( 'fp-user-data' ) ); } else { that.setPianoUserData(); } that.fetchCustomFields( 'onboarding_flow' ); that.fetchCustomFields( 'events_registration_fields' ); that.fetchCustomFields( 'comments_form', function() { FP.Utils.Piano.enableCommenting(); } ); } // VIP cache cookie has already been set // cookie duration is 1 day if ( typeof $.cookie( 'vip-go-seg' ) !== 'undefined' && ! FP.Singletons.UserAltAccess.isIPAccess ) { // // TO-DO // - set cookie with all the that.isInsider, etc. sub details and that.userData data as well // this can be evaluated here to set all the data relative to the FP.Singletons.User object // if( tp.user.isUserValid() ) { that.setPianoUserData(); } that.requestCallback.requestComplete(true); return; } else if( tp.user.isUserValid() ) { // VIP cache cookie has not been set var pianoUserData = tp.pianoId.getUser(); tpUserId = pianoUserData.uid; // Reload page for Piano users var reloadPage = true; // Do not reload if user is also an IP Access user // as this causes a redirect loop if( FP.Singletons.UserAltAccess.isIPAccess ) reloadPage = false; Promise.all([ that.setUserCacheGroup( tpUserId, reloadPage ), ]).then(function (results) { that.requestCallback.requestComplete(true); }).catch(function (reason) { //reject(reason); }); // User is not logged into Piano } else { that.requestCallback.requestComplete(true); } }, /** * Helper to determine if user is coming from the app, * or has either IP access or link access * * @return {void} */ isOtherAccess: function () { var that = this; if( FP.Utils.Piano.isUserFromApp() || FP.Singletons.UserAltAccess.isIPAccess || FP.Singletons.UserAltAccess.isLinkAccess ) { that.isPrem = true; that.isSub = true; that.isISpyPlus = true; // only set the gated content to show if the current post is not an FP Insider post if ( !postDataPianoFinal.includes('FP Insider') ) { // Workaround for IP access users coming from proxy URL // to ensure the full article content displays $( '.content-ungated' ).hide(); $( '.content-gated' ).show(); } if( FP.Singletons.UserAltAccess.isIPAccess ) { that.isIPAccess = FP.Singletons.UserAltAccess.ipAccessData.access; that.ipAccessData = FP.Singletons.UserAltAccess.ipAccessData; if( 'Insider' === FP.Singletons.UserAltAccess.ipAccessData.access_level ) { that.isInsider = true; if( FP.Singletons.User.isInsider ) { $( 'body' ).addClass( 'insider_user_ip' ); } } // Send pixel to Facebook to exclude IP access subs // from our paid marketing campaigns FP.Utils.Piano.sendSignedFbPixel( 'ip_access', { is_ip_access: 'true' } ); // Hide comment-related elements from IP Access clients, for now $( '.hide-ip-access' ).remove(); } if( FP.Singletons.UserAltAccess.isLinkAccess ) { that.isLinkAccess = FP.Singletons.UserAltAccess.isLinkAccess.access; that.linkAccessData = FP.Singletons.UserAltAccess.linkAccessData; } } that.requestCallback.requestComplete(true); return; }, /** * Helper to set user's Piano custom fields in the FP.Singletons.User object */ fetchCustomFields: function( form_name, callback ) { tp.pianoId.loadExtendedUser( { extendedUserLoaded: function ( data ) { FP.Singletons.User.userData.customFields = FP.Singletons.User.userData.customFields || []; for ( var i in data.custom_field_values ) { var fieldName = data.custom_field_values[i].field_name; var fieldValue = data.custom_field_values[i].value; FP.Singletons.User.userData.customFields[fieldName] = fieldValue; } if( 'onboarding_flow' === form_name ) { $.event.trigger('pianoOnboardingDataReady'); } // Only continue below if processing custom fields from the comments form if( 'comments_form' !== form_name ) return; if ( FP.Singletons.User.isSub ) { var username_set = !!FP.Singletons.User.userData.customFields.comments_username; if ( ! username_set ) { $( '.comment-username-text' ).hide(); if(!FP.Singletons.User.userData.last_name) FP.Singletons.User.userData.last_name = ' '; FP.Singletons.User.userData.customFields.comments_username = FP.Singletons.User.userData.first_name + FP.Singletons.User.userData.last_name.charAt(0); $( '.comment-username-form.user-content' ).show(); } } if ( 'true' === FP.Singletons.User.userData.customFields.commenting_guidelines_consent ){ $( 'input[name="commenting-guidelines-consent"]' ).attr( 'checked', 'checked' ); } $.cookie( 'fp-user-data', JSON.stringify( FP.Singletons.User.userData ), { expires: 1, path: '/' } ); if ( callback ) { callback(); } }, formName: form_name } ); }, /** * Helper to set user's Piano data in the FP.Singletons.User object * * @return {void} */ setPianoUserData: function() { var that = this; var pianoUserData = tp.pianoId.getUser(); if( pianoUserData ) { // Set uid if not already present if ( ! that.userData.uid ) { that.userData.uid = pianoUserData.uid; } // Set remaining user data that.userData.email = pianoUserData.email; that.userData.first_name = pianoUserData.firstName; that.userData.last_name = pianoUserData.lastName; that.userData.personal_name = that.userData.first_name + ' ' + that.userData.last_name; } }, /** * Helper to set user's subscription levels in the FP.Singletons.User object * * @param {object} userLevels User level data from VIP cache cookie * * @return {void} */ setUserSubLevels: function( userLevels ) { var that = this; that.isInsider = userLevels.isInsider; that.isPrem = userLevels.isPremium || userLevels.isInsider; that.isSub = userLevels.isSub || userLevels.isPremium || userLevels.isInsider; that.isISpyPlus = userLevels.isIspyPlus || userLevels.isPremium || userLevels.isInsider; that.isReg = userLevels.isReg; that.hasAccount = userLevels.hasAccount || userLevels.isReg || userLevels.isSub || userLevels.isPremium || userLevels.isInsider; }, /** * Helper to set user cache group with VIP * * @return {void} */ setUserCacheGroup: function ( pianoUid, reload ) { var that = this; return new Promise( function( resolve, reject ) { $.ajax({ type: 'POST', url: '/wp-admin/admin-ajax.php', data: { action: 'set_user_cache_group', uid: pianoUid, token: window.pianoData.cache_group_nonce }, success: function( response ) { that.setUserSubLevels( response ); if( tp.user.isUserValid() ) { that.setPianoUserData(); } that.fetchCustomFields( 'onboarding_flow' ); that.fetchCustomFields( 'comments_form', function() { FP.Utils.Piano.enableCommenting(); if( true === reload ) { location.reload(); } } ); } }).done( resolve ).fail( reject ); } ); }, /** * Helper to get user subscription info * * @return {void} */ getUserSubscriptionInfo: function () { var that = this; return $.ajax({ url: '/piano-user-check/results/', data: { '__fp_endpoint_piano_ajax' : 1, '__fp_endpoint_piano_action' : 'user_subscription', '__fp_endpoint_piano_user_id' : that.userData.uid, }, cache: true }); }, /** * Check if the email address has a Piano account. * * @param {string} email * * @returns {Object} jQuery jqXHR object. */ checkEmailHasSiteAccount: function (email) { return $.ajax({ url: '/piano-user-check/results/', data: { '__fp_endpoint_piano_ajax' : 1, '__fp_endpoint_piano_action' : 'email', '__fp_endpoint_piano_user_email': email }, cache: false }); }, /** * Log user into Piano account. * * @param {string} email * @param {string} password * * @returns {Object} jQuery jqXHR object. */ userLogin: function (email, password) { return $.ajax({ url: '/piano-user-check/results/', data: { '__fp_endpoint_piano_ajax' : 1, '__fp_endpoint_piano_action' : 'login', '__fp_endpoint_piano_user_email' : email, '__fp_endpoint_piano_user_password': password }, cache: false }); }, /** * Register user account in Piano. * * @param {string} email * @param {string} password * @param {string} firstname * @param {string} lastname * * @returns {Object} jQuery jqXHR object. */ userRegister: function (email, password, firstname, lastname) { return $.ajax({ url: '/piano-user-check/results/', data: { '__fp_endpoint_piano_ajax' : 1, '__fp_endpoint_piano_action' : 'register', '__fp_endpoint_piano_user_email' : email, '__fp_endpoint_piano_user_password' : password, '__fp_endpoint_piano_user_firstname': firstname, '__fp_endpoint_piano_user_lastname' : lastname, '__fp_endpoint_piano_user_consent' : true }, cache: false }); }, /** * Helper to update user auto renew value * * @return {void} */ updateUserAutoRenew: function ( subscriptionId, autoRenew ) { var that = this; return $.ajax({ url: '/piano-user-update/results/', data: { '__fp_endpoint_piano_ajax_update_user' : 1, '__fp_endpoint_piano_action_update_user' : 'update_user_auto_renew', '__fp_endpoint_piano_user_subscription_id' : subscriptionId, '__fp_endpoint_piano_user_auto_renew' : autoRenew, '__fp_endpoint_piano_user_nonce' : window.pianoData.cache_group_nonce || '', }, cache: false }); }, /** * Helper to send analytic data * * @return {void} */ trackLoginData: function() { var that = this; // Set user group per subscription level var user_group = ''; var subscriber_state = ''; if( that.isInsider ) { user_group = 'insider_subscriber'; subscriber_state = 'Subscribed - Insider'; } else if( that.isPrem ) { user_group = 'premium_subscriber'; subscriber_state = 'Subscribed - Premium'; } else if( that.isSub ) { user_group = 'basic_subscriber'; subscriber_state = 'Subscribed - Basic'; } else if( that.isISpyPlus ) { user_group = 'i_spy_plus_user'; subscriber_state = 'Subscribed - I Spy Plus'; } else if( that.isReg || that.hasAccount ) { user_group = 'registered_user'; subscriber_state = 'Registered'; } // Continue if user is authenticated via Piano or IP/Link access if( '' !== user_group ) { var user_id = ''; var event_category = ''; if( FP.Singletons.UserAltAccess.isIPAccess ) { user_id = that.ipAccessData.client_guid; user_group = 'default-IP_access'; event_category = 'IP'; } else if( FP.Singletons.UserAltAccess.isLinkAccess ) { user_id = that.linkAccessData.ID; user_group = 'default-link_access'; event_category = 'LinkAccess'; } else { user_id = that.userData.uid; event_category = 'Piano'; } // Send data to GA gtag('event', 'track_login', {'LID': user_id}); gtag('event', 'track_login', {'RGRP': user_group}); gtag('event', 'track_login', {'VID': user_id}); if(typeof zaraz !== 'undefined') { let pageScope = { scope: 'page' }; zaraz.set('subscriberState', subscriber_state, pageScope); zaraz.set('accessId', user_id, pageScope); zaraz.set('accessGroup', user_group, pageScope); } dataLayer.push({ 'subscriberState': subscriber_state, 'accessId': user_id, 'accessGroup': user_group }); // Send data to GA gtag('event', 'matchedSubscriber', { 'event_category': event_category }); } else { $('body').addClass('anon_user'); // Send data to GA gtag('event', 'matchedNonSubscriber', { 'event_category': 'Nonsub' }); } // Only send the ViewContent event on article pages if ( -1 < postDataPiano.indexOf( 'article' ) ) { if ( window.fbq ) { fbq( 'track', 'ViewContent', { article_content_tier: 'metered', is_subscriber: ( '' !== user_group && 'registered_user' !== user_group ) } ); } } }, }; FP.Singletons.User.setAccess(); }]); } $(document).on('altAccessCheckComplete', function( event, postDataPianoFinal ) { initializePiano( postDataPianoFinal ); }); }(jQuery); ; //~Singletons/UserAltAccess // // Helper funcs for evaluating alternate access - traffic from app, IP access, or link access !function ($) { // Check for FP.Singletons instance FP.Singletons = FP.Singletons || {}; FP.Singletons.UserAltAccess = { isIPAccess: false, isLinkAccess: false, ipAccessData: {}, linkAccessData: {}, isAltAccess: function () { var that = this; new Promise(function (resolve, reject) { return Promise.all([ that.getIpAccessData() /* that.getLinkAccessData() - REMOVED FOR NOW AS WE DON'T HAVE ANY LINK ACCESS CLIENTS */ ]) .then(function (results) { var ipAccessResults = results[0]; that.isIPAccess = ipAccessResults.access; var postDataPianoFinal = postDataPiano; if( that.isIPAccess ) { // set user data that.ipAccessData = ipAccessResults; // Reset 'article' value to avoid triggering paywall for (var i = 0; i < postDataPianoFinal.length; i++) { if (postDataPianoFinal[i] == 'article') postDataPianoFinal[i] = 'article-ipaccess'; } // Add a new Piano tag to allow user access to Insider content if( that.ipAccessData.access_level === 'Insider' ) { postDataPianoFinal.push('article-ipaccess-insider'); } } // additional call to ensure vip-go-seg cookie gets set $.ajax({ type: 'POST', url: '/wp-admin/admin-ajax.php', data: { action: 'set_user_cache_group', ip_proxy_access_level: that.ipAccessData.access_level.toLowerCase(), token: pianoData.cache_group_nonce }, success: function( response ) { // handle response here if needed } }).done( resolve ).fail( reject ); /* REMOVED FOR NOW AS WE DON'T HAVE ANY LINK ACCESS CLIENTS var linkAccessResults = results[1]; that.isLinkAccess = linkAccessResults.access; if( that.isLinkAccess ) { // set user data that.linkAccessData = linkAccessResults; // Reset 'article' value to avoid triggering paywall for (var i = 0; i < postDataPianoFinal.length; i++) { if (postDataPianoFinal[i] == 'article') postDataPianoFinal[i] = 'article-linkaccess'; } } */ $.event.trigger('altAccessCheckComplete', [ postDataPianoFinal ]); resolve(true); }) .catch(function (results) { var ipAccessResults = results[0]; if( typeof ipAccessResults !== 'undefined' && typeof ipAccessResults.access !== 'undefined' ) { that.isIPAccess = ipAccessResults.access; } $.event.trigger('altAccessCheckComplete', [ postDataPiano ]); resolve(true); }).finally(() => { // Added to dispatch event via vanilla JS in both instances const altEvt = new CustomEvent('accessAltComplete'); window.dispatchEvent(altEvt, FP.Singletons.UserAltAccess); }); }); return; }, /** * Get IP access data from server * * E.g., * ```javascript * FP.Singletons.UserAltAccess.getIpAccessData( * function (data) { * // ... * }, * function (reason) { * // ... * } * ); * ``` * * @return {Promise} { * {Boolean} access * {null/String} access_type * {Number} expires * {null/String} client_guid * {null/String} message * } */ getIpAccessData: function () { return new Promise(getIpAccessDataHelper); }, /** * Get link access data from the server for the "Universal Link" concept * * E.g., * ```javascript * FP.Singletons.UserAltAccess.getLinkAccessData().then(data => console.log(data)); * // { access: false, message: '' } * ``` * * @return {Promise} { * {Number} ID * {Boolean} access * {String} message * } */ getLinkAccessData: function () { new Promise(function (resolve, reject) { var accessToken = getLinkAccessToken(); var cachedAccessToken = getCachedLinkAccessToken(); if (!accessToken && !cachedAccessToken) { setTimeout(function () { resolve({ ID: 0, access: false, message: '', }); }, 10); return; } function format_string(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, index) { return undefined === args[index] ? match : args[index]; }); } $.getJSON(format_string(FP.Config.api.link_access, (accessToken || cachedAccessToken))) .done(function (data) { resolve(data); if (accessToken && accessToken !== cachedAccessToken) { setCachedLinkAccessToken(accessToken); } }) .fail(reject); }) }, /** * Helper to determine whether user is coming from app; * if `true` we don't want to gate * * E.g., * ```javascript * console.log(FP.Singletons.UserAltAccess.isFromApp()); * // `true` or `false` * ``` * * @return {Boolean} */ isFromApp: (function () { var isFromApp = ( 'true' === FP.Utils.url.getUrlParameter('app') ); return function () { return isFromApp; }; })(), }; FP.Singletons.UserAltAccess.isAltAccess(); //=Constants var LOCALSTORAGE_ENC_KEY = 'FP-ip-access--enc'; var LOCALSTORAGE_LINK_ACCESS_KEY = 'FP-link-access--data'; var EXPIRATION_LINK_ACCESS_DATA = 1e3 * 60 * 60 * 24; //=24 hours in milliseconds /** * Helper to retrieve IP access data * * @param {Function} resolve * @param {Function} reject */ function getIpAccessDataHelper (resolve, reject) { // Retrieve data from server var data = {}; var enc = window.localStorage.getItem(LOCALSTORAGE_ENC_KEY); if (enc) { data.enc = enc; } else { data.proxy_host = document.location.hostname; } $.ajax({ type: "POST", url: FP.Config.api.ip_access, data: data, timeout: 3000, success: function( response ) { if (response.enc) { window.localStorage.setItem(LOCALSTORAGE_ENC_KEY, response.enc); } else { window.localStorage.removeItem(LOCALSTORAGE_ENC_KEY); } resolve(response.pay); }, error: function( jqXHR, textStatus, errorThrown ) { window.localStorage.removeItem(LOCALSTORAGE_ENC_KEY); } }) .done( resolve ) .fail(function () { reject([{ access: false, access_type: null, expires: -1, client_guid: null, message: null }]); }); } /** * Helper to get link access token match from URL hash * * @return {String} */ function getLinkAccessToken () { var result = /(?:^k|\Wk)\/([%.~\w-]+)\//.exec(document.location.hash); return (result !== null && result[1]) || ''; } /** * Helper to get cached link access token if available * * @return {String} */ function getCachedLinkAccessToken () { var cachedData = JSON.parse(window.localStorage.getItem(LOCALSTORAGE_LINK_ACCESS_KEY)); if ( !cachedData || !cachedData.token || !cachedData.expires || (new Date()).getTime() >= cachedData.expires ) { window.localStorage.removeItem(LOCALSTORAGE_LINK_ACCESS_KEY); return ''; } return cachedData.token; } /** * Helper to set cached link access token * * @param {String} accessToken */ function setCachedLinkAccessToken (accessToken) { if (!accessToken) { return; } window.localStorage.setItem(LOCALSTORAGE_LINK_ACCESS_KEY, JSON.stringify({ token: accessToken, expires: (new Date()).getTime() + EXPIRATION_LINK_ACCESS_DATA })); } /** * Helper to show IP message to specific users * * @param {String} ipAccessRecord */ function showIPMessage (ipAccessRecord) { var guidsToTarget = [ '02ec422849c64bce852ddd1d0fef7dc2', // Ministry of Defence UK '54635fd3a57e4780aa661658f73f4ad2', // Australian Department of Foreign Affairs 'dbaeae4f0b5442ef8a26a5aaeb65f87c', // Congressional Research Service 'e4f4504bcb754855a923152216edf04b', // Council de EU '30863845273342dcaee3e48f86ce4990', // Canadian Parliament ]; if( guidsToTarget.indexOf(ipAccessRecord.client_guid) > -1 ) { $('.ip-access-note-in-post').show(); } } }(jQuery); ;