1.0.1 • Published 5 years ago
diacart v1.0.1
Diacart
Diacart is a shopping cart based on localStorage. It provides a declarative interface that allows you to fully customize the cart.
Features
- Easy and fast integration into your frontend
- Simple customization of templates (based on lit-html)
- lit-html provides quick template redrawing (lit-html only ever updates the parts of templates that actually change - it doesn’t re-render the entire view.)
- Multi-tab sync
- Compatible with all major browsers
Installation
npm install diacart -S
Usage
Insert the container diacart html-code on the cart page:
<div data-diacart-container></div>
Insert add to cart button to your products catalog:
Add two attributes to the button:
data-diacart-add-to-cart - Defines the function of the button.
data-diacart-item-json - Defines JSON with the following product properties:
- id - product ID
- name - product name
- price - product price as number
- image - product thumb as image link
- quantity (default: 1) - selected quantity of product
Escape quotes in JSON before inserting it into the data-diacart-item-json attribute.
<button type="button" data-diacart-add-to-cart data-diacart-item-json='{"id": 46, "name": "Aliquam vehicula dui purus (id46)", "price": 1300, "image": "https://picsum.photos/300/200?image=513"}' Add to cart</button>
Insert JS
import Diacart from "diacart";
import { html, render } from "lit-html"; // in case you want to change the default templates
// All parameters are optional. You can omit the option parameter in Diacart, then the default options will be used.
const diacart = new Diacart({
name: "diacart",
title: "Shopping cart",
totalPriceText: "Total amount",
totalQuantityText: "Total quantity",
removeFromCartBtnText: "",
emptyCartText: "Your shopping cart is empty",
orderBtnText: "Checkout",
clearBtnText: "Clear cart",
currency: "$",
groupBy: "id", // 'null', 'undefined' or false to not group
itemHasQuantity: true, // 'true' or 'false'
itemHasPrice: true, // 'true' or 'false'
// selectors
containerSelector: "[data-diacart-container]", // here will be rendered template
miniContainerSelector: "[data-diacart-mini-container]", // here will be rendered miniTemplate
totalPriceContainerSelector: "[data-diacart-total-price-container]", // here will be rendered totalPriceTemplate
totalQuantityContainerSelector: "[data-diacart-total-quantity-container]", // here will be rendered totalQuantityTemplate
addToCartBtnSelector: "[data-diacart-add-to-cart]", // the 'add' function will be attached to them
removeFromCartBtnSelector: "[data-diacart-remove-from-cart]", // the 'remove' function will be attached to them
quantityInputSelector: "[data-diacart-quantity-input]",
orderBtnSelector: "[data-diacart-order]", // the 'order' function will be attached to them
clearBtnSelector: "[data-diacart-clear]", // the 'clear' function will be attached to them
// template rendering functions
templateTagFunction: html, // MUST specify these parameters if you want to override templates!
templateRenderFunction: render, // MUST specify these parameters if you want to override templates!
// template functions
template: diacartObject => {
const { options, storage, totalPrice } = diacartObject;
return html`
<div class="diacart-wrapper">
<section class="diacart">
<div class="diacart__header">
<div class="diacart-grid">
<div
class="diacart-grid-col diacart-grid-col--flex diacart__header-col"
>
<div class="diacart__title">${options.title || ""}</div>
</div>
<div
class="diacart-grid-col diacart-grid-col--auto diacart__header-col${!storage.length
? " diacart-hidden"
: ""}"
>
<button
class="diacart__clear-btn diacart-btn diacart-btn--default diacart-btn--medium"
data-diacart-clear
>
${options.clearBtnText || ""}
</button>
</div>
</div>
</div>
<div class="diacart__items">
${!storage.length
? html`
<div class="diacart-empty">
<h2 class="diacart-empty__title">
${options.emptyCartText}
</h2>
</div>
`
: storage.map((item, id) =>
options.itemTemplate({ id, item, options })
)}
<div
class="diacart__footer${!storage.length ? " diacart-hidden" : ""}"
>
<div class="diacart__footer-container">
<div class="diacart__total-price">
${options.totalPriceText
? options.totalPriceText + ": "
: ""}<span class="diacart__total-price-accent"
>${options.totalPriceTemplate({
options,
totalPrice
})}</span
>
</div>
<button
class="diacart__order-btn diacart-btn diacart-btn--primary diacart-btn--medium"
data-diacart-order
>
${options.orderBtnText || ""}
</button>
</div>
</div>
</div>
</section>
</div>
`;
}, // cart template as a function
itemTemplate: ({ id, item, options }) => {
return html`
<div
class="diacart-item"
data-diamodal-item
data-diacart-item-id="${id || ""}"
>
<div class="diacart-grid">
${!item.image
? ""
: html`
<div
class="diacart-grid-col diacart-grid-col--v-gutter diacart-grid-col--auto diacart-item__image-col"
>
<a
href="${item.link || ""}"
title="${item.name || ""}"
class="diacart-item__image"
style="background-image: url('${item.image || ""}');"
></a>
</div>
`}
<div
class="diacart-grid-col diacart-grid-col--v-gutter diacart-grid-col--flex diacart-item__text-col"
>
<div class="diacart-grid">
<div class="diacart-grid-col diacart-grid-col--flex">
<a href="${item.link || ""}" class="diacart-item__title"
>${item.name || ""}</a
>
</div>
<div class="diacart-grid-col diacart-grid-col--auto">
<button
class="diacart-item__remove-btn"
data-diacart-remove-from-cart
data-diacart-item-id="${id || ""}"
>
${options.removeFromCartBtnText || ""}
</button>
</div>
</div>
<div class="diacart-item__options diacart-grid diacart-grid--v-end">
${options.itemHasQuantity && item.quantity
? html`
<div
class="diacart-grid-col diacart-grid-col--auto diacart-item-option"
>
<div class="diacart-item__quantity diacart-counter">
<div class="diacart-item-option__title">
${options.totalQuantityText}:
</div>
<div
class="diacart-item-option__value diacart-counter__container diacart-grid diacart-grid--no-gutter"
>
<button
class="diacart-grid__col diacart-grid__col--auto diacart-counter__btn diacart-counter__plus-btn"
>
+
</button>
<input
class="diacart-grid__col diacart-grid__col--flex diacart-counter__input"
type="number"
name="quantity"
data-diacart-quantity-input
data-diacart-item-id="${id || ""}"
.value="${item.quantity || 1}"
/>
<button
class="diacart-grid__col diacart-grid__col--auto diacart-counter__btn diacart-counter__minus-btn"
>
-
</button>
</div>
</div>
</div>
`
: ""}
<div class="diacart-grid-col diacart-grid-col--flex">
${options.itemHasPrice && item.price
? html`
<div class="diacart-item__price">
${options.currency || ""} ${item.price || ""}
</div>
`
: ""}
</div>
</div>
</div>
</div>
</div>
`;
}, // cart item template as a function, used in 'template' function
miniTemplate: diacartObject => html``, // mini cart template as a function
totalPriceTemplate: diacartObject => {
const { options, totalPrice } = diacartObject;
return (options.currency + " " || "") + parseFloat(totalPrice).toFixed(2);
}, // total price template as a function
totalQuantityTemplate: diacartObject => {
const { totalQuantity } = diacartObject;
return parseInt(totalQuantity);
} // total quantity template as a function
});
// events
function onAdd(addedItemId) {
console.log("onAdd arguments: ", addedItemId);
}
function onUpdate(updatedItemId, updateObj) {
console.log("onUpdate arguments: ", updatedItemId, updateObj);
}
function onStorageUpdate(newValue, prevValue) {
console.log("onStorageUpdate arguments: ", newValue, prevValue);
}
function onRemove(removedItemObj) {
console.log("onRemove arguments: ", removedItemObj);
}
function onOrder(items) {
console.log("onOrder arguments:", items);
}
function onClear() {
console.log("onClear has no arguments");
}
function onRender() {
console.log("onRender has no arguments");
}
diacart.on("add", onAdd); // will be called at every product adding
diacart.on("update", onUpdate); // will be called at every product updating
diacart.on("storageUpdate", onStorageUpdate); // will be called at every storage updating
diacart.on("remove", onRemove); // will be called at every removing product from cart
diacart.on("order", onOrder); // will be called at every ordering
diacart.once("clear", onClear); // will be called only once when clearing the cart
diacart.on("render", onRender); // will be called at every rerendering
const productData = {
id: 46,
name: "Aliquam vehicula dui purus (id46)",
price: 1300,
image: "https://picsum.photos/300/200?image=513"
};
const cartItemId = diacart.add(productData); // add product, triggers 'add' event
diacart.update(cartItemId, { name: "New name" }); // update product by id, triggers 'update' event
console.log(diacart.hasItem({ name: "New name" })); // check on whether a product exists on a specific query
diacart.remove(cartItemId); // remove product by id, triggers 'remove' event
console.log(diacart.hasItem({ name: "New name" }));
diacart.add(productData); // add product, triggers 'add' event
diacart.order(); // order cart, triggers 'order' event
diacart.clear(); // clear cart, triggers 'clear' event
diacart.removeListener("order", onOrder); // remove event listener