Skip to content

Instantly share code, notes, and snippets.

@marioloncarek
Created March 18, 2019 15:44
Show Gist options
  • Save marioloncarek/fb6f6c69391371bb33c63e284daae686 to your computer and use it in GitHub Desktop.
Save marioloncarek/fb6f6c69391371bb33c63e284daae686 to your computer and use it in GitHub Desktop.
import {Power3, TweenMax} from 'gsap/TweenMax';
import {formatMoney} from '@shopify/theme-currency/currency';
import 'whatwg-fetch';
import serialize from 'form-serialize';
export default class AjaxCart {
constructor() {
this.defaults = {
cartModal: '.js-ajax-cart-modal',
cartModalClose: '.js-ajax-cart-modal-close',
cartDrawer: '.js-ajax-cart-drawer',
cartDrawerContent: '.js-ajax-cart-drawer-content',
cartDrawerClose: '.js-ajax-cart-drawer-close',
cartDrawerTrigger: '.js-ajax-cart-drawer-trigger',
cartOverlay: '.js-ajax-cart-overlay',
cartCounter: '.js-ajax-cart-counter',
addToCart: '.js-ajax-add-to-cart',
removeFromCart: '.js-ajax-remove-from-cart',
removeFromCartNoDot: 'js-ajax-remove-from-cart',
checkoutButton: '.js-ajax-checkout-button',
bodyClass: 'is-overlay-opened',
};
this.cartModal = document.querySelector(this.defaults.cartModal);
this.cartModalClose = document.querySelector(this.defaults.cartModalClose);
this.cartDrawer = document.querySelector(this.defaults.cartDrawer);
this.cartDrawerContent = document.querySelector(this.defaults.cartDrawerContent);
this.cartDrawerClose = document.querySelector(this.defaults.cartDrawerClose);
this.cartDrawerTrigger = document.querySelector(this.defaults.cartDrawerTrigger);
this.cartOverlay = document.querySelector(this.defaults.cartOverlay);
this.cartCounter = document.querySelector(this.defaults.cartCounter);
this.addToCart = document.querySelectorAll(this.defaults.addToCart);
this.checkoutButton = document.querySelector(this.defaults.checkoutButton);
this.htmlSelector = document.documentElement;
this.fetchCart();
this.addToCart.forEach((item) => {
item.addEventListener('click', (event) => {
event.preventDefault();
const formID = item.parentNode.getAttribute('id');
this.addProductToCart(formID);
});
});
this.cartOverlay.addEventListener('click', () => {
this.closeFailModal();
this.closeCartDrawer();
this.closeCartOverlay();
});
this.cartDrawerClose.addEventListener('click', () => {
this.closeCartDrawer();
this.closeCartOverlay();
});
this.cartDrawerTrigger.addEventListener('click', (event) => {
event.preventDefault();
this.openCartDrawer();
this.openCartOverlay();
});
this.cartModalClose.addEventListener('click', () => {
this.closeFailModal();
this.closeCartDrawer();
this.closeCartOverlay();
});
}
fetchCart(callback) {
window.fetch('/cart.js', {
credentials: 'same-origin',
method: 'GET',
})
.then((resp) => resp.json())
.then((cart) => {
this.currentCartItemNumber(cart);
if (cart.item_count === 0) {
this.renderBlankCart();
this.checkoutButton.classList.add('is-hidden');
} else {
this.renderCart(cart);
this.checkoutButton.classList.remove('is-hidden');
if ((typeof callback) === 'function') {
callback(cart);
}
}
})
.catch((error) => {
this.ajaxRequestFail();
throw new Error(error);
});
}
addProductToCart(formID, callback) {
const form = document.querySelector(`#${formID}`);
const formData = serialize(form, {hash: true});
window.fetch('/cart/add.js', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
})
.then((resp) => resp.json())
.then((cart) => {
if ((typeof callback) === 'function') {
callback(cart);
} else {
this.addToCartOk();
}
})
.catch((error) => {
this.ajaxRequestFail();
throw new Error(error);
});
}
changeItem(line, callback) {
const quantity = 0;
window.fetch('/cart/change.js', {
method: 'POST',
credentials: 'same-origin',
body: JSON.stringify({line, quantity}),
headers: {
'Content-Type': 'application/json',
},
})
.then((resp) => resp.json())
.then((cart) => {
if ((typeof callback) === 'function') {
callback(cart);
} else {
this.fetchCart();
}
})
.catch((error) => {
this.ajaxRequestFail();
throw new Error(error);
});
}
currentCartItemNumber(cart) {
this.cartCounter.innerHTML = cart.item_count;
}
addToCartOk() {
this.fetchAndOpenCart();
}
fetchAndOpenCart() {
this.fetchCart(() => {
this.openCartDrawer();
this.openCartOverlay();
});
}
ajaxRequestFail() {
this.openFailModal();
this.openCartOverlay();
}
renderCart(cart) {
this.clearCartDrawer();
cart.items.forEach((item, index) => {
const cartSingleProduct = `
<div class="ajax-cart-item__single" data-line="${Number(index + 1)}">
<div class="ajax-cart-item__info-wrapper">
<div class="ajax-cart-item__image" style="background-image: url(${item.image});"></div>
<div class="ajax-cart-item__info">
<a href="${item.url}" class="ajax-cart-item__title">${item.product_title}</a>
<div class="ajax-cart-item__variant">${item.variant_title}</div>
<div class="ajax-cart-item__quantity">Quantity: ${item.quantity}</div>
</div>
</div>
<div class="ajax-cart-item__price">${formatMoney(item.line_price)}</div>
<a class="ajax-cart-item__remove ${this.defaults.removeFromCartNoDot}">Remove</a>
</div>
`;
this.cartDrawerContent.innerHTML += cartSingleProduct;
});
const cartSubTotal = `
<div class="ajax-cart-drawer__subtotal">
<span>Subtotal: </span>
<span class="ajax-cart-drawer__subtotal-price">${formatMoney(cart.total_price)}</span>
</div>
`;
this.cartDrawerContent.innerHTML += cartSubTotal;
const removeFromCart = document.querySelectorAll(this.defaults.removeFromCart);
removeFromCart.forEach((item) => {
item.addEventListener('click', () => {
const line = item.parentNode.getAttribute('data-line');
this.changeItem(line);
});
});
}
renderBlankCart() {
this.clearCartDrawer();
this.cartDrawerContent.innerHTML = '<div class="ajax-cart__empty">Your Cart is currenty empty!</div>';
}
openCartDrawer() {
TweenMax.to(this.cartDrawer, 0.5, {
x: -480,
ease: Power3.easeInOut,
});
}
closeCartDrawer() {
TweenMax.to(this.cartDrawer, 0.5, {
x: 0,
ease: Power3.easeInOut,
});
}
clearCartDrawer() {
this.cartDrawerContent.innerHTML = '';
}
openFailModal() {
TweenMax.to(this.cartModal, 0.4, {
autoAlpha: 1,
ease: Power3.easeOut,
});
}
closeFailModal() {
TweenMax.to(this.cartModal, 0.2, {
autoAlpha: 0,
ease: Power3.easeOut,
});
}
openCartOverlay() {
this.htmlSelector.classList.add(this.defaults.bodyClass);
TweenMax.to(this.cartOverlay, 0.5, {
autoAlpha: 1,
ease: Power3.easeInOut,
});
}
closeCartOverlay() {
this.htmlSelector.classList.remove(this.defaults.bodyClass);
TweenMax.to(this.cartOverlay, 0.5, {
autoAlpha: 0,
ease: Power3.easeInOut,
});
}
}
// tipovi ajax carta (mini cart, lijevi i desni drawer, popup, quantity change in cart)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment