免费 Shopify 模板的版本 11.0.0 或更高版本中支持快速订单列表分区。如果您想在商店中添加“快速订单列表”分区,则可将商店模板更新为最新版本。
如果您不想更改或更新模板,则可以使用 Liquid 或 Javascript 向您的模板中添加代码,以在产品页面上显示“快速订单列表”分区。
在更新您的模板文件之前,请确保复制您的模板以创建备份副本。
这属于高级教程。如果您不擅长查阅和编辑模板代码,则您可以与开发人员合作或聘请 Shopify 专家。
您可以将代码添加到您模板的以下文件中,以支持“快速订单列表”分区:
main-product.liquid 或等效文件 步骤: 在 Shopify 后台中,转至在线商店 > 模板。 找到要编辑的模板,点击 ... 按钮打开操作菜单,然后点击编辑代码。 打开要编辑的文件。 在文件底部创建新行,然后添加以下代码: {%#theme-check-disable%}{%-assignitems_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">{%-ifproduct.has_only_default_variant-%}Product{%-else-%}Variant{%-endif-%}</th> <th class="large-up-hide right caption-with-letter-spacing" scope="col">{%-ifproduct.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">{%-ifproduct.has_only_default_variant-%}Product subtotal{%-else-%}Variant total{%-endif-%}</th> </tr> </thead> <tbody>{%-ifproduct.has_only_default_variant-%}{%#theme-check-disable%}{%assigncart_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{%unlessproduct.featured_media%}variant-item__image-container--no-img{%endunless%}">{%ifproduct.featured_media%}{%-assignimg_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>{%-ifproduct.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>{%-ifproduct.selected_or_first_available_variant.sku-%}<span class="variant-item__sku break">{{product.selected_or_first_available_variant.sku|escape}}</span>{%-endif-%}</div>{%-assignitem_price=product.selected_or_first_available_variant.price|money-%}{%-ifproduct.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-%}{%-ifproduct.selected_or_first_available_variant.availableandproduct.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>{%-ifproduct.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">{%-ifproduct.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%}{%assigncart_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>{%-ifcart_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>{%-assignitem_price=product.selected_or_first_available_variant.price|money-%}<td class="variant-item__price small-hide medium-hide">{%-ifvariant.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-%}{%-ifproduct.selected_or_first_available_variant.availableandproduct.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>{%-ifproduct.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-%}{%-forvariantinproduct.variants-%}{%#theme-check-disable%}{%assigncart_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{%unlessvariant.image%}variant-item__image-container--no-img{%endunless%}">{%ifvariant.image%}{%-assignimg_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>{%-ifvariant.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>{%-ifvariant.sku-%}<span class="variant-item__sku break">{{variant.sku|escape}}</span>{%-endif-%}</div>{%-assignitem_price=variant.price|money-%}{%-ifvariant.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-%}{%-ifvariant.availableandvariant.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>{%-ifvariant.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">{%-ifvariant.available==false-%}<span class="variant-item__sold-out h4">Sold out</span>{%-else-%}{%comment%}TODO: Remove theme check{%endcomment%}{%#theme-check-disable%}{%assigncart_qty=cart|item_count_for_variant:variant.id%}{%#theme-check-enable%}{%render'quantity-input',variant:variant%}{%-endif-%}</div>{%-ifcart_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>{%-assignitem_price=variant.price|money-%}<td class="variant-item__price small-hide medium-hide">{%-ifvariant.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-%}{%-ifvariant.availableandvariant.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>{%-ifvariant.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>{%-ifproduct.has_only_default_variantorproduct.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>{%-ifproduct.has_only_default_variantorproduct.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">{%-ifcart.taxes_includedandshop.shipping_policy.body!=blank-%}Tax included. <a href="{{shop.shipping_policy.url}}">Shipping</a> and discounts calculated at checkout.{%-elsifcart.taxes_included-%}Tax included and shipping and discounts calculated at checkout{%-elsifshop.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> 点击保存。
添加 Javascript 快速订单列表代码
当多属性的购物车数量发生变化时,产品小计、多属性小计和可能出现的错误状态将会更新。可以使用 Javascript 代码获取更新后的值。
您可以向 theme.js 文件或等效文件中添加代码。
步骤:
在 Shopify 后台中,转至在线商店 > 模板。 找到要编辑的模板,点击 ... 按钮打开操作菜单,然后点击编辑代码。 打开 theme.js 文件。 在文件底部创建新行,然后添加以下代码: classQuickOrderListRemoveButtonextendsHTMLElement{constructor(){super();this.addEventListener('click',(event)=>{event.preventDefault();constquickOrderList=this.closest('quick-order-list');quickOrderList.updateQuantity(this.dataset.index,0);});}}customElements.define('quick-order-list-remove-button',QuickOrderListRemoveButton);classQuickOrderListRemoveAllButtonextendsHTMLElement{constructor(){super();constallVariants=Array.from(document.querySelectorAll('[data-variant-id]'));constitems={}lethasVariantsInCart=false;this.quickOrderList=this.closest('quick-order-list');allVariants.forEach((variant)=>{constcartQty=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);}elseif(this.dataset.action===this.actions.remove){this.quickOrderList.updateMultipleQty(items);this.toggleConfirmation(true,false);}elseif(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);classQuickOrderListextendsHTMLElement{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');constform=this.querySelector('form');form.addEventListener('submit',this.onSubmit.bind(this));constdebouncedOnChange=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 updatethis.onCartUpdate();});this.sectionId=this.dataset.id;}disconnectedCallback(){if(this.cartUpdateUnsubscriber){this.cartUpdateUnsubscriber();}}onChange(event){constinputValue=parseInt(event.target.value);constcartQuantity=parseInt(event.target.dataset.cartQuantity);constindex=event.target.dataset.index;constname=document.activeElement.getAttribute('name');constquantity=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)=>{consthtml=newDOMParser().parseFromString(responseText,'text/html');constsourceQty=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=>{constsectionElement=document.getElementById(section.id);if(sectionElement&§ionElement.parentElement&§ionElement.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));});}constelementToReplace=sectionElement&§ionElement.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');constbody=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)=>{returnresponse.text();}).then((state)=>{constparsedState=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);letrouteUrl=routes.cart_change_url;letbody=JSON.stringify({quantity,id,sections:this.getSectionsToRender().map((section)=>section.section),sections_url:window.location.pathname});letfetchConfigType;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)=>{returnresponse.text();}).then((state)=>{constparsedState=JSON.parse(state);constquantityElement=document.getElementById(`Quantity-${id}`);constitems=document.querySelectorAll('.variant-item');if(parsedState.description||parsedState.errors){constvariantItem=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);lethasError=false;constcurrentItem=parsedState.items.find((item)=>item.variant_id===parseInt(id));constupdatedValue=currentItem?currentItem.quantity:undefined;if(updatedValue&&updatedValue!==quantity){this.updateError(updatedValue,id);hasError=true;}constvariantItem=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();}elseif(action===this.actions.add){this.updateMessage(parseInt(quantity))}elseif(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){constinput=quantityElement??document.getElementById(`Quantity-${id}`);input.value=input.getAttribute('value');}setErrorMessage(message=null){this.errorMessageTemplate=this.errorMessageTemplate??document.getElementById(`QuickOrderListErrorTemplate-${this.sectionId}`).cloneNode(true);consterrorElements=document.querySelectorAll('.quick-order-list-error');errorElements.forEach((errorElement)=>{errorElement.innerHTML='';if(!message)return;constupdatedMessageElement=this.errorMessageTemplate.cloneNode(true);updatedMessageElement.content.querySelector('.quick-order-list-error-message').innerText=message;errorElement.appendChild(updatedMessageElement.content);});}updateMessage(quantity=null){constmessages=this.querySelectorAll('.quick-order-list__message-text');consticons=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;}constisQuantityNegative=quantity<0;constabsQuantity=Math.abs(quantity);consttextTemplate=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){letmessage='';if(typeofupdatedValue==='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){constvariantItemErrorDesktop=document.getElementById(`Quick-order-list-item-error-desktop-${id}`);constvariantItemErrorMobile=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);constcartStatus=document.getElementById('quick-order-list-live-region-text');cartStatus.setAttribute('aria-hidden',false);setTimeout(()=>{cartStatus.setAttribute('aria-hidden',true);},1000);}getSectionInnerHTML(html,selector){returnnewDOMParser().parseFromString(html,'text/html').querySelector(selector).innerHTML;}toggleLoading(id,enable){constquickOrderList=document.getElementById(this.quickOrderListId);constquickOrderListItems=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); 点击保存。