Skip to content

Commit

Permalink
Support Combined Listings and 2k Variants (#3246)
Browse files Browse the repository at this point in the history
* Updated option value picker to use product_option_value.variant, update availability handling to rely on async variant pagination

Removed old event handler, update buy-buttons to handle selected_variant undefined case

Fix for cases where selected_or_first_available_variant is null

Only pass variant if present

Fix JS error where param wasn't being passed to callback

Added support for duplicated option names in option value picker and swatches

Fix misnamed function in quick order list

Add parent option values to quick order list

Fix JS error if active media is not found

Fix mismatched unsubscriber function name

* fix bad merge
  • Loading branch information
lhoffbeck committed Mar 19, 2024
1 parent 74595af commit a2c6f54
Show file tree
Hide file tree
Showing 15 changed files with 447 additions and 318 deletions.
1 change: 1 addition & 0 deletions assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -3240,6 +3240,7 @@ details-disclosure > details {
opacity: 1;
animation: none;
transition: none;
transform: none;
}

.scroll-trigger.scroll-trigger--design-mode.animate--slide-in {
Expand Down
5 changes: 5 additions & 0 deletions assets/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ const PUB_SUB_EVENTS = {
quantityUpdate: 'quantity-update',
variantChange: 'variant-change',
cartError: 'cart-error',
sectionRefreshed: 'section-refreshed',
};

const SECTION_REFRESH_RESOURCE_TYPE = {
product: 'product',
};
549 changes: 322 additions & 227 deletions assets/global.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions assets/pickup-availability.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ if (!customElements.get('pickup-availability')) {
}

fetchAvailability(variantId) {
if (!variantId) return;

let rootUrl = this.dataset.rootUrl;
if (!rootUrl.endsWith('/')) {
rootUrl = rootUrl + '/';
Expand Down
2 changes: 2 additions & 0 deletions assets/quick-add.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
.quick-add-modal .scroll-trigger.scroll-trigger {
animation: none;
opacity: 1;
transform: none;
}

.quick-add-modal__content {
Expand Down Expand Up @@ -170,6 +171,7 @@ quick-add-modal .product__column-sticky {
}

quick-add-modal .product:not(.product--no-media) .product__info-wrapper {
padding-top: 2rem;
padding-left: 4rem;
max-width: 54%;
width: calc(54% - var(--grid-desktop-horizontal-spacing) / 2);
Expand Down
74 changes: 38 additions & 36 deletions assets/quick-add.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,83 +25,85 @@ if (!customElements.get('quick-add-modal')) {
.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);
const productElement = responseHTML.querySelector('section[id^="MainProduct-"]');

this.preprocessHTML(productElement);
HTMLUpdateUtility.setInnerHTML(this.modalContent, 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(() => {
this.bindProductChangeCallbacks();
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);
bindProductChangeCallbacks() {
const swapProductUtility = this.querySelector('variant-selects')?.swapProductUtility;
if (swapProductUtility) {
swapProductUtility.addPreProcessCallback(this.preprocessHTML.bind(this));
swapProductUtility.addPostProcessCallback(() => {
this.modalContent = this.querySelector('[id^="QuickAddInfo-"]');
this.bindProductChangeCallbacks();
});
newScriptTag.appendChild(document.createTextNode(oldScriptTag.innerHTML));
oldScriptTag.parentNode.replaceChild(newScriptTag, oldScriptTag);
}
}

preprocessHTML(productElement) {
productElement.classList.forEach((classApplied) => {
if (classApplied.startsWith('color-') || classApplied === 'gradient')
this.modalContent.classList.add(classApplied);
});
this.preventDuplicatedIDs(productElement);
this.removeDOMElements(productElement);
this.removeGalleryListSemantic(productElement);
this.updateImageSizes(productElement);
this.preventVariantURLSwitching(productElement);
}

preventVariantURLSwitching() {
const variantPicker = this.modalContent.querySelector('variant-selects');
preventVariantURLSwitching(productElement) {
const variantPicker = productElement.querySelector('variant-selects');
if (!variantPicker) return;

variantPicker.setAttribute('data-update-url', 'false');
}

removeDOMElements() {
const pickupAvailability = this.productElement.querySelector('pickup-availability');
removeDOMElements(productElement) {
const pickupAvailability = productElement.querySelector('pickup-availability');
if (pickupAvailability) pickupAvailability.remove();

const productModal = this.productElement.querySelector('product-modal');
const productModal = productElement.querySelector('product-modal');
if (productModal) productModal.remove();

const modalDialog = this.productElement.querySelectorAll('modal-dialog');
const modalDialog = 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) => {
preventDuplicatedIDs(productElement) {
const sectionId = productElement.dataset.section;
productElement.innerHTML = productElement.innerHTML.replaceAll(sectionId, `quickadd-${sectionId}`);
productElement.querySelectorAll('variant-selects, product-info').forEach((element) => {
element.dataset.originalSection = sectionId;
});
}

removeGalleryListSemantic() {
const galleryList = this.modalContent.querySelector('[id^="Slider-Gallery"]');
removeGalleryListSemantic(productElement) {
const galleryList = productElement.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');
updateImageSizes(productElement) {
const product = productElement.querySelector('.product');
const desktopColumns = product.classList.contains('product--columns');
if (!desktopColumns) return;

Expand Down
21 changes: 15 additions & 6 deletions assets/quick-order-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class QuickOrderListRemoveAllButton extends HTMLElement {

customElements.define('quick-order-list-remove-all-button', QuickOrderListRemoveAllButton);


class QuickOrderList extends HTMLElement {
constructor() {
super();
Expand Down Expand Up @@ -97,6 +96,7 @@ class QuickOrderList extends HTMLElement {
}

cartUpdateUnsubscriber = undefined;
sectionRefreshUnsubscriber = undefined;

onSubmit(event) {
event.preventDefault();
Expand All @@ -108,15 +108,24 @@ class QuickOrderList extends HTMLElement {
return;
}
// If its another section that made the update
this.onCartUpdate();
this.refresh();
});

this.sectionRefreshUnsubscriber = subscribe(PUB_SUB_EVENTS.sectionRefreshed, (event) => {
const isParentSectionUpdated =
this.sectionId && (event.data?.sectionId ?? '') === `${this.sectionId.split('__')[0]}__main`;

if (isParentSectionUpdated) {
this.refresh();
}
});

this.sectionId = this.dataset.id;
}

disconnectedCallback() {
if (this.cartUpdateUnsubscriber) {
this.cartUpdateUnsubscriber();
}
this.cartUpdateUnsubscriber?.();
this.sectionRefreshUnsubscriber?.();
}

defineInputsAndQuickOrderTable() {
Expand All @@ -140,7 +149,7 @@ class QuickOrderList extends HTMLElement {
}
}

onCartUpdate() {
refresh() {
fetch(`${window.location.pathname}?section_id=${this.sectionId}`)
.then((response) => response.text())
.then((responseText) => {
Expand Down
6 changes: 4 additions & 2 deletions sections/main-product.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,9 @@
{%- when 'complementary' -%}
<product-recommendations
class="complementary-products quick-add-hidden{% if block.settings.make_collapsible_row %} is-accordion{% endif %}{% if block.settings.enable_quick_add %} complementary-products-contains-quick-add{% endif %}"
data-url="{{ routes.product_recommendations_url }}?section_id={{ section.id }}&product_id={{ product.id }}&limit={{ block.settings.product_list_limit }}&intent=complementary"
data-url="{{ routes.product_recommendations_url }}?limit={{ block.settings.product_list_limit }}&intent=complementary"
data-section-id="{{ section.id }}"
data-product-id="{{ product.id }}"
>
{%- if recommendations.performed and recommendations.products_count > 0 -%}
<aside
Expand Down Expand Up @@ -2273,4 +2275,4 @@
}
]
}
{% endschema %}
{% endschema %}
4 changes: 3 additions & 1 deletion sections/related-products.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
<div class="color-{{ section.settings.color_scheme }} gradient">
<product-recommendations
class="related-products page-width section-{{ section.id }}-padding isolate{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
data-url="{{ routes.product_recommendations_url }}?section_id={{ section.id }}&product_id={{ product.id }}&limit={{ section.settings.products_to_show }}"
data-url="{{ routes.product_recommendations_url }}?limit={{ section.settings.products_to_show }}"
data-section-id="{{ section.id }}"
data-product-id="{{ product.id }}"
>
{% if recommendations.performed and recommendations.products_count > 0 %}
<h2 class="related-products__heading inline-richtext {{ section.settings.heading_size }}">
Expand Down
10 changes: 8 additions & 2 deletions snippets/buy-buttons.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@
type="hidden"
name="id"
value="{{ product.selected_or_first_available_variant.id }}"
{% if product.selected_or_first_available_variant.available == false or quantity_rule_soldout %}
{% if product.selected_or_first_available_variant.available == false
or quantity_rule_soldout
or product.selected_or_first_available_variant == nil
%}
disabled
{% endif %}
class="product-variant-id"
Expand All @@ -80,7 +83,10 @@
type="submit"
name="add"
class="product-form__submit button button--full-width {% if show_dynamic_checkout %}button--secondary{% else %}button--primary{% endif %}"
{% if product.selected_or_first_available_variant.available == false or quantity_rule_soldout %}
{% if product.selected_or_first_available_variant.available == false
or quantity_rule_soldout
or product.selected_or_first_available_variant == nil
%}
disabled
{% endif %}
>
Expand Down
2 changes: 2 additions & 0 deletions snippets/price.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
endif
-%}

{%- unless target == nil -%}
<div
class="
price
Expand Down Expand Up @@ -126,3 +127,4 @@
</span>
{%- endif -%}
</div>
{% endunless %}
Loading

0 comments on commit a2c6f54

Please sign in to comment.