Documentación para Diseñadores

Crea tus propias plantillas en Tienda Nube

Carrito de compras rápidas

Esta funcionalidad permite agregar productos al carrito de compras de manera asincrónica (sin necesidad de redireccionar al usuario a la página del carrito).

1. Configuración

Agregar las siguientes líneas en el archivo /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.

Agregar esta línea en el archivo /config/defaults.txt :

ajax_cart = 0

Agregar estas líneas en el archivo /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 del theme (/layouts/layout.tpl)

Modificar la inclusión del sniplet del carrito, reemplazando este código:

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

Por el siguiente:

<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 la inclusión del plugin livequery del condicional {% if template= 'cart' %} e incluirlo con el resto de los plugins, para que esté disponible en todo el sitio:

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

Adicionar el siguiente script de javascript dentro de unos 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 %}

Reemplazar el selector de jQuery en la función changeVariant:

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

por el siguiente:

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

Modificar los selectores de jQuery con ID (#) por selectores con clases (.):

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

Así debe quedar la función:

$(".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 del carrito

Agregar el archivo /snipplets/cart_ajax.tpl (ejemplo del código en el theme 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>

En el archivo /snipplets/shipping_cost_calculator.tpl reemplazar los ids por clases.

Debería quedar de la siguiente manera:

{% 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 %}

En el archivo /snipplets/shipping_options.tpl eliminar el siguiente condicional:

{% if not variant %}

4. Templates

En el archivo /templates/product.tpl agregar la clase js-addtocart de la siguiente manera:

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

En el archivo /snipplets/quick-shop.tpl agregar la clase js-addtocart de la siguiente manera:

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

5. CSS

Adicionar el CSS correspondiente al theme. Ejemplo del código en 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 el SASS correspondiente al theme. Ejemplo del código en 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. Activación

Una vez incluida la funcionalidad, es necesario activarla desde el administrador de la tienda en la página Personalizar tu diseño, dentro de la opción Carrito de compras.

Sin compromiso de compra ni estadía mínima. No hay costo de registro o cancelación.