Compatibilidade: Dawn 5.0 e versões anteriores SOMENTE
Muitos de nossos clientes têm perguntado sobre uma gaveta de carrinho Ajax para Shopify. Criar uma barra lateral é simples, mas desenvolver um carrinho que seja atualizado em tempo real sem a necessidade de atualizar a página é mais complexo. É aqui que a gaveta do carrinho Ajax entra em ação. Este recurso permite que você adicione uma gaveta de carrinho usando apenas código JavaScript puro com API Shopify Ajax e API de renderização de seção do Shopify, sem a necessidade de aplicativos ou bibliotecas externas.
Observe que esta funcionalidade já está incluída nas versões mais recentes dos temas GRATUITOS do Shopify 2.0, embora o design e a funcionalidade possam ser diferentes
Confira a loja DEMO aqui 💻. Botão de visualização rápida não incluído. Senha: made4uo
O que você está comprando:
- Mude o fundo da gaveta
- Adicionar uma nota de carrinho
- Tem a opção de abrir o carrinho sempre que o cliente acessar a URL do carrinho
- C art atualiza sem atualizar o navegador
- Você também pode gostar do recurso adicionado
O que torna nosso código melhor:
- Não usamos bibliotecas externas, com isso dito, nosso código não terá nenhum efeito mínimo no desempenho de velocidade do seu site
- Não deixamos nem adicionamos códigos para anunciar em nosso site
- Nosso código é compatível com dispositivos móveis
Quaisquer problemas relacionados ao código serão corrigidos sem custo adicional, excluindo solicitações de customização de código. Basta entrar em contato conosco em "Converse conosco". Estamos a apenas um botão de distância.
Para iniciar:
1. Vá para Admin store > Temas > Ações > Editar código.
2. Vá para a pasta Seções e crie uma nova seção, nomeie-a como “shopify-ajax-cart-drawer” e cole o código abaixo.
| {{ 'component-cart.css' | asset_url | stylesheet_tag }} {{ 'component-cart-items.css' | asset_url | stylesheet_tag }} {{ 'component-totals.css' | asset_url | stylesheet_tag }} {{ 'component-price.css' | asset_url | stylesheet_tag }} {{ 'component-discounts.css' | asset_url | stylesheet_tag }} {{ 'component-loading-overlay.css' | asset_url | stylesheet_tag }} <link rel="stylesheet" href=" {{ 'component-card.css' | asset_url }} " media="print" onload="this.media='all'"> <link rel="stylesheet" href=" {{ 'section-product-recommendations.css' | asset_url }} " media="print" onload="this.media='all'"> <noscript> {{ 'component-card.css' | asset_url | stylesheet_tag }} </noscript> <noscript> {{ 'section-product-recommendations.css' | asset_url | stylesheet_tag }} </noscript> <script src=" {{ 'cart.js' | asset_url }} " defer="defer"></script> <div class="cart-overlay"> </div> <cart-items class="close-drawer {% if cart == empty %} está vazio {% endif %} "data-open-cart-with-url= {{section.settings.open_with_url}} > {% include "icon-close" %} <div class="title-wrapper-with-link"> <h2 class="title title--primary"> {{ 'sections.cart.title' | t }} </h2> {{ routes.all_products_collection_url }} {{ 'general.continue_shopping' | t }} </a> </div> <div class="cart__warnings"> <h2 class="cart__empty-text"> {{ 'sections.cart.empty' | t }} </h2> {{ routes.all_products_collection_url }} {{ 'general.continue_shopping' | t }} </a> {%- if shop.customer_accounts_enabled and customer == nil -%} <h2 class="cart__login-title"> {{ 'sections.cart.login.title' | t }} </h2> <p class="cart__login-paragraph"> {{ 'sections.cart.login.paragraph_html' | t: link: routes.account_login_url }} </p> {%- endif -%} </div> <form action=" {{ routes.cart_url }} " class="cart__contents critic-hidden" method="post" id="cart"> <div class="cart__items" id="cart-drawer" data-id=" {{ section.id }} "> <div class="js-contents"> {%- if cart != empty -%} <table class="cart-items"> <corpo> {%- for item in cart.items -%} <tr class="cart-item" id="CartItem- {{ item.index | plus: 1 }} "> <td class="cart-item__details"> <div class="cart-item__media"> {% if item.image %} {% comment %} Deixe um espaço vazio devido a uma exibição CSS vazia: nenhuma regra {% endcomment %} {{ item.url }} </a> <div class="cart-item__image-container gradiente global-media-settings"> <img src=" {{ item.image | image_url: width: 300 }} " class="carrinho-item__imagem" alt=" {{ item.image.alt | escape }} " carregando = "preguiçoso" largura = "150" height=" {{ 150 | divided_by: item.image.aspect_ratio | ceil }} " > </div> {% endif %} </div> {%- if section.settings.show_vendor -%} <p class="caption-with-letter-spacing"> {{ item.product.vendor }} </p> {%- endif -%} </td> <td class="cart-item__totals direito médio-esconder grande-para cima"> <div class="loading-overlay oculto"> <div class="loading-overlay__spinner"> <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> </svg> </div> </div> <div class="cart-item__price-wrapper"> {%- if item.original_line_price != item.final_line_price -%} <dl class="cart-item__discounted-prices"> <dt class="visualmente oculto"> {{ 'products.product.price.regular_price' | t }} </dt> <dd> <s class="cart-item__old-price preço preço--end"> {{ item.original_line_price | money }} </s> </dd> <dt class="visualmente oculto"> {{ 'products.product.price.sale_price' | t }} </dt> <dd class="preço preço--fim"> {{ item.final_line_price | money }} </dd> </dl> {%- else -%} <span class="preço preço--fim"> {{ item.original_line_price | money }} </span> {%- endif -%} {%- if item.variant.available and item.unit_price_measurement -%} <div class="legenda do preço unitário"> <span class="visually-hidden"> {{ 'products.product.price.unit_price' | t }} </span> {{ item.variant.unit_price | money }} <span aria-hidden="true">/</span> <span class="visually-hidden"> {{ 'accessibility.unit_price_separator' | t }} </span> {%- if item.variant.unit_price_measurement.reference_value != 1 -%} {{- item.variant.unit_price_measurement.reference_value -}} {%- endif -%} {{ item.variant.unit_price_measurement.reference_unit }} </div> {%- endif -%} </div> </td> <td class="cart-item__totals right small-hide"> <div class="cart-item__quantity"> <div class="cart-item__quantity-wrapper"> <label class="visually-hidden" for="Quantidade- {{ item.index | plus: 1 }} "> {{ 'products.product.quantity.label' | t }} </label> <quantidade-input class="quantidade"> <button class="quantity__button no-js-hidden" name="menos" type="button"> <span class="visually-hidden"> {{ 'products.product.quantity.decrease' | t: product: item.product.title | escape }} </span> {% render 'icon-minus' %} </button> <input class="quantidade__input" tipo = "número" nome="atualizações[]" valor=" {{ item.quantity }} " min="0" aria-label=" {{ 'products.product.quantity.input_label' | t: product: item.product.title | escape }} " id="Quantidade- {{ item.index | plus: 1 }} " índice de dados = " {{ item.index | plus: 1 }} "> <button class="quantity__button no-js-hidden" name="plus" type="button"> <span class="visually-hidden"> {{ 'products.product.quantity.increase' | t: product: item.product.title | escape }} </span> {% render 'icon-plus' %} </button> </quantidade-entrada> <cart-remove-button id="Remover- {{ item.index | plus: 1 }} "data-index=" {{ item.index | plus: 1 }} "> {{ item.url_to_remove }} {% render 'icon-remove' %} </a> </cart-remove-button> </div> <div class="cart-item__error" id="Line-item-error- {{ item.index | plus: 1 }} " role="alert"> <small class="cart-item__error-text"></small> <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-error" viewBox="0 0 13 13"> <circle cx="6.5" cy="6.50049" r="5.5" acidente vascular cerebral="branco" acidente vascular cerebral-width="2"/> <circle cx="6.5" cy="6.5" r="5.5" fill="#EB001B" acidente vascular cerebral="#EB001B" acidente vascular cerebral-width="0.7"/> <caminho d = "M5.87413 3.52832L5.97439 7.57216H7.02713L7.12739 3.52832H5.87413ZM6.50076 9.66091C6.88091 9.66091 7.18169 9.37267 7.18 169 9.00504C7.18169 8.63742 6.88091 8.34917 6.50076 8.34917C6.12061 8.34917 5.81982 8.63742 5.81982 9.00504C5 .81982 9,37267 6,12061 9,66091 6,50076 9,66091Z" fill="branco"/> <caminho d = "M5.87413 3.17832H5.51535L5.52424 3.537L5.6245 7.58083L5.63296 7.92216H5.97439H7.02713H7.36856L7.37702 7.58083L7.47728 3.537L7.48617 3.17832H7.12739H5.87413ZM6.50076 10.0109C7 0,06121 10,0109 7,5317 9,57872 7,5317 9,00504C7,5317 8,43137 7,06121 7,99918 6,50076 7,99918C5,94031 7,99918 5,46982 8,431 37 5,46982 9,00504C5,46982 9,57872 5,94031 10,0109 6,50076 10,0109Z" fill="branco" acidente vascular cerebral="#EB001B" largura de curso="0,7 "/> </svg> </div> </div> <div class="loading-overlay oculto"> <div class="loading-overlay__spinner"> <svg aria-hidden="true" focusable="false" role="presentation" class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"> <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> </svg> </div> </div> <div class="cart-item__price-wrapper"> {%- if item.original_line_price != item.final_line_price -%} <dl class="cart-item__discounted-prices"> <dt class="visualmente oculto"> {{ 'products.product.price.regular_price' | t }} </dt> <dd> <s class="cart-item__old-price preço preço--end"> {{ item.original_line_price | money }} </s> </dd> <dt class="visualmente oculto"> {{ 'products.product.price.sale_price' | t }} </dt> <dd class="preço preço--fim"> {{ item.final_line_price | money }} </dd> </dl> {%- else -%} <span class="preço preço--fim"> {{ item.original_line_price | money }} </span> {%- endif -%} {%- if item.variant.available and item.unit_price_measurement -%} <div class="legenda do preço unitário"> <span class="visually-hidden"> {{ 'products.product.price.unit_price' | t }} </span> {{ item.variant.unit_price | money }} <span aria-hidden="true">/</span> <span class="visually-hidden"> {{ 'accessibility.unit_price_separator' | t }} </span> {%- if item.variant.unit_price_measurement.reference_value != 1 -%} {{- item.variant.unit_price_measurement.reference_value -}} {%- endif -%} {{ item.variant.unit_price_measurement.reference_unit }} </div> {%- endif -%} </div> </td> </tr> <tr> <td colspan="2" style="padding-top: 1rem"> {{ item.url }} {{ item.product.title | escape }} </a> <div class="preço-produto"> {%- if item.original_price != item.final_price -%} <div class="cart-item__discounted-prices"> <span class="visualmente oculto"> {{ 'products.product.price.regular_price' | t }} </span> <s class="cart-item__old-price product-option"> {{- item.original_price | money -}} </s> <span class="visualmente oculto"> {{ 'products.product.price.sale_price' | t }} </span> <strong class="cart-item__final-price product-option"> {{ item.final_price | money }} </strong> </div> {%- else -%} <div class="produto-opção"> {{ item.original_price | money }} </div> {%- endif -%} </div> {%- if item.product.has_only_default_variant == false or item.properties.size != 0 or item.selling_plan_allocation != nil -%} {%- if item.product.has_only_default_variant == false -%} {%- for option in item.options_with_values -%} <div class="produto-opção"> <dt> {{ option.name }} : </dt> <dd> {{ option.value }} </dd> </div> {%- endfor -%} {%- endif -%} {%- for property in item.properties -%} {%- assign property_first_char = property.first | slice: 0 -%} {%- if property.last != blank and property_first_char != '_' -%} <div class="produto-opção"> <dt> {{ property.first }} : </dt> <dd> {%- if property.last contains '/uploads/' -%} {{ property.last }} {{ property.last | split: '/' | last }} </a> {%- else -%} {{ property.last }} {%- endif -%} </dd> </div> {%- endif -%} {%- endfor -%} <p class="product-option"> {{ item.selling_plan_allocation.selling_plan.name }} </p> {%- endif -%} <ul class="discounts list-unstyled" role="list" aria-label=" {{ 'customer.order.discount' | t }} "> {%- for discount in item.discounts -%} <li class="descontos__desconto"> {%- render 'icon-discount' -%} {{ discount.title }} </li> {%- endfor -%} </ul> </td> </tr> {%- endfor -%} </tbody> </tabela> {%- endif -%} <div class="cart__footer"> {%- if section.settings.show_cart_note -%} <cart-note class="cart__note campo"> <label for="Cart-note"> {{ 'sections.cart.note' | t }} </label> <textarea class="text-area field__input" name="note" form="cart" id="Cart-note" placeholder=" {{ 'sections.cart.note' | t }} "> {{ cart.note }} </textarea> </cart-note> {%- endif -%} <div class="cart__blocks"> <div class="js-contents" {{ block.shopify_attributes }} > <div class="totais"> <h3 class="totals__subtotal"> {{ 'sections.cart.subtotal' | t }} </h3> <p class="totals__subtotal-value"> {{ cart.total_price | money_with_currency }} </p> </div> <div> {%- if cart.cart_level_discount_applications.size > 0 -%} <ul class="discounts list-unstyled" role="list" aria-label=" {{ 'customer.order.discount' | t }} "> {%- for discount in cart.cart_level_discount_applications -%} <li class="discounts__discount descontos__discount--position"> {%- render 'icon-discount' -%} {{ discount.title }} (- {{ discount.total_allocated_amount | money }} ) </li> {%- endfor -%} </ul> {%- endif -%} </div> <small class="tax-note caption-large rte"> {%- if cart.taxes_included and shop.shipping_policy.body != blank -%} {{ 'sections.cart.taxes_included_and_shipping_policy_html' | t: link: shop.shipping_policy.url }} {%- elsif cart.taxes_included -%} {{ 'sections.cart.taxes_included_but_shipping_at_checkout' | t }} {%- elsif shop.shipping_policy.body != blank -%} {{ 'sections.cart.taxes_and_shipping_policy_at_checkout_html' | t: link: shop.shipping_policy.url }} {%- else -%} {{ 'sections.cart.taxes_and_shipping_at_checkout' | t }} {%- endif -%} </small> </div> <div class="cart__ctas" {{ block.shopify_attributes }} > <noscript> <button type="submit" class="cart__update-button button button--secondary" form="cart"> {{ 'sections.cart.update' | t }} </button> </noscript> <button type="submit" id="checkout" class="cart__checkout-button button" name="checkout" {% if cart == empty %} desabilitado {% endif %} form="cart"> {{ 'sections.cart.checkout' | t }} </button> </div> {%- if additional_checkout_buttons -%} <div class="cart__dynamic-checkout-buttons adicionais-checkout-buttons"> {{ content_for_additional_checkout_buttons }} </div> {%- endif -%} <div id="cart-errors"></div> </div> </div> </div> </div> <p class="visually-hidden" id="cart-live-region-text" aria-live="polite" role="status"></p> <p class="visually-hidden" id="shopping-cart-line-item-status" aria-live="polite" aria-hidden="true" role="status"> {{ 'accessibility.loading' | t }} </p> </form> <cart-recommendations class="product-recommendations" data-products=" {{ section.settings.number_of_products }} "> {% if recommendations.performed and recommendations.products_count > 0 %} <h2 class="product-recommendations__heading"> {{ section.settings.heading | escape }} </h2> <componente deslizante> <ul class="cart-slider" id="Slider- {{ section.id }} " role="list"> {% for recommendation in recommendations.products %} <li id="Slide- {{ section.id }} "> {% if section.settings.old_version %} {% render 'product-card', product_card_product: recommendation, media_size: section.settings.image_ratio, show_secondary_image: section.settings.show_secondary_image, add_image_padding: section.settings.add_image_padding, show_vendor: section.settings.show_vendor, show_image_outline: section.settings.show_image_outline, show_rating: section.settings.show_rating %} {% else %} {% render "card-product", card_product: recommendation, media_aspect_ratio: seção.settings.image_ratio, show_vendor: seção.settings.show_vendor, show_rating: seção.settings.show_rating %} {% endif %} </li> {% endfor %} </ul> {% endif %} {% if recommendations.products_count > 2 %} <div class="botões deslizantes no-js-hidden"> <button type="button" class="slider-button slider-button--prev" name="anterior" aria-label=" {{ 'general.slider.previous_slide' | t }} " aria-controls="Slider - {{ section.id }} "> {% render 'icon-caret' %} </button> <div class="slider-counter caption"> <span class="slider-counter--current">1</span> <span aria-hidden="true"> / </span> <span class="visually-hidden"> {{ 'general.slider.of' | t }} </span> <span class="slider-counter--total"> {{ recommendations.products_count }} </span> </div> <button type="button" class="slider-button slider-button--next" name="next" aria-label=" {{ 'general.slider.next_slide' | t }} " aria-controls="Slider - {{ section.id }} "> {% render 'icon-caret' %} </button> </div> {% endif %} </slider-component> </cart-recommendations> </cart-items> {% javascript %} classe CartNote estende HTMLElement { construtor() { super(); this.addEventListener('mudança', debounce((evento) => { const body = JSON.stringify({nota: event.target.value }); fetch(`${routes.cart_update_url}`, {...fetchConfig(), ...{ corpo }} ); }, 300)) } } customElements.define('nota do carrinho', CartNote); {% endjavascript %} <roteiro> document.addEventListener('DOMContentLoaded', function() { função éIE() { const ua = window.navigator.userAgent; const msie = ua.indexOf('MSIE '); const tridente = ua.indexOf('Trident/'); return (msie > 0 || tridente > 0); } se (!isIE()) retornar; const cartSubmitInput = document.createElement('input'); cartSubmitInput.setAttribute('nome', 'checkout'); cartSubmitInput.setAttribute('tipo', 'oculto'); document.querySelector('#cart').appendChild(cartSubmitInput); document.querySelector('#checkout').addEventListener('click', function(event) { document.querySelector('#cart').submit(); }); }); </script> <estilo> .cart-overlay { posição: fixa; Mostrar nenhum; fundo: transparente; largura: 100%; altura: 100%; superior: 0; esquerda: 0; índice z: 5; } .show-sobreposição { display: bloco !importante; } itens do carrinho { posição: fixa; altura: 100%; largura: 100%; largura máxima: 40rem; plano de fundo: {{section.settings.background}} ; índice z: 10; direita: 0; preenchimento: 3rem; estouro-y: rolar; transição: direita 0,7s cúbico-bezier(0,94,0,28,1,-0,08); } itens do carrinho .icon-close { posição: absoluta; altura: 2rem; largura: 2rem; direita: 3rem; } itens do carrinho .icon-close:hover { traço: rgba(var(--color-foreground),.75); largura do traço: 1px; } .carrinho__contents{ margem: automático; largura: 100%; } .cart-item__price-wrapper .price--end { alinhamento de texto: esquerda; } itens do carrinho .item do carrinho { exibição: flexível; } itens do carrinho .cart-item__media { largura: 13rem; } .cart-item carrinho-remove-button{ margem: 0 !importante; altura: não definido! Importante; } botão de remoção do carrinho svg.icon-remove { altura: 2,5rem; largura: 2,5rem; } itens do carrinho .totals { exibição: flexível; alinhar itens: centro; justificar-conteúdo: espaço entre; } itens do carrinho .quantidade { largura: 8rem; altura mínima: 2rem; altura: 3,5rem; } entrada de quantidade .quantity__button { largura: 2rem; } .Carrinho Vazio { exibição: nenhum !importante; } .fechar gaveta { direita: -60rem; } itens do carrinho .cart__footer { direção flexível: coluna; margem superior: 2rem; } itens do carrinho .title-wrapper-com-link { margem inferior: 0; } itens do carrinho .cart__footer>*+* { margem superior: 4rem; margem esquerda: 0; } itens do carrinho .itens do carrinho { layout da tabela: fixo; } .cart__footer > * { largura: 100% } .cart-items .cart-item__totals { alinhamento de texto: esquerda; largura: 100%; } .cart-item .cart-item__quantity, .cart-items .cart-items__heading--wide { preenchimento à esquerda: 0! Importante; } .is-empty cart-recomendations { exibição: nenhum !importante; } componente deslizante de recomendações de carrinho { largura: 100%; } .cart-slider { posição: relativa; exibição: flexível; largura: 100%; flex-wrap: herdar; estouro-x: automático; scroll-snap-type: x obrigatório; comportamento de rolagem: suave; rolagem-preenchimento-esquerda: 1,5rem; -webkit-overflow-scrolling: toque; margem inferior: 1rem; preenchimento-in-line-start: 0; estilo de lista: nenhum; } .cart-slider li { largura mínima: 50% } .cart-slider li:not(:primeiro-filho) { margem esquerda: 1rem } .cart-slider { cor da barra de rolagem: rgb(var(--color-foreground)) rgba(var(--color-foreground), 0,04); -ms-estilo overflow: nenhum; largura da barra de rolagem: nenhuma; } .cart-slider::-webkit-scrollbar { altura: 0,4rem; largura: 0,4rem; Mostrar nenhum; } itens do carrinho .cart__warnings { posição: relativa; margem: automático; topo: 50%; esquerda: 50%; transformar: traduzir(-50%, -50%); } </estilo> {% schema %} { "name": "Gaveta do carrinho", "configurações": [ { "tipo": "caixa de seleção", "id": "show_vendor", "padrão": falso, "label": "t:sections.main-cart-items.settings.show_vendor.label" }, { "tipo": "caixa de seleção", "id": "show_cart_note", "padrão": falso, "label": "t:sections.main-cart-footer.settings.show_cart_note.label" }, { "tipo": "caixa de seleção", "id": "abrir_com_url", "padrão": falso, "label": "Abrir gaveta com URL do carrinho", "info": "A gaveta do carrinho abre sempre que a URL termina com /carrinho" }, { "tipo": "cor", "id": "plano de fundo", "padrão": "#F27272", "label": "Cor de fundo da gaveta" }, { "tipo": "cabeçalho", "content": "Recomendação de produto" }, { "tipo": "parágrafo", "content": "t:sections.product-recommendations.settings.paragraph__1.content" }, { "tipo": "texto", "id": "título", "default": "Você também pode gostar", "label": "t:sections.product-recommendations.settings.heading.label" }, { "tipo": "intervalo", "id": "número_de_produtos", "min": 2, "máximo": 10, "passo 1, "padrão": 4, "label": "Máximo de produtos para mostrar" }, { "tipo": "cabeçalho", "content": "t:sections.product-recommendations.settings.header__2.content" }, { "tipo": "caixa de seleção", "id": "versão_antiga", "padrão": falso, "label": "Verifique se você possui a versão Dawn 2.5 e inferior" }, { "tipo": "selecionar", "id": "proporção_imagem", "opções": [ { "valor": "adaptar", "label": "t:sections.product-recommendations.settings.image_ratio.options__1.label" }, { "valor": "retrato", "label": "t:sections.product-recommendations.settings.image_ratio.options__2.label" }, { "valor": "quadrado", "label": "t:sections.product-recommendations.settings.image_ratio.options__3.label" } ], "padrão": "adaptar", "label": "t:sections.product-recommendations.settings.image_ratio.label" }, { "tipo": "caixa de seleção", "id": "show_rating", "padrão": falso, "label": "t:sections.product-recommendations.settings.show_rating.label", "info": "t:sections.product-recommendations.settings.show_rating.info" } ] } {% endschema %} |
3. Na mesma pasta, Seções, encontre o header.liquid. Encontre a palavra "cart_url". Substitua o código destacado (consulte a imagem abaixo) pelo código abaixo.

