Documentação para Web Designers

Crie seus próprios layouts na Nuvem Shop

Carrinho de compras rápidas

Esta funcionalidade permite adicionar produtos ao carrinho de compras de maneira assincrônica (sem necessidade de redirecionar o usuário para a página do carrinho).

1. Configuração

Adicionar as seguintes linhas ao arquivo /config/settings.txt :

Carrito de compras
 checkbox
   name = ajax_cart
   description = Carrito de compras rápidas. Tus clientes pueden agregar y ver los productos que van a comprar sin necesidad de ir a otra página, ya que la información está siempre visible.

Adicionar esta linha ao arquivo /config/defaults.txt :

ajax_cart = 0

Adicionar as seguintes linhas ao arquivo /config/translations.txt :

es "Editar carrito"
pt "Editar carrinho"
en "Edit my cart"

es "Carrito de compras rápidas. Tus clientes pueden agregar y ver los productos que van a comprar sin necesidad de ir a otra página, ya que la información está siempre visible."
pt "Carrinho de compra rápida. Seus clientes podem escolher produtos e conferir o que vão comprar sem a necessidade abrir outra página, já que a informação está sempre visível."
en "AJAX Cart"

2. Layout do design (/layouts/layout.tpl)

Modificar a inclusão de sniplet do carrinho, substituindo este código:

<div class="cart-snipplet hidden-phone">
    {% if not store.is_catalog and template != 'cart' %}
        {% snipplet "cart.tpl" as "cart" %}
    {% endif %}

Pelo seguinte:

<div class="cart-snipplet {% if not settings.ajax_cart %}hidden-phone{% endif %}">
{% if not store.is_catalog and template != 'cart' %}
    {% if settings.ajax_cart %}
        {% snipplet "cart_ajax.tpl" as "cart" %}
    {% else %}
        {% snipplet "cart.tpl" as "cart" %}
    {% endif %}
{% endif %}

Eliminar a inclusão do plugin Livequery da condicional {% if template= 'cart' %} e adicioná-lo junto ao resto dos plugins para que esteja disponível em todo o site:

{{ 'js/jquery.livequery.min.js' | static_url | script_tag }}

Adicionar o seguinte script de Javascript dentro de uma das tags <script>:

{% if settings.ajax_cart %}
    $(document).on("click", ".js-addtocart", function(e) {
        if(!$(this).hasClass('contact')) {
            e.preventDefault();
            $prod_form = $(this).closest("form");
            LS.addToCart(
                $prod_form,
                '{{ "Agregar al carrito" | translate }}',
                '{{ "Agregando..." | translate }}',
                '{{ "No hay suficiente stock para agregar este producto al carrito." | translate }}' );
        }
    });

    $(document).on("click", ".js-toggleCart", function(e) {
        e.preventDefault();
        LS.toggleCart();
    });

    $('input.shipping-method:checked').livequery(function(){
        var shippingPrice = $(this).attr("data-price");
        LS.addToTotal(shippingPrice);
    });

    $(document).on( "click", "input.shipping-method", function() {
        var elem = $(this);
        var shippingPrice = elem.attr("data-price");
        elem.click(function() {
            LS.addToTotal(shippingPrice);
        });
    });

{% endif %}

Substituir o seletor de jQuery na função changeVariant:

function changeVariant(variant){
    $("#shipping-calculator-response").hide();
    …
}

Pelo seguinte:

function changeVariant(variant){
    $("#single-product .shipping-calculator-response").hide();  
    …
}

Modificar os seletores de jQuery com ID (#) pelos seletores com classes (.):

$("#calculate-shipping-button").click(function(e) {
    …
});

A função deve ficar assim:

$(".calculate-shipping-button").click(function(e) {
    e.preventDefault();
    LS.calculateShippingAjax(
        $(this).parent().find("input.shipping-zipcode").val(),
        '{{store.shipping_calculator_url | escape('js')}}',
        $(this).closest(".shipping-calculator") );
});

3. Sniplets do carrinho

Adicionar o arquivo /snipplets/cart_ajax.tpl (exemplo do código no tema Luxury):

<div id="ajax-cart" class="cart-summary">
    <a href="#" class="js-toggleCart">
      <span class="items">
        <span id="cart-amount">{{ "{1}" | translate(cart.items_count ) }}</span> 
        <small>x</small> 
        <span id="cart-total">{{ cart.total | money }}</span>
      </span>
      <span class="item-img"><i class="fa fa-shopping-cart"></i></span>
    </a>
</div>
<div id="ajax-cart-details" style="display: none;">
    <button type="button" class="button close-cart js-toggleCart secondary-button">
        <i class="fa fa-angle-left" aria-hidden="true"></i> 
        <span class="hidden-phone">{{ "Seguir comprando" | translate }}</span>
        <span class="visible-phone">{{ "Volver" | translate }}</span>
    </button>
    <h2 class="m-bottom">{{ "Resumen del carrito de compras" | translate }}</h2>
    <div class="overflow-none ajax-cart_titles p-half-top p-half-bottom">
      <div class="ajax-cart_titles_product-col p-half-left pull-left" style="width: 45%">
          <h5 class="ajax-cart_titles_header">{{ "Producto" | translate }}</h5>
        </div>
        <div class="ajax-cart_titles_subtotal-col text-right p-half-right pull-right" style="width: 45%">
          <h5 class="ajax-cart_titles_header">{{ "Subtotal" | translate }}</h5>
        </div>
    </div>
    <div class="ajax-cart">
      {% if cart.items %}
        {% for item in cart.items %}
        <div class="overflow-none ajax-cart-item">
          <div class="ajax-cart-item_image-col p-half-top p-half-bottom p-quarter-left p-quarter-right text-center ajax-cart-item_item-row">
            <img src="{{ item.featured_image | product_image_url('original') }}" class="ajax-cart-item_img full-width" />
          </div>
          <div class="ajax-cart-item_desc-col p-half-all ajax-cart-item_item-row full-width text-wrap">
            <a class="ajax-cart-item-link" href="{{ item.url }}">{{ item.name }}</a><br/>
                {{ item.unit_price | money }}<br/>
                x {{ item.quantity }}
          </div>
          <div class="ajax-cart-item_subtotal-col text-right p-half-all ajax-cart-item_item-row">
            {{ item.subtotal | money }}
          </div>
        </div>
        {% endfor %}
      {% endif %}
    </div>
    <div class="ajax-cart-total overflow-none p-half-top text-right">
      <h3 class="m-none p-quarter-right d-inline-block">{{ "Total" | translate }}:</h3>
      <h3 id="cart-table-total" class="m-none d-inline-block text-primary">{{ cart.total | money }}</h3>
    </div>
    <div id="ajax-cart-shipping">
        {% snipplet "shipping_cost_calculator.tpl" with shipping_calculator_show = settings.shipping_calculator_cart_page %}
    </div>
    <div id="ajax-cart-totalwshipping" class="total-price d-inline-block full-width text-right text-center-xs m-half-top"></div>
    <div class="full-width pull-left ajax-cart-bottom m-top">
        {% set cart_total = (settings.cart_minimum_value * 100) %}
        <div class="ajax-cart_edit-cart-container text-left pull-left text-center-xs">
            <a href="{{ store.cart_url }}" class="btn btn-link m-half-top m-bottom-xs p-left-none p-right-none">{{ 'Editar carrito' | translate }}</a>
        </div>
        <div class="pull-right ajax-cart_finish-buy-container" {{ cart.total < cart_total ? 'style="display:none"' }} id="ajax-cart-submit-div">
            <form action="{{ store.cart_url }}" method="post">
                <input class="button pull-right ajax-cart_finish-buy-btn" type="submit" name="go_to_checkout" value="{{ 'Iniciar Compra' | translate }}"/>
            </form>
        </div>
        <div class="clear-both p-half-top" {{ cart.total >= cart_total ? 'style="display:none"' }} id="ajax-cart-minumum-div">
            <div class="alert alert-warning" role="alert">
            <h4 class="text-center">{{ "El monto mínimo de compra (subtotal) es de" | translate }} {{ cart_total | money }}</h4>
            </div>
        </div>
        <input type="hidden" id="ajax-cart-minimum-value" value="{{ cart_total }}"/>
    </div>
</div>
<div id="ajax-cart-backdrop" class="js-toggleCart" style="display: none;"></div>

Substituir os IDs por classes no arquivo /snipplets/shipping_cost_calculator.tpl

Devem ficar da seguinte maneira:

{% if shipping_calculator_show %}
    <div class="shipping-calculator">
        <div class="shipping-calculator-form" {% if shipping_calculator_variant and not shipping_calculator_variant.available %}style="display: none;" {% endif %}>
            <div class="ssb">{{ "Ingrese aquí su código postal para calcular su costo de envío" | translate }}:</div>
            <input type="text" name="zipcode" value="{{ cart.shipping_zipcode }}" class="shipping-zipcode">
            {% if shipping_calculator_variant %}
                <input type="hidden" name="variant_id" id="shipping-variant-id" value="{{ shipping_calculator_variant.id }}">
            {% endif %}
            <button class="button calculate-shipping-button">{{ "Calcular costo de envío" | translate }}</button>
            <span class="loading" style="display: none;"><i class="fa fa-circle-o-notch fa-spin"></i></span>
            <span class='alert alert-error invalid-zipcode' style="display: none;">{{ "El código postal es inválido." | translate }}</span>
        </div>
        <div class="shipping-calculator-response" style="display: none;"></div>
    </div>
{% endif %}

Eliminar a seguinte condicional no arquivo /snipplets/shipping_options.tpl :

{% if not variant %}

4. Templates

Adicionar a classe js-addtocart ao arquivo /templates/product.tpl da seguinte maneira:

<input type="submit" class="button addToCart js-addtocart {{state}}" value="{{ texts[state] | translate }}" {% if state == 'nostock' %}disabled{% endif %} />

Adicionar a classe js-addtocart ao arquivo /snipplets/quick-shop.tpl da seguinte maneira:

<input type="submit" class="button addToCart js-addtocart {{ state }}" value="{{ texts[state] | translate }}" {% if state == 'nostock' %}disabled{% endif %}

5. CSS

Adicionar o CSS correspondente ao tema. Exemplo do código no Luxury:

#ajax-cart-details {
    position: fixed;
    top: 0;
    right: 0;
    width: 500px;
    height: 100%;
    z-index: 99999999;
    padding: 20px;
    border-left: 1px solid black;
    overflow-y: scroll;
    text-align: left;
}
#ajax-cart-details h2{
    font-size: 24px;
    line-height: initial;
}
@media (max-width: 480px){
    #ajax-cart-details {
        width: 90%;
    }
}
#ajax-cart-backdrop {
    background-color: rgba(0,0,0,0.8);
    position: fixed;
    top: 0;
    height: 120%;
    width:100%;
    left: 0;
    z-index: 999999;
}
.close-cart {
    margin: 0 0 20px 0;
    padding: 4px 10px 0 10px;
}
.close-cart:hover i {
    color: #fff;
}
table#cart-table {
    margin: 20px 0;
}
#ajax-cart-shipping {
    width: 100%;
    margin-top: 20px;
}
#ajax-cart-shipping .shipping-option {
    width: 100%;
}
#ajax-cart-shipping .shipping-calculator li input[type="radio"] + .shipping-option {
    border: 2px solid transparent;
}
#ajax-cart-shipping .shipping-calculator li input[type="radio"]:checked + .shipping-option {
    border: 2px solid red;
}
#ajax-cart-totalwshipping {
    font-weight: bold;
    font-size: 20pt;
    float: right;
}
#ajax-cart-shipping .shipping-calculator ul.shipping-list li {
    margin-bottom: 20px;
    clear: both;
    width: 100%;
}
#ajax-cart-shipping .shipping-calculator ul.shipping-list li:last-child{
    margin-bottom: 0;
}
#ajax-cart-shipping .shipping-calculator-form {
    margin-top: 0;
}
div.addToCartButton div.alert {
    margin-top: 20px;
}
.edit-cart {
    margin: 0 0 10px 0;
    text-align: left;
}
.ajax-cart-bottom{
    margin-bottom: 50px
}
.ajax-cart-shipping .shipping-option_image{
    margin-left: 0;
    width: 100px;
}
.ajax-cart-shipping .shipping-option_text{
    width: 60%;
}
.ajax-cart-bottom_edit-cart-link, 
.ajax-cart-bottom_start-order-btn { 
    width: 50% 
}

