Abschnitt "Schnelle Bestellliste" zum Theme-Code hinzufügen
Plananforderung
Die B2B-Funktion ist nur für bestimmte Shops mit dem Shopify Plus-Plan verfügbar. Für Informationen zum Preis für den Shopify Plus-Plan kannst du gerne Kontakt mit uns aufnehmen .
Der Abschnitt Schnelle Bestellliste wird von kostenlosen Shopify-Themes , Version 11.0.0 oder höher, unterstützt. Wenn du den Abschnitt "Schnelle Bestellliste" zu deinem Shop hinzufügen möchtest, kannst du das Theme deines Shops auf die neueste Version aktualisieren .
Wenn du dein Theme nicht ändern oder aktualisieren möchtest , kannst du deinem Theme mithilfe von Liquid oder Javascript Code hinzufügen, um den Abschnitt "Schnelle Bestellliste" auf deinen Produktseiten anzuzeigen.
Bevor du Aktualisierungen an deinen Theme-Dateien vornimmst, stelle sicher, dass du dein Theme duplizierst , um eine Sicherheitskopie zu erstellen.
Bringe dein Geschäft voran
Dies ist ein Tutorial für Fortgeschrittene. Wenn du mit dem Lesen und Bearbeiten von Theme-Code nicht vertraut bist, kannst du mit einem Entwickler zusammenarbeiten oder einen Shopify-Partner engagieren .
Liquid-Code für schnelle Bestellliste hinzufügen Du kannst in deinem Theme Code zu den folgenden Dateien hinzufügen, um den Abschnitt "Schnelle Bestellliste" zu unterstützen:
main-product.liquid
oder äquivalent
Schritte:
Gehe im Shopify-Adminbereich zu Onlineshop > Themes .
Suche das Theme, das du bearbeiten möchtest, klicke auf die Schaltfläche ... , um das Aktionsmenü zu öffnen, und klicke dann auf Code bearbeiten .
Öffne die Datei, die du bearbeiten möchtest.
Erstelle eine neue Zeile am Ende der Datei und füge folgenden Code hinzu:
{% # theme-check-disable %}
{%- assign items_in_cart = cart | line_items_for : product | sum : 'quantity' -%}
{% # theme-check-enable %}
<div class="color-background-1 gradient">
<quick-order-list
class="page-width"
id="quick-order-list"
data-id="{{ section . id }} "
>
<form
action="{{ routes . cart_update_url }} "
class="quick-order-list__contents critical-hidden"
method="post"
id="QuickOrderList"
>
<div class="quick-order-list__container" id="main-variant-items">
<div class="js-contents">
<table class="quick-order-list__table">
<caption class="visually-hidden">
Quick Order List
</caption>
<thead>
<tr>
<th class="caption-with-letter-spacing" scope="col">
{%- if product . has_only_default_variant -%}
Product
{%- else -%}
Variant
{%- endif -%}
</th>
<th class="large-up-hide right caption-with-letter-spacing" scope="col">
{%- if product . has_only_default_variant -%}
Product subtotal
{%- else -%}
Variant total
{%- endif -%}
</th>
<th
class="quick-order-list__table-heading--wide small-hide medium-hide caption-with-letter-spacing"
scope="col"
>
Quantity
</th>
<th
class="quick-order-list__table-heading--wide small-hide medium-hide caption-with-letter-spacing"
scope="col"
>
Price
</th>
<th class="small-hide medium-hide right caption-with-letter-spacing" scope="col">
{%- if product . has_only_default_variant -%}
Product subtotal
{%- else -%}
Variant total
{%- endif -%}
</th>
</tr>
</thead>
<tbody>
{%- if product . has_only_default_variant -%}
{% # theme-check-disable %}
{% assign cart_qty = cart | item_count_for_variant : product . selected_or_first_available_variant . id %}
{% # theme-check-enable %}
<tr
class="variant-item"
id="Variant-{{ product . selected_or_first_available_variant . id }} "
data-variant-id="{{ product . selected_or_first_available_variant . id }} "
data-cart-qty="{{ cart_qty }} "
>
<td class="variant-item__inner">
<div class="variant-item__media">
<div class="variant-item__image-container gradient global-media-settings{% unless product . featured_media %} variant-item__image-container--no-img {% endunless %} ">
{% if product . featured_media %}
{%- assign img_height = 43 | divided_by : product . featured_media . aspect_ratio | ceil -%}
{{
product . featured_media
| image_url : width : 86
| image_tag :
loading : 'lazy' ,
fetchpriority : 'low' ,
decoding : 'async' ,
class : 'variant-item__image' ,
width : 43 ,
height : img_height ,
widths : '86' ,
alt : product . featured_media . alt
| escape
}}
{% endif %}
</div>
</div>
<div class="small-hide medium-hide">
<span class="variant-item__name h4 break">{{ product . title | escape }} </span>
{%- if product . sku -%}
<span class="variant-item__sku break">{{ product . selected_or_first_available_variant . sku | escape }} </span>
{%- endif -%}
</div>
</td>
<td class="variant-item__details large-up-hide">
<div class="variant-item__info">
<span class="variant-item__name h4 break">{{ variant . title | escape }} </span>
{%- if product . selected_or_first_available_variant . sku -%}
<span class="variant-item__sku break">{{ product . selected_or_first_available_variant . sku | escape }} </span>
{%- endif -%}
</div>
{%- assign item_price = product . selected_or_first_available_variant . price | money -%}
{%- if product . selected_or_first_available_variant . compare_at_price -%}
<dl class="variant-item__discounted-prices">
<dt class="visually-hidden">
Regular price
</dt>
<dd>
<s class="variant-item__old-price price price--end">
{{ product . selected_or_first_available_variant . compare_at_price | money }}
</s>
</dd>
<dt class="visually-hidden">
Sale price
</dt>
<dd class="price">
<span class="price">
{{ item_price }} /ea
</span>
</dd>
</dl>
{%- else -%}
<span class="price">
{{ item_price }} /ea
</span>
{%- endif -%}
{%- if product . selected_or_first_available_variant . available and product . selected_or_first_available_variant . unit_price_measurement -%}
<div class="unit-price caption">
<span class="visually-hidden">Unit price</span>
{{ product . selected_or_first_available_variant . unit_price | money }}
<span aria-hidden="true">/</span>
<span class="visually-hidden"> per </span>
{%- if product . selected_or_first_available_variant . unit_price_measurement . reference_value != 1 -%}
{{- product . selected_or_first_available_variant . unit_price_measurement . reference_value -}}
{%- endif -%}
{{ product . selected_or_first_available_variant . unit_price_measurement . reference_unit }}
</div>
{%- endif -%}
</td>
<td class="variant-item__totals right large-up-hide">
{%- render 'loading-overlay' -%}
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
{% # theme-check-disable %}
<span class="price">{{ cart | line_items_for : product . selected_or_first_available_variant | sum : 'original_line_price' | money }} </span>
{% # theme-check-enable %}
</td>
<td class="variant-item__quantity">
<quantity-popover>
<div class="variant-item__quantity-wrapper quantity-popover-wrapper variant-item__quantity-wrapper--no-info">
<label class="visually-hidden" for="Quantity-{{ variant . id }} ">
Quantity
</label>
<div class="quantity-popover-container">
{%- if product . selected_or_first_available_variant . available == false -%}
<span class="variant-item__sold-out h4"> Sold out </span>
{%- else -%}
{% comment %} TODO: Remove theme check {% endcomment %}
{% # theme-check-disable %}
{% assign cart_qty = cart | item_count_for_variant : product . selected_or_first_available_variant . id %}
{% # theme-check-enable %}
{% render 'quantity-input' , variant : product . selected_or_first_available_variant %}
{%- endif -%}
</div>
{%- if cart_qty > 0 -%}
<quick-order-list-remove-button
id="Remove-{{ product . selected_or_first_available_variant . id }} "
data-index="{{ product . selected_or_first_available_variant . id }} "
>
<a
href="{{ product . selected_or_first_available_variant . url_to_remove }} "
class="button button--tertiary"
aria-label="Remove {{ variant . title }} "
>
{% render 'icon-remove' %}
</a>
</quick-order-list-remove-button>
{%- endif -%}
</div>
<div
class="variant-item__error large-up-hide"
id="Quick-order-list-item-error-mobile-{{ product . selected_or_first_available_variant . id }} "
role="alert"
>
<small class="variant-item__error-text"></small>
{% render 'icon-error' %}
</div>
</quantity-popover>
</td>
{%- assign item_price = product . selected_or_first_available_variant . price | money -%}
<td class="variant-item__price small-hide medium-hide">
{%- if variant . compare_at_price -%}
<dl class="variant-item__discounted-prices">
<dt class="visually-hidden">
Regular price
</dt>
<dd>
<s class="variant-item__old-price price price--end">
{{ product . selected_or_first_available_variant . compare_at_price | money }}
</s>
</dd>
<dt class="visually-hidden">
Sale price
</dt>
<dd class="price">
<span class="price">
{{ item_price }} /ea
</span>
</dd>
</dl>
{%- else -%}
<span class="price">
{{ item_price }} /ea
</span>
{%- endif -%}
{%- if product . selected_or_first_available_variant . available and product . selected_or_first_available_variant . unit_price_measurement -%}
<div class="unit-price caption">
<span class="visually-hidden">Unit price</span>
{{ variant . unit_price | money }}
<span aria-hidden="true">/</span>
<span class="visually-hidden"> per </span>
{%- if product . selected_or_first_available_variant . unit_price_measurement . reference_value != 1 -%}
{{- product . selected_or_first_available_variant . unit_price_measurement . reference_value -}}
{%- endif -%}
{{ product . selected_or_first_available_variant . unit_price_measurement . reference_unit }}
</div>
{%- endif -%}
</td>
<td class="variant-item__totals right small-hide medium-hide">
{%- render 'loading-overlay' -%}
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
{% # theme-check-disable %}
<span class="price">{{ cart | line_items_for : product . selected_or_first_available_variant | sum : 'original_line_price' | money }} </span>
{% # theme-check-enable %}
</td>
</tr>
<tr class="small-hide medium-hide hidden desktop-row-error">
<td></td>
<td>
<div class="variant-item__error" id="Quick-order-list-item-error-desktop-{{ variant . id }} " role="alert">
<small class="variant-item__error-text"></small>
{% render 'icon-error' %}
</div>
</td>
<td></td>
<td></td>
</tr>
{%- else -%}
{%- for variant in product . variants -%}
{% # theme-check-disable %}
{% assign cart_qty = cart | item_count_for_variant : variant . id %}
{% # theme-check-enable %}
<tr
class="variant-item"
id="Variant-{{ variant . id }} "
data-variant-id="{{ variant . id }} "
data-cart-qty="{{ cart_qty }} "
>
<td class="variant-item__inner">
<div class="variant-item__media">
<div class="variant-item__image-container gradient global-media-settings{% unless variant . image %} variant-item__image-container--no-img {% endunless %} ">
{% if variant . image %}
{%- assign img_height = 43 | divided_by : variant . image . aspect_ratio | ceil -%}
{{
variant . image
| image_url : width : 86
| image_tag :
loading : 'lazy' ,
fetchpriority : 'low' ,
decoding : 'async' ,
class : 'variant-item__image' ,
width : 43 ,
height : img_height ,
widths : '86' ,
alt : variant . image . alt
| escape
}}
{% endif %}
</div>
</div>
<div class="small-hide medium-hide">
<span class="variant-item__name h4 break">{{ variant . title | escape }} </span>
{%- if variant . sku -%}
<span class="variant-item__sku break">{{ variant . sku | escape }} </span>
{%- endif -%}
</div>
</td>
<td class="variant-item__details large-up-hide">
<div class="variant-item__info">
<span class="variant-item__name h4 break">{{ variant . title | escape }} </span>
{%- if variant . sku -%}
<span class="variant-item__sku break">{{ variant . sku | escape }} </span>
{%- endif -%}
</div>
{%- assign item_price = variant . price | money -%}
{%- if variant . compare_at_price -%}
<dl class="variant-item__discounted-prices">
<dt class="visually-hidden">
Regular price
</dt>
<dd>
<s class="variant-item__old-price price price--end">
{{ variant . compare_at_price | money }}
</s>
</dd>
<dt class="visually-hidden">
Sale price
</dt>
<dd class="price">
<span class="price">
{{ item_price }} /ea
</span>
</dd>
</dl>
{%- else -%}
<span class="price">
{{ item_price }} /ea
</span>
{%- endif -%}
{%- if variant . available and variant . unit_price_measurement -%}
<div class="unit-price caption">
<span class="visually-hidden">Unit price</span>
{{ variant . unit_price | money }}
<span aria-hidden="true">/</span>
<span class="visually-hidden"> per </span>
{%- if variant . unit_price_measurement . reference_value != 1 -%}
{{- variant . unit_price_measurement . reference_value -}}
{%- endif -%}
{{ variant . unit_price_measurement . reference_unit }}
</div>
{%- endif -%}
</td>
<td class="variant-item__totals right large-up-hide">
{%- render 'loading-overlay' -%}
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
{% # theme-check-disable %}
<span class="price">{{ cart | line_items_for : variant | sum : 'original_line_price' | money }} </span>
{% # theme-check-enable %}
</td>
<td class="variant-item__quantity">
<quantity-popover>
<div class="variant-item__quantity-wrapper quantity-popover-wrapper variant-item__quantity-wrapper--no-info">
<label class="visually-hidden" for="Quantity-{{ variant . id }} ">
Quantity
</label>
<div class="quantity-popover-container">
{%- if variant . available == false -%}
<span class="variant-item__sold-out h4">Sold out</span>
{%- else -%}
{% comment %} TODO: Remove theme check {% endcomment %}
{% # theme-check-disable %}
{% assign cart_qty = cart | item_count_for_variant : variant . id %}
{% # theme-check-enable %}
{% render 'quantity-input' , variant : variant %}
{%- endif -%}
</div>
{%- if cart_qty > 0 -%}
<quick-order-list-remove-button
id="Remove-{{ variant . id }} "
data-index="{{ variant . id }} "
>
<a
href="{{ variant . url_to_remove }} "
class="button button--tertiary"
aria-label="Remove {{ variant . title }} "
>
{% render 'icon-remove' %}
</a>
</quick-order-list-remove-button>
{%- endif -%}
</div>
<div
class="variant-item__error large-up-hide"
id="Quick-order-list-item-error-mobile-{{ variant . id }} "
role="alert"
>
<small class="variant-item__error-text"></small>
{% render 'icon-error' %}
</div>
</quantity-popover>
</td>
{%- assign item_price = variant . price | money -%}
<td class="variant-item__price small-hide medium-hide">
{%- if variant . compare_at_price -%}
<dl class="variant-item__discounted-prices">
<dt class="visually-hidden">
Regular price
</dt>
<dd>
<s class="variant-item__old-price price price--end">
{{ variant . compare_at_price | money }}
</s>
</dd>
<dt class="visually-hidden">
Sale price
</dt>
<dd class="price">
<span class="price">
{{ item_price }} /ea
</span>
</dd>
</dl>
{%- else -%}
<span class="price">
{{ item_price }} /ea
</span>
{%- endif -%}
{%- if variant . available and variant . unit_price_measurement -%}
<div class="unit-price caption">
<span class="visually-hidden">Unit price</span>
{{ variant . unit_price | money }}
<span aria-hidden="true">/</span>
<span class="visually-hidden"> per </span>
{%- if variant . unit_price_measurement . reference_value != 1 -%}
{{- variant . unit_price_measurement . reference_value -}}
{%- endif -%}
{{ variant . unit_price_measurement . reference_unit }}
</div>
{%- endif -%}
</td>
<td class="variant-item__totals right small-hide medium-hide">
{%- render 'loading-overlay' -%}
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
{% # theme-check-disable %}
<span class="price">{{ cart | line_items_for : variant | sum : 'original_line_price' | money }} </span>
{% # theme-check-enable %}
</td>
</tr>
<tr class="small-hide medium-hide hidden desktop-row-error">
<td></td>
<td>
<div class="variant-item__error" id="Quick-order-list-item-error-desktop-{{ variant . id }} " role="alert">
<small class="variant-item__error-text"></small>
{% render 'icon-error' %}
</div>
</td>
<td></td>
<td></td>
</tr>
{%- endfor -%}
{%- endif -%}
</tbody>
</table>
</div>
<noscript>
{%- if product . has_only_default_variant or product . variants . size == 1 -%}
<button type="submit" class="button button--secondary right" formnovalidate form="QuickOrderList">
Update
</button>
{%- endif -%}
</noscript>
</div>
<p class="visually-hidden" id="quick-order-list-live-region-text" aria-live="polite" role="status"></p>
<p
class="visually-hidden"
id="shopping-cart-variant-item-status"
aria-live="polite"
aria-hidden="true"
role="status"
>
Loading...
</p>
</form>
{%- if product . has_only_default_variant or product . variants . size == 1 -%}
<span class="quick-order-list-error">
{% comment %} Populated by JS {% endcomment %}
</span>
{%- else -%}
<div class="quick-order-list__total gradient" id="quick-order-list-total">
<div class="quick-order-list-total__info">
<div class="quick-order-list-total__column small-hide medium-hide">
<div class="quick-order-list-buttons">
<a
href="{{ routes . cart_url }} "
class="quick-order-list__button button button--secondary small-hide medium-hide"
>
<span class="quick-order-list__button-text">View cart</span>
</a>
<div class="variant-remove-total">
{%- render 'loading-overlay' -%}
<quick-order-list-remove-all-button
class="no-js-hidden"
data-action="confirm"
>
<button class="button button--tertiary" type="button">
{% render 'icon-remove' %}
<span class="text-body">Remove all</span>
</button>
</quick-order-list-remove-all-button>
</div>
</div>
<span class="quick-order-list__message caption-large" role="status">
<span class="quick-order-list__message-icon hidden">{%- render 'icon-checkmark' -%} </span>
<span class="quick-order-list__message-text"></span>
</span>
<span class="quick-order-list-error">
{% comment %} Populated by JS {% endcomment %}
</span>
</div>
<div class="quick-order-list__total-items">
<h3>
{{ items_in_cart }}
</h3>
<p class="h5">Total items</p>
</div>
<div class="quick-order-list-total__price">
<noscript>
<button type="submit" class="button button--secondary" formnovalidate form="QuickOrderList">
Update
</button>
</noscript>
<div class="totals__product-total">
<h3 class="totals__subtotal-value">
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
{% # theme-check-disable %}
{{ cart | line_items_for : product | sum : 'original_line_price' | money }}
{% # theme-check-enable %}
</h3>
<p class="totals__subtotal h5">Product subtotal</p>
</div>
<small class="tax-note caption-large rte">
{%- if cart . taxes_included and shop . shipping_policy . body != blank -%}
Tax included. <a href="{{ shop . shipping_policy . url }} ">Shipping</a> and discounts calculated at checkout.
{%- elsif cart . taxes_included -%}
Tax included and shipping and discounts calculated at checkout
{%- elsif shop . shipping_policy . body != blank -%}
Taxes, Discounts and <a href="{{ shop . shipping_policy . url }} ">shipping</a> calculated at checkout
{%- else -%}
Taxes, discounts and shipping calculated at checkout
{%- endif -%}
</small>
</div>
<div class="quick-order-list-total__column large-up-hide">
<div class="quick-order-list-buttons">
<a
href="{{ routes . cart_url }} "
class="quick-order-list__button button button--secondary button--full-width"
>
<span class="quick-order-list__button-text">View cart</span>
</a>
<div class="variant-remove-total">
{%- render 'loading-overlay' -%}
<quick-order-list-remove-all-button
class="no-js-hidden"
data-action="confirm"
>
<button class="button button--tertiary" type="button">
{% render 'icon-remove' %}
<span class="text-body">Remove all</span>
</button>
</quick-order-list-remove-all-button>
</div>
</div>
<span class="quick-order-list__message caption-large" role="status">
<span class="quick-order-list__message-icon hidden">{%- render 'icon-checkmark' -%} </span>
<span class="quick-order-list__message-text"></span>
</span>
<span class="quick-order-list-error">
{% comment %} Populated by JS {% endcomment %}
</span>
</div>
</div>
<div class="quick-order-list-total__confirmation hidden">
<span class="text-body">
Remove all {{ items_in_cart }} items from your cart?
</span>
<quick-order-list-remove-all-button
data-action="remove"
>
<button
class="quick-order-list__button-confirm button button--secondary"
type="button"
>
Remove all
</button>
</quick-order-list-remove-all-button>
<quick-order-list-remove-all-button
data-action="cancel"
>
<button
class="quick-order-list__button-cancel button button--tertiary"
type="button"
>
Cancel
</button>
</quick-order-list-remove-all-button>
</div>
</div>
{%- endif -%}
</quick-order-list>
<template id="QuickOrderListErrorTemplate-{{ section . id }} ">
{% render 'icon-error' %}
<span class="quick-order-list-error-message caption-large" role="alert"></span>
</template>
</div>
Klicke auf Speichern .
Javascript-Code für schnelle Bestellliste hinzufügen Wenn sich die Warenkorbmenge einer Variante ändert, werden die Produkt-Zwischensumme, die Varianten-Zwischensumme und der mögliche Fehlerstatus aktualisiert. Die aktualisierten Werte können mithilfe des JavaScript-Codes abgerufen werden.
Du kannst Code zur Datei theme.js
oder zum Äquivalent hinzufügen.
Schritte:
Gehe im Shopify-Adminbereich zu Onlineshop > Themes .
Suche das Theme, das du bearbeiten möchtest, klicke auf die Schaltfläche ... , um das Aktionsmenü zu öffnen, und klicke dann auf Code bearbeiten .
Öffne die Datei theme.js
.
Erstelle eine neue Zeile am Ende der Datei und füge folgenden Code hinzu:
class QuickOrderListRemoveButton extends HTMLElement {
constructor () {
super ();
this . addEventListener ( ' click ' , ( event ) => {
event . preventDefault ();
const quickOrderList = this . closest ( ' quick-order-list ' );
quickOrderList . updateQuantity ( this . dataset . index , 0 );
});
}
}
customElements . define ( ' quick-order-list-remove-button ' , QuickOrderListRemoveButton );
class QuickOrderListRemoveAllButton extends HTMLElement {
constructor () {
super ();
const allVariants = Array . from ( document . querySelectorAll ( ' [data-variant-id] ' ));
const items = {}
let hasVariantsInCart = false ;
this . quickOrderList = this . closest ( ' quick-order-list ' );
allVariants . forEach (( variant ) => {
const cartQty = parseInt ( variant . dataset . cartQty );
if ( cartQty > 0 ) {
hasVariantsInCart = true ;
items [ parseInt ( variant . dataset . variantId )] = 0 ;
}
});
if ( ! hasVariantsInCart ) {
this . classList . add ( ' hidden ' );
}
this . actions = {
confirm : ' confirm ' ,
remove : ' remove ' ,
cancel : ' cancel '
}
this . addEventListener ( ' click ' , ( event ) => {
event . preventDefault ();
if ( this . dataset . action === this . actions . confirm ) {
this . toggleConfirmation ( false , true );
} else if ( this . dataset . action === this . actions . remove ) {
this . quickOrderList . updateMultipleQty ( items );
this . toggleConfirmation ( true , false );
} else if ( this . dataset . action === this . actions . cancel ) {
this . toggleConfirmation ( true , false );
}
});
}
toggleConfirmation ( showConfirmation , showInfo ) {
this . quickOrderList . querySelector ( ' .quick-order-list-total__confirmation ' ). classList . toggle ( ' hidden ' , showConfirmation );
this . quickOrderList . querySelector ( ' .quick-order-list-total__info ' ). classList . toggle ( ' hidden ' , showInfo )
}
}
customElements . define ( ' quick-order-list-remove-all-button ' , QuickOrderListRemoveAllButton );
class QuickOrderList extends HTMLElement {
constructor () {
super ();
this . cart = document . querySelector ( ' cart-drawer ' );
this . actions = {
add : ' ADD ' ,
update : ' UPDATE '
}
this . quickOrderListId = ' quick-order-list '
this . variantItemStatusElement = document . getElementById ( ' shopping-cart-variant-item-status ' );
const form = this . querySelector ( ' form ' );
form . addEventListener ( ' submit ' , this . onSubmit . bind ( this ));
const debouncedOnChange = debounce (( event ) => {
this . onChange ( event );
}, ON_CHANGE_DEBOUNCE_TIMER );
this . addEventListener ( ' change ' , debouncedOnChange . bind ( this ));
}
cartUpdateUnsubscriber = undefined ;
onSubmit ( event ) {
event . preventDefault ();
}
connectedCallback () {
this . cartUpdateUnsubscriber = subscribe ( PUB_SUB_EVENTS . cartUpdate , ( event ) => {
if ( event . source === this . quickOrderListId ) {
return ;
}
// If its another section that made the update
this . onCartUpdate ();
});
this . sectionId = this . dataset . id ;
}
disconnectedCallback () {
if ( this . cartUpdateUnsubscriber ) {
this . cartUpdateUnsubscriber ();
}
}
onChange ( event ) {
const inputValue = parseInt ( event . target . value );
const cartQuantity = parseInt ( event . target . dataset . cartQuantity );
const index = event . target . dataset . index ;
const name = document . activeElement . getAttribute ( ' name ' );
const quantity = inputValue - cartQuantity ;
if ( cartQuantity > 0 ) {
this . updateQuantity ( index , inputValue , name , this . actions . update );
} else {
this . updateQuantity ( index , quantity , name , this . actions . add );
}
}
onCartUpdate () {
fetch ( ` ${ window . location . pathname } ?section_id= ${ this . sectionId } ` )
. then (( response ) => response . text ())
. then (( responseText ) => {
const html = new DOMParser (). parseFromString ( responseText , ' text/html ' );
const sourceQty = html . querySelector ( this . quickOrderListId );
this . innerHTML = sourceQty . innerHTML ;
})
. catch ( e => {
console . error ( e );
});
}
getSectionsToRender () {
return [
{
id : this . quickOrderListId ,
section : document . getElementById ( this . quickOrderListId ). dataset . id ,
selector : ' .js-contents '
},
{
id : ' cart-icon-bubble ' ,
section : ' cart-icon-bubble ' ,
selector : ' .shopify-section '
},
{
id : ' quick-order-list-live-region-text ' ,
section : ' cart-live-region-text ' ,
selector : ' .shopify-section '
},
{
id : ' quick-order-list-total ' ,
section : document . getElementById ( this . quickOrderListId ). dataset . id ,
selector : ' .quick-order-list__total '
},
{
id : ' CartDrawer ' ,
selector : ' #CartDrawer ' ,
section : ' cart-drawer '
}
];
}
renderSections ( parsedState ) {
this . getSectionsToRender (). forEach (( section => {
const sectionElement = document . getElementById ( section . id );
if ( sectionElement && sectionElement . parentElement && sectionElement . parentElement . classList . contains ( ' drawer ' )) {
parsedState . items . length > 0 ? sectionElement . parentElement . classList . remove ( ' is-empty ' ) : sectionElement . parentElement . classList . add ( ' is-empty ' );
setTimeout (() => {
document . querySelector ( ' #CartDrawer-Overlay ' ). addEventListener ( ' click ' , this . cart . close . bind ( this . cart ));
});
}
const elementToReplace = sectionElement && sectionElement . querySelector ( section . selector ) ? sectionElement . querySelector ( section . selector ) : sectionElement ;
if ( elementToReplace ) {
elementToReplace . innerHTML =
this . getSectionInnerHTML ( parsedState . sections [ section . section ], section . selector );
}
}));
}
updateMultipleQty ( items ) {
this . querySelector ( ' .variant-remove-total .loading-overlay ' ). classList . remove ( ' hidden ' );
const body = JSON . stringify ({
updates : items ,
sections : this . getSectionsToRender (). map (( section ) => section . section ),
sections_url : window . location . pathname
});
this . updateMessage ();
this . setErrorMessage ();
fetch ( ` ${ routes . cart_update_url } ` , { ... fetchConfig (), ...{ body } })
. then (( response ) => {
return response . text ();
})
. then (( state ) => {
const parsedState = JSON . parse ( state );
this . renderSections ( parsedState );
}). catch (() => {
this . setErrorMessage ( ' There was an error while updating your cart. Please try again. ' );
})
. finally (() => {
this . querySelector ( ' .variant-remove-total .loading-overlay ' ). classList . add ( ' hidden ' );
});
}
updateQuantity ( id , quantity , name , action ) {
this . toggleLoading ( id , true );
let routeUrl = routes . cart_change_url ;
let body = JSON . stringify ({
quantity ,
id ,
sections : this . getSectionsToRender (). map (( section ) => section . section ),
sections_url : window . location . pathname
});
let fetchConfigType ;
if ( action === this . actions . add ) {
fetchConfigType = ' javascript ' ;
routeUrl = routes . cart_add_url ;
body = JSON . stringify ({
items : [
{
quantity : parseInt ( quantity ),
id : parseInt ( id )
}
],
sections : this . getSectionsToRender (). map (( section ) => section . section ),
sections_url : window . location . pathname
});
}
this . updateMessage ();
this . setErrorMessage ();
fetch ( ` ${ routeUrl } ` , { ... fetchConfig ( fetchConfigType ), ...{ body } })
. then (( response ) => {
return response . text ();
})
. then (( state ) => {
const parsedState = JSON . parse ( state );
const quantityElement = document . getElementById ( `Quantity- ${ id } ` );
const items = document . querySelectorAll ( ' .variant-item ' );
if ( parsedState . description || parsedState . errors ) {
const variantItem = document . querySelector ( `[id^="Variant- ${ id } "] .variant-item__totals.small-hide .loading-overlay` );
variantItem . classList . add ( ' loading-overlay--error ' );
this . resetQuantityInput ( id , quantityElement );
if ( parsedState . errors ) {
this . updateLiveRegions ( id , parsedState . errors );
} else {
this . updateLiveRegions ( id , parsedState . description );
}
return ;
}
this . classList . toggle ( ' is-empty ' , parsedState . item_count === 0 );
this . renderSections ( parsedState );
let hasError = false ;
const currentItem = parsedState . items . find (( item ) => item . variant_id === parseInt ( id ));
const updatedValue = currentItem ? currentItem . quantity : undefined ;
if ( updatedValue && updatedValue !== quantity ) {
this . updateError ( updatedValue , id );
hasError = true ;
}
const variantItem = document . getElementById ( `Variant- ${ id } ` );
if ( variantItem && variantItem . querySelector ( `[name=" ${ name } "]` )) {
variantItem . querySelector ( `[name=" ${ name } "]` ). focus ();
}
publish ( PUB_SUB_EVENTS . cartUpdate , { source : this . quickOrderListId , cartData : parsedState });
if ( hasError ) {
this . updateMessage ();
} else if ( action === this . actions . add ) {
this . updateMessage ( parseInt ( quantity ))
} else if ( action === this . actions . update ) {
this . updateMessage ( parseInt ( quantity - quantityElement . dataset . cartQuantity ))
} else {
this . updateMessage ( - parseInt ( quantityElement . dataset . cartQuantity ))
}
}). catch (( error ) => {
this . querySelectorAll ( ' .loading-overlay ' ). forEach (( overlay ) => overlay . classList . add ( ' hidden ' ));
this . resetQuantityInput ( id );
console . error ( error );
this . setErrorMessage ( ' There was an error while updating your cart. Please try again. ' );
})
. finally (() => {
this . toggleLoading ( id );
});
}
resetQuantityInput ( id , quantityElement ) {
const input = quantityElement ?? document . getElementById ( `Quantity- ${ id } ` );
input . value = input . getAttribute ( ' value ' );
}
setErrorMessage ( message = null ) {
this . errorMessageTemplate = this . errorMessageTemplate ?? document . getElementById ( `QuickOrderListErrorTemplate- ${ this . sectionId } ` ). cloneNode ( true );
const errorElements = document . querySelectorAll ( ' .quick-order-list-error ' );
errorElements . forEach (( errorElement ) => {
errorElement . innerHTML = '' ;
if ( ! message ) return ;
const updatedMessageElement = this . errorMessageTemplate . cloneNode ( true );
updatedMessageElement . content . querySelector ( ' .quick-order-list-error-message ' ). innerText = message ;
errorElement . appendChild ( updatedMessageElement . content );
});
}
updateMessage ( quantity = null ) {
const messages = this . querySelectorAll ( ' .quick-order-list__message-text ' );
const icons = this . querySelectorAll ( ' .quick-order-list__message-icon ' );
if ( quantity === null || isNaN ( quantity )) {
messages . forEach ( message => message . innerHTML = '' );
icons . forEach ( icon => icon . classList . add ( ' hidden ' ));
return ;
}
const isQuantityNegative = quantity < 0 ;
const absQuantity = Math . abs ( quantity );
const textTemplate = isQuantityNegative
? ( absQuantity === 1 ? ` ${ absQuantity } item removed` : ` ${ absQuantity } items removed` )
: ( quantity === 1 ? ` ${ absQuantity } item added` : ` ${ absQuantity } items added` )
messages . forEach (( msg ) => msg . innerHTML = textTemplate );
if ( ! isQuantityNegative ) {
icons . forEach (( i ) => i . classList . remove ( ' hidden ' ));
}
}
updateError ( updatedValue , id ) {
let message = '' ;
if ( typeof updatedValue === ' undefined ' ) {
message = ' There was an error while updating your cart. Please try again. ' ;
} else {
message = `You can only add ${ updatedValue } of this item to your cart.` ;
}
this . updateLiveRegions ( id , message );
}
updateLiveRegions ( id , message ) {
const variantItemErrorDesktop = document . getElementById ( `Quick-order-list-item-error-desktop- ${ id } ` );
const variantItemErrorMobile = document . getElementById ( `Quick-order-list-item-error-mobile- ${ id } ` );
if ( variantItemErrorDesktop ) {
variantItemErrorDesktop . querySelector ( ' .variant-item__error-text ' ). innerHTML = message ;
variantItemErrorDesktop . closest ( ' tr ' ). classList . remove ( ' hidden ' );
}
if ( variantItemErrorMobile ) variantItemErrorMobile . querySelector ( ' .variant-item__error-text ' ). innerHTML = message ;
this . variantItemStatusElement . setAttribute ( ' aria-hidden ' , true );
const cartStatus = document . getElementById ( ' quick-order-list-live-region-text ' );
cartStatus . setAttribute ( ' aria-hidden ' , false );
setTimeout (() => {
cartStatus . setAttribute ( ' aria-hidden ' , true );
}, 1000 );
}
getSectionInnerHTML ( html , selector ) {
return new DOMParser ()
. parseFromString ( html , ' text/html ' )
. querySelector ( selector ). innerHTML ;
}
toggleLoading ( id , enable ) {
const quickOrderList = document . getElementById ( this . quickOrderListId );
const quickOrderListItems = this . querySelectorAll ( `#Variant- ${ id } .loading-overlay` );
if ( enable ) {
quickOrderList . classList . add ( ' quick-order-list__container--disabled ' );
[... quickOrderListItems ]. forEach (( overlay ) => overlay . classList . remove ( ' hidden ' ));
document . activeElement . blur ();
this . variantItemStatusElement . setAttribute ( ' aria-hidden ' , false );
} else {
quickOrderList . classList . remove ( ' quick-order-list__container--disabled ' );
quickOrderListItems . forEach (( overlay ) => overlay . classList . add ( ' hidden ' ));
}
}
}
customElements . define ( ' quick-order-list ' , QuickOrderList );
Klicke auf Speichern .