{"version":3,"file":"default/js/productListing.js","mappings":"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","sources":["webpack://vodafoneziggo/webpack/runtime/chunk loaded","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/VZAccordion.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/VZSpinner.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/modal.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/productListing/components/VZPlpProductTile.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/productListing/components/VZPlpQuantitySelector.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/cookies.js","webpack://vodafoneziggo/./cartridges/app_business_scan/cartridge/client/default/js/components/modal.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/VZPlpSidebar.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/VZLayoutToggle.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/components/VZAdvisoryCard.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/productListing/filterAndSortBar.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/constants.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/urlUtils.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/util.js","webpack://vodafoneziggo/./cartridges/app_vodafone_ziggo/cartridge/client/default/js/util/validation.js","webpack://vodafoneziggo/webpack/bootstrap","webpack://vodafoneziggo/webpack/runtime/amd options","webpack://vodafoneziggo/webpack/runtime/compat get default export","webpack://vodafoneziggo/webpack/runtime/define property getters","webpack://vodafoneziggo/webpack/runtime/global","webpack://vodafoneziggo/webpack/runtime/hasOwnProperty shorthand","webpack://vodafoneziggo/webpack/runtime/runtimeId","webpack://vodafoneziggo/webpack/runtime/jsonp chunk loading","webpack://vodafoneziggo/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","'use strict';\n\nexport default class VZAccordion extends HTMLElement {\n constructor() {\n super();\n }\n\n connectedCallback() {\n this.activeClass = 'is-open';\n\n this.accordion = this.querySelector('.accordion');\n this.accordionItem = this.accordion.querySelector('.js-accordion-item');\n this.accordionButton = this.accordion.querySelector('.js-accordion-button');\n this.accordionContent = this.accordion.querySelector('.js-accordion-content');\n\n this.accordionButton.addEventListener('click', this.onClick.bind(this));\n }\n\n onClick() {\n this.toggleClasses();\n }\n\n toggleClasses() {\n if (this.accordionButton.getAttribute('aria-expanded') === 'true') {\n this.accordionItem.classList.add(this.activeClass);\n } else {\n this.accordionItem.classList.remove(this.activeClass);\n }\n }\n}\n\nif (!window.customElements.get('vz-accordion')) {\n window.customElements.define('vz-accordion', VZAccordion);\n}\n","'use strict';\n\nimport Lottie from 'lottie-web/build/player/lottie_light.min';\nconst redSpinnerData = require('./spinners/spinner_animation_min.json');\n\n/**\n * @class VZSpinner\n * @param {HTMLElement} [parent] - Parent element for the spinner to be added in.\n * @description\n * Creates a VZ-Spinner component\n *\n * @example\n * \n *
\n *
\n *
\n *
\n */\nclass VZSpinner extends HTMLElement {\n constructor(parentEl) {\n super();\n\n this.showing = false;\n this.stop = this.stop.bind(this);\n this.veil = null;\n\n const parentElement = parentEl || document.body;\n const location = parentElement.tagName === 'IMG' ? parentElement.parentElement : parentElement;\n location.appendChild(this);\n\n this.lottie = Lottie.loadAnimation({\n container: this.veil.querySelector('.spinner'),\n renderer: 'svg',\n loop: true,\n autoplay: false,\n animationData: redSpinnerData\n });\n }\n\n /**\n * @public\n * @param {string} [msg] - A message to be shown below the spinner.\n * @returns {Promise} promise\n */\n start(msg) {\n return new Promise((resolve) => {\n if (this.showing) resolve();\n const parentPosition = window.getComputedStyle(this.parentElement).getPropertyValue('position');\n\n if (parentPosition === 'static') {\n if (this.parentElement.tagName !== 'BODY') {\n this.parentElement.style.position = 'relative';\n }\n this.parentElement.classList.add('veiled');\n }\n\n if (msg) {\n this.veil.insertAdjacentHTML('beforeend', `
${msg}
`);\n }\n\n this.showing = true;\n setTimeout(() => {\n if (this.showing) {\n this.lottie?.play();\n this.veil.classList.add('show');\n }\n resolve();\n }, 500);\n });\n }\n\n /**\n * @public\n * @returns {Promise} promise\n */\n stop() {\n return new Promise((resolve) => {\n if (!this.showing) resolve();\n if (this.parentElement.classList.contains('veiled')) {\n this.parentElement.style.position = '';\n this.parentElement.classList.remove('veiled');\n }\n\n const content = this.veil.querySelector('.content');\n if (content) content.remove();\n this.veil.classList.remove('show');\n this.showing = false;\n this.lottie?.stop();\n resolve();\n });\n }\n\n connectedCallback() {\n this.innerHTML = `\n
\n
\n
\n
\n `;\n\n this.veil = this.querySelector('.veil');\n this.veil.addEventListener('click', (evt) => evt.stopPropagation());\n }\n}\n\nwindow.VZSpinner = window.customElements.get('vz-spinner') || VZSpinner;\nexport default window.VZSpinner;\n\nif (!window.customElements.get('vz-spinner')) {\n window.customElements.define('vz-spinner', VZSpinner);\n}\n","import { CONST } from 'Util/util';\nimport { validateForm, validateField } from 'app_vodafone_ziggo/util/validation';\nimport Modal from 'bootstrap/js/src/modal';\nimport VZSpinner from 'Components/VZSpinner';\nimport { appendCsrfToUrl } from 'app_vodafone_ziggo/util/urlUtils';\n\nwindow.bs = window.bs || {};\nwindow.bs.Modal = Modal;\n\nconst spinner = document.querySelector('vz-spinner') || new VZSpinner();\n\nconst selectors = {\n errorModal: 'error-modal',\n activeModal: '.modal.show',\n modalStepContainer: '.js-modal-step-container',\n modalStep: '.js-modal-step',\n modalStepInputs: '.form-control, .custom-control'\n};\n\n/**\n * @function showErrorModal\n * @param {string|null} title - The title of the modal\n * @param {string|null} body - The error message within the modal\n * @param {string|null} cta - The cta text within the modal\n */\nfunction showErrorModal(title, body, cta) {\n const errorModalHtml = `\n
\n
\n
\n
\n

${title}

\n \n
\n\n
\n
\n
${body}
\n
\n
\n\n \n
\n \n
\n
\n
\n
`;\n\n const existingModal = document.getElementById(selectors.errorModal);\n\n if (existingModal) {\n window.bs.Modal.getInstance(existingModal).show();\n } else {\n document.body.insertAdjacentHTML('beforeend', errorModalHtml);\n const modal = new window.bs.Modal(document.getElementById(selectors.errorModal));\n modal.show();\n window.addEventListener(CONST.events.popstate, () => {\n modal.hide();\n });\n }\n}\n\n/**\n * @public resetModalState\n * @param {HTMLElement} modal - A DOM modal element\n *\n * In case of a modal that has multiple steps\n * Loop over the steps to remove the active class\n * and add the active class to the first step\n */\nfunction resetModalState(modal) {\n [...modal.querySelectorAll(selectors.modalStep)].forEach((step, index) => {\n if (index === 0) {\n step.classList.add(CONST.classes.active);\n } else {\n step.classList.remove(CONST.classes.active);\n }\n });\n}\n\n/**\n * @public createModalByUrl\n * @param {string} targetId - The id of the target modal\n * @param {string} targetEndpoint - The url to call which should return the modal html\n * @returns {Promise} - Promise\n *\n * @description\n * Will create/show a modal based on a URL to a pipeline.\n * That pipeline should return a template with the modal HTML for more creative freedom\n */\nfunction createModalByUrl(targetId, targetEndpoint) {\n const modalId = `modal-${targetId}`;\n const existingModal = document.getElementById(modalId);\n\n if (existingModal) {\n return new Promise((resolve) => {\n resetModalState(existingModal);\n window.bs.Modal.getInstance(existingModal).show();\n resolve(existingModal);\n });\n }\n\n spinner.start();\n return fetch(targetEndpoint)\n .then((res) => {\n if (res.status === 500) throw new Error('Fetch failed');\n return res.text();\n })\n .then((response) => {\n document.body.insertAdjacentHTML('beforeend', response);\n\n const modalElement = document.getElementById(modalId);\n const modal = new window.bs.Modal(modalElement);\n\n new ModalClass(modal); // eslint-disable-line\n modal.show();\n document.dispatchEvent(new CustomEvent('custom_modal:shown'));\n return modalElement;\n })\n .catch((response) => {\n console.error('error', response);\n return response;\n })\n .finally(spinner.stop);\n}\n\n/**\n * @class ModalClass\n */\nclass ModalClass {\n constructor(modalInstance) {\n this.modal = modalInstance._element; // eslint-disable-line no-underscore-dangle\n this.modalActiveStep = this.modal.querySelector(`${selectors.modalStep}.${CONST.classes.active}`);\n this.modalFields = [...this.modal.querySelectorAll(selectors.modalStepInputs)];\n\n this.validateModalField = this.validateModalField.bind(this);\n this.submitStepForm = this.submitStepForm.bind(this);\n this.appendModalStep = this.appendModalStep.bind(this);\n\n this.modalFields.forEach((field) => {\n field.addEventListener(CONST.events.blur, (event) => {\n this.lastFocussedField = event.target;\n });\n\n field.addEventListener(CONST.events.keyUp, this.validateModalField);\n field.addEventListener(CONST.events.change, this.validateModalField);\n });\n\n this.modalActiveStep.addEventListener(CONST.events.submit, this.submitStepForm);\n\n const customEvent = new CustomEvent('modalLoaded', {\n detail: {\n modal: this.modal\n }\n });\n document.dispatchEvent(customEvent);\n }\n\n /**\n * @method validateModalField\n * @param {event} event - The submit event\n */\n validateModalField(event) {\n // If we're using tab, make sure to validate the previous field instead of the new field\n if (this.lastFocussedField && event.key && event.key.toLowerCase() === 'tab') {\n validateField(this.lastFocussedField);\n this.lastFocussedField = event.target;\n } else {\n const currField = event.target;\n this.lastFocussedField = currField;\n validateField(currField);\n }\n }\n\n /**\n * @method submitStepForm\n * @param {event} event - The submit event\n */\n submitStepForm(event) {\n event.preventDefault();\n const form = event.target;\n\n const validForm = validateForm(form);\n if (!validForm) {\n return;\n }\n\n const endpoint = form.getAttribute('action');\n const formData = new FormData(form);\n const csrfName = form && form.getAttribute(CONST.attributes.csrfName);\n const csrfToken = form && form.getAttribute(CONST.attributes.csrfToken);\n formData.append(csrfName, csrfToken);\n\n /* eslint-disable no-underscore-dangle */\n if (window._dd && window._dd.user && window._dd.user.ids && window._dd.user.ids.ga_id) {\n formData.append('gaId', window._dd.user.ids.ga_id);\n }\n /* eslint-enable no-underscore-dangle */\n\n spinner.start();\n\n fetch(endpoint, {\n method: 'POST',\n body: formData\n })\n .then((res) => res.text())\n .then(this.appendModalStep)\n .catch((error) => {\n console.error('submitStepForm error', error);\n })\n .finally(spinner.stop);\n }\n\n /**\n * @method scrollToTop\n */\n static scrollToTop() {\n const activeModal = document.querySelector(selectors.activeModal);\n const supportsNativeSmoothScroll = 'scrollBehavior' in document.documentElement.style;\n if (supportsNativeSmoothScroll) {\n activeModal.scrollTo({\n top: 0,\n left: 0,\n behavior: 'smooth'\n });\n } else {\n activeModal.scrollTop = 0;\n }\n }\n\n /**\n * @method appendModalStep\n * @param {string} response - The response containing the next step\n */\n appendModalStep(response) {\n const modalStepContainer = document.querySelector(`${selectors.activeModal} ${selectors.modalStepContainer}`);\n const currentStep = modalStepContainer.querySelector(`${selectors.modalStep}.${CONST.classes.active}`);\n\n currentStep.classList.remove(CONST.classes.active);\n modalStepContainer.insertAdjacentHTML('beforeend', response);\n\n const newStep = modalStepContainer.querySelector(`${selectors.modalStep}:last-child`);\n newStep.classList.add(CONST.classes.active);\n\n this.constructor.scrollToTop();\n\n const customEvent = new CustomEvent('modalStep', {\n detail: {\n currentStep: currentStep,\n newStep: newStep\n }\n });\n document.dispatchEvent(customEvent);\n }\n}\n\n/**\n * @function refreshToken\n * @description Calls an endpoint to execute authorization when the Business Scan contact me modals are opened - BO-1488.\n */\nfunction refreshToken() {\n const container = document.querySelector('[data-refresh-token-url]');\n const { refreshTokenUrl } = container.dataset;\n if (!refreshTokenUrl) return;\n\n const endpoint = appendCsrfToUrl(refreshTokenUrl);\n\n fetch(endpoint);\n}\n\nexport { showErrorModal, createModalByUrl, refreshToken };\n","'use strict';\n\nimport { documentReady, arraysAreEqual } from 'Util/util';\n\nexport default class VZPlpProductTile extends HTMLElement {\n constructor() {\n super();\n }\n\n /**\n * Invoked when the element is added to the DOM.\n * Sets up event listeners and initializes the component's state.\n */\n connectedCallback() {\n this.plpSidebar = document.querySelector('vz-plp-sidebar');\n this.plpBasket = JSON.parse(this.plpSidebar.getAttribute('plp-basket'));\n\n this.productId = this.getAttribute('product-id');\n this.productName = this.getAttribute('product-name');\n this.productPrice = this.getAttribute('product-price');\n this.oneOffPrice = this.getAttribute('product-one-off-price');\n\n this.dependencyName = this.getAttribute('product-to-add-name');\n this.dependencyPrice = this.getAttribute('product-to-add-price');\n this.dependencyOneOffPrice = this.getAttribute('product-to-add-one-off-price');\n this.productDependency = this.getAttribute('product-dependency') !== 'null' ? this.getAttribute('product-dependency') : null;\n this.dependencyLabel = this.querySelector('.js-dependency-label');\n this.isDependent = false;\n\n this.productExcluded = this.getAttribute('product-excluded');\n this.excludedLabel = this.querySelector('.js-excluded-label');\n this.isProductExcluded = false;\n this.productExcludedTile = this.productExcluded ? document.querySelector(`.js-${this.productExcluded}-product-tile`) : null;\n this.productExcludedLabel = this.productExcludedTile?.querySelector('.js-excluded-label');\n\n this.qtySelectorWrapper = this.querySelector('vz-plp-quantity-selector');\n this.selectorContainer = this.querySelectorAll('.js-selector-container');\n this.qty = this.qtySelectorWrapper?.querySelector('.js-quantity-field')?.value;\n\n this.toggle = this.querySelector('.js-plp-toggle');\n this.isSelected = this.toggle?.checked;\n\n this.isProgrammaticUpdate = false;\n\n this.setAttribute('qty', this.qty);\n this.setAttribute('is-selected', this.isSelected);\n\n this.setCurrentState = this.setCurrentState.bind(this);\n this.setQty = this.setQty.bind(this);\n this.setIsSelected = this.setIsSelected.bind(this);\n this.updateBasket = this.updateBasket.bind(this);\n\n document.addEventListener('plp:basketUpdated', this.setCurrentState);\n this.qtySelectorWrapper?.addEventListener('plp:tileUpdated', this.setQty);\n this.qtySelectorWrapper?.addEventListener('plp:qtySelectorReady', this.setCurrentState);\n this.toggle?.addEventListener('change', this.setIsSelected);\n documentReady(this.setCurrentState);\n }\n\n /**\n * @function disconnectedCallback\n * @description Removes event listeners when the component is disconnected from the DOM\n * @returns {void}\n */\n disconnectedCallback() {\n document.removeEventListener('plp:basketUpdated', this.setCurrentState);\n document.removeEventListener('plp:tileUpdated', this.setQty);\n this.qtySelectorWrapper?.removeEventListener('plp:qtySelectorReady', this.setCurrentState);\n this.toggle?.removeEventListener('change', this.setIsSelected);\n }\n\n /**\n * @function observedAttributes\n * @description observes the mentioned attribute and fires attributeChangedCallback when the value has changed\n * @returns {Attr} this attribute's value is an encoded JSON string so should be decoded when using.\n */\n static get observedAttributes() {\n return ['is-selected', 'qty'];\n }\n\n /**\n * @function attributeChangedCallback\n * @description fired when an observed attribute changes\n * @param {string} name the name of the attribute\n * @param {any} oldValue the previous value of the attribute\n * @param {any} newValue the new value of the attribute\n */\n attributeChangedCallback(name, oldValue, newValue) {\n if (\n !this.isProgrammaticUpdate &&\n ((name === 'is-selected' && oldValue !== newValue) || (name === 'qty' && oldValue !== newValue)) &&\n oldValue !== 'initial' &&\n newValue !== 'initial'\n ) {\n this.updateBasket();\n }\n }\n\n /**\n * Updates the basket data based on the component's state.\n */\n updateBasket() {\n let updatedBasket = JSON.parse(this.plpSidebar.getAttribute('plp-basket'));\n updatedBasket = updatedBasket.filter((item) => item.id !== this.productId && item.id !== this.productDependency);\n\n if (parseInt(this.qty, 10) > 0 || this.isSelected) {\n const productObj = {\n id: this.productId,\n price: this.productPrice,\n oneOffPrice: this.oneOffPrice,\n name: this.productName,\n qty: this.isSelected ? 1 : this.qty,\n dependency: this.productDependency,\n isDependent: this.isDependent,\n dependsOn: null,\n excluded: this.productExcluded,\n isProductExcluded: this.productExcluded\n };\n\n updatedBasket.push(productObj);\n\n if (this.productDependency && this.productDependency !== 'null' && this.productDependency !== null) {\n const dependencyProduct = {\n id: this.productDependency,\n price: this.dependencyPrice,\n oneOffPrice: this.dependencyOneOffPrice,\n name: this.dependencyName,\n qty: 1,\n dependency: null,\n isDependent: true,\n dependsOn: this.productName,\n excluded: null,\n isProductExcluded: false\n };\n\n updatedBasket.push(dependencyProduct);\n }\n }\n\n // No replacement if updated and current basket have same products\n if (arraysAreEqual(updatedBasket, this.plpBasket)) {\n return;\n }\n\n this.plpBasket = updatedBasket;\n this.plpSidebar.setAttribute('plp-basket', JSON.stringify(this.plpBasket));\n\n document.dispatchEvent(new CustomEvent('plp:basketUpdated'));\n }\n\n /**\n * Updates the quantity value based on the quantity selector input.\n */\n setQty() {\n this.qty = this.qtySelectorWrapper?.querySelector('.js-quantity-field')?.value;\n this.setAttribute('qty', this.qty);\n }\n\n /**\n * Updates the \"isSelected\" state based on the toggle input.\n */\n setIsSelected() {\n this.isSelected = this.toggle?.checked;\n this.setAttribute('is-selected', this.isSelected);\n }\n\n /**\n * Sets the current state of the component based on basket data and other attributes.\n */\n setCurrentState() {\n this.plpBasket = JSON.parse(this.plpSidebar.getAttribute('plp-basket'));\n const currentItemInBasket = this.plpBasket.filter((item) => item.id === this.productId);\n this.isProgrammaticUpdate = true;\n\n if (currentItemInBasket.length > 0) {\n this.isDependent = currentItemInBasket[0].isDependent;\n this.isProductExcluded = currentItemInBasket[0].isProductExcluded;\n\n if (currentItemInBasket[0].dependsOn) this.dependencyLabel.querySelector('strong').textContent = currentItemInBasket[0].dependsOn;\n\n if (this.qtySelectorWrapper) {\n const qty = parseInt(currentItemInBasket[0].qty, 10);\n const inputField = this.qtySelectorWrapper.querySelector('input');\n inputField.value = qty.toFixed();\n inputField.setAttribute('value', qty.toFixed());\n this.qtySelectorWrapper.dispatchEvent(new CustomEvent('plp:setQty'));\n } else {\n const oldVal = this.toggle.checked;\n this.toggle.checked = true;\n if (oldVal !== this.toggle.checked) {\n this.toggle?.dispatchEvent(new CustomEvent('change'));\n }\n }\n } else if (this.qtySelectorWrapper) {\n this.isDependent = false;\n this.isProductExcluded = false;\n const inputField = this.qtySelectorWrapper.querySelector('input');\n inputField.value = 0;\n inputField.setAttribute('value', 0);\n this.qtySelectorWrapper.dispatchEvent(new CustomEvent('plp:setQty'));\n } else {\n this.isDependent = false;\n this.isProductExcluded = false;\n const oldVal = this.toggle.checked;\n this.toggle.checked = false;\n if (oldVal !== this.toggle.checked) {\n this.toggle?.dispatchEvent(new CustomEvent('change'));\n }\n }\n\n this.isProgrammaticUpdate = false;\n\n Array.from(this.selectorContainer).forEach((el) => el.classList.toggle('d-none', this.isDependent));\n\n this.productExcludedTile?.classList.toggle('disabled', !!this.isProductExcluded);\n\n this.dependencyLabel?.classList.toggle('d-none', !this.isDependent);\n this.productExcludedLabel?.classList.toggle('d-none', !this.isProductExcluded);\n }\n}\n\nif (!window.customElements.get('vz-plp-product-tile')) {\n window.customElements.define('vz-plp-product-tile', VZPlpProductTile);\n}\n","'use strict';\n\nimport * as debounce from 'lodash/debounce';\n\nexport default class VZPlpQuantitySelector extends HTMLElement {\n constructor() {\n super();\n\n this.excludedAttributes = ['class', 'data-configurator-type', 'data-url', 'data-general-error'];\n\n this.onInput = this.onInput.bind(this);\n\n this.toggleIncreaseAndDecreaseButtons = this.toggleIncreaseAndDecreaseButtons.bind(this);\n }\n\n connectedCallback() {\n this.forbiddenValues = ['e', '+', ',', '-', '.', 69, 187, 188, 189, 190];\n this.activeClass = 'has-value';\n\n this.debounceRate = parseFloat(this.getAttribute('debounce-rate')) || 500;\n this.debouncedChange = debounce(this.onChange.bind(this), this.debounceRate);\n\n this.parentId = this.getAttribute('data-parent-id');\n this.parent = document.querySelector(`#${this.parentId}`);\n this.aside = this.parent.querySelector('.js-aside');\n\n this.minQuantity = parseInt(this.getAttribute('data-min-qty'), 10);\n\n this.quantityField = this.querySelector('.js-quantity-field');\n this.quantityFieldOriginalValue = this.quantityField.value;\n\n this.quantityField.addEventListener('blur', this.onBlur.bind(this));\n\n this.addEventListener('input', this.onInput.bind(this));\n this.addEventListener('keydown', this.onKeyDown.bind(this));\n this.addEventListener('paste', this.onPaste);\n this.addEventListener('plp:setQty', this.onChange.bind(this));\n\n [...this.querySelectorAll('.js-quantity-decrease, .js-quantity-increase')].forEach((element) => {\n element.addEventListener('click', this.decreaseOrIncrease.bind(this));\n });\n this.dispatchEvent(new CustomEvent('plp:qtySelectorReady'));\n }\n\n toggleIncreaseAndDecreaseButtons(disableOrEnable) {\n const buttons = [...this.querySelectorAll('.js-quantity-decrease, .js-quantity-increase')];\n buttons.forEach((button) => (disableOrEnable === 'disable' ? button.setAttribute('disabled', true) : button.removeAttribute('disabled')));\n }\n\n onBlur(e) {\n if (e.target.value.length !== 0) return;\n\n e.target.value = '0';\n\n this.validateMinMax();\n this.debouncedChange();\n }\n\n onInput(e) {\n if (e.target.value.length === 0) return;\n\n this.validateMinMax();\n this.debouncedChange();\n }\n\n onKeyDown(e) {\n if (this.forbiddenValues.indexOf(e.key || e.keyCode) !== -1) {\n e.preventDefault();\n }\n }\n\n onPaste(e) {\n e.preventDefault();\n\n const newValue = e.clipboardData.getData('text').replace(/\\D/g, '');\n\n e.target.value = '';\n e.target.value = newValue;\n\n this.validateMinMax();\n this.debouncedChange();\n }\n\n decreaseOrIncrease(e) {\n e.preventDefault();\n\n const field = this.quantityField;\n const currentValue = parseInt(field.value, 10);\n const decrease = e.target.classList.contains('js-quantity-decrease');\n\n if (window.isNaN(currentValue)) {\n field.value = field.min;\n } else if (decrease) {\n field.value = currentValue === this.minQuantity ? 0 : currentValue - 1;\n } else {\n field.value = currentValue === 0 || currentValue < this.minQuantity ? this.minQuantity : currentValue + 1;\n }\n\n this.validateMinMax();\n this.debouncedChange();\n }\n\n validateMinMax() {\n const field = this.quantityField;\n const moreThanMax = parseInt(field.value, 10) > field.max;\n const lessThanMin = parseInt(field.value, 10) < field.min;\n\n if (field.max && moreThanMax) field.value = field.max;\n if (lessThanMin) field.value = field.min;\n }\n\n onChange() {\n const field = this.quantityField;\n\n // Keep minimum allowed quantity in mind\n if (field.value > 0 && field.value < this.minQuantity) field.value = this.minQuantity;\n\n this.toggleClasses(field.value);\n this.dispatchEvent(new CustomEvent('plp:tileUpdated'));\n\n if (field.value === this.quantityFieldOriginalValue) return;\n\n field.setAttribute('value', field.value);\n field.dispatchEvent(new CustomEvent('fieldUpdated'));\n }\n\n toggleClasses(value) {\n if (value > 0) {\n this.aside.classList.add(this.activeClass);\n } else {\n this.aside.classList.remove(this.activeClass);\n }\n }\n}\n\nif (!window.customElements.get('vz-plp-quantity-selector')) {\n window.customElements.define('vz-plp-quantity-selector', VZPlpQuantitySelector);\n}\n","/**\n * @public setCookie\n * @param {string} cookieName - The cookie name\n * @param {string} cookieValue - The cookie value\n * @param {string} domain - The domain\n * @param {string} expirationDays - The expiration in days\n */\nfunction setCookie(cookieName, cookieValue, domain, expirationDays = 30) {\n const date = new Date();\n date.setTime(date.getTime() + expirationDays * 24 * 60 * 60 * 1000);\n const expires = `expires=${date.toUTCString()}`;\n const domainAndPath = `${domain ? `domain=${domain};` : ''}path=/; secure; sameSite=None`;\n const cookieString = `${cookieName}=${cookieValue};${expires};${domainAndPath}`;\n\n document.cookie = cookieString;\n}\n\n/**\n * @public getCookie\n * @param {string} cookieName - The cookie name\n * @return {string|null} The value of the cookie || null\n */\nfunction getCookie(cookieName) {\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${cookieName}=`);\n if (parts.length === 2) return parts.pop().split(';').shift();\n return null;\n}\n\nexport { setCookie, getCookie };\n","'use strict';\n\nimport { CONST, documentReady, addEvent } from 'app_vodafone_ziggo/util/util';\nimport { createModalByUrl, refreshToken } from 'Root/modal';\n\n/**\n * @private addBsIdAsHiddenInputField\n * @param {HTMLElement} modal - The modal\n *\n * @description\n * Will add the currentBsId as a hidden input field to the form, necessary for\n * the share-advice and lets-talk forms/modals.\n */\nfunction addBsIdAsHiddenInputField(modal) {\n const adviceStep = document.querySelector('.js-bscan-step.bscan-advice');\n const currentBsId = adviceStep ? adviceStep.getAttribute('data-bscan-id') : null;\n\n if (currentBsId) {\n const form = modal.querySelector('form');\n const fragment = document.createElement('input');\n\n fragment.setAttribute('type', 'hidden');\n fragment.setAttribute('name', 'currentBsId');\n fragment.setAttribute('value', currentBsId);\n\n form.appendChild(fragment);\n }\n}\n\n/**\n * @private addPlpInputFields\n * @param {HTMLElement} modal - The modal\n *\n * @description\n * Populates hidden input fields to the specified modal form containing the 'plp-basket' and plp url attribute value.\n */\nfunction addPlpInputFields(modal) {\n const plpBasket = document.querySelector('vz-plp-sidebar')?.getAttribute('plp-basket');\n const plpBasketInput = modal.querySelector('#plpBasket');\n const plpUrlInput = modal.querySelector('#plpUrl');\n\n if (plpBasketInput) {\n plpBasketInput.setAttribute('value', plpBasket);\n }\n if (plpUrlInput) {\n plpUrlInput.setAttribute('value', window.location.href.split('?')[0]);\n }\n}\n\n/**\n * @private getModal\n * @param {event} event - The event\n *\n * @description\n * Will retrieve the id and url from the link, then create a modal based on the id and url\n */\nfunction getModal(event) {\n event.preventDefault();\n const link = event.target;\n const modalId = link.getAttribute('data-modal-id');\n const modalUrl = link.getAttribute('data-modal-url');\n const isPlp = link.getAttribute('data-page-type') === 'plp';\n\n if (modalId && modalUrl) {\n createModalByUrl(modalId, modalUrl)\n .then((modal) => {\n if (isPlp) {\n addPlpInputFields(modal);\n } else {\n addBsIdAsHiddenInputField(modal);\n }\n })\n .then(refreshToken);\n }\n}\n\n/**\n * @private showModal\n * @param {string} selector - The selector for the modal\n * @param {string} errorMessage - The message to show in the console in case the modal can't be found in the dom\n *\n * @description\n * Will show a specific modal based on parameters\n */\nfunction showModal(selector, errorMessage) {\n const modalElement = document.getElementById(selector);\n let modalInstance = window.bs.Modal.getInstance(modalElement);\n\n if (!modalInstance) {\n modalInstance = new window.bs.Modal(modalElement);\n }\n\n if (modalInstance) {\n modalInstance.show();\n } else {\n console.error(errorMessage);\n }\n}\n\ndocumentReady(() => {\n addEvent(document, CONST.events.click, '.js-modal-link', getModal);\n});\n\nexport { showModal };\n","'use strict';\n\nimport { CONST, documentReady, assignStyling, formatToPriceString, arraysAreEqual, tryParseJSON } from 'Util/util';\nimport { setCookie, getCookie } from 'Util/cookies';\nimport * as debounce from 'lodash/debounce';\nimport 'app_business_scan/components/modal.js';\n\n/**\n * @class VZPlpSidebar\n */\nclass VZPlpSidebar extends HTMLElement {\n constructor() {\n super();\n window.dataLayer = window.dataLayer || [];\n }\n\n /**\n * @function connectedCallback\n * @description Initializes the component and sets up event listeners\n * @returns {void}\n */\n connectedCallback() {\n // Sidebar\n this.sidebar = this;\n this.sidebarClasses = {\n open: 'plp-sidebar--open',\n closed: 'plp-sidebar--closed',\n lineItem: 'plp-sidebar__line-item',\n dependencyItem: 'plp-sidebar__dependency-item',\n removeItem: 'plp-sidebar__remove-item border-0 bg-white',\n adjustForSidebar: 'adjust-for-sidebar',\n hidden: 'd-none',\n hiddenOnEmpty: 'js-hidden-on-empty',\n visibleOnEmpty: 'js-visible-on-empty',\n hiddenOnClosed: 'js-hidden-on-closed'\n };\n\n // Basket data\n this.plpBasket = JSON.parse(this.getAttribute('plp-basket'));\n this.hasOneOffPrices = false;\n\n // Header\n this.pageHeader = document.querySelector('.js-navigation');\n this.filterBar = document.querySelector('.js-filter-bar');\n\n // Fields\n this.priceText = this.getAttribute('price-text');\n this.qtyText = this.getAttribute('qty-text');\n this.emptyText = this.getAttribute('empty-text');\n this.labelText = this.getAttribute('label-text');\n\n // Content\n this.sidebarTitle = this.querySelector('.js-sidebar-title');\n this.sidebarContent = this.querySelector('.js-sidebar-content');\n this.sidebarTotal = this.querySelector('.js-sidebar-total');\n this.hiddenOnEmpty = this.sidebar.querySelectorAll(`.${this.sidebarClasses.hiddenOnEmpty}`);\n this.visibleOnEmpty = this.sidebar.querySelectorAll(`.${this.sidebarClasses.visibleOnEmpty}`);\n\n // Styling\n this.sidebarTopOffset = 19;\n this.stickyBreakpoint = parseInt(CONST.breakpoints.lg, 10);\n\n // Disclaimers\n this.disclaimerOneOff = document.querySelector('.js-disclaimer-one-off');\n this.disclaimerOneOffMobile = document.querySelector('.js-disclaimer-one-off-mobile');\n\n // Mobile\n this.hiddenOnClosed = this.sidebar.querySelectorAll(`.${this.sidebarClasses.hiddenOnClosed}`);\n this.tapAreaFooter = document.querySelector('.js-card-footer-tap-area');\n this.tapAreaHeader = document.querySelector('.js-card-header-tap-area');\n\n // Chat\n this.chatButton = document.querySelector('.dimelo_chat_item_markup');\n\n // Methods\n this.initialize = this.initialize.bind(this);\n this.showLineItems = this.showLineItems.bind(this);\n this.updateHeader = this.updateHeader.bind(this);\n this.updateFooter = this.updateFooter.bind(this);\n this.deleteItem = this.deleteItem.bind(this);\n this.handleFloatingSidebar = this.handleFloatingSidebar.bind(this);\n this.handleFullOrEmptyState = this.handleFullOrEmptyState.bind(this);\n this.toggleDisclaimers = this.toggleDisclaimers.bind(this);\n this.calculateMaxHeightSidebarBody = this.calculateMaxHeightSidebarBody.bind(this);\n this.calculateMaxHeightMobileSidebarBody = this.calculateMaxHeightMobileSidebarBody.bind(this);\n this.openMobileSidebar = this.openMobileSidebar.bind(this);\n this.closeMobileSidebar = this.closeMobileSidebar.bind(this);\n this.tapAreaFooter.addEventListener('click', this.openMobileSidebar);\n this.tapAreaHeader.addEventListener('click', this.closeMobileSidebar);\n\n // Init\n this.initialize();\n\n // Cookies\n if (getCookie('plpBasket')) {\n this.setAttribute('plp-basket', decodeURIComponent(getCookie('plpBasket')));\n document.dispatchEvent(new CustomEvent('plp:basketUpdated')); // Trigger product tiles update\n }\n }\n\n openMobileSidebar() {\n this.sidebar.classList.remove(this.sidebarClasses.closed);\n this.sidebar.classList.add(this.sidebarClasses.open);\n\n if (this.hiddenOnClosed.length > 0) {\n this.hiddenOnClosed.forEach((element) => {\n element.classList.remove(this.sidebarClasses.hidden);\n });\n }\n }\n\n closeMobileSidebar() {\n this.sidebar.classList.add(this.sidebarClasses.closed);\n this.sidebar.classList.remove(this.sidebarClasses.open);\n\n if (this.hiddenOnClosed.length > 0) {\n this.hiddenOnClosed.forEach((element) => {\n element.classList.add(this.sidebarClasses.hidden);\n });\n }\n }\n\n /**\n * @function disconnectedCallback\n * @description Removes event listeners when the component is disconnected from the DOM\n * @returns {void}\n */\n disconnectedCallback() {\n Array.from(this.querySelectorAll('.js-remove-item')).forEach((deleteIcon) => {\n deleteIcon.removeEventListener('click', this.deleteItem);\n });\n }\n\n /**\n * @function observedAttributes\n * @description observes the mentioned attribute and fires attributeChangedCallback when the value has changed\n * @returns {Attr} this attribute's value is an encoded JSON string so should be decoded when using.\n */\n static get observedAttributes() {\n return ['plp-basket'];\n }\n\n /**\n * @function attributeChangedCallback\n * @description fired when an observed attribute changes\n * @param {string} name the name of the attribute\n * @param {any} oldValue the previous value of the attribute\n * @param {any} newValue the new value of the attribute\n */\n attributeChangedCallback(name, oldValue, newValue) {\n if (name === 'plp-basket' && oldValue !== newValue && this.sidebarContent) {\n const oldBasket = tryParseJSON(oldValue);\n const newBasket = tryParseJSON(newValue);\n\n this.constructor.trackChanges(oldBasket, newBasket);\n this.plpBasket = newBasket;\n\n setCookie('plpBasket', encodeURIComponent(newValue), window.location.hostname, 30);\n\n this.initialize();\n }\n }\n\n /**\n * Displays line items in the sidebar.\n * @function showLineItems\n * @returns {void}\n */\n showLineItems() {\n const productsMarkup = this.plpBasket.reduce((result, product) => {\n const qty = parseInt(product.qty, 10);\n const costs = parseFloat(product.price, 10) * qty;\n const label = product.isDependent\n ? `\n ${this.labelText}\n \n `\n : `\n \n `;\n\n return `\n ${result}\n
\n
\n \n ${product.name} x ${qty}\n \n ${label}\n
\n \n ${this.priceText} ${formatToPriceString(costs)}\n \n
\n `;\n }, '');\n\n // Update card body with line items\n this.sidebarContent.innerHTML = productsMarkup;\n\n // Add event listener for line item removal\n Array.from(this.querySelectorAll('.js-remove-item')).forEach((deleteIcon) => {\n deleteIcon.addEventListener('click', this.deleteItem);\n });\n\n this.updateHeader();\n this.updateFooter();\n }\n\n /**\n * Toggles the disclaimer content based on selected products.\n * @function toggleDisclaimers\n * @returns {void}\n */\n toggleDisclaimers() {\n const isEmptyBasket = this.plpBasket.length === 0;\n\n this.hasOneOffPrices = this.plpBasket.filter((product) => product.oneOffPrice !== 'null' && product.oneOffPrice !== '0.00').length > 0;\n\n this.disclaimerOneOffMobile?.classList.add(this.sidebarClasses.hidden);\n this.disclaimerOneOff?.classList.add(this.sidebarClasses.hidden);\n\n // Don't show disclaimers if basket is empty or no selected products have one-off prices\n if (isEmptyBasket) return;\n\n if (window.innerWidth < this.stickyBreakpoint) {\n this.disclaimerOneOffMobile?.classList.toggle(this.sidebarClasses.hidden, !this.hasOneOffPrices);\n } else {\n this.disclaimerOneOff?.classList.toggle(this.sidebarClasses.hidden, !this.hasOneOffPrices);\n }\n }\n\n /**\n * Updates the footer content based on selected products.\n * @function updateFooter\n * @returns {void}\n */\n updateFooter() {\n // Calculate total price\n const totalPrice = this.plpBasket.reduce((total, product) => total + parseFloat(product.price, 10) * parseInt(product.qty, 10), 0);\n\n // Update footer total text\n this.sidebarTotal.innerHTML = formatToPriceString(totalPrice);\n }\n\n /**\n * Updates the header content based on selected products.\n * @function updateHeader\n * @returns {void}\n */\n updateHeader() {\n // Calculate number of line items\n const numberProductsSelected = parseInt(this.plpBasket.length, 10);\n\n // Update card header with correct text\n this.sidebarTitle.innerHTML = numberProductsSelected === 0 ? this.emptyText : this.qtyText.replace('{0}', numberProductsSelected);\n }\n\n /**\n * Deletes a line item from the sidebar.\n * @function deleteItem\n * @param {Event} e - The click event.\n * @returns {void}\n */\n deleteItem(e) {\n const currentLineItem = e.target.closest('.js-line-item');\n\n if (currentLineItem) {\n const productIdToRemove = currentLineItem.dataset.productId;\n const productToRemove = this.plpBasket.find((product) => product.id === productIdToRemove);\n const dependencyProductId = productToRemove?.dependency;\n\n this.plpBasket = this.plpBasket.filter((product) => product.id !== productIdToRemove && product.id !== dependencyProductId);\n\n this.setAttribute('plp-basket', JSON.stringify(this.plpBasket));\n\n document.dispatchEvent(new CustomEvent('plp:basketUpdated')); // Trigger product tiles update\n }\n }\n\n /**\n * Initializes the sidebar component.\n * @function initialize\n * @returns {void}\n */\n initialize() {\n if (this.plpBasket.length > 0) this.showLineItems();\n\n this.handleFullOrEmptyState();\n\n documentReady(this.handleFloatingSidebar);\n\n window.addEventListener(\n 'resize',\n debounce(() => {\n if (window.innerWidth < this.stickyBreakpoint) {\n this.closeMobileSidebar();\n } else {\n this.openMobileSidebar();\n }\n\n this.handleFloatingSidebar();\n this.toggleDisclaimers();\n }),\n 150\n );\n }\n\n /**\n * Handles the appearance of the floating sidebar at certain resolutions.\n * @function handleFloatingSidebar\n * @returns {void}\n */\n handleFullOrEmptyState() {\n const isEmptyBasket = this.plpBasket.length === 0;\n\n this.updateHeader();\n this.toggleDisclaimers();\n\n // Toggle elements only visible when basket is empty\n if (this.visibleOnEmpty.length > 0) {\n this.visibleOnEmpty.forEach((element) => {\n element.classList.toggle(this.sidebarClasses.hidden, !isEmptyBasket);\n });\n }\n\n // Toggle elements only visible when basket is NOT empty\n if (this.hiddenOnEmpty.length > 0) {\n this.hiddenOnEmpty.forEach((element) => {\n element.classList.toggle(this.sidebarClasses.hidden, isEmptyBasket);\n });\n }\n\n // Adjust chat button for mobile sidebar\n if (this.chatButton && window.innerWidth < this.stickyBreakpoint) this.chatButton?.classList.toggle(this.sidebarClasses.adjustForSidebar, !isEmptyBasket);\n }\n\n /**\n * @function handleFloatingSidebar\n * @private\n * @description Handles the styling required for the sidebar to become sticky at certain resolutions\n */\n handleFloatingSidebar() {\n const isEmptyBasket = this.plpBasket.length === 0;\n\n this.sidebar.classList.toggle(this.sidebarClasses.hidden, window.innerWidth < this.stickyBreakpoint && isEmptyBasket);\n\n if (window.innerWidth < this.stickyBreakpoint) {\n // Adjust and display chat button for mobile\n if (this.chatButton) this.chatButton?.classList.toggle(this.sidebarClasses.adjustForSidebar, !isEmptyBasket);\n\n this.sidebar.style.removeProperty('position');\n this.sidebar.style.removeProperty('top');\n this.sidebar.style.removeProperty('bottom');\n this.sidebar.style.removeProperty('width');\n\n // Mobile sidebar is sticky to the bottom\n this.sidebar.style.removeProperty('top');\n\n assignStyling(this.sidebar, {\n position: 'fixed',\n bottom: '0',\n left: '0',\n right: '0'\n });\n\n if (!isEmptyBasket) {\n assignStyling(this.sidebarContent, {\n 'max-height': `${this.calculateMaxHeightMobileSidebarBody()}px`\n });\n }\n\n if (this.sidebar.classList.contains(this.sidebarClasses.open)) {\n this.openMobileSidebar();\n } else {\n this.closeMobileSidebar();\n }\n } else {\n // Adjust and display chat button for desktop\n if (this.chatButton) this.chatButton.classList.remove(this.sidebarClasses.adjustForSidebar, this.sidebarClasses.hidden);\n\n this.filterBar = document.querySelector('.js-filter-bar');\n\n this.openMobileSidebar();\n\n // Add some space between filter bar and sidebar when sticky\n const sidebarStickyMarginTop = this.filterBar ? 8 : 0;\n\n // Desktop sidebar is sticky to the right column\n this.sidebar.style.removeProperty('bottom', 'left', 'right');\n\n assignStyling(this.sidebar, {\n position: 'sticky',\n top: `${parseInt(this.pageHeader.offsetHeight, 10) + (this.filterBar ? parseInt(this.filterBar.offsetHeight, 10) + sidebarStickyMarginTop : this.sidebarTopOffset)}px`\n });\n\n if (!isEmptyBasket) {\n assignStyling(this.sidebarContent, {\n 'max-height': `${this.calculateMaxHeightSidebarBody()}px`\n });\n }\n }\n }\n\n /**\n * Calculates the maximum height of the sidebar body.\n * @function calculateMaxHeightSidebarBody\n * @returns {number} - The calculated maximum height.\n */\n calculateMaxHeightSidebarBody() {\n // Line item total height\n const lineItem = this.querySelector('.js-line-item');\n const lineItemHeight = lineItem.clientHeight > 0 ? lineItem.clientHeight : 56; // 3.5rem\n const lineItemSpacingType = window.getComputedStyle(lineItem).getPropertyValue('margin-bottom');\n const lineItemSpacing = lineItemSpacingType ? lineItemSpacingType.replace('px', '') : 16; // 1rem\n const lineItemTotalHeight = lineItemHeight + parseInt(lineItemSpacing, 10);\n const lineItemsToShow = 3.5;\n const lastLineItemHeightToRemove = window.innerWidth < this.stickyBreakpoint ? 8 : 4; // 0.5rem || 0.25rem\n\n // + extraLineItemHeight\n return lineItemTotalHeight * lineItemsToShow - lastLineItemHeightToRemove;\n }\n\n /**\n * Calculates the maximum height of the mobile sidebar body.\n * @function calculateMaxHeightMobileSidebarBody\n * @returns {number} - The calculated maximum height.\n */\n calculateMaxHeightMobileSidebarBody() {\n // Same as desktop sidebar (BO-3191)\n return this.calculateMaxHeightSidebarBody();\n }\n\n /**\n * Tracks plp basket changes and logs them to the dataLayer.\n *\n * @param {Array} oldArray - The original plp basket.\n * @param {Array} newArray - The updated plp basket.\n */\n static trackChanges(oldArray, newArray) {\n // If new basket set from cookies, do not track as it is initial page load\n if (getCookie('plpBasket')) {\n const savedBasket = tryParseJSON(decodeURIComponent(getCookie('plpBasket')));\n\n if (arraysAreEqual(savedBasket, newArray)) return;\n }\n\n const oldMap = new Map(oldArray.map((item) => [item.id, item]));\n const newMap = new Map(newArray.map((item) => [item.id, item]));\n\n // Track added and updated products\n newArray.forEach((newItem) => {\n const oldItem = oldMap.get(newItem.id) || {\n qty: 0,\n name: newItem.name\n };\n\n if (oldItem.qty !== newItem.qty) {\n const change = newItem.qty - oldItem.qty;\n\n if (change > 0) {\n // Push one event per each 1 qty change\n for (let i = 0; i < change; i++) {\n window.dataLayer.push({\n event: 'mkb_solutions_cart',\n solutions_product: oldItem.name,\n solutions_cart: 'increased'\n });\n }\n } else if (change < 0) {\n for (let i = 0; i < Math.abs(change); i++) {\n window.dataLayer.push({\n event: 'mkb_solutions_cart',\n solutions_product: oldItem.name,\n solutions_cart: 'decreased'\n });\n }\n }\n }\n });\n\n // Track removed products\n oldArray.forEach((oldItem) => {\n if (!newMap.has(oldItem.id)) {\n window.dataLayer.push({\n event: 'mkb_solutions_cart',\n solutions_product: oldItem.name,\n solutions_cart: 'removed'\n });\n }\n });\n }\n}\n\nexport default window.customElements.get('vz-plp-sidebar') || VZPlpSidebar;\n\nif (!window.customElements.get('vz-plp-sidebar')) {\n window.customElements.define('vz-plp-sidebar', VZPlpSidebar);\n}\n","/* eslint-disable vars-on-top */\n/* eslint-disable prefer-template */\n\n'use strict';\n\nimport { CONST } from 'app_vodafone_ziggo/util/util';\nimport * as debounce from 'lodash/debounce';\n\n/**\n * @class VZLayoutToggle\n * @description\n * Creates a VZLayoutToggle component\n * ---\n * 'data-layout-key' : local storage entry ID |\n * 'data-layout-id-default' : default choice ID |\n * 'data-layout-container' : parent container identifier |\n * 'data-layout-enabled-breakpoint' : breakpoint from which enabled |\n * 'data-layout-id' : layout IDs ('agenda', 'grid', 'other') |\n * 'data-layout-class' : CSS classes to add to parent container\n *\n * @example\n * \n *
\n * \n * \n *
\n * \n */\nclass VZLayoutToggle extends HTMLElement {\n constructor() {\n super();\n\n // Classes\n this.activeClass = 'layout-toggle--active';\n\n // Configurables\n this.dataLayoutLocalStorageKey = this.getAttribute(CONST.vzLayoutToggle.localStorageKey) || CONST.localStorage.preferredLayoutId;\n this.dataLayoutIdDefault = this.getAttribute(CONST.vzLayoutToggle.idDefault) || 'agenda';\n this.dataLayoutContainer = this.getAttribute(CONST.vzLayoutToggle.container) || null;\n this.enabledOnBreakpoint = parseInt(this.getAttribute(CONST.vzLayoutToggle.enabledBreakpoint) || CONST.breakpoints.lg, 10);\n\n // Toggles and layout container\n this.toggles = this.querySelectorAll('.js-layout-toggle');\n this.layoutContainer = document.querySelector(`.${this.dataLayoutContainer}`);\n }\n\n /**\n * Fetches the previously stored layout choice from local storage using the local storage key for this instance of VZLayoutToggle.\n * If the entry does not exist sets a default value.\n * @function fetch\n * @returns {void}\n */\n fetch() {\n this.activeLayoutId = window.localStorage.getItem(this.dataLayoutLocalStorageKey) || this.dataLayoutIdDefault;\n }\n\n /**\n * Checks if the previously stored layout choice is valid for this instance of VZLayoutToggle.\n * If not, resets it to the default value.\n * @function setup\n * @returns {void}\n */\n setup() {\n var activeToggleExists = this.querySelector(`[${CONST.vzLayoutToggle.id}=${this.activeLayoutId}]`) || null;\n\n if (!activeToggleExists) this.activeLayoutId = this.dataLayoutIdDefault;\n }\n\n /**\n * Triggers an update to toggleLayout with the initial layout choice.\n * @function enable\n * @returns {void}\n */\n enable() {\n this.activeToggle = this.querySelector(`[${CONST.vzLayoutToggle.id}=${this.activeLayoutId}]`);\n this.activeLayoutClass = this.activeToggle.getAttribute(CONST.vzLayoutToggle.class) || 'active';\n\n this.toggleLayout(this.activeToggle);\n }\n\n /**\n * Triggers an update to setPreferredLayout and toggleClasses with the new layout choice.\n * @function toggleLayout\n * @param {Event} e - The click event.\n * @returns {void}\n */\n toggleLayout(e) {\n var toggle = e.target ? e.target : e;\n var layoutId = toggle.getAttribute(CONST.vzLayoutToggle.id);\n var layoutClass = toggle.getAttribute(CONST.vzLayoutToggle.class);\n\n this.setPreferredLayout(layoutId, layoutClass);\n this.toggleClasses(toggle);\n }\n\n /**\n * Updates activeLayoutId, activeLayoutClass and local storage with the new layout choice.\n * @function setPreferredLayout\n * @param {string} layoutId - The chosen layout identifier.\n * @param {string} layoutClass - The chosen layout identifier class.\n * @returns {void}\n */\n setPreferredLayout(layoutId, layoutClass) {\n this.activeLayoutId = layoutId;\n this.activeLayoutClass = layoutClass;\n\n window.localStorage.setItem(this.dataLayoutLocalStorageKey, this.activeLayoutId);\n }\n\n /**\n * Toggles the highlight classes for the toggles and layout container element.\n * @function toggleClasses\n * @param {HTMLElement} selectedToggle - The chosen layout toggle.\n * @returns {void}\n */\n toggleClasses(selectedToggle) {\n this.toggles.forEach((toggle) => {\n var layoutClass = toggle.getAttribute(CONST.vzLayoutToggle.class);\n this.layoutContainer.classList.remove(layoutClass);\n\n toggle.classList.remove(this.activeClass);\n });\n\n selectedToggle.classList.add(this.activeClass);\n\n this.layoutContainer.classList.add(this.activeLayoutClass);\n }\n\n /**\n * Shows VZLayoutToggle.\n * @function show\n * @returns {void}\n */\n show() {\n this.classList.remove('d-none');\n }\n\n /**\n * Hides VZLayoutToggle.\n * @function hide\n * @returns {void}\n */\n hide() {\n this.classList.add('d-none');\n }\n\n /**\n * Handles VZLayoutToggle visibility on window resize.\n * @function handleResize\n * @returns {void}\n */\n handleResize() {\n if (window.innerWidth < this.enabledOnBreakpoint) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * @function connectedCallback\n * @description Initializes the component and sets up event listeners.\n * @returns {void}\n */\n connectedCallback() {\n // There is no valid layout container specified\n if (!this.dataLayoutContainer || !this.layoutContainer) return;\n\n this.fetch();\n this.setup();\n this.enable();\n\n // Make visible if enabled for current breakpoint\n if (window.innerWidth >= this.enabledOnBreakpoint) this.show();\n\n // Events\n this.toggles.forEach((toggle) => {\n toggle.addEventListener('click', this.toggleLayout.bind(this));\n });\n\n window.addEventListener(\n 'resize',\n debounce(() => {\n this.handleResize();\n }),\n 150\n );\n }\n}\n\nwindow.VZLayoutToggle = window.customElements.get('vz-layout-toggle') || VZLayoutToggle;\nexport default window.VZLayoutToggle;\n\nif (!window.customElements.get('vz-layout-toggle')) {\n window.customElements.define('vz-layout-toggle', VZLayoutToggle);\n}\n","'use strict';\n\nexport default class VZAdvisoryCard extends HTMLElement {\n constructor() {\n super();\n\n this.shown = false;\n this.visibilityClass = 'show';\n this.waiting = 60_000;\n\n this.sidebar = this.getAttribute('sidebar');\n this.basket = this.getAttribute('basket');\n\n this.wrapper = this.closest('.js-advisory-card-wrapper');\n }\n\n static get observedAttributes() {\n return ['delay'];\n }\n\n attributeChangedCallback(attrName, oldVal, newVal) {\n if (attrName === 'delay' && oldVal !== newVal && this.shown === false) {\n this.waiting = parseFloat(newVal);\n this.showAdvisoryCard.bind(this)();\n }\n }\n\n /**\n * @private connectedCallback\n * @description\n * When entering the DOM, set a timeout to show\n * the advisory card after X seconds and adds a\n * DOM listener to the PLP sidebar events\n */\n connectedCallback() {\n this.timeout = this.showAdvisoryCard.bind(this)();\n\n document.addEventListener('plp:basketUpdated', this.hideAdvisoryCard.bind(this));\n this.querySelector('.js-dismiss').addEventListener('click', this.hideAdvisoryCard.bind(this));\n\n // Hide chat button if basket is empty on initial load\n this.constructor.toggleChatBubble(this.isEmptyBasket());\n }\n\n /**\n * @private disconnectedCallback\n * @description\n * Clears the timeout on DOM removal\n */\n disconnectedCallback() {\n clearTimeout(this.timeout);\n }\n\n /**\n * @public isEmptyBasket\n * @returns {boolean} - Whether basket is empty.\n * @description\n * Checks if the basket is empty.\n */\n isEmptyBasket() {\n const sidebar = document.querySelector(this.sidebar);\n const basket = JSON.parse(sidebar.getAttribute(this.basket));\n\n return basket.length === 0;\n }\n\n /**\n * @public showAdvisoryCard\n * @description\n * Waits for a timeout and then shows the advisory card if the basket is still empty\n */\n showAdvisoryCard() {\n this.timeout = setTimeout(() => {\n // Check if basket is empty\n if (!this.isEmptyBasket()) return;\n\n // Set the height of the card as a CSS variable\n const height = this.getBoundingClientRect().height;\n\n if (this.wrapper) this.wrapper.style.setProperty('--advisory-card-height', `${height}px`);\n\n // Show advisory card\n this.classList.add(this.visibilityClass);\n this.setAttribute('aria-hidden', 'false');\n this.shown = true;\n }, this.waiting);\n }\n\n /**\n * @public destroy\n * @description\n * If the element is not customer facing, it will\n * clear the timeout and remove the element from\n * the DOM.\n */\n destroy() {\n if (!this.classList.contains(this.visibilityClass)) {\n clearTimeout(this.timeout);\n\n this.parentElement?.parentElement?.removeChild(this.parentElement);\n\n // Show chat button when advisory card is closed\n this.constructor.toggleChatBubble(false);\n }\n }\n\n /**\n * @public hideAdvisoryCard\n * @description\n * Hides the advisory card\n */\n hideAdvisoryCard() {\n this.classList.remove(this.visibilityClass);\n this.setAttribute('aria-hidden', 'true');\n\n // Wait for the animation to be done before removing the element from the DOM.\n const transitionDuration = parseFloat(window.getComputedStyle(this).transitionDuration) * 1000;\n setTimeout(() => {\n this.destroy();\n }, transitionDuration);\n }\n\n /**\n * @private static toggleChatBubble\n * @param {boolean} value Toggle chat button display class\n * @description\n * Hides or shows the Dimelo chat bubble\n */\n static toggleChatBubble(value) {\n const chatBubble = document.querySelector('.dimelo_chat_item_markup');\n\n if (chatBubble) chatBubble.classList.toggle('d-none', value);\n }\n}\n\nif (!window.customElements.get('vz-advisory-card')) {\n window.customElements.define('vz-advisory-card', VZAdvisoryCard);\n}\n","'use-strict';\n\nimport { CONST } from 'Util/util';\nimport VZSpinner from 'Components/VZSpinner';\n\nclass FilterAndSortBar {\n constructor() {\n // Filter\n this.selectedFilters = [];\n this.isFilterBarSticky = false;\n this.mdBreakpoint = parseInt(CONST.breakpoints.lg, 10);\n\n this.spinner = document.querySelector('vz-spinner') || new VZSpinner();\n\n this.initializeFilterBar();\n this.initializeSorting();\n\n window.addEventListener('resize', () => this.updateFilterBarHeight());\n window.dataLayer = window.dataLayer || [];\n }\n\n /**\n * @function initialize\n * @private\n * @description initializes the file\n */\n initializeFilterBar() {\n this.filterBar = document.querySelector('.js-filter-bar');\n\n // Filter Bar is not configured correctly\n if (!this.filterBar) return;\n\n this.filterBarWrapper = document.querySelector('.js-filter-bar-wrapper');\n\n this.filters = this.filterBar.querySelectorAll('.js-filter');\n this.filtersWrapper = this.filterBar.querySelector('.js-filter-bar-content');\n this.allProductsFilter = this.filterBar.querySelector('.js-filter-reset');\n this.productList = document.querySelector('.js-product-listing');\n\n this.updateFilterBarHeight();\n\n // Bind the click event to the 'all products' button\n if (this.allProductsFilter) {\n this.allProductsFilter.addEventListener('click', () => {\n this.clearAllFilters();\n this.allProductsFilter.classList.add('active');\n this.selectedFilters = [];\n this.updateSelectedFiltersDataAttribute();\n this.applyChanges(this.allProductsFilter.getAttribute('data-href'));\n });\n }\n\n // Bind the click event to the rest of the filter buttons\n this.filters.forEach((filter) => {\n if (filter !== this.allProductsFilter) {\n filter.addEventListener('click', () => {\n this.toggleFilter(filter, Array.from(this.filters).indexOf(filter));\n });\n }\n });\n\n if (this.allProductsFilter && !Array.from(this.filters).some((filter) => filter.classList.contains('active'))) {\n this.allProductsFilter.classList.add('active');\n }\n\n // Scroll event listeners\n this.filtersWrapper.addEventListener('scroll', () => this.handleFilterScroll());\n this.showFadingEffect();\n\n if (this.filterBarWrapper && this.filterBarWrapper.classList.contains('js-filter-bar-sticky')) {\n window.addEventListener('scroll', () => this.handleScroll());\n }\n }\n\n /**\n * @function initializeSorting\n * @private\n * @description Initializes the sorting functionality\n */\n initializeSorting() {\n this.sorting = document.querySelector('.js-filter-bar-sort');\n\n // Sorting is not configured correctly\n if (!this.sorting) return;\n\n this.sorting.addEventListener('change', (event) => {\n const selectedOption = event.target.options[event.target.selectedIndex];\n const url = selectedOption.value;\n this.applyChanges(url);\n });\n }\n\n /**\n * @function updateDom\n * @private\n * @param {Object} results - The parsed HTML response from the fetch request\n * @param {string} selector - The CSS selector of the DOM element to update\n * @description Updates the specified DOM element with the parsed HTML response\n * @returns {Promise} promise - Resolves when the DOM update is complete\n */\n static updateDom(results, selector) {\n return new Promise((resolve) => {\n const updates = results.querySelector(selector);\n const target = document.querySelector(selector);\n\n if (document.startViewTransition) {\n const transition = document.startViewTransition(() => {\n target.innerHTML = updates.innerHTML;\n });\n\n transition.finished.then(resolve);\n } else {\n target.innerHTML = updates.innerHTML;\n resolve();\n }\n });\n }\n\n /**\n * @function updateBrowserURL\n * @static\n * @description Updates the browser URL with the value of the 'seoPermalink' from the document\n */\n static updateBrowserURL() {\n const seoPermaLink = document.querySelector('.seoPermalink')?.value;\n if (typeof seoPermaLink !== 'undefined') {\n window.history.pushState({ urlPath: seoPermaLink }, '', seoPermaLink);\n }\n }\n\n /**\n * @function parseResults\n * @private\n * @param {Object} response - The response from the fetch request\n * @description Updates the DOM with the parsed HTML response and re-initializes the event listeners on the DOM elements\n */\n parseResults(response) {\n const parser = new DOMParser();\n const results = parser.parseFromString(response, 'text/html');\n const elementsToUpdate = ['.js-product-listing', '.js-filter-bar-wrapper'];\n const domUpdatePromises = elementsToUpdate.map((selector) => FilterAndSortBar.updateDom(results, selector));\n\n Promise.all(domUpdatePromises).then(() => {\n this.initializeFilterBar();\n this.initializeSorting();\n FilterAndSortBar.updateBrowserURL();\n this.spinner.stop();\n });\n }\n\n /**\n * @function scrollToProductList\n * @private\n * @description Scrolls the window to the product list if it is past the top of the product list\n */\n scrollToProductList() {\n const productListRect = this.productList.getBoundingClientRect();\n const filterBarTopOffset = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--filter-bar-top-offset').trim(), 10);\n const offsetHeight = this.filterBar.height + filterBarTopOffset;\n\n // Calculate the scroll amount and scroll if it is past the top of the product list\n const scrollAmount = productListRect.top - offsetHeight;\n if (scrollAmount < 0) {\n window.scrollBy({\n top: scrollAmount,\n behavior: 'smooth'\n });\n }\n }\n\n /**\n * @function clearAllFilters\n * @private\n * @description Clear all filters and remove the 'active' class\n */\n clearAllFilters() {\n this.filters.forEach((filter) => {\n filter.classList.remove('active');\n });\n }\n\n /**\n * @function toggleFilter\n * @private\n * @param {HTMLElement} filter - The filter to toggle\n * @param {number} index - The index of the filter\n * @description Toggle the active state of a filter\n */\n toggleFilter(filter, index) {\n filter.classList.toggle('active');\n this.activeFilters = Array.from(document.getElementsByClassName('filter-bar-btn active')).filter((btn) => !btn.classList.contains('js-filter-reset'));\n if (filter.classList.contains('active')) {\n this.selectedFilters.push(index);\n if (this.allProductsFilter) {\n this.allProductsFilter.classList.remove('active');\n }\n } else {\n this.selectedFilters = this.selectedFilters.filter((i) => i !== index);\n\n if (this.allProductsFilter && this.selectedFilters.length === 0) {\n this.allProductsFilter.classList.add('active');\n }\n }\n this.activeFiltersType = '';\n if (this.activeFilters.length > 0) {\n this.activeFiltersType = Array.from(this.activeFilters)\n .map((activeFilter) => activeFilter.getAttribute('data-value'))\n .join('_');\n }\n\n this.updateSelectedFiltersDataAttribute();\n this.applyChanges(filter.getAttribute('data-href'));\n\n window.dataLayer.push({\n event: 'mkb_solutions_filter',\n solutions_filter: this.activeFiltersType\n });\n }\n\n /**\n * @function updateSelectedFiltersDataAttribute\n * @private\n * @description Update the selected filters data attribute on the filter bar element\n */\n updateSelectedFiltersDataAttribute() {\n const value = this.selectedFilters.length > 0 ? this.selectedFilters.toString() : '';\n this.filterBar.setAttribute('data-selected-filters', value);\n }\n\n /**\n * @function handleFilterScroll\n * @private\n * @description Handles the horizontal scrolling event for the filters wrapper to show/hide the fading effect.\n */\n handleFilterScroll() {\n this.showFadingEffect();\n }\n\n /**\n * @function handleScroll\n * @private\n * @description Handles the global (vertical) scrolling event to check the sticky state of the filter bar.\n */\n handleScroll() {\n this.checkIfFilterBarIsSticky();\n }\n\n /**\n * @function checkIfFilterBarIsSticky\n * @private\n * @description Checks if the filter bar is in a sticky state based on its current position.\n */\n checkIfFilterBarIsSticky() {\n const style = window.getComputedStyle(this.filterBarWrapper);\n if (style.position !== 'sticky') {\n this.filterBarWrapper.classList.remove('is-sticky');\n return;\n }\n\n const rect = this.filterBarWrapper.getBoundingClientRect();\n const filterBarTopOffset = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--filter-bar-top-offset').trim(), 10);\n const isCurrentlySticky = rect.top <= filterBarTopOffset;\n\n if (isCurrentlySticky !== this.isFilterBarSticky) {\n this.isFilterBarSticky = isCurrentlySticky;\n this.filterBarWrapper.classList.toggle('is-sticky', this.isFilterBarSticky);\n }\n }\n\n /**\n * @function showFadingEffect\n * @private\n * @description Toggles the fading effect classes based on the scroll state of the filters wrapper.\n */\n showFadingEffect() {\n const { scrollLeft, clientWidth, scrollWidth } = this.filtersWrapper;\n\n const overflowLeft = scrollLeft > 0;\n const overflowRight = scrollWidth - scrollLeft > clientWidth;\n\n this.filterBar.classList.toggle('fade-left', overflowLeft);\n this.filterBar.classList.toggle('fade-right', overflowRight);\n }\n\n /**\n * @function updateFilterBarHeight\n * @private\n * @description Updates the height of the filter bar based on its bounding rectangle\n */\n updateFilterBarHeight() {\n if (this.filterBar) this.filterBar.height = this.filterBar.getBoundingClientRect().height;\n }\n\n /**\n * @function applyChanges\n * @private\n * @param {string} url - The URL to fetch data from\n * @description Fetches the data from the provided URL and applies the changes (filtering or sorting)\n */\n applyChanges(url) {\n this.spinner.start();\n\n fetch(url)\n .then((response) => response.text())\n .then((response) => {\n const parser = new DOMParser();\n const results = parser.parseFromString(response, 'text/html');\n\n return FilterAndSortBar.updateDom(results, '.js-product-listing').then(() => this.parseResults(response));\n })\n .then(() => {\n this.scrollToProductList();\n this.spinner.stop();\n })\n .catch((error) => {\n this.spinner.stop();\n console.error('Error:', error);\n });\n }\n}\n\n(() => new FilterAndSortBar())();\n","'use strict';\n\nconst computedStyles = getComputedStyle(document.documentElement);\n\n/**\n * @constant {Object} events - All common events\n * @property {string} blur - Blur event\n * @property {string} change - Change event\n * @property {string} click - Click event\n * @property {string} keyUp - Keyup event\n * @property {string} load - Load event\n * @property {string} mousedown - Mouse down event\n * @property {string} mouseleave - Mouse leave event\n * @property {string} mouseover - Mouse over event\n * @property {string} popstate - Popstate event\n * @property {string} resize - Resize event\n * @property {string} scroll - Scroll event\n * @property {string} submit - Submit event\n * @property {string} update - Custom update event\n */\nconst events = {\n blur: 'blur',\n change: 'change',\n click: 'click',\n input: 'input',\n keyUp: 'keyup',\n load: 'load',\n mousedown: 'mousedown',\n mouseleave: 'mouseleave',\n mouseover: 'mouseover',\n paste: 'paste',\n popstate: 'popstate',\n resize: 'resize',\n responseError: 'responseError',\n scroll: 'scroll',\n submit: 'submit',\n transitionEnd: 'transitionend',\n update: 'update',\n invalid: 'invalid'\n};\n\n/**\n * @constant {Object} selectors - Common selectors\n * @property {string} body - body\n * @property {Object} form - form related selectors\n * @property {string} checkbox - checkbox\n * @property {string} form - form\n * @property {string} input - input\n * @property {string} inputFieldClear - .js-input-clear\n * @property {string} inputFieldFeedback - .js-invalid-feedback\n * @property {string} label - label\n * @property {string} radio - radio\n * @property {string} select - select\n * @property {string} submit - [type=\"submit\"]\n * @property {string} textarea - textarea\n * @property {string} html - html\n * @property {string} htmlBody - html, body\n * @property {string} img - img\n * @property {string} input - input\n */\nconst selectors = {\n body: 'body',\n form: {\n checkbox: 'input[type=\"checkbox\"]',\n file: 'input[type=\"file\"]',\n form: 'form',\n input: 'input',\n inputFieldClear: '.js-input-clear',\n inputFieldFeedback: '.js-invalid-feedback',\n label: 'label',\n radio: 'input[type=\"radio\"]',\n select: 'select',\n submit: '[type=\"submit\"]',\n textarea: 'textarea'\n },\n html: 'html',\n htmlBody: 'html, body',\n img: 'img',\n input: 'input',\n interactiveElements: 'input, button, select, textarea, a[href]'\n};\n\n/**\n * @constant {Object} classes - Common classes\n * @property {string} active - active\n * @property {Object} buttons - buttons\n * @property {string} next - next\n * @property {string} previous - previous\n * @property {string} warning - warning\n * @property {string} dBlock - d-block\n * @property {string} dFlex - d-flex\n * @property {string} dInlineBlock - d-inline-block\n * @property {string} dNone - d-none\n * @property {string} disabled - disabled\n * @property {string} empty - empty\n * @property {string} inactive - inactive\n * @property {string} invalid - invalid\n * @property {string} hidden - hidden\n * @property {string} last - last\n * @property {string} show - show\n * @property {string} valid - valid\n */\nconst classes = {\n active: 'active',\n buttons: {\n next: 'js-button-next',\n previous: 'js-button-previous',\n warning: 'js-button-warning'\n },\n dBlock: 'd-block',\n dFlex: 'd-flex',\n dInlineBlock: 'd-inline-block',\n dNone: 'd-none',\n disabled: 'disabled',\n empty: 'empty',\n inactive: 'inactive',\n invalid: 'invalid',\n hidden: 'hidden',\n last: 'last',\n show: 'show',\n valid: 'valid'\n};\n\n/**\n * @constant {Object} attributes - Common attributes\n * @property {string} action - action\n * @property {string} class - class\n * @property {string} csrfToken - data-csrf-token\n * @property {string} csrfName - data-csrf-name\n * @property {string} disabled - disabled\n * @property {string} exclude - data-exclude\n * @property {string} href - href\n * @property {string} id - id\n * @property {string} pattern - pattern\n * @property {string} url - url\n * @property {string} readonly - readonly\n * @property {string} target - data-bs-target\n * @property {string} value - value\n * @property {Object} validation - Validation related attributes\n * @property {string} patternMismatch - data-pattern-mismatch\n * @property {string} valueMissing - data-missing-error\n */\nconst attributes = {\n action: 'action',\n class: 'class',\n checked: 'checked',\n csrfToken: 'data-csrf-token',\n csrfName: 'data-csrf-name',\n disabled: 'disabled',\n exclude: 'data-exclude',\n href: 'href',\n id: 'id',\n pattern: 'pattern',\n placeholder: 'placeholder',\n required: 'required',\n readonly: 'readonly',\n selected: 'selected',\n target: 'data-bs-target',\n url: 'url',\n value: 'value',\n validation: {\n patternMismatch: 'data-pattern-mismatch',\n valueMissing: 'data-missing-error',\n tooShort: 'data-too-short'\n }\n};\n\n/**\n * @constant {Object} breakpoints - Common reusable breakpoints\n * @property {string} xxs - 0\n * @property {string} xs - 368\n * @property {string} sm - 576\n * @property {string} md - 768\n * @property {string} lg - 992\n * @property {string} xl - 1200\n * @property {string} xxl - 1400\n */\n\nconst breakpoints = {\n xxs: parseInt(computedStyles.getPropertyValue('--breakpoint-xxs'), 10),\n xs: parseInt(computedStyles.getPropertyValue('--breakpoint-xs'), 10),\n sm: parseInt(computedStyles.getPropertyValue('--breakpoint-sm'), 10),\n md: parseInt(computedStyles.getPropertyValue('--breakpoint-md'), 10),\n lg: parseInt(computedStyles.getPropertyValue('--breakpoint-lg'), 10),\n xl: parseInt(computedStyles.getPropertyValue('--breakpoint-xl'), 10),\n xxl: parseInt(computedStyles.getPropertyValue('--breakpoint-xxl'), 10)\n};\n\n/**\n * @constant {Object} localStorage - constants for local storage items\n * @property {string} preferredLayoutId - preferredLayoutId\n */\nconst localStorage = {\n preferredLayoutId: 'preferredLayoutId'\n};\n\n/**\n * @constant {Object} bscanSteps - constants for Business Scan Steps\n * @property {string} ADVICE - The advice Step\n * @property {string} INTRO - The intro Step\n * @property {string} GROUPED_QUESTIONS - The grouped questions Step\n * @property {string} THANKYOU - The thank you Step\n */\nconst bscanSteps = {\n INTRO: 'intro',\n STATEMENTS_DONE: 'bs-statements-done',\n GROUPED_QUESTIONS: 'js-bscan-question-group',\n ADVICE: 'bs-advice',\n THANKYOU: 'bs-thank-you'\n};\n\n/**\n * @constant {Object} vzLayoutToggle - Attributes used for VZLayoutToggle\n * @property {string} class - data-layout-class\n * @property {string} container - data-layout-container\n * @property {string} enabledBreakpoint - data-layout-enabled-breakpoint\n * @property {string} id - data-layout-id\n * @property {string} idDefault - data-layout-id-default\n * @property {string} localStorageKey - data-layout-key\n */\nconst vzLayoutToggle = {\n class: 'data-layout-class',\n container: 'data-layout-container',\n enabledBreakpoint: 'data-layout-enabled-breakpoint',\n id: 'data-layout-id',\n idDefault: 'data-layout-id-default',\n localStorageKey: 'data-layout-key'\n};\n\nexport default {\n bscanSteps,\n attributes,\n breakpoints,\n classes,\n events,\n selectors,\n localStorage,\n vzLayoutToggle\n};\n","'use stict';\n\nimport 'core-js/features/array/at';\n\n/**\n * @private splitUpUrl\n * @param {string} url - The url to split up\n * @returns {Object} values\n *\n * @description\n * Will return an object with different parts of the url\n */\nexport function splitUpUrl(url) {\n if (!url.includes('?')) return {};\n\n let hash;\n let paramUrl = url.split('?').at(1);\n\n // if there is a hash at the end, store the hash\n if (paramUrl.includes('#')) {\n hash = paramUrl.split('#').at(1);\n paramUrl = paramUrl.split('#').at(0);\n }\n\n return {\n domain: url.split('?').at(0),\n params: paramUrl.split('&'),\n hash: hash\n };\n}\n\n/**\n * @public removeParamFromURL\n * @param {string} url - The url from which the parameter will be removed\n * @param {string} name - The name of the parameter that will be removed from url\n * @returns {string} url\n *\n * @description\n * remove the parameter and its value from the given url and returns the\n * changed url\n */\nexport function removeParamFromURL(url, name) {\n if (!url.includes('?') || !url.includes(`${name}=`)) return url;\n\n const urlValues = splitUpUrl(url);\n const newParams = urlValues.params.filter((param) => param.split('=').at(0) !== name);\n\n return `${urlValues.domain}?${newParams.join('&')}${urlValues.hash ? `#${urlValues.hash}` : ''}`;\n}\n\n/**\n * @public getParamFromURL\n * @param {string} url - The url from which the parameter will be retrieved\n * @param {string} name - The name of the parameter that will be retrieved from url\n * @returns {string} The value of the parameter\n *\n * @description\n * remove the parameter and its value from the given url and returns the\n * changed url\n */\nexport function getParamFromURL(url, name) {\n if (!url.includes('?') || !url.includes(`${name}=`)) return url;\n\n const urlValues = splitUpUrl(url);\n const nameMatch = urlValues.params.find((item) => item.includes(`${name}=`));\n\n return nameMatch && nameMatch.split('=').at(1);\n}\n\n/**\n * @public appendParamToURL\n * @param {string} url - The url to which the parameter will be added\n * @param {string} name - The name of the parameter\n * @param {string} value the value of the parameter\n * @returns {string} url\n *\n * @description\n * appends the parameter with the given name and value to the given url\n * and returns the changed url\n */\nexport function appendParamToURL(url, name, value) {\n let newURL = url;\n // remove if the param already exists\n if (url.includes(`${name}=`)) {\n newURL = removeParamFromURL(url, name);\n }\n const separator = newURL.includes('?') ? '&' : '?';\n return `${newURL}${separator}${name}=${encodeURIComponent(value)}`;\n}\n\n/**\n * @public appendCsrfToUrl\n * @description Takes a URL and adds a CSRF token to it\n * @param {string} url - The URL to append the CSRF token on\n * @returns {string} The URL with the CSRF token appended\n */\nexport function appendCsrfToUrl(url) {\n const separator = url.includes('?') ? '&' : '?';\n return `${url}${separator}${window.csrf.tokenName}=${window.csrf.token}`;\n}\n\n/**\n * @public removeHash\n * @description Will remove the hash from the url\n */\nexport function removeHash() {\n window.history.replaceState({}, document.title, window.location.pathname + window.location.search);\n}\n\nexport const getUrlFromAttributes = (url, component, excludedAttributes) => {\n const newUrl = new URL(url);\n const urlParams = newUrl.searchParams;\n\n // Get all attributeNames except for the irrelevant ones.\n const attributeNames = component.getAttributeNames().filter((attributeName) => !excludedAttributes.includes(attributeName));\n\n // Filter the attributeNames which will be replaced by the new URL.\n attributeNames\n .filter((param) => !urlParams.has(param.replaceAll('-', '')))\n .forEach((attr) => {\n const attrValue = component.getAttribute(attr);\n if (attrValue) {\n const attrName = attr.replaceAll('-', '');\n // Append all other attributes to the new URL\n urlParams.append(attrName, attrValue);\n }\n });\n\n return `${newUrl.origin}${newUrl.pathname}?${urlParams}`;\n};\n\n/**\n * This function checks if the provided element is a part of BM Hardware card. In case of true it appends\n * the 'editIndex' parameter to the URL with the index of the current BM Hardware card, in order to keep the\n * card open after Product-Variation ajax.\n *\n * @public appendBmHardwareCardIndex\n * @param {HTMLElement} element - The HTML element triggering the ajax.\n * @param {string} url - The URL to which the parameter will be appended.\n * @returns {string} The modified URL with the appended parameter.\n */\nexport function appendBmHardwareCardIndex(element, url) {\n let newURL = url;\n if (!element.closest('.js-hardware-device-card')?.classList.contains('is-collapsed') && element.closest('.js-hardware-phones')) {\n newURL = appendParamToURL(url, 'editIndex', element.closest('.js-hardware-phones').dataset.index);\n }\n return newURL;\n}\n","'use strict';\n\nimport CONST from './constants';\n\n/**\n * addEvent - Will add an event listener to an element inside a parent\n *\n * @param {string} parent - The parent element\n * @param {string} passedEvent - The event\n * @param {string} selector - The targeted element\n * @param {function} handler - The handler\n */\nfunction addEvent(parent, passedEvent, selector, handler) {\n parent.addEventListener(\n passedEvent,\n function fnAddEvent(event) {\n // If the clicked element matches the selector, or is a child of the selector\n if (event.target.matches(`${selector} , ${selector} *`)) {\n handler.apply(event.target.closest(selector), arguments);\n }\n },\n false\n );\n}\n\n/**\n * @public documentReady\n * @param {Function} fn - function to be called after document is done loading.\n */\nfunction documentReady(fn) {\n if (document.readyState !== 'loading') {\n fn();\n } else {\n document.addEventListener('DOMContentLoaded', fn);\n }\n}\n\n/**\n * @public exists\n * @param {*} selection - The element or nodelist to verify for existence\n * @returns {boolean} - Boolean value stating the existance of the selection\n * @description\n * Verifies existance of a certain element by checking for type, null and length\n * Usage: use with either querySelector() or querySelectorAll()\n * querySelector will not have a 'length', e.g. this would return true if other conditions are true\n * querySelectorAll will have a 'length', e.g. this would return true if all conditions are true\n */\nfunction exists(selection) {\n return typeof selection !== 'undefined' && selection !== null && ('length' in selection ? selection.length > 0 : true);\n}\n\n/**\n * @public getPosition\n * @param {*} element - The element to get the position for\n * @returns {Object} - An object containing the left and top position of the element\n *\n * @description\n * Will get the position of an element relative to the document\n */\nfunction getPosition(element) {\n let top = element.offsetTop;\n let left = element.offsetLeft;\n\n let currentElement = element;\n while (currentElement.offsetParent && currentElement.offsetParent !== window) {\n currentElement = currentElement.offsetParent;\n top += currentElement.offsetTop;\n left += currentElement.offsetLeft;\n }\n\n return { left, top };\n}\n\n/**\n * isKeyInObject\n * @param {Object} object - The object\n * @param {string} key - The key\n * @returns {boolean} - True or false\n */\nfunction isKeyInObject(object, key) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\n/**\n * @private isAemMobileView\n * @returns {boolean} - Whether the user is on a \"mobile\" viewport or not based on AEM rules\n *\n * @description\n * Checks to see whether the user is on a \"mobile\" viewport or not based on AEM rules\n * Please note that www.vodafone.nl/zakelijk will show the mobile menu from viewports 1023 and smaller\n */\nfunction isAemMobileView() {\n return window.innerWidth < 1024;\n}\n\n/**\n * @memberof util\n * @param {string} breakpointKey from constants that should match css breakpoint\n * @param {boolean} [isUp] by default is true since mobile first, reverses condition\n * @return {boolean} whether window is larger than specified breakpoint\n */\nfunction isMediaBreakpoint(breakpointKey, isUp = true) {\n if (!isKeyInObject(CONST.breakpoints, breakpointKey)) {\n console.error(`fn isMediaBreakpoint: ${breakpointKey} -- does not exist in constants breakpoints object`); // eslint-disable-line\n }\n\n const outerWidth = window.innerWidth;\n const breakpointValue = parseInt(CONST.breakpoints[breakpointKey], 10);\n\n return isUp ? outerWidth > breakpointValue : outerWidth < breakpointValue - 1;\n}\n\n/**\n * @memberof util\n * @return {Object} An object containing the name and value of the current breakpoint\n */\nfunction getCurrentBreakpoint() {\n const breakpoints = CONST.breakpoints;\n const screenSize = document.documentElement.clientWidth;\n const currentBreakpoint = [...Object.keys(breakpoints)].reverse().find((key) => screenSize > breakpoints[key]);\n\n return {\n name: currentBreakpoint,\n value: breakpoints[currentBreakpoint]\n };\n}\n\n/**\n * @memberof util\n * @return {number} a unique number\n */\nfunction generateUniqueNumber() {\n return performance.now().toString().replace('.', 0);\n}\n\n/**\n * @public empty\n * @param {*} element - The element to remove child nodes from\n * @description\n * Empties a given element completely while the given element has child nodes.\n * Plain strings are also considered child nodes and are thus also removed.\n */\nfunction removeChildNodes(element) {\n while (element.hasChildNodes()) {\n element.removeChild(element.lastChild);\n }\n}\n\n/**\n * @public tryParseJSON\n * @param {string} string - The possible JON string\n * @returns {Object} - Either the JSON object or an empty object for consistent return\n * @description\n * Copied from https://stackoverflow.com/a/20392392\n */\nfunction tryParseJSON(string) {\n try {\n const o = JSON.parse(string);\n\n // Handle non-exception-throwing cases:\n // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,\n // but... JSON.parse(null) returns null, and typeof null === \"object\",\n // so we must check for that, too. Thankfully, null is falsey, so this suffices:\n if (o && typeof o === 'object') {\n return o;\n }\n } catch (e) {} // eslint-disable-line no-empty\n\n return {};\n}\n\n/**\n * @function isIOS\n * @public\n * @description returns a boolean to determine whether a device's OS is IOS or not\n * @returns {boolean} whether the device OS is IOS or not\n */\nfunction isIOS() {\n return (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream;\n}\n\n/**\n * @function isMobile\n * @returns {boolean} whether the device is an mobile device or not\n */\nfunction isMobile() {\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n}\n\n/**\n * @public scrollTo\n * @param {Object} data - The optional object containing the top & left positions to scroll to\n */\nfunction scrollTo(data) {\n const position = data || {\n top: 0,\n left: 0\n };\n\n const stickyHeader = document.querySelector('.page-header');\n const headerHeight = stickyHeader ? stickyHeader.offsetHeight : 0;\n const supportsNativeSmoothScroll = 'scrollBehavior' in document.documentElement.style;\n let positionTop = position.top;\n\n if (headerHeight > 0) {\n positionTop = position.top - headerHeight - 15; // Removing an additional 15px to put some space between the sticky site header and the element\n }\n\n if (supportsNativeSmoothScroll) {\n document.documentElement.scrollTo({\n top: positionTop,\n left: position.left,\n behavior: 'smooth'\n });\n } else {\n document.documentElement.scrollTop = positionTop;\n }\n}\n\n/**\n * @function toggleButtonState\n * @description Enables or disabled the button passed in based on the value of the second parameter.\n * @param {HTMLElement} button - A button element to be enabled or disabled.\n * @param {boolean} enable - True for enable and false for disable.\n */\nfunction toggleButtonState(button, enable) {\n if (enable) {\n button.classList.remove('disabled');\n button.removeAttribute('disabled');\n } else {\n button.classList.add('disabled');\n button.setAttribute('disabled', 'disabled');\n }\n}\n\n/**\n * @function removeAccentCharacters\n * @description Removes a accents from a string.\n * @param {string} string - The string from which we want to remove accents.\n * @returns {string} The string without accents.\n */\nfunction removeAccentCharacters(string) {\n return string.normalize('NFD').replace(/\\p{Diacritic}/gu, '');\n}\n\n/**\n * @function chunkArrayInGroups\n * @param {Array} arr - Array to be splitted\n * @param {number} size - Max size of the array chunk\n * @return {Array} - Array of grouped chunks\n * @description Splitting an array up into chunks of a given size\n */\nfunction chunkArrayInGroups(arr, size) {\n var groupedChunks = [];\n for (let i = 0; i < arr.length; i += size) {\n groupedChunks.push(arr.slice(i, i + size));\n }\n return groupedChunks;\n}\n\n/**\n * @function chunkGroupArrayInGroups\n * @param {Array} groupArr - Array to be splitted\n * @return {Array} - Array of grouped chunks\n * @description Splitting an array up into chunks of a given size\n */\nfunction chunkGroupArrayInGroups(groupArr) {\n // This one sorts and groups the alike product groups together\n // We need to send the requests to backend in a specific order, so we make it grouped\n const chunkGroups = [];\n Object.keys(groupArr).forEach((groupKey) => {\n const arr = groupArr[groupKey];\n const groupedChunks = [];\n // Sorts the product objects based on pids\n arr.sort((a, b) => {\n return a.pid >= b.pid ? 1 : -1;\n });\n for (let i = 0; i < arr.length; i += Math.round(arr.length / 3)) {\n groupedChunks.push(arr.slice(i, i + Math.round(arr.length / 3)));\n }\n // This makes sure that we have a separate business mobile group to send to backend\n groupedChunks.forEach((chunk, chunkIndex) => {\n Object.keys(chunk).forEach((key, index) => {\n const item = chunk[key];\n if (item?.pdpConfiguratorType === 'business-mobile') {\n chunk.splice(index, 1);\n if (chunk.length < 1) groupedChunks.splice(chunkIndex, 1);\n groupedChunks.push(item);\n }\n });\n });\n chunkGroups.push(groupedChunks);\n });\n return chunkGroups;\n}\n\n/**\n * @function trackPdpEccomerceEvent\n * @param {string} productType - Configurator type\n * @param {Object} step - Step to track\n * @description Builds and submits ecommerce event to track btn clicks on PDP\n */\nfunction trackPdpEccomerceEvent(productType, step) {\n const products = {\n brand: 'vodafone',\n category: `business-sme/acquisition/postpaid/${productType.replace(/\\s|business-/gi, '')}`,\n market: 'b2b'\n };\n\n const ecommerceObject = {\n event: 'checkout',\n events: {\n category: 'ecommerce',\n action: 'checkout'\n },\n ecommerce: {\n checkout: {\n action: 'checkout',\n has_vodafone: true,\n has_ziggo: true,\n products: products,\n step_name: step.name,\n step_nr: step.number\n }\n }\n };\n\n /* eslint-disable no-underscore-dangle */\n if (ecommerceObject && window._ddm) {\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(ecommerceObject);\n window._ddm.trigger('ecommerce.checkout', {\n data: ecommerceObject.ecommerce.checkout\n });\n }\n /* eslint-enable no-underscore-dangle */\n}\n\n/**\n * @function assignStyling\n * @private\n * @param {Element} el - Element\n * @param {Object} styles - Styles\n * @description Assign a style object to an element\n */\nfunction assignStyling(el, styles) {\n Object.assign(el.style, styles);\n}\n\n/**\n * Calculate the total width of a collection of elements.\n *\n * @param {NodeListOf} elements - A collection of HTML elements.\n * @param {number} spacing - flex gap value in px.\n * @returns {number} The total width of all elements.\n */\nfunction getTotalWidth(elements, spacing = 0) {\n return Array.from(elements).reduce((totalWidth, element) => {\n const elementStyles = window.getComputedStyle(element);\n const elementWidth = element.offsetWidth + parseFloat(elementStyles.marginLeft) + parseFloat(elementStyles.marginRight);\n return totalWidth + elementWidth;\n }, spacing);\n}\n\n/**\n * Checks if a flex container is wrapped by comparing the total width of its flex items\n * with the container's width.\n *\n * @param {HTMLElement} flexContainer - The HTML element representing the flex container.\n * @param {NodeListOf} flexItems - A collection of HTML elements representing the flex items.\n * @param {number} spacing - flex gap value in px.\n * @returns {boolean} True if the flex container is wrapped, false if all items fit in a single row.\n */\nfunction isFlexContainerWrapped(flexContainer, flexItems, spacing) {\n const containerWidth = flexContainer.clientWidth;\n const itemsTotalWidth = getTotalWidth(flexItems, spacing);\n // Check if the items are wrapped by comparing their total width with the container width.\n const isWrapped = itemsTotalWidth > containerWidth;\n return isWrapped;\n}\n\n/**\n * @function loadCSS\n * @param {string} url - The URL of the CSS file to load.\n * @description Creates a link element and appends it to the document head to load a CSS file.\n */\nfunction loadCSS(url) {\n if (!url || document.querySelector(`link[href=\"${url}\"]`)) {\n return;\n }\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n}\n\n/**\n * The function formats input to money string\n *\n * @param {number} num Source number\n * @returns {string} Formatted string € 1.111,11\n */\nfunction formatToPriceString(num) {\n const parts = Number.parseFloat(num, 10).toFixed(2).toString().split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.');\n if (parts[1] === '00') {\n return `€ ${parts[0]},00`;\n }\n return `€ ${parts.join(',')}`;\n}\n\n/**\n * Checks if two arrays of objects are equal by comparing their elements.\n *\n * @param {Array} arr1 - The first array to compare.\n * @param {Array} arr2 - The second array to compare.\n * @returns {boolean} True if the arrays are equal, false otherwise.\n */\nfunction arraysAreEqual(arr1, arr2) {\n if (arr1.length !== arr2.length) {\n return false;\n }\n\n return (\n !arr1.some((obj1) => !arr2.some((obj2) => JSON.stringify(obj1) === JSON.stringify(obj2))) &&\n !arr2.some((obj2) => !arr1.some((obj1) => JSON.stringify(obj1) === JSON.stringify(obj2)))\n );\n}\n\nexport {\n CONST,\n addEvent,\n documentReady,\n exists,\n generateUniqueNumber,\n getCurrentBreakpoint,\n getPosition,\n isIOS,\n isMobile,\n isKeyInObject,\n isAemMobileView,\n isMediaBreakpoint,\n removeChildNodes,\n scrollTo,\n tryParseJSON,\n toggleButtonState,\n removeAccentCharacters,\n chunkArrayInGroups,\n chunkGroupArrayInGroups,\n trackPdpEccomerceEvent,\n assignStyling,\n isFlexContainerWrapped,\n getTotalWidth,\n loadCSS,\n formatToPriceString,\n arraysAreEqual\n};\n","'use strict';\n\nimport { CONST } from 'Util/util';\nimport { getFieldValidationMessage } from 'Components/form/form';\n\nconst validationAttributes = ['valueMissing', 'patternMismatch', 'tooShort'];\n\n/**\n * toggleValidityClass\n * @param {boolean} [isValid] - valid or not - true or false\n * @param {HTMLElement} [target] - target element\n */\nfunction toggleValidityClass(isValid, target) {\n if (isValid) {\n target.classList.remove('invalid');\n target.classList.add('valid');\n } else {\n target.classList.add('invalid');\n target.classList.remove('valid');\n }\n}\n\n/**\n * removeValidationMessageElement\n * @param {HTMLElement} [target] - target element\n */\nfunction removeValidationMessageElement(target) {\n const element = target.parentElement.querySelector('.error-msg');\n if (element) element.remove();\n}\n\n/**\n * createValidationMessageElement\n * @param {string} [message] - validation message\n * @param {HTMLElement} [target] - target element\n */\nfunction createValidationMessageElement(message, target) {\n const element =\n target.parentElement.querySelector('.error-msg') ||\n (function createErrorElement() {\n const el = document.createElement('small');\n el.classList.add('error-msg', 'text-primary');\n return el;\n })();\n element.innerText = message;\n if (target.dataset.selectedId && target.dataset.selectedId.includes('verblijfsdocument')) element.classList.add('d-inline-flex');\n target.parentElement.insertAdjacentElement('beforeend', element);\n}\n\n/**\n * @public validateField\n * @param {HTMLFormElement} field - The form field\n * @return {boolean} valid - Whether the field is valid or not\n */\nfunction validateField(field) {\n let validField = true;\n\n validationAttributes.forEach((attribute) => {\n if (field.validity && field.validity[attribute]) {\n const errorMessage = field.getAttribute(CONST.attributes.validation[attribute]);\n validField = false;\n createValidationMessageElement(errorMessage, field);\n toggleValidityClass(false, field);\n }\n });\n\n if (validField) {\n removeValidationMessageElement(field);\n toggleValidityClass(true, field);\n }\n\n return validField;\n}\n\n/**\n * @public validateForm\n * @param {HTMLForm} form - The form\n * @return {boolean} valid - Whether the form is valid or not\n */\nfunction validateForm(form) {\n let validForm = true;\n const formFields = [...form.querySelectorAll(CONST.selectors.form.input), ...form.querySelectorAll(CONST.selectors.form.textarea)];\n const dropdowns = [...form.querySelectorAll('.js-custom-select-validation')];\n\n formFields.forEach((field) => {\n if (field.type === 'hidden') {\n return;\n }\n\n const validField = validateField(field);\n\n if (!validField) {\n validForm = false;\n }\n });\n\n dropdowns.forEach((dropdown) => {\n const validField = dropdown.checkValidity();\n\n if (!validField) {\n validForm = false;\n }\n });\n\n return validForm;\n}\n\n/**\n * @private validate\n * @param {Event} evt - blur or invalid event\n * @param {string} [msg] - validation message\n */\nfunction validate(evt, msg) {\n const message = msg || getFieldValidationMessage(evt.target);\n if (message) {\n createValidationMessageElement(message, evt.target);\n toggleValidityClass(false, evt.target);\n } else {\n removeValidationMessageElement(evt.target);\n toggleValidityClass(true, evt.target);\n }\n}\n\nexport { validateForm, validateField, validate, removeValidationMessageElement, toggleValidityClass };\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","__webpack_require__.j = 644;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t644: 0,\n\t274: 0,\n\t231: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkvodafoneziggo\"] = globalThis[\"webpackChunkvodafoneziggo\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [395,661,139], () => (__webpack_require__(9682)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","VZAccordion","HTMLElement","constructor","super","connectedCallback","this","activeClass","accordion","querySelector","accordionItem","accordionButton","accordionContent","addEventListener","onClick","bind","toggleClasses","getAttribute","classList","add","remove","window","customElements","get","define","redSpinnerData","require","VZSpinner","parentEl","showing","stop","veil","parentElement","document","body","tagName","appendChild","lottie","Lottie","container","renderer","loop","autoplay","animationData","start","msg","Promise","resolve","getComputedStyle","getPropertyValue","style","position","insertAdjacentHTML","setTimeout","play","contains","content","innerHTML","evt","stopPropagation","bs","Modal","spinner","selectors","errorModal","activeModal","modalStepContainer","modalStep","modalStepInputs","createModalByUrl","targetId","targetEndpoint","modalId","existingModal","getElementById","querySelectorAll","forEach","step","index","CONST","classes","active","getInstance","show","fetch","then","res","status","Error","text","response","modalElement","modal","ModalClass","dispatchEvent","CustomEvent","catch","console","error","finally","modalInstance","_element","modalActiveStep","modalFields","validateModalField","submitStepForm","appendModalStep","field","events","blur","event","lastFocussedField","target","keyUp","change","submit","customEvent","detail","key","toLowerCase","validateField","currField","preventDefault","form","validateForm","endpoint","formData","FormData","csrfName","attributes","csrfToken","append","_dd","user","ids","ga_id","method","scrollToTop","documentElement","scrollTo","top","left","behavior","scrollTop","currentStep","newStep","refreshToken","refreshTokenUrl","dataset","appendCsrfToUrl","VZPlpProductTile","plpSidebar","plpBasket","JSON","parse","productId","productName","productPrice","oneOffPrice","dependencyName","dependencyPrice","dependencyOneOffPrice","productDependency","dependencyLabel","isDependent","productExcluded","excludedLabel","isProductExcluded","productExcludedTile","productExcludedLabel","qtySelectorWrapper","selectorContainer","qty","value","toggle","isSelected","checked","isProgrammaticUpdate","setAttribute","setCurrentState","setQty","setIsSelected","updateBasket","documentReady","disconnectedCallback","removeEventListener","observedAttributes","attributeChangedCallback","name","oldValue","newValue","updatedBasket","filter","item","id","parseInt","productObj","price","dependency","dependsOn","excluded","push","dependencyProduct","arraysAreEqual","stringify","currentItemInBasket","length","textContent","inputField","toFixed","oldVal","Array","from","el","VZPlpQuantitySelector","excludedAttributes","onInput","toggleIncreaseAndDecreaseButtons","forbiddenValues","debounceRate","parseFloat","debouncedChange","debounce","onChange","parentId","parent","aside","minQuantity","quantityField","quantityFieldOriginalValue","onBlur","onKeyDown","onPaste","element","decreaseOrIncrease","disableOrEnable","button","removeAttribute","e","validateMinMax","indexOf","keyCode","clipboardData","getData","replace","currentValue","decrease","isNaN","min","moreThanMax","max","lessThanMin","getCookie","cookieName","parts","cookie","split","pop","shift","getModal","link","modalUrl","isPlp","plpBasketInput","plpUrlInput","location","href","addPlpInputFields","adviceStep","currentBsId","fragment","createElement","addBsIdAsHiddenInputField","addEvent","click","VZPlpSidebar","dataLayer","sidebar","sidebarClasses","open","closed","lineItem","dependencyItem","removeItem","adjustForSidebar","hidden","hiddenOnEmpty","visibleOnEmpty","hiddenOnClosed","hasOneOffPrices","pageHeader","filterBar","priceText","qtyText","emptyText","labelText","sidebarTitle","sidebarContent","sidebarTotal","sidebarTopOffset","stickyBreakpoint","breakpoints","lg","disclaimerOneOff","disclaimerOneOffMobile","tapAreaFooter","tapAreaHeader","chatButton","initialize","showLineItems","updateHeader","updateFooter","deleteItem","handleFloatingSidebar","handleFullOrEmptyState","toggleDisclaimers","calculateMaxHeightSidebarBody","calculateMaxHeightMobileSidebarBody","openMobileSidebar","closeMobileSidebar","decodeURIComponent","deleteIcon","oldBasket","tryParseJSON","newBasket","trackChanges","cookieValue","domain","expirationDays","date","Date","setTime","getTime","cookieString","toUTCString","setCookie","encodeURIComponent","hostname","productsMarkup","reduce","result","product","costs","label","formatToPriceString","isEmptyBasket","innerWidth","totalPrice","total","numberProductsSelected","currentLineItem","closest","productIdToRemove","productToRemove","find","dependencyProductId","removeProperty","assignStyling","bottom","right","sidebarStickyMarginTop","offsetHeight","lineItemHeight","clientHeight","lineItemSpacingType","lineItemSpacing","oldArray","newArray","savedBasket","oldMap","Map","map","newMap","newItem","oldItem","i","solutions_product","solutions_cart","Math","abs","has","VZLayoutToggle","dataLayoutLocalStorageKey","vzLayoutToggle","localStorageKey","localStorage","preferredLayoutId","dataLayoutIdDefault","idDefault","dataLayoutContainer","enabledOnBreakpoint","enabledBreakpoint","toggles","layoutContainer","activeLayoutId","getItem","setup","enable","activeToggle","activeLayoutClass","class","toggleLayout","layoutId","layoutClass","setPreferredLayout","setItem","selectedToggle","hide","handleResize","VZAdvisoryCard","shown","visibilityClass","waiting","basket","wrapper","attrName","newVal","showAdvisoryCard","timeout","hideAdvisoryCard","toggleChatBubble","clearTimeout","height","getBoundingClientRect","setProperty","destroy","removeChild","transitionDuration","chatBubble","FilterAndSortBar","selectedFilters","isFilterBarSticky","mdBreakpoint","initializeFilterBar","initializeSorting","updateFilterBarHeight","filterBarWrapper","filters","filtersWrapper","allProductsFilter","productList","clearAllFilters","updateSelectedFiltersDataAttribute","applyChanges","toggleFilter","some","handleFilterScroll","showFadingEffect","handleScroll","sorting","url","options","selectedIndex","updateDom","results","selector","updates","startViewTransition","finished","updateBrowserURL","seoPermaLink","history","pushState","urlPath","parseResults","DOMParser","parseFromString","domUpdatePromises","all","scrollToProductList","productListRect","filterBarTopOffset","trim","scrollAmount","scrollBy","activeFilters","getElementsByClassName","btn","activeFiltersType","activeFilter","join","solutions_filter","toString","checkIfFilterBarIsSticky","rect","isCurrentlySticky","scrollLeft","clientWidth","scrollWidth","overflowLeft","overflowRight","computedStyles","bscanSteps","INTRO","STATEMENTS_DONE","GROUPED_QUESTIONS","ADVICE","THANKYOU","action","disabled","exclude","pattern","placeholder","required","readonly","selected","validation","patternMismatch","valueMissing","tooShort","xxs","xs","sm","md","xl","xxl","buttons","next","previous","warning","dBlock","dFlex","dInlineBlock","dNone","empty","inactive","invalid","last","valid","input","load","mousedown","mouseleave","mouseover","paste","popstate","resize","responseError","scroll","transitionEnd","update","checkbox","file","inputFieldClear","inputFieldFeedback","radio","select","textarea","html","htmlBody","img","interactiveElements","separator","includes","csrf","tokenName","token","passedEvent","handler","matches","apply","arguments","fn","readyState","string","o","styles","Object","assign","num","Number","arr1","arr2","obj1","obj2","validationAttributes","toggleValidityClass","isValid","removeValidationMessageElement","createValidationMessageElement","message","innerText","selectedId","insertAdjacentElement","validField","attribute","validity","errorMessage","validForm","formFields","dropdowns","type","dropdown","checkValidity","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","call","m","amdO","O","chunkIds","priority","notFulfilled","Infinity","fulfilled","j","keys","every","splice","r","n","getter","__esModule","d","a","definition","defineProperty","enumerable","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","data","moreModules","runtime","chunkLoadingGlobal","__webpack_exports__"],"sourceRoot":""}