/****** PROPERTIES HELPERS ******/

/*CSS properties helpers minified, to unminify it you have to copy the code and paste it here http://unminify.com/, after that paste the unminified code here */

.text-danger{color:red}.border-box{box-sizing:border-box;}.c-pointer{cursor:pointer}.f-none{float:none!important}.d-none{display:none}.d-inline{display:inline}.d-block{display:block}.d-inline-block{display:inline-block}.p-relative{position:relative}.p-absolute{position:absolute}.p-fixed{position:fixed}.clear-both{clear:both}.opacity-80{opacity:.8}.opacity-50{opacity:.5}.full-height{height:100%}.full-width{width:100%}.z-index-above{z-index:999999}.m-top{margin-top:20px}.m-bottom{margin-bottom:20px}.m-right{margin-right:20px}.m-left{margin-left:20px}.m-all{margin:20px}.m-half-top{margin-top:10px}.m-half-bottom{margin-bottom:10px}.m-half-right{margin-right:10px}.m-half-left{margin-left:10px!important}.m-half-all{margin:10px}.m-quarter-top{margin-top:5px}.m-quarter-right{margin-right:5px}.m-quarter-bottom{margin-bottom:5px}.m-quarter-left{margin-left:5px}.m-none-left{margin-left:0!important}.m-quarter-all{margin:5px}.m-double-top{margin-top:40px}.m-double-right{margin-right:40px}.m-double-bottom{margin-bottom:40px}.m-auto{margin:auto}.m-none{margin:0!important}.m-none-bottom{margin-bottom:0}.m-none-top{margin-top:0!important}.m-center{margin:0 auto;position:relative;display:block}.p-double-top{padding-top:40px!important}.p-double-right{padding-right:40px!important}.p-double-bottom{padding-bottom:40px!important}.p-double-left{padding-left:40px!important}.p-top{padding-top:20px!important}.p-none-top{padding-top:0!important}.p-right{padding-right:20px!important}.p-right-none{padding-right:0!important}.p-left-none{padding-left:0!important}.p-bottom{padding-bottom:20px!important}.p-none-bottom{padding-bottom:0!important}.p-left{padding-left:20px!important}.p-all{padding:20px!important}.p-half-top{padding-top:10px!important}.p-half-right{padding-right:10px!important}.p-half-bottom{padding-bottom:10px!important}.p-half-left{padding-left:10px!important}.p-half-all{padding:10px!important}.p-quarter-top{padding-top:5px}.p-quarter-right{padding-right:5px}.p-quarter-bottom{padding-bottom:5px}.p-quarter-left{padding-left:5px}.p-quarter-all{padding:5px}.p-none{padding:0!important}.col-tight{padding-left:8px;padding-right:8px}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-wrap{-ms-word-break:break-all;word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto}.font-weight-normal{font-weight:400}.text-decoration-none{text-decoration:none}.text-line-through{text-decoration:line-through}.text-underline{text-decoration:underline}.font-italic{font-style:italic}.font-normal{font-weight:normal}.font-bold{font-weight:700}.line-height-inherit{line-height:inherit}.line-height-initial{line-height:initial}ul.list-style-none li{list-style:none}.mail-to a,.mail-to a:hover,.no-link,.no-link:focus,.no-link:hover{text-decoration:none}.border-radius-none{border-radius:0}.overflow-none{overflow:hidden}.overflow-y{overflow-y:auto}

