Skip to content

Commit

Permalink
Re-merge PR #3246
Browse files Browse the repository at this point in the history
  • Loading branch information
lhoffbeck committed May 2, 2024
1 parent ba52194 commit 38b9aea
Show file tree
Hide file tree
Showing 15 changed files with 426 additions and 289 deletions.
1 change: 1 addition & 0 deletions assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -3257,6 +3257,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',
};
512 changes: 307 additions & 205 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.quick-add-modal__content--bulk {
Expand Down Expand Up @@ -282,6 +283,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
10 changes: 10 additions & 0 deletions assets/quick-order-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ if (!customElements.get('quick-order-list')) {
}

cartUpdateUnsubscriber = undefined;
sectionRefreshUnsubscriber = undefined;

onSubmit(event) {
event.preventDefault();
Expand All @@ -128,11 +129,20 @@ if (!customElements.get('quick-order-list')) {
this.addMultipleDebounce();
});
});
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() {
this.cartUpdateUnsubscriber?.();
this.sectionRefreshUnsubscriber?.();
}

defineInputsAndQuickOrderTable() {
Expand Down
4 changes: 3 additions & 1 deletion 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
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 %}
65 changes: 29 additions & 36 deletions snippets/product-variant-options.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,11 @@
%}
{% endcomment %}
{%- liquid
assign variants_available_arr = product.variants | map: 'available'
assign variants_option1_arr = product.variants | map: 'option1'
assign variants_option2_arr = product.variants | map: 'option2'
assign variants_option3_arr = product.variants | map: 'option3'

assign product_form_id = 'product-form-' | append: section.id
-%}

{%- for value in option.values -%}
{%- liquid
assign option_disabled = true

for option1_name in variants_option1_arr
case option.position
when 1
if variants_option1_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
assign option_disabled = false
endif
when 2
if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
assign option_disabled = false
endif
when 3
if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == product.selected_or_first_available_variant.option2 and variants_option3_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
assign option_disabled = false
endif
endcase
endfor

assign swatch_focal_point = null
if value.swatch.image
assign image_url = value.swatch.image | image_url: width: 50
Expand All @@ -56,63 +32,75 @@
else
assign swatch_value = null
endif

assign option_disabled = true
if value.variant.available
assign option_disabled = false
endif
-%}

{%- capture input_id -%}
{{ section.id }}-{{ option.position }}-{{ forloop.index0 -}}
{%- endcapture -%}

{%- capture input_name -%}
{{ option.name }}-{{ option.position }}
{%- endcapture -%}

{%- capture input_dataset -%}
data-available="{{ value.variant.available }}"
data-product-url="{{ value.product_url }}"
data-option-value-id="{{ value.id }}"
{%- endcapture -%}

{%- capture label_unavailable -%}
<span class="visually-hidden label-unavailable">
{{- 'products.product.variant_sold_out_or_unavailable' | t -}}
</span>
{%- endcapture -%}

{%- if picker_type == 'swatch' -%}
{% liquid
assign checked = false
if option.selected_value == value
assign checked = true
endif
%}
{%- capture help_text -%}
<span class="visually-hidden">{{ value | escape }}</span>
{{ label_unavailable }}
{%- endcapture -%}
{%
render 'swatch-input',
id: input_id,
name: option.name,
name: input_name,
value: value | escape,
swatch: value.swatch,
product_form_id: product_form_id,
checked: checked,
checked: value.selected,
visually_disabled: option_disabled,
shape: block.settings.swatch_shape,
help_text: help_text
help_text: help_text,
additional_props: input_dataset
%}
{%- elsif picker_type == 'button' -%}
<input
type="radio"
id="{{ input_id }}"
name="{{ option.name }}"
name="{{ input_name }}"
value="{{ value | escape }}"
form="{{ product_form_id }}"
{% if option.selected_value == value %}
{% if value.selected %}
checked
{% endif %}
{% if option_disabled %}
class="disabled"
{% endif %}
{{ input_dataset }}
>
<label for="{{ input_id }}">
{{ value -}}
{{ label_unavailable }}
</label>
{%- elsif picker_type == 'dropdown' or picker_type == 'swatch_dropdown' -%}
<option
id="{{ input_id }}"
value="{{ value | escape }}"
{% if option.selected_value == value %}
{% if value.selected %}
selected="selected"
{% endif %}
{% if swatch_value and picker_type == 'swatch_dropdown' %}
Expand All @@ -121,6 +109,7 @@
data-option-swatch-focal-point="{{ swatch_focal_point }}"
{% endif %}
{% endif %}
{{ input_dataset }}
>
{% if option_disabled -%}
{{- 'products.product.value_unavailable' | t: option_value: value -}}
Expand All @@ -129,4 +118,8 @@
{%- endif %}
</option>
{%- endif -%}

<script type="application/json" data-resource="{{ input_id }}">
{{ value.variant | json }}
</script>
{%- endfor -%}
Loading

0 comments on commit 38b9aea

Please sign in to comment.