SHX-Theme/assets/quick-add.js

125 lines
5.0 KiB
JavaScript

if (!customElements.get('quick-add-modal')) {
customElements.define(
'quick-add-modal',
class QuickAddModal extends ModalDialog {
constructor() {
super();
this.modalContent = this.querySelector('[id^="QuickAddInfo-"]');
}
hide(preventFocus = false) {
const cartNotification = document.querySelector('cart-notification') || document.querySelector('cart-drawer');
if (cartNotification) cartNotification.setActiveElement(this.openedBy);
this.modalContent.innerHTML = '';
if (preventFocus) this.openedBy = null;
super.hide();
}
show(opener) {
opener.setAttribute('aria-disabled', true);
opener.classList.add('loading');
opener.querySelector('.loading__spinner').classList.remove('hidden');
fetch(opener.getAttribute('data-product-url'))
.then((response) => response.text())
.then((responseText) => {
const responseHTML = new DOMParser().parseFromString(responseText, 'text/html');
this.productElement = responseHTML.querySelector('section[id^="MainProduct-"]');
this.productElement.classList.forEach((classApplied) => {
if (classApplied.startsWith('color-') || classApplied === 'gradient')
this.modalContent.classList.add(classApplied);
});
this.preventDuplicatedIDs();
this.removeDOMElements();
this.setInnerHTML(this.modalContent, this.productElement.innerHTML);
if (window.Shopify && Shopify.PaymentButton) {
Shopify.PaymentButton.init();
}
if (window.ProductModel) window.ProductModel.loadShopifyXR();
this.removeGalleryListSemantic();
this.updateImageSizes();
this.preventVariantURLSwitching();
super.show(opener);
})
.finally(() => {
opener.removeAttribute('aria-disabled');
opener.classList.remove('loading');
opener.querySelector('.loading__spinner').classList.add('hidden');
});
}
setInnerHTML(element, html) {
element.innerHTML = html;
// Reinjects the script tags to allow execution. By default, scripts are disabled when using element.innerHTML.
element.querySelectorAll('script').forEach((oldScriptTag) => {
const newScriptTag = document.createElement('script');
Array.from(oldScriptTag.attributes).forEach((attribute) => {
newScriptTag.setAttribute(attribute.name, attribute.value);
});
newScriptTag.appendChild(document.createTextNode(oldScriptTag.innerHTML));
oldScriptTag.parentNode.replaceChild(newScriptTag, oldScriptTag);
});
}
preventVariantURLSwitching() {
const variantPicker = this.modalContent.querySelector('variant-selects');
if (!variantPicker) return;
variantPicker.setAttribute('data-update-url', 'false');
}
removeDOMElements() {
const pickupAvailability = this.productElement.querySelector('pickup-availability');
if (pickupAvailability) pickupAvailability.remove();
const productModal = this.productElement.querySelector('product-modal');
if (productModal) productModal.remove();
const modalDialog = this.productElement.querySelectorAll('modal-dialog');
if (modalDialog) modalDialog.forEach((modal) => modal.remove());
}
preventDuplicatedIDs() {
const sectionId = this.productElement.dataset.section;
this.productElement.innerHTML = this.productElement.innerHTML.replaceAll(sectionId, `quickadd-${sectionId}`);
this.productElement.querySelectorAll('variant-selects, product-info').forEach((element) => {
element.dataset.originalSection = sectionId;
});
}
removeGalleryListSemantic() {
const galleryList = this.modalContent.querySelector('[id^="Slider-Gallery"]');
if (!galleryList) return;
galleryList.setAttribute('role', 'presentation');
galleryList.querySelectorAll('[id^="Slide-"]').forEach((li) => li.setAttribute('role', 'presentation'));
}
updateImageSizes() {
const product = this.modalContent.querySelector('.product');
const desktopColumns = product.classList.contains('product--columns');
if (!desktopColumns) return;
const mediaImages = product.querySelectorAll('.product__media img');
if (!mediaImages.length) return;
let mediaImageSizes =
'(min-width: 1000px) 715px, (min-width: 750px) calc((100vw - 11.5rem) / 2), calc(100vw - 4rem)';
if (product.classList.contains('product--medium')) {
mediaImageSizes = mediaImageSizes.replace('715px', '605px');
} else if (product.classList.contains('product--small')) {
mediaImageSizes = mediaImageSizes.replace('715px', '495px');
}
mediaImages.forEach((img) => img.setAttribute('sizes', mediaImageSizes));
}
}
);
}