/* Mobile Helpers */
@media (max-width: 767px) {
    .full-width-xs{width: 100%}.clear-both-xs{clear:both}.f-none-xs{float:none!important}.pull-left-xs{float: left!important;}.d-inline-block-xs{display:inline-block!important}.p-none-xs{padding:0!important}.p-left-none-xs{padding-left:0}.p-right-none-xs{padding-right:0}.p-half-left-xs{padding-left:10px!important}.p-quarter-left-xs{padding-left:5px}.p-quarter-right-xs{padding-right:5px}.p-right-xs{padding-right: 20px!important}.p-half-right-xs{padding-right:10px!important}.p-double-right-xs{padding-right:40px!important}.p-top-xs{padding-top:20px!important}.p-half-top-xs{padding-top:10px}.p-bottom-xs{padding-bottom:20px}.p-half-bottom-xs{padding-bottom:10px}.p-double-bottom-xs{padding-bottom:40px}.m-none-xs{margin:0!important}.m-bottom-xs{margin-bottom:20px}.m-half-bottom-xs{margin-bottom:10px}.m-quarter-bottom-xs{margin-bottom:5px!important}.m-top-xs{margin-top:20px}.m-half-top-xs{margin-top:10px}.m-quarter-top-xs{margin-top:5px}.m-none-top-xs{margin-top:0}.m-none-bottom-xs{margin-bottom:0;}.text-center-xs{text-align:center}.text-left-xs{text-align:left}.col-tight-xs{padding-left:8px;padding-right:8px}.drop-shadow-xs{-moz-box-shadow:0 0 3px #ccc;-webkit-box-shadow:0 0 3px #ccc;box-shadow:0 0 3px #ccc}.border-top-none-xs{border-top:0!important}.border-bottom-none-xs{border-bottom:0!important}.horizontal-container{overflow-x:scroll;width:100%;}.horizontal-container::-webkit-scrollbar{width:1px;height:0}.horizontal-container::-webkit-scrollbar-track{background:0 0;border-radius:10px}.horizontal-container::-webkit-scrollbar-thumb{border-radius:1px}.horizontal-container ul, .horizontal-products-scroller{white-space:nowrap}
}

6. SASS

Adicionar o SASS correspondente ao tema. Exemplo do código no Luxury:

#ajax-cart-details{
    background: $back; 
 }
