diff --git a/assets/global.js b/assets/global.js index cf341dadf64..95deeff3aa6 100644 --- a/assets/global.js +++ b/assets/global.js @@ -26,27 +26,16 @@ class SectionId { } class HTMLUpdateUtility { - #preProcessCallbacks = []; - #postProcessCallbacks = []; - constructor() {} - addPreProcessCallback(callback) { - this.#preProcessCallbacks.push(callback); - } - - addPostProcessCallback(callback) { - this.#postProcessCallbacks.push(callback); - } - /** * Used to swap an HTML node with a new node. * The new node is inserted as a previous sibling to the old node, the old node is hidden, and then the old node is removed. * * The function currently uses a double buffer approach, but this should be replaced by a view transition once it is more widely supported https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API */ - viewTransition(oldNode, newContent) { - this.#preProcessCallbacks.forEach((callback) => callback(newContent)); + viewTransition(oldNode, newContent, preProcessCallbacks = [], postProcessCallbacks = []) { + preProcessCallbacks?.forEach((callback) => callback(newContent)); const newNodeWrapper = document.createElement('div'); HTMLUpdateUtility.setInnerHTML(newNodeWrapper, newContent.outerHTML); @@ -62,7 +51,7 @@ class HTMLUpdateUtility { oldNode.parentNode.insertBefore(newNode, oldNode); oldNode.style.display = 'none'; - this.#postProcessCallbacks.forEach((callback) => callback(newNode)); + postProcessCallbacks?.forEach((callback) => callback(newNode)); setTimeout(() => oldNode.remove(), 500); } diff --git a/assets/product-info.js b/assets/product-info.js index a817cfda123..606ee3a779e 100644 --- a/assets/product-info.js +++ b/assets/product-info.js @@ -6,9 +6,11 @@ if (!customElements.get('product-info')) { quantityForm = undefined; onVariantChangeUnsubscriber = undefined; cartUpdateUnsubscriber = undefined; - swapProductUtility = undefined; + htmlUpdateUtility = undefined; abortController = undefined; pendingRequestUrl = null; + preProcessHtmlCallbacks = []; + postProcessHtmlCallbacks = []; constructor() { super(); @@ -29,7 +31,7 @@ if (!customElements.get('product-info')) { } addPreProcessCallback(callback) { - this.swapProductUtility.addPreProcessCallback(callback); + this.preProcessHtmlCallbacks.push(callback); } initQuantityHandlers() { @@ -50,11 +52,11 @@ if (!customElements.get('product-info')) { } initializeProductSwapUtility() { - this.swapProductUtility = new HTMLUpdateUtility(); - this.swapProductUtility.addPreProcessCallback((html) => + this.htmlUpdateUtility = new HTMLUpdateUtility(); + this.preProcessHtmlCallbacks.push((html) => html.querySelectorAll('.scroll-trigger').forEach((element) => element.classList.add('scroll-trigger--cancel')) ); - this.swapProductUtility.addPostProcessCallback((newNode) => { + this.postProcessHtmlCallbacks.push((newNode) => { window?.Shopify?.PaymentButton?.init(); window?.ProductModel?.loadShopifyXR(); publish(PUB_SUB_EVENTS.sectionRefreshed, { @@ -106,11 +108,21 @@ if (!customElements.get('product-info')) { // If we are in an embedded context (quick add, featured product, etc), only swap product info. // Otherwise, refresh the entire page content and sibling sections. if (this.dataset.updateUrl === 'false') { - this.swapProductUtility.viewTransition(this, html.querySelector('product-info')); + this.htmlUpdateUtility.viewTransition( + this, + html.querySelector('product-info'), + this.preProcessHtmlCallbacks, + this.postProcessHtmlCallbacks + ); } else { document.querySelector('head title').innerHTML = html.querySelector('head title').innerHTML; - this.swapProductUtility.viewTransition(document.querySelector('main'), html.querySelector('main')); + this.htmlUpdateUtility.viewTransition( + document.querySelector('main'), + html.querySelector('main'), + this.preProcessHtmlCallbacks, + this.postProcessHtmlCallbacks + ); } }; } @@ -159,7 +171,13 @@ if (!customElements.get('product-info')) { updateOptionValues(html) { const variantSelects = html.querySelector('variant-selects'); - if (variantSelects) this.variantSelectors.innerHTML = variantSelects.innerHTML; + if (variantSelects) { + this.htmlUpdateUtility.viewTransition( + this.variantSelectors, + variantSelects, + this.preProcessHtmlCallbacks, + ); + } } handleUpdateProductInfo(productUrl) { @@ -180,6 +198,7 @@ if (!customElements.get('product-info')) { const updateSourceFromDestination = (id, shouldHide = (source) => false) => { const source = html.getElementById(`${id}-${this.sectionId}`); + debugger; const destination = this.querySelector(`#${id}-${this.dataset.section}`); if (source && destination) { destination.innerHTML = source.innerHTML; diff --git a/assets/quick-add.js b/assets/quick-add.js index dbbcdb0d3fc..5125a974c2f 100644 --- a/assets/quick-add.js +++ b/assets/quick-add.js @@ -100,7 +100,7 @@ if (!customElements.get('quick-add-modal')) { updateImageSizes(productElement) { const product = productElement.querySelector('.product'); - const desktopColumns = product.classList.contains('product--columns'); + const desktopColumns = product?.classList.contains('product--columns'); if (!desktopColumns) return; const mediaImages = product.querySelectorAll('.product__media img');