(() => { const openButton = document.querySelector('[data-menu-open]'); const closeButton = document.querySelector('[data-menu-close]'); const navigation = document.querySelector('[data-mobile-navigation]'); let previousFocus = null; const focusableSelector = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'; const closeMenu = ({ restoreFocus = true } = {}) => { if (!navigation || !openButton) return; navigation.hidden = true; openButton.setAttribute('aria-expanded', 'false'); document.body.classList.remove('menu-open'); if (restoreFocus && previousFocus instanceof HTMLElement) previousFocus.focus(); }; const openMenu = () => { if (!navigation || !openButton) return; previousFocus = document.activeElement; navigation.hidden = false; openButton.setAttribute('aria-expanded', 'true'); document.body.classList.add('menu-open'); closeButton?.focus(); }; openButton?.addEventListener('click', () => { if (navigation?.hidden === false) closeMenu(); else openMenu(); }); closeButton?.addEventListener('click', () => closeMenu()); navigation?.addEventListener('click', (event) => { if (event.target === navigation) closeMenu(); }); navigation?.querySelectorAll('a').forEach((link) => { link.addEventListener('click', () => closeMenu({ restoreFocus: false })); }); document.addEventListener('keydown', (event) => { if (!navigation || navigation.hidden) return; if (event.key === 'Escape') { closeMenu(); return; } if (event.key !== 'Tab') return; const focusable = [...navigation.querySelectorAll(focusableSelector)].filter((element) => element instanceof HTMLElement); if (!focusable.length) return; const first = focusable[0]; const last = focusable[focusable.length - 1]; if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); } else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); } }); window.addEventListener('resize', () => { if (window.innerWidth > 980 && navigation && !navigation.hidden) { closeMenu({ restoreFocus: false }); } }); document.querySelectorAll('.shop-v7-filters').forEach((form) => { form.addEventListener('submit', () => { form.querySelectorAll('input[name="min_price"], input[name="max_price"]').forEach((input) => { if (input instanceof HTMLInputElement && input.value.trim() === '') { input.disabled = true; } }); }); }); const zoomOpen = document.querySelector('[data-product-zoom-open]'); const zoomDialog = document.querySelector('[data-product-zoom-dialog]'); const zoomClose = document.querySelector('[data-product-zoom-close]'); if (zoomOpen && zoomDialog instanceof HTMLDialogElement) { zoomOpen.addEventListener('click', () => zoomDialog.showModal()); zoomClose?.addEventListener('click', () => zoomDialog.close()); zoomDialog.addEventListener('click', (event) => { if (event.target === zoomDialog) zoomDialog.close(); }); } const mainGalleryImage = document.querySelector('.canonical-product-main-media img, .product-gallery-main-v4 img'); const zoomGalleryImage = document.querySelector('.product-zoom-dialog img'); document.querySelectorAll('[data-gallery-src]').forEach((button) => { button.addEventListener('click', () => { const source = button.getAttribute('data-gallery-src'); if (!source) return; if (mainGalleryImage instanceof HTMLImageElement) mainGalleryImage.src = source; if (zoomGalleryImage instanceof HTMLImageElement) zoomGalleryImage.src = source; document.querySelectorAll('[data-gallery-src]').forEach((item) => item.classList.remove('is-active')); button.classList.add('is-active'); }); }); // Variable-product validation without blocking browser alerts. document.querySelectorAll('form.variations_form').forEach((form) => { const button = form.querySelector('.single_add_to_cart_button'); if (!(button instanceof HTMLButtonElement)) return; let notice = form.querySelector('.dana-variation-notice'); if (!(notice instanceof HTMLElement)) { notice = document.createElement('p'); notice.className = 'dana-variation-notice'; notice.setAttribute('role', 'status'); notice.setAttribute('aria-live', 'polite'); button.parentElement?.insertBefore(notice, button); } const clearValidation = () => { form.querySelectorAll('.dana-option-missing').forEach((field) => field.classList.remove('dana-option-missing')); if (notice instanceof HTMLElement) { notice.textContent = ''; notice.hidden = true; } }; form.querySelectorAll('select, input').forEach((field) => { field.addEventListener('change', clearValidation); field.addEventListener('input', clearValidation); }); const validateBeforeAdd = (event) => { clearValidation(); const variationId = form.querySelector('input.variation_id'); const variationSelects = [...form.querySelectorAll('select[name^="attribute_"]')]; const emptyVariation = variationSelects.find((field) => field instanceof HTMLSelectElement && !field.value); const requiredCustom = [...form.querySelectorAll('.dana-product-options [required]')]; const emptyCustom = requiredCustom.find((field) => field instanceof HTMLInputElement || field instanceof HTMLSelectElement ? !field.value.trim() : false); if (emptyVariation || !(variationId instanceof HTMLInputElement) || !variationId.value || variationId.value === '0') { event.preventDefault(); event.stopImmediatePropagation(); emptyVariation?.classList.add('dana-option-missing'); if (notice instanceof HTMLElement) { notice.textContent = 'Выберите размер и формат изделия.'; notice.hidden = false; } emptyVariation?.focus(); return false; } if (emptyCustom) { event.preventDefault(); event.stopImmediatePropagation(); emptyCustom.classList.add('dana-option-missing'); if (notice instanceof HTMLElement) { notice.textContent = 'Заполните обязательные параметры изделия.'; notice.hidden = false; } emptyCustom.focus(); return false; } return true; }; button.addEventListener('click', validateBeforeAdd, true); form.addEventListener('submit', (event) => { clearValidation(); const variationId = form.querySelector('input.variation_id'); const variationSelects = [...form.querySelectorAll('select[name^="attribute_"]')]; const emptyVariation = variationSelects.find((field) => field instanceof HTMLSelectElement && !field.value); const requiredCustom = [...form.querySelectorAll('.dana-product-options [required]')]; const emptyCustom = requiredCustom.find((field) => field instanceof HTMLInputElement || field instanceof HTMLSelectElement ? !field.value.trim() : false); if (emptyVariation || !(variationId instanceof HTMLInputElement) || !variationId.value || variationId.value === '0') { event.preventDefault(); event.stopImmediatePropagation(); emptyVariation?.classList.add('dana-option-missing'); if (notice instanceof HTMLElement) { notice.textContent = 'Выберите размер и формат изделия.'; notice.hidden = false; } emptyVariation?.focus(); return; } if (emptyCustom) { event.preventDefault(); event.stopImmediatePropagation(); emptyCustom.classList.add('dana-option-missing'); if (notice instanceof HTMLElement) { notice.textContent = 'Заполните обязательные параметры изделия.'; notice.hidden = false; } emptyCustom.focus(); } }, true); }); })();