.ajax-cart_titles, .ajax-cart-item:last-child { 
    font-family: $fonthead;
    border-top: 1px solid rgba($secondary, $opac2);
    border-bottom: 1px solid rgba($secondary, $opac2);
}
.ajax-cart_titles .ajax-cart_titles_header { 
    font-weight: normal; 
    text-transform: uppercase; 
    font-size: 12px; 
    letter-spacing: 1px 
}
.ajax-cart-item { 
    font-family: $fonthead; 
    border-bottom: 1px solid rgba($secondary, $opac2); 
    background: rgba(150, 150, 150, 0.06); 
}
.ajax-cart-item:last-child { 
    font-family: $fonthead; 
    border-top: none; 
    border-bottom: 2px solid rgba($secondary, $opac2) 
}
.ajax-cart-item_image-col {
    width:100px; 
    min-width: 35px;
}
.ajax-cart-item_subtotal-col { 
    width: 40%; 
}
.ajax-cart-item .ajax-cart-item_img { 
    max-height: 60px; 
    max-width: 60px; 
    object-fit: contain; 
}
.ajax-cart-item .ajax-cart-item-link { 
    color: $primary 
}
.ajax-cart-item { 
    display: table; 
}
.ajax-cart-item .ajax-cart-item_item-row {
    float: none;
    display: table-cell;
    vertical-align: top;
}
.ajax-cart-total { 
    font-family: $fonthead; 
}
.ajax-cart-total h3 { 
    font-size: 20px; 
}
.ajax-cart-shipping{
    border-top: 1px solid rgba($secondary, $opac2);
    border-bottom: 1px solid rgba($secondary, $opac2);
}

7. Ativação

Uma vez adicionada a funcionalidade, é preciso ativá-la através do painel de administração da loja, na opção Personalizar seu layout > Carrinho de Compras.