function getFocusableElements(container) { return Array.from( container.querySelectorAll( "summary, a[href], button:enabled, [tabindex]:not([tabindex^='-']), [draggable], area, input:not([type=hidden]):enabled, select:enabled, textarea:enabled, object, iframe" ) ); } function calcVHUnits() { document.documentElement.style.setProperty('--viewport-height', `${window.innerHeight}px`); } ['load', 'scroll', 'resize'].forEach(eventName => window.addEventListener(eventName, calcVHUnits)); function isIOS() { return ( /iPad|iPhone|iPod|iPad Simulator|iPhone Simulator|iPod Simulator/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) ); } document.querySelectorAll('[id^="Details-"] summary').forEach((summary) => { summary.setAttribute('role', 'button'); summary.setAttribute('aria-expanded', summary.parentElement.hasAttribute('open')); if(summary.nextElementSibling.getAttribute('id')) { summary.setAttribute('aria-controls', summary.nextElementSibling.id); } summary.addEventListener('click', (event) => { event.currentTarget.setAttribute('aria-expanded', !event.currentTarget.closest('details').hasAttribute('open')); }); if (summary.closest('header-drawer')) return; summary.parentElement.addEventListener('keyup', onKeyUpEscape); }); const trapFocusHandlers = {}; function trapFocus(container, elementToFocus = container) { var elements = getFocusableElements(container); var first = elements[0]; var last = elements[elements.length - 1]; removeTrapFocus(); trapFocusHandlers.focusin = (event) => { if ( event.target !== container && event.target !== last && event.target !== first ) return; document.addEventListener('keydown', trapFocusHandlers.keydown); }; trapFocusHandlers.focusout = function() { document.removeEventListener('keydown', trapFocusHandlers.keydown); }; trapFocusHandlers.keydown = function(event) { if (event.code.toUpperCase() !== 'TAB') return; // If not TAB key // On the last focusable element and tab forward, focus the first element. if (event.target === last && !event.shiftKey) { event.preventDefault(); first.focus(); } // On the first focusable element and tab backward, focus the last element. if ( (event.target === container || event.target === first) && event.shiftKey ) { event.preventDefault(); last.focus(); } }; document.addEventListener('focusout', trapFocusHandlers.focusout); document.addEventListener('focusin', trapFocusHandlers.focusin); elementToFocus.focus(); } // Here run the querySelector to figure out if the browser supports :focus-visible or not and run code based on it. try { document.querySelector(":focus-visible"); } catch { focusVisiblePolyfill(); } function focusVisiblePolyfill() { const navKeys = ['ARROWUP', 'ARROWDOWN', 'ARROWLEFT', 'ARROWRIGHT', 'TAB', 'ENTER', 'SPACE', 'ESCAPE', 'HOME', 'END', 'PAGEUP', 'PAGEDOWN'] let currentFocusedElement = null; let mouseClick = null; window.addEventListener('keydown', (event) => { if(navKeys.includes(event.code.toUpperCase())) { mouseClick = false; } }); window.addEventListener('mousedown', (event) => { mouseClick = true; }); window.addEventListener('focus', () => { if (currentFocusedElement) currentFocusedElement.classList.remove('focused'); if (mouseClick) return; currentFocusedElement = document.activeElement; currentFocusedElement.classList.add('focused'); }, true); } function pauseAllMedia() { document.querySelectorAll('.js-youtube').forEach((video) => { video.contentWindow.postMessage('{"event":"command","func":"' + 'pauseVideo' + '","args":""}', '*'); }); document.querySelectorAll('.js-vimeo').forEach((video) => { video.contentWindow.postMessage('{"method":"pause"}', '*'); }); document.querySelectorAll('video').forEach((video) => { if (!video.getAttribute('controls')) { return; } video.pause() }); document.querySelectorAll('product-model').forEach((model) => { if (model.modelViewerUI) model.modelViewerUI.pause(); }); } function removeTrapFocus(elementToFocus = null) { document.removeEventListener('focusin', trapFocusHandlers.focusin); document.removeEventListener('focusout', trapFocusHandlers.focusout); document.removeEventListener('keydown', trapFocusHandlers.keydown); if (elementToFocus) elementToFocus.focus(); } function onKeyUpEscape(event) { if (event.code.toUpperCase() !== 'ESCAPE') return; const openDetailsElement = event.target.closest('details[open]'); if (!openDetailsElement) return; const summaryElement = openDetailsElement.querySelector('summary'); openDetailsElement.removeAttribute('open'); summaryElement.setAttribute('aria-expanded', false); summaryElement.focus(); } class QuantityInput extends HTMLElement { constructor() { super(); this.input = this.querySelector('input'); this.changeEvent = new Event('change', { bubbles: true }) this.querySelectorAll('button').forEach( (button) => button.addEventListener('click', this.onButtonClick.bind(this)) ); } onButtonClick(event) { event.preventDefault(); const previousValue = this.input.value; event.target.name === 'plus' ? this.input.stepUp() : this.input.stepDown(); if (previousValue !== this.input.value) this.input.dispatchEvent(this.changeEvent); } } customElements.define('quantity-input', QuantityInput); function debounce(fn, wait) { let t; return (...args) => { clearTimeout(t); t = setTimeout(() => fn.apply(this, args), wait); }; } function fetchConfig(type = 'json') { return { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': `application/${type}` } }; } /* * Shopify Common JS * */ if ((typeof window.Shopify) == 'undefined') { window.Shopify = {}; } Shopify.bind = function(fn, scope) { return function() { return fn.apply(scope, arguments); } }; Shopify.setSelectorByValue = function(selector, value) { for (var i = 0, count = selector.options.length; i < count; i++) { var option = selector.options[i]; if (value == option.value || value == option.innerHTML) { selector.selectedIndex = i; return i; } } }; Shopify.addListener = function(target, eventName, callback) { target.addEventListener ? target.addEventListener(eventName, callback, false) : target.attachEvent('on'+eventName, callback); }; Shopify.postLink = function(path, options) { options = options || {}; var method = options['method'] || 'post'; var params = options['parameters'] || {}; var form = document.createElement("form"); form.setAttribute("method", method); form.setAttribute("action", path); for(var key in params) { var hiddenField = document.createElement("input"); hiddenField.setAttribute("type", "hidden"); hiddenField.setAttribute("name", key); hiddenField.setAttribute("value", params[key]); form.appendChild(hiddenField); } document.body.appendChild(form); form.submit(); document.body.removeChild(form); }; Shopify.CountryProvinceSelector = function(country_domid, province_domid, options) { this.countryEl = document.getElementById(country_domid); this.provinceEl = document.getElementById(province_domid); this.provinceContainer = document.getElementById(options['hideElement'] || province_domid); Shopify.addListener(this.countryEl, 'change', Shopify.bind(this.countryHandler,this)); this.initCountry(); this.initProvince(); }; Shopify.CountryProvinceSelector.prototype = { initCountry: function() { var value = this.countryEl.getAttribute('data-default'); Shopify.setSelectorByValue(this.countryEl, value); this.countryHandler(); }, initProvince: function() { var value = this.provinceEl.getAttribute('data-default'); if (value && this.provinceEl.options.length > 0) { Shopify.setSelectorByValue(this.provinceEl, value); } }, countryHandler: function(e) { var opt = this.countryEl.options[this.countryEl.selectedIndex]; var raw = opt.getAttribute('data-provinces'); var provinces = JSON.parse(raw); this.clearOptions(this.provinceEl); if (provinces && provinces.length == 0) { this.provinceContainer.style.display = 'none'; } else { for (var i = 0; i < provinces.length; i++) { var opt = document.createElement('option'); opt.value = provinces[i][0]; opt.innerHTML = provinces[i][1]; this.provinceEl.appendChild(opt); } this.provinceContainer.style.display = ""; } }, clearOptions: function(selector) { while (selector.firstChild) { selector.removeChild(selector.firstChild); } }, setOptions: function(selector, values) { for (var i = 0, count = values.length; i < values.length; i++) { var opt = document.createElement('option'); opt.value = values[i]; opt.innerHTML = values[i]; selector.appendChild(opt); } } }; Shopify.money_format = "${{amount}}"; Shopify.formatMoney = function(cents, format) { if (typeof cents == 'string') { cents = cents.replace('.',''); } var value = ''; var placeholderRegex = /\{\{\s*(\w+)\s*\}\}/; var formatString = (format || this.money_format); function defaultOption(opt, def) { return (typeof opt == 'undefined' ? def : opt); } function formatWithDelimiters(number, precision, thousands, decimal) { precision = defaultOption(precision, 2); thousands = defaultOption(thousands, ','); decimal = defaultOption(decimal, '.'); if (isNaN(number) || number == null) { return 0; } number = (number/100.0).toFixed(precision); var parts = number.split('.'), dollars = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + thousands), cents = parts[1] ? (decimal + parts[1]) : ''; return dollars + cents; } switch(formatString.match(placeholderRegex)[1]) { case 'amount': value = formatWithDelimiters(cents, 2); break; case 'amount_no_decimals': value = formatWithDelimiters(cents, 0); break; case 'amount_with_comma_separator': value = formatWithDelimiters(cents, 2, '.', ','); break; case 'amount_no_decimals_with_comma_separator': value = formatWithDelimiters(cents, 0, '.', ','); break; } return formatString.replace(placeholderRegex, value); }; class MenuDrawer extends HTMLElement { constructor() { super(); this.mainDetailsToggle = this.querySelector('details'); this.searchInput = this.querySelector('input[type="search"]'); this.scrollContainer = this.querySelector('[data-scroll-container]'); this.addEventListener('keyup', this.onKeyUp.bind(this)); this.addEventListener('focusout', this.onFocusOut.bind(this)); this.bindEvents(); } bindEvents() { this.querySelectorAll('summary').forEach(summary => summary.addEventListener('click', this.onSummaryClick.bind(this))); this.querySelectorAll('button').forEach(button => button.addEventListener('click', this.onCloseButtonClick.bind(this))); } onKeyUp(event) { if(event.code.toUpperCase() !== 'ESCAPE') return; const openDetailsElement = event.target.closest('details[open]'); if(!openDetailsElement) return; openDetailsElement === this.mainDetailsToggle ? this.closeMenuDrawer(event, this.mainDetailsToggle.querySelector('summary')) : this.closeSubmenu(openDetailsElement); } onSummaryClick(event) { const summaryElement = event.currentTarget; const detailsElement = summaryElement.parentNode; const isOpen = detailsElement.hasAttribute('open'); const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"); function addTrapFocus() { trapFocus(summaryElement.nextElementSibling, detailsElement.querySelector('button')); summaryElement.nextElementSibling.removeEventListener('transitionend', addTrapFocus); } if (detailsElement === this.mainDetailsToggle) { if(isOpen) event.preventDefault(); isOpen ? this.closeMenuDrawer(event, summaryElement) : this.openMenuDrawer(summaryElement); } else { setTimeout(() => { if (document.querySelector('.mobile-facets__inner[data-scroll-container]')) { document.querySelector('.mobile-facets__inner[data-scroll-container]').scrollTo(0,0) } detailsElement.classList.add('menu-opening'); summaryElement.setAttribute('aria-expanded', true); !reducedMotion || reducedMotion.matches ? addTrapFocus() : summaryElement.nextElementSibling.addEventListener('transitionend', addTrapFocus); }, 100); } } openMenuDrawer(summaryElement) { setTimeout(() => { this.mainDetailsToggle.classList.add('menu-opening'); }); summaryElement.setAttribute('aria-expanded', true); trapFocus(this.mainDetailsToggle, summaryElement); bodyScrollLock.disableBodyScroll(this.scrollContainer); } closeMenuDrawer(event, elementToFocus = false) { this.mainDetailsToggle.classList.remove('menu-opening'); this.mainDetailsToggle.querySelectorAll('details').forEach(details => { details.removeAttribute('open'); details.classList.remove('menu-opening'); }); removeTrapFocus(elementToFocus); this.closeAnimation(this.mainDetailsToggle); bodyScrollLock.enableBodyScroll(this.scrollContainer); } onFocusOut(event) { setTimeout(() => { const isPredictiveSearchOpened = this.searchInput?.classList?.contains('has-search-input') || null; if (this.mainDetailsToggle.hasAttribute('open') && !this.mainDetailsToggle.contains(document.activeElement) && !isPredictiveSearchOpened && !this.searchInput.contains(document.activeElement)) this.closeMenuDrawer(); }); } onCloseButtonClick(event) { const detailsElement = event.currentTarget.closest('details'); this.closeSubmenu(detailsElement); } closeSubmenu(detailsElement) { detailsElement.classList.remove('menu-opening'); detailsElement.querySelector('summary').setAttribute('aria-expanded', false); removeTrapFocus(detailsElement.querySelector('summary')); this.closeAnimation(detailsElement); } closeAnimation(detailsElement) { let animationStart; const handleAnimation = (time) => { if (animationStart === undefined) { animationStart = time; } const elapsedTime = time - animationStart; if (elapsedTime < 400) { window.requestAnimationFrame(handleAnimation); } else { detailsElement.removeAttribute('open'); if (detailsElement.closest('details[open]')) { trapFocus(detailsElement.closest('details[open]'), detailsElement.querySelector('summary')); } } } window.requestAnimationFrame(handleAnimation); } } customElements.define('menu-drawer', MenuDrawer); class HeaderDrawer extends MenuDrawer { constructor() { super(); this.scrollContainersInner = this.querySelectorAll('[data-scroll-container-inner]'); } openMenuDrawer(summaryElement) { this.header = this.header || document.getElementById('shopify-section-header'); this.borderOffset = this.borderOffset || this.closest('.header').classList.contains('header--border-bottom') ? 1 : 0; document.documentElement.style.setProperty('--header-bottom-position', `${parseInt(this.header.getBoundingClientRect().bottom - this.borderOffset)}px`); this.header.classList.add('menu-open'); this.announcementBar = document.querySelector('#shopify-section-announcement-bar:not(#shopify-section-header + #shopify-section-announcement-bar)'); this.announcementBarHeight = this.announcementBar ? this.announcementBar.offsetHeight : 0; this.announcementBarOffset = this.announcementBarHeight > 0 && window.pageYOffset < this.announcementBarHeight ? this.announcementBarHeight : 0; summaryElement.nextElementSibling.style.top = `${ this.announcementBarOffset + this.header.offsetHeight }px`; setTimeout(() => { this.mainDetailsToggle.classList.add('menu-opening'); }); summaryElement.setAttribute('aria-expanded', true); trapFocus(this.mainDetailsToggle, summaryElement); bodyScrollLock.disableBodyScroll(this.scrollContainer); this.scrollContainersInner.forEach((container) => { bodyScrollLock.disableBodyScroll(container); }) } closeMenuDrawer(event, elementToFocus) { super.closeMenuDrawer(event, elementToFocus); this.header.classList.remove('menu-open'); bodyScrollLock.enableBodyScroll(this.scrollContainer); this.scrollContainersInner.forEach((container) => { bodyScrollLock.enableBodyScroll(container); }) } } customElements.define('header-drawer', HeaderDrawer); class ModalDialog extends HTMLElement { constructor() { super(); this.querySelectorAll('[id^="ModalClose-"]').forEach((button) => { button.addEventListener( 'click', this.hide.bind(this) ); }); this.addEventListener('keyup', (event) => { if (event.code.toUpperCase() === 'ESCAPE') this.hide(); }); if (this.classList.contains('media-modal')) { this.addEventListener('pointerup', (event) => { if (event.pointerType === 'mouse' && !event.target.closest('deferred-media, product-model')) this.hide(); }); } else { this.addEventListener('click', (event) => { if (event.target.nodeName === 'MODAL-DIALOG') this.hide(); }); } } connectedCallback() { if (this.moved || (this.hasAttribute('data-prevent-move') && window.innerWidth >= 990) || (this.hasAttribute('data-prevent-move-mobile') && window.innerWidth < 990)) return; this.moved = true; document.body.appendChild(this); } show(opener) { this.openedBy = opener; bodyScrollLock.disableBodyScroll( this.querySelector('[data-scroll-container]') || this.querySelector('[role="dialog"] > *') ); this.setAttribute('open', ''); setTimeout(() => { trapFocus(this, this.querySelector('[role="dialog"]')); window.pauseAllMedia(); }, 300); } hide() { bodyScrollLock.enableBodyScroll( this.querySelector('[data-scroll-container]') || this.querySelector('[role="dialog"] > *') ); this.removeAttribute('open'); removeTrapFocus(this.openedBy); window.pauseAllMedia(); if (this.hasAttribute('data-remove-on-close')) { window.modals = window.modals || {}; window.modals[this.id] = document.body.removeChild(this); } } } customElements.define('modal-dialog', ModalDialog); class ModalOpener extends HTMLElement { constructor() { super(); const button = this.querySelector('button'); if (!button) return; button.addEventListener('click', () => { const modal = document.querySelector(this.getAttribute('data-modal')); if (modal) modal.show(button); }); } } customElements.define('modal-opener', ModalOpener); class CurrencyForm extends HTMLElement{ constructor(){ super(); const button = this.querySelector("div"); const ul = this.querySelector("ul"); if (!button || !ul) return; ul.style.display = "none"; button.onclick = function () { const ulIsShow = ul.style.display === "block"; ul.style.display = ulIsShow ? "none" : "block"; } ul.onclick = function (event) { event = event || window.event; var target = event.target; if (target.nodeName === "LI") { ul.style.display = "none"; } } document.onclick = function (event) { var tDom = event.target; const ulIsShow = ul.style.display === "block"; if (ul!==tDom && !ul.contains(tDom) && button!==tDom && !button.contains(tDom) && ulIsShow) { ul.style.display = "none"; } } } } customElements.define('currency-form', CurrencyForm); class CurrencyCode extends HTMLElement{ constructor(){ super(); let currentCurrency = this.getCookie("current-selected-currency"); if(!currentCurrency){ currentCurrency = localStorage.getItem("currency") } const currencyElement = this.querySelector('.currency_iso_code'); currencyElement.innerHTML = currentCurrency; } getCookie(cookie_name) { var allcookies = document.cookie; var cookie_pos = allcookies.indexOf(cookie_name); if (cookie_pos != -1) { cookie_pos = cookie_pos + cookie_name.length + 1; var cookie_end = allcookies.indexOf(";", cookie_pos); if (cookie_end == -1) { cookie_end = allcookies.length; } var value = unescape(allcookies.substring(cookie_pos, cookie_end)); } return value; } } customElements.define('country-code', CurrencyCode); class DeferredMedia extends HTMLElement { constructor() { super(); const poster = this.querySelector('[id^="Deferred-Poster-"]'); if (!poster) return; poster.addEventListener('click', this.loadContent.bind(this)); } loadContent(focus = true) { window.pauseAllMedia(); if (!this.getAttribute('loaded')) { const content = document.createElement('div'); content.appendChild(this.querySelector('template').content.firstElementChild.cloneNode(true)); this.setAttribute('loaded', true); const deferredElement = this.appendChild(content.querySelector('video, model-viewer, iframe')); if (isIOS()) deferredElement.controls = true; if (focus) deferredElement.focus(); } } } customElements.define('deferred-media', DeferredMedia); const getOffsetTop = (element) => { let offsetTop = 0 do { if (!isNaN(element.offsetTop)) { offsetTop += element.offsetTop } } while ((element = element.offsetParent)) return offsetTop } const isInViewport = (element) => { const windowBottom = window.pageYOffset + window.innerHeight; return windowBottom >= getOffsetTop(element); } document.querySelectorAll('[data-fade-in]').forEach((element) => { ['load', 'scroll', 'shopify:section:load'].forEach((eventName) => { window.addEventListener(eventName, () => { if (!isInViewport(element)) { return; } element.classList.add('fade-in'); }) }) }) function setCookie(name, value, days) { let expires = ''; if (days) { let date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); expires = '; expires=' + date.toUTCString(); } document.cookie = name + '=' + (value || '') + expires + '; path=/'; } function getCookie(name) { let nameEQ = name + '='; let ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); } return null; } function eraseCookie(name) { document.cookie = name + '=; Max-Age=-99999999;'; } $(function(){ function bindEvent (e) { this.$container = $(e) this.$list = this.$container.find('ul').children('li') this.$list.each((i, el) => { $(el).find('.m-faq_title').click(() => { const height = $(el).find('.m-faq_main-content').outerHeight() const $main = $(el).find('.m-faq_main') if ($(el).hasClass('open')) { $(el).removeClass('open') $main.height(0) } else { $(el).addClass('open') $main.height(height) } }) }) } $('.m-faqs').each(function(i, el) { bindEvent(el) }) var $goToTop = $('#back-to-top'); $goToTop.hide(); $(window).scroll(function(){ if ($(window).scrollTop()>100) $goToTop.fadeIn(); else $goToTop.fadeOut(); }); $goToTop.on("click", function () { $('body,html').animate({scrollTop:0},1000); return false; }); })