| <cart-toggle class="header__icon header__icon--cart link focus-inset" id="cart-icon-bubble"> {%- liquid if cart == empty render 'icon-cart-empty' else render 'icon-cart' endif -%} <span class="visually-hidden"> {{ 'templates.cart.cart' | t }} </span> {%- if cart != empty -%} <div class="cart-count-bubble"> {%- if cart.item_count < 100 -%} <span aria-hidden="true"> {{ cart.item_count }} </span> {%- endif -%} <span class="visually-hidden"> {{ 'sections.header.cart_count' | t: count: cart.item_count }} </span> </div> {%- endif -%} </cart-toggle> |
4. Na mesma área, você pode ver a “notificação de carrinho”. Consulte a imagem abaixo.

5. Vá para a pasta Ativos, abra product-form.js e substitua o código pelo código abaixo.
| if (!customElements.get('formulário-produto')) { customElements.define('formulário-produto', class ProductForm estende HTMLElement { construtor() { super(); este.formulário = este.querySelector('formulário'); this.form.querySelector('[nome=id]').disabled = false; this.form.addEventListener('enviar', this.onSubmitHandler.bind(this)); this.cartItems = document.querySelector('cart-items'); this.submitButton = this.querySelector('[type="submit"]'); } onSubmitHandler(evt) { evt.preventDefault(); if (this.submitButton.getAttribute('aria-disabled') === 'true') return; this.handleErrorMessage(); this.submitButton.setAttribute('aria-disabled', true); this.submitButton.classList.add('carregando'); this.querySelector('.loading-overlay__spinner').classList.remove('hidden'); constconfig = fetchConfig('javascript'); config.headers['X-Requested-With'] = 'XMLHttpRequest'; exclua config.headers['Content-Type']; const formData = new FormData(this.form); formData.append('seções', this.cartItems.getSectionsToRender().map((seção) => seção.id)); formData.append('sections_url', window.location.pathname); config.body=formData; buscar(`${routes.cart_add_url}`,configuração) .then((resposta) => resposta.json()) .then((resposta) => { if (resposta.status) { this.handleErrorMessage(response.descrição); const soldOutMessage = this.submitButton.querySelector('.mensagem esgotada'); if (!soldOutMessage) retornar; this.submitButton.setAttribute('aria-disabled', true); this.submitButton.querySelector('span').classList.add('oculto'); soldOutMessage.classList.remove('oculto'); este.erro = verdadeiro; retornar; } este.erro = falso; const quickAddModal = this.closest('quick-add-modal'); if (quickAddModal) { document.body.addEventListener('modalClosed', () => { setTimeout(() => { this.cartItems.renderContents(response) }); }, { uma vez: verdadeiro }); quickAddModal.hide(true); } outro { this.cartItems.renderContents(resposta); } this.cartItems.viewDrawer(); }) .catch((e) => { console.erro(e); }) .finalmente(() => { this.submitButton.classList.remove('carregando'); if (!this.error) this.submitButton.removeAttribute('aria-disabled'); this.querySelector('.loading-overlay__spinner').classList.add('hidden'); }); } handleErrorMessage(errorMessage = false) { this.errorMessageWrapper = this.errorMessageWrapper || this.querySelector('.product-form__error-message-wrapper'); if (!this.errorMessageWrapper) retornar; esta.errorMessage = esta.errorMessage || this.errorMessageWrapper.querySelector('.product-form__error-message'); this.errorMessageWrapper.toggleAttribute('oculto', !errorMessage); if (mensagem de erro) { this.errorMessage.textContent = mensagem de erro; } } }); } |
6. Ainda na mesma pasta, Asset, encontre cart.js e substitua o código pelo código abaixo.
| class CartRemoveButton estende HTMLElement { construtor() { super(); this.addEventListener('clique', (evento) => { event.preventDefault(); this.closest('itens do carrinho').updateQuantity(this.dataset.index, 0); }); } } customElements.define('cart-remove-button', CartRemoveButton); class CartItems estende HTMLElement { construtor() { super(); this.closeBtn = this.querySelector('.icon-close'); this.openBtn = document.querySelector('cart-toggle'); this.overlay = document.querySelector('.cart-overlay'); this.closeBtn.addEventListener('clique', this.viewDrawer.bind(this)); this.openBtn.addEventListener('clique', this.viewDrawer.bind(this)); this.overlay.addEventListener('clique', this.overlayListener.bind(this)) this.lineItemStatusElement = document.getElementById('shopping-cart-line-item-status'); this.currentItemCount = Array.from(this.querySelectorAll('[name="updates[]"]')) .reduce((total, quantidadeInput) => total + parseInt(quantityInput.value), 0); this.debouncedOnChange = debounce((evento) => { this.onChange(evento); }, 300); this.addEventListener('alterar', this.debouncedOnChange.bind(this)); this.cartFooter = document.getElementById('main-cart-footer'); this.parsedId; this.productRecommendation = this.querySelector('recomendações de carrinho'); this.openWithUrl = this.dataset.openCartWithUrl; if(this.openWithUrl == 'verdadeiro') { if(location.href.includes('/carrinho')) { this.viewDrawer(); } } } overlayListener() { if(this.overlay.classList.contains('show-overlay')) { this.viewDrawer(); } } getProductRecommendation(parsedId) { this.parsedId = analisadoId; const númeroOfProducts = this.productRecommendation.dataset.products; const url = `/recomendações/produtos?section_id=cart-drawer&product_id=${this.parsedId}&limit=${numberOfProducts}`; buscar(url) .then(resposta => resposta.texto()) .então(texto => { const html = document.createElement('div'); html.innerHTML = texto; recomendações const = html.querySelector('recomendações de carrinho'); if (recomendações && recomendações.innerHTML.trim().length) { this.productRecommendation.innerHTML = recomendações.innerHTML; } if (html.querySelector('.grid__item')) { this.productRecommendation.classList.add('recomendações de produto--carregadas'); } }) .catch(e => { console.erro(e); }); } viewDrawer() { this.classList.toggle('fechar gaveta'); this.overlay.classList.toggle('show-overlay'); } onChange(evento) { this.updateQuantity(event.target.dataset.index, event.target.value, document.activeElement.getAttribute('nome')); } getSectionsToRender() { retornar [ { id: 'gaveta-carrinho', seção: document.getElementById('cart-drawer').dataset.id, seletor: '.js-contents', }, { id: 'carrinho-ícone-bolha', seção: 'carrinho-ícone-bolha', seletor: '.shopify-section' }, { id: 'cart-live-region-text', seção: 'cart-live-region-text', seletor: '.shopify-section' } ]; } renderContents(parsedState) { this.parsedId = parsedState.product_id; this.getProductRecommendation(parsedState.product_id) this.classList.toggle('está vazio', parsedState.item_count === 0); if (this.cartFooter) this.cartFooter.classList.toggle('está vazio', parsedState.item_count === 0); this.getSectionsToRender().forEach((seção => { const elementoToReplace = document.getElementById(seção.id).querySelector(seção.selector) || document.getElementById(seção.id); elementToReplace.innerHTML = this.getSectionInnerHTML(parsedState.sections[seção.seção], seção.selector); })); this.updateLiveRegions(1, parsedState.item_count); const lineItem = document.getElementById(`CartItem-1`); if (lineItem && lineItem.querySelector(`[name="${name}"]`)) lineItem.querySelector(`[name="${name}"]`).focus(); this.disableLoading(); } updateQuantity(linha, quantidade, nome) { this.enableLoading(linha); const corpo = JSON.stringify({ linha, quantidade, seções: this.getSectionsToRender().map((seção) => seção.seção), seções_url: window.location.pathname }); fetch(`${routes.cart_change_url}`, {...fetchConfig(), ...{ corpo }} ) .then((resposta) => { retornar resposta.text(); }) .then((estado) => { const parsedState = JSON.parse(estado); this.parsedId = parsedState.product_id; this.classList.toggle('está vazio', parsedState.item_count === 0); if (this.cartFooter) this.cartFooter.classList.toggle('está vazio', parsedState.item_count === 0); this.getProductRecommendation(parsedState.items[0].product_id); this.getSectionsToRender().forEach((seção => { const elementoToReplace = document.getElementById(seção.id).querySelector(seção.selector) || document.getElementById(seção.id); elementToReplace.innerHTML = this.getSectionInnerHTML(parsedState.sections[seção.seção], seção.selector); })); this.updateLiveRegions(linha,parsedState.item_count); const lineItem = document.getElementById(`CartItem-${line}`); if (lineItem && lineItem.querySelector(`[name="${name}"]`)) lineItem.querySelector(`[name="${name}"]`).focus(); this.disableLoading(); }).catch(() => { this.querySelectorAll('.loading-overlay').forEach((overlay) => overlay.classList.add('hidden')); document.getElementById('erros do carrinho').textContent = window.cartStrings.error; this.disableLoading(); }); } updateLiveRegions(linha, itemCount) { if (this.currentItemCount === itemCount) { document.getElementById(`Line-item-error-${line}`) .querySelector('.cart-item__error-text') .innerHTML = window.cartStrings.quantityError.replace( '[quantidade]', document.getElementById(`Quantidade-${linha}`).valor ); } this.currentItemCount = itemCount; this.lineItemStatusElement.setAttribute('aria-hidden', true); const cartStatus = document.getElementById('cart-live-region-text'); cartStatus.setAttribute('aria-oculto', false); setTimeout(() => { cartStatus.setAttribute('aria-hidden', true); }, 1000); } getSectionInnerHTML(html, seletor) { retornar novo DOMParser() .parseFromString(html, 'texto/html') .querySelector(seletor).innerHTML; } enableLoading(linha) { document.getElementById('cart-drawer').classList.add('cart__items--disabled'); this.querySelectorAll(`#CartItem-${line} .loading-overlay`).forEach((overlay) => overlay.classList.remove('hidden')); document.activeElement.blur(); this.lineItemStatusElement.setAttribute('aria-hidden', false); } desativarLoading() { document.getElementById('cart-drawer').classList.remove('cart__items--disabled'); } } customElements.define('itens do carrinho', CartItems); |
7. Vá para a pasta de layout e abra theme.liquid. Encontre a "barra de anúncio" e cole o código abaixo antes dela.
| {% section ' shopify-ajax-cart-drawer ' %} |
8. Quase pronto, só falta limpar. Precisamos excluir os arquivos da seção a seguir para remover os erros. Abra a pasta Seção e encontre "main-cart-items.liquid", abra o arquivo e clique em "excluir arquivo". O mesmo acontece com "main-cart-footer.liquid".
É isso. (",)
2 comentários
Hi @Sanjay,
Line item properties will need to be added to the code. Regarding the selling plan, the code is derive from Dawn cart, if the original code of Dawn supports it then yes.
IS this code support extra line items property and selling plan option ?