>

Julio 12

2018

Sin usar base de datos

Una de las cosas que más suele preocupar a los que estamos empezando en la programación web es cómo hacer un carro de la compra, sobre todo, si no tenemos acceso a una base de datos, o si no queremos tener que estar consultando la base de datos constantemente.

Hoy os presento este simple carro en JAVASCRIPT que se puede personalizar muy fácilmente.

El código JAVASCRIPT

Este código es la unión de varios códigos de las páginas que se enlazan en este documento. Podéis ampliar la información visitando a los enlaces.

//cart options
/**
* Carro de compra simple
* @param {any} sessionName nombre del carro para almacenar
* @param {any} items lista de elementos, necesita id, product, price, qty como minimo. Pero puedes almacenar todo lo que quieras
*/
function Cart(sessionName, items) {
if (sessionName !== undefined && sessionName !== null) { this.sessionName = sessionName; }
else { this.sessionName = 'carro'; }
if (items !== undefined && items !== null) { this.items = items; }
else {
if (sessionName !== undefined && sessionName !== null) {
try {
this.items = JSON.parse(localStorage[sessionName]);
} catch (e) {
this.items = [];
}
}
else { this.items = []; }
}

/**
* Agregar un item al carro
* @param {any} item Objeto con los datos del item. Minimo estas propiedades id, product, price, qty
* @param {any} itemImg objeto contenedor o identificador ej. #miproducto de la imagen para hacer volar la imagen hacia el carro
* @param {any} cart objeto contenedor del carro o identificador ej. #micarro
*/
Cart.prototype.add = function (item, itemImg, cart) {
var add = true;
for (var i = 0; i < this.items.length; i++) {
if ((item.id == this.items[i].id)) {
this.items[i].qty = parseFloat(item.qty) + parseFloat(this.items[i].qty);
this.items[i].price = parseFloat(item.price);
add = false;
}
}
if (add === true) this.items.push(item);
localStorage.setItem(this.sessionName, JSON.stringify(this.items));

//si envia la imagen y el carro vuela la imagen hacia el carro
if (itemImg !== undefined && itemImg !== null &&
cart !== undefined && cart !== null)
flyToElement(itemImg, cart);

return this.items;
};

/**
* Recoge los datos del id consultado
* @param {any} id identificador del item a eliminar
*/
Cart.prototype.getItemById = function (id) {
var miItem;
for (var i = 0; i < this.items.length; i++) {
id == this.items[i].id ? miItem = this.items[i] : false;
}
return miItem;
};

/**
* Recoge los datos del item consultado
* @param {any} product nombre dle producto a consulta
*/
Cart.prototype.getItemByProduct = function (product) {
var miItem;
for (var i = 0; i < this.items.length; i++) {
product == this.items[i].product ? miItem = this.items[i] : false;
}
return miItem;
};

/**
* Elimina el item seleccionado del carro
* @param {any} id identificador del item a eliminar
*/
Cart.prototype.remove = function (id) {
for (var i = 0; i < this.items.length; i++) {
id == this.items[i].id ? this.items.splice(i, 1) : false;
}
localStorage.setItem(this.sessionName, JSON.stringify(this.items));
return this.items;
};

/** Elimina el carro */
Cart.prototype.clear = function () {
this.items = [];
localStorage.removeItem(this.sessionName);
return true;
};

/** Devulve el contenido del carro */
Cart.prototype.get = function () {
return this.items;
};

/**
* Enviar el objeto con los datos para el carro
* @param {any} items Ojeto con al menos estas propiedades id, product, price, qty
*/
Cart.prototype.set = function (items) {
this.items = items;
localStorage.setItem(this.sessionName, JSON.stringify(this.items));
};

/** Devuelve el total de lineas del carro */
Cart.prototype.count = this.items.length;

/** Devuelve el total del carro */
Cart.prototype.getTotal = function () {
var total = 0;
$.each(this.items, function (key, value) {
total += (value.price * value.qty);
});
return total;
};

/**
* Imprimir en la ventana del carro
* @param {any} div objeto contenedor del carro o identificador ej. #micarro
*/
Cart.prototype.printHTMLEdit = function (div) {
$(div).empty();
var carrito = '< ul>'
$.each(this.items, function (key, value) {
carrito += '< li class="sbmincart-item sbmincart-item-changed">' +
' < div class="col-md-8 col-xs-8">' +
' < span class="sbmincart-name">' + value.product + '< /span>' +
' < /div>' +
' < div class="col-md-3 col-xs-3">' +
' < span class="sbmincart-price">' + value.price + '< /span>' +
' < /div>' +
' < div class="col-md-1 col-xs-1" style="padding:0;margin:0;text-align: right;">' +
' < button type="button" class="btn btn-link" onclick="DelItem(' + value.id + ')">< i class="fa fa-trash">< /button>' +
' < /div>' +
'< /li>';
});
carrito += "< /ul>";
$(div).append(carrito);
var total = this.getTotal();
$(div).append('< div class="sbmincart-footer">
Total: ' + total + '< /div>< /div>');

};

/**
* Hacer volar la imagen del articulo seleccionado hasta el carro de compra
* @param {any} flyer objeto original o identificador ej. #miproducto
* @param {any} flyingTo objeto hacia donde volar o identificador ej. #micarro
*/
function flyToElement(flyer, flyingTo) {
var $func = $(this);
var divider = 3;
var flyerClone = $(flyer).clone();
$(flyerClone).css({ position: 'absolute', top: $(flyer).offset().top + "px", left: $(flyer).offset().left + "px", opacity: 1, 'z-index': 1000 });
$('body').append($(flyerClone));
var gotoX = $(flyingTo).offset().left + ($(flyingTo).width() / 2) - ($(flyer).width() / divider) / 2;
var gotoY = $(flyingTo).offset().top + ($(flyingTo).height() / 2) - ($(flyer).height() / divider) / 2;

$(flyerClone).animate({
opacity: 0.4,
left: gotoX,
top: gotoY,
width: $(flyer).width() / divider,
height: $(flyer).height() / divider
}, 700,
function () {
$(flyingTo).fadeOut('fast', function () {
$(flyingTo).fadeIn('fast', function () {
$(flyerClone).fadeOut('fast', function () {
$(flyerClone).remove();
});
});
});
});
}
}

El código HTML y CSS

En este ejemplo os proporciono un poco de CSS y de HTML para usar, pero se puede personalizar fácilmente para adaptarlo a la página web que estás creando.

CSS

    #staplesbmincart ul {
clear: both;
float: left;
width: 100%;
margin: 5px 0 20px;
padding: 1em;
list-style-type: none;
}

#staplesbmincart .sbmincart-empty ul {
display: none;
}

#staplesbmincart .sbmincart-closer {
float: right;
margin: -3px -10px 0;
padding: 0 10px;
background: 0;
border: 0;
font-size: 25px;
cursor: pointer;
font-weight: bold;
outline: none;
}

#staplesbmincart .sbmincart-item {
clear: left;
padding: 7px 0;
min-height: 35px;
font-size: 1em;
}

#staplesbmincart .sbmincart-item + .sbmincart-item {
border - top: 1px solid #f2f2f2;
}

#staplesbmincart .sbmincart-item a {
color: #333;
text-decoration: none;
}

#staplesbmincart .sbmincart-details-name {
float: left;
}

#staplesbmincart .sbmincart-details-quantity {
float: left;
}

#staplesbmincart .sbmincart-details-remove {
float: left;
}

#staplesbmincart .sbmincart-details-price {
float: left;
text-align: right;
}

#staplesbmincart .sbmincart-quantity {
height: 18px;
padding: 2px 4px;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
font-size: 13px;
text-align: right;
transition: border linear 0.2s, box-shadow linear 0.2s;
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
}

#staplesbmincart .sbmincart-quantity:hover {
border - color: #0078C1;
}

#staplesbmincart .sbmincart-quantity:focus {
border - color: #0078C1;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 3px rgba(0, 120, 193, 0.4);
}

#staplesbmincart .sbmincart-remove {
width: 18px;
height: 19px;
margin: 2px 0 0;
padding: 0;
background: #b7b7b7;
border: 1px solid #a3a3a3;
border-radius: 3px;
color: #fff;
font-size: 13px;
opacity: 0.70;
cursor: pointer;
}

#staplesbmincart .sbmincart-remove:hover {
opacity: 1;
}

#staplesbmincart .sbmincart-footer {
clear: left;
text-align: right;
margin-right: 1.5em;
position: relative;
padding: 0 0 0 50px;
}

p.sbmincart-empty-text {
color: #f44336;
font-weight: 500;
}

#staplesbmincart .sbmincart-subtotal {
bottom: 3px;
padding-left: 0;
font-size: 16px;
font-weight: bold;
display: block;
}

HTML

Este HTML está basado en BOOTSTRAP 3  o superior.
< div class="modal fade" id="staplesbmincart" >
< div class="modal-dialog modal-dialog-centered" role="document" >
< div class="modal-content" >
< div class="modal-header" >
< h4 >Cart
< button type="button" data-dismiss="modal" class="close" >< i class="fa fa-close" >< /i >< /button >
< /h4 >
< /div >
< div class="modal-body" >
< div class="row" id="myCart" >

