Add the Quick order list section to your theme code
TheQuick order list 部分is supported onfree Shopify themes , version 11.0.0 or later. If you want to add the Quick order list section to your store, then you canupdate your store's theme to the latest version.
If you don't want to change orupdate your theme , then you can add code to your theme usingLiquid orJavascript to display the Quick order list section on your product pages.
Before you make updates to your theme files, ensure that youduplicate your theme to create a backup copy.
Grow your business
This is an advanced tutorial. If you're not comfortable reading and editing theme code, then you can work with a developer orhire a Shopify Partner .
Add Liquid Quick order list code
You can add code to the following files in your theme to support the Quick order list section:
main-product.liquid
or equivalent
Steps:
From your Shopify admin, go to欧宝体育官网入口首页 >Themes .
Find the theme that you want to edit, click the... button to open the actions menu, and then clickEdit code .
Open the file that you want to edit.
Create a new line at the bottom of the file, and add the following code:
{% # theme-check-disable%} {%- assign items_in_cart = 车 | line_items_for : product | sum : 'quantity' -%} {% # theme-check-enable%} {{部分 . id }} " > {%- if product . has_only_default_variant or product . variants . size == 1 -%} {% comment %} Populated by JS {% endcomment %} {%- else -%} {%- render 'icon-checkmark' -%} {% comment %} Populated by JS {% endcomment %} {{ items_in_cart }} Total items
Update {% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %} {% # theme-check-disable%} {{ 车 | line_items_for : product | sum : 'original_line_price' | money }} {% # theme-check-enable%} Product subtotal
{%- if 车 . taxes_included and shop . shipping_policy . body != blank -%} Tax included. {{shop . shipping_policy . url }} ">Shipping and discounts calculated at checkout.{%- elsif 车 . taxes_included -%} Tax included and shipping and discounts calculated at checkout{%- elsif shop . shipping_policy . body != blank -%} Taxes, Discounts and {{shop . shipping_policy . url }} ">shipping calculated at checkout{%- else -%} Taxes, discounts and shipping calculated at checkout{%- endif -%} {%- render 'icon-checkmark' -%} {% comment %} Populated by JS {% endcomment %} Remove all{{ items_in_cart }} items from your cart? Remove all Cancel
{%- endif -%} {{部分 . id }} ">{% render 'icon-error' %}
ClickSave .
Add Javascript Quick order list code
When a variant's cart quantity changes, the product subtotal, variant subtotal, and possible error state will be updated. The updated values can be fetched by using Javascript code.
You can add code to thetheme.js
file or equivalent.
Steps:
From your Shopify admin, go to欧宝体育官网入口首页 >Themes .
Find the theme that you want to edit, click the... button to open the actions menu, and then clickEdit code .
Open thetheme.js
file.
Create a new line at the bottom of the file, and add the following code:
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 车Qty = parseInt ( variant . dataset . 车Qty ); if ( 车Qty > 0 ) { hasVariantsInCart = true ; items [ parseInt ( variant . dataset . variantId )] = 0 ; } }); if ( ! hasVariantsInCart ) { this . classList . add ( ' hidden ' ); } this . actions = { confirm : ' confirm ' , remove : ' remove ' , 取消 : ' 取消 ' } 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 . 取消 ) { 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 . 车 = document . querySelector ( ' 车-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 )); } 车UpdateUnsubscriber = undefined ; onSubmit ( event ) { event . preventDefault (); } connectedCallback () { this . 车UpdateUnsubscriber = subscribe ( PUB_SUB_EVENTS . 车Update , ( event ) => { if ( event . source === this . quickOrderListId ) { return ; } // If its another section that made the update this . onCartUpdate (); }); this . 部分Id = this . dataset . id ; } disconnectedCallback () { if ( this . 车UpdateUnsubscriber ) { this . 车UpdateUnsubscriber (); } } onChange ( event ) { const inputValue = parseInt ( event . target . value ); const 车Quantity = parseInt ( event . target . dataset . 车Quantity ); const index = event . target . dataset . index ; const name = document . activeElement . getAttribute ( ' name ' ); const quantity = inputValue - 车Quantity ; if ( 车Quantity > 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 . 部分Id } ` ) . 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 , 部分 : document . getElementById ( this . quickOrderListId ). dataset . id , selector : ' .js-contents ' }, { id : ' 车-icon-bubble ' , 部分 : ' 车-icon-bubble ' , selector : ' .shopify-section ' }, { id : ' quick-order-list-live-region-text ' , 部分 : ' 车-live-region-text ' , selector : ' .shopify-section ' }, { id : ' quick-order-list-total ' , 部分 : document . getElementById ( this . quickOrderListId ). dataset . id , selector : ' .quick-order-list__total ' }, { id : ' CartDrawer ' , selector : ' #CartDrawer ' , 部分 : ' 车-drawer ' } ]; } renderSections ( parsedState ) { this . getSectionsToRender (). forEach (( 部分 => { const 部分Element = document . getElementById ( 部分 . id ); if ( 部分Element && 部分Element . parentElement && 部分Element . parentElement . classList . contains ( ' drawer ' )) { parsedState . items . length > 0 ? 部分Element . parentElement . classList . remove ( ' is-empty ' ) : 部分Element . parentElement . classList . add ( ' is-empty ' ); setTimeout (() => { document . querySelector ( ' #CartDrawer-Overlay ' ). addEventListener ( ' click ' , this . 车 . close . bind ( this . 车 )); }); } const elementToReplace = 部分Element && 部分Element . querySelector ( 部分 . selector ) ? 部分Element . querySelector ( 部分 . selector ) : 部分Element ; if ( elementToReplace ) { elementToReplace . innerHTML = this . getSectionInnerHTML ( parsedState . 部分s [ 部分 . 部分 ], 部分 . selector ); } })); } updateMultipleQty ( items ) { this . querySelector ( ' .variant-remove-total .loading-overlay ' ). classList . remove ( ' hidden ' ); const body = JSON . stringify ({ updates : items , 部分s : this . getSectionsToRender (). map (( 部分 ) => 部分 . 部分 ), 部分s_url : window . location . pathname }); this . updateMessage (); this . setErrorMessage (); fetch ( ` ${ routes . 车_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 . 车_change_url ; let body = JSON . stringify ({ quantity , id , 部分s : this . getSectionsToRender (). map (( 部分 ) => 部分 . 部分 ), 部分s_url : window . location . pathname }); let fetchConfigType ; if ( action === this . actions . add ) { fetchConfigType = ' javascript ' ; routeUrl = routes . 车_add_url ; body = JSON . stringify ({ items : [ { quantity : parseInt ( quantity ), id : parseInt ( id ) } ], 部分s : this . getSectionsToRender (). map (( 部分 ) => 部分 . 部分 ), 部分s_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 . 车Update , { source : this . quickOrderListId , 车Data : 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 . 车Quantity )) } else { this . updateMessage ( - parseInt ( quantityElement . dataset . 车Quantity )) } }). 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 . 部分Id } ` ). 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 车Status = document . getElementById ( ' quick-order-list-live-region-text ' ); 车Status . setAttribute ( ' aria-hidden ' , false ); setTimeout (() => { 车Status . 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 );
ClickSave .