< /div >
< /div >
< div class="modal-footer" >
< div class="col-md-6" >
< a ID="hlCart" runat="server" class="btn btn-success pull-left" >View Shipment < i class="fa fa-truck" >< /i >< /a >
< /div >
< div class="col-md-6" >
< button type="button" data-dismiss="modal" onclick="cart.clean()" class="btn btn-link" >Clear< /button >
< /div >
< /div >
< /div >
< /div >
< /div >

Inicializar el script

Para inicializar el script debes de poner en cada página que lo necesite utilizar este código

var cart = new Cart('[nombre del carro]');

Además, tenemos una pequeña dependencia de JQUERY por lo que además del código que te he mostrado tienes que hacer referencia a alguna versión de JQUERY desde la 1.11.3. Esta dependencia es por el efecto de volar, si no lo quieres usar lo eliminas del script y punto.

En el parámetro [nombre del carro] el el nombre que va a tener el objeto que contendrá todos los datos del carro y se van a grabar en un localStorage, pero si quieres lo puedes cambiar a un sessionStorage o incluso a una cookie (nada recomendable).

Uso del script

El objeto que almacenará los datos en el carro es muy abierto, pero si no cambias nada en el script las propiedades obligatorias son ID, PRODUCT, PRICE, QTY. Todos estos datos los puedes incluir directamente en los botones cuando defines el código HTML y lo usas con algo como estoÑ

$('.buy-item').click(function(){
var item = {
'id': $(this).attr('data-id'),
'product': $(this).attr('data-product'),
'qty': $(this).attr('data-qty'),
// M's propiedades aqui...
'price': parseFloat($(this).attr('data-price'))
}
cart.add(item);
});

De esta manera se va llenando el carro. No necesitas nada más.

Métodos y Propiedades

Mi granito de arena, si han leído los enlaces, es que he ampliado las opciones de este script, agregando funciones de búsqueda y propiedades directas.

cart.add(item, itemImg, cart)

Esta es la función que va a agregar el artículo al carro. itemImg es el objeto o identificador que contiene la imagen que quieres que vuele hacia el carro. cart es el objeto o identificador del carro donde tiene que llegar esa imagen volando.

Mi granito de arena en este script fue comprobar si el ID del producto enviado ya existe en el carro para agregarlo en la misma línea y no agregar una línea nueva cada vez, como se ve en el script original.

Otro granito de arena es el uso del script flyToElement(itemImg, cart) que es el encargado de hacer volar la imagen hacia el carro. Éste es el que crea la dependencia de JQUERY y puede eliminar del script si no te interesa.

cart.remove(id)

Elimina el carro el producto seleccionado con el ID enviado.

cart.clear()

Elimina el carro completo. Lo que es vaciar el carro.

cart.get()

Recoge el contenido del carro. Para poder manipularlo desde otros scripts.

cart.set()

Cargar el contenido del carro. Si por ejemplo lo tienes almacenado en una base de datos y al entrar en la página necesita ser llenado.

cart.getTotal()

Devuelve el la suma total de todas las líneas.

cart.printHTMLEdit(div)

Muestra el contenido del carro. Esta es la función que puedes personalizar para adaptar el carro a tu página web. div es el objeto o identificador de dónde debe mostrar el carro. Esto puede ser en una ventana popup o en la misma página web.

cart.count

De mi propia cosecha, una propiedad que devuelve directamente la cantidad de elementos que hay en el carro. Muy útil para mostrar, por ejemplo, el contador de cuántas líneas tiene tu carro.

cart.getItemById(id)

Más de mi propia cosecha, devuelve el objeto con los datos del producto seleccionado por el ID enviado.

car.getItemByProduct(product)

Mi última función agregada, devuelve el objeto con los datos del producto seleccionado por el nombre PRODUCT. Se puede mejorar ya que si hay más de uno con el mismo nombre, poco normal pero puede ser, devolverá siempre el último encontrado.

Conclusiones

Como ya he dicho es un carro muy simple. No necesita de base de datos y es muy fácilmente personalizable. Espero que lo disfrutéis. Un día de estos lo subiré en ZIP, ahora es tarde y no tengo ganas.

Happy codding


#javascript #jquery #web



2 Comentarios

    • webmaster
      Tuesday, January 9, 2018 11:04 PM

    Si Sauron, puedes personalizar el objeto ITEMS con todas las propiedades que quieras, lo unico que tienes que tener en cuenta, que si no modificas nada mas en el script, las propiedades obligatorias son ID, PRODUCT, PRICE y QTY. Gracias por tu visita.

      Sauron
      Tuesday, January 9, 2018 1:24 PM

    Muy interesante este articulo. Pero una pregunta. Se puede personalizar el objeto de los ITEMS para utilizar mas propiedades? Gracias



Archivo