Skip to content

Commit

Permalink
Add/Update/Remove/empty cart without refreshing the page
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Moffat authored and Mark Moffat committed Jan 4, 2020
1 parent f96d833 commit 3373a60
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 51 deletions.
6 changes: 6 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ handlebars = handlebars.create({
'/': lvalue / rvalue,
'%': lvalue % rvalue
}[operator];
},
showCartButtons: (cart) => {
if(!cart){
return'd-none';
}
return'';
}
}
});
Expand Down
159 changes: 134 additions & 25 deletions public/javascripts/expressCart.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable prefer-arrow-callback, no-var, no-tabs */
/* globals showNotification */
/* globals showNotification, numeral */
$(document).ready(function (){
if($(window).width() < 768){
$('.menu-side').on('click', function(e){
Expand All @@ -19,13 +19,6 @@ $(document).ready(function (){
$('#offcanvasClose').hide();
}

// If cart was open before reload, open it again
var isCartOpen = (localStorage.getItem('cartOpen') === 'true');
if(isCartOpen === true){
localStorage.setItem('cartOpen', false);
$('body').addClass('pushy-open-right');
}

$('#userSetupForm').validator().on('submit', function(e){
if(!e.isDefaultPrevented()){
e.preventDefault();
Expand Down Expand Up @@ -304,8 +297,8 @@ $(document).ready(function (){
}
})
.done(function(msg){
$('#cart-count').text(msg.totalCartItems);
showNotification(msg.message, 'success', true);
showNotification(msg.message, 'success');
updateCartDiv();
})
.fail(function(msg){
showNotification(msg.responseJSON.message, 'danger');
Expand Down Expand Up @@ -335,8 +328,8 @@ $(document).ready(function (){
data: { productId: $(this).attr('data-id') }
})
.done(function(msg){
$('#cart-count').text(msg.totalCartItems);
showNotification(msg.message, 'success', true);
showNotification(msg.message, 'success');
updateCartDiv();
})
.fail(function(msg){
showNotification(msg.responseJSON.message, 'danger');
Expand All @@ -350,7 +343,7 @@ $(document).ready(function (){
url: '/product/emptycart'
})
.done(function(msg){
$('#cart-count').text(msg.totalCartItems);
updateCartDiv();
showNotification(msg.message, 'success', true);
});
});
Expand Down Expand Up @@ -405,8 +398,8 @@ function deleteFromCart(element){
data: { productId: element.attr('data-id') }
})
.done(function(msg){
setCartOpen();
showNotification(msg.message, 'success', true);
showNotification(msg.message, 'success');
updateCartDiv();
})
.fail(function(msg){
showNotification(msg.responseJSON.message, 'danger');
Expand All @@ -423,14 +416,6 @@ function cartUpdate(element){
}
}

function setCartOpen(){
if($('body').hasClass('pushy-open-right') === true){
localStorage.setItem('cartOpen', true);
}else{
localStorage.setItem('cartOpen', false);
}
}

function updateCart(element){
// update cart on server
$.ajax({
Expand All @@ -442,8 +427,7 @@ function updateCart(element){
}
})
.done(function(msg){
setCartOpen();
showNotification(msg.message, 'success', true);
updateCartDiv();
})
.fail(function(msg){
showNotification(msg.responseJSON.message, 'danger', true);
Expand Down Expand Up @@ -487,3 +471,128 @@ function getSelectedOptions(){
});
return options;
}

function updateCartDiv(){
$.ajax({
method: 'GET',
url: '/checkout/cartdata'
})
.done(function(result){
// Update the cart div
var cart = result.cart;
var session = result.session;
var productHtml = '';
var totalAmount = numeral(session.totalCartAmount).format('0.00');

// Work out the shipping
var shippingTotalAmt = numeral(session.totalCartShipping).format('0.00');
var shippingTotal = `<strong id="shipping-amount">${result.currencySymbol}${shippingTotalAmt}</strong>`;
if(shippingTotalAmt === 0){
shippingTotal = '<strong id="shipping-amount">FREE</strong>';
}

// If the cart has contents
if(cart){
$('#cart-empty').empty();
Object.keys(cart).forEach(function(productId){
var item = cart[productId];
// Setup the product
var productTotalAmount = numeral(item.totalItemPrice).format('0.00');
var optionsHtml = '';
var optionIndex = 1;
Object.keys(item.options).forEach(function(key){
var option = item.options[key];
if(optionIndex === Object.keys(item.options).length){
optionsHtml += `<strong>${upperFirst(option.name)}</strong>: ${option.value}`;
}else{
optionsHtml += `<strong>${upperFirst(option.name)}</strong>: ${option.value} / `;
}
optionIndex++;
});
var productImage = `<img class="img-fluid" src="/uploads/placeholder.png" alt="${item.title} product image"></img>`;
if(item.productImage){
productImage = `<img class="img-fluid" src="${item.productImage}" alt="${item.title} product image"></img>`;
}

// Setup the product html
productHtml += `
<div class="d-flex flex-row bottom-pad-15">
<div class="col-4 col-md-3">
${productImage}
</div>
<div class="col-12 col-md-7">
<div class="row h-200">
<div class="col-sm-12 text-left no-pad-left">
<h6><a href="/product/${item.link}">${item.title}</a></h6>
</div>
<div class="col-sm-12 text-left no-pad-left">
${optionsHtml}
</div>
<div class="col-md-8 no-pad-left">
<div class="input-group">
<div class="input-group-prepend">
<button class="btn btn-outline-primary btn-qty-minus" type="button">-</button>
</div>
<input type="number" class="form-control cart-product-quantity text-center" id="${productId}-qty" data-id="${productId}" maxlength="2" value="${item.quantity}">
<div class="input-group-append">
<button class="btn btn-outline-primary btn-qty-add" type="button">+</button>
</div>
</div>
</div>
<div class="col-md-4 text-right">
<button class="btn btn-outline-danger btn-delete-from-cart" data-id="${productId}" type="button"><i class="far fa-trash-alt" data-id="${productId}" aria-hidden="true"></i></button>
</div>
</div>
</div>
<div class="col-12 col-md-2 align-self-center text-right no-pad-right">
<strong class="my-auto">${result.currencySymbol}${productTotalAmount}</strong>
</div>
</div>`;
});

$('#cartBodyWrapper').html(productHtml);
$('#cart-count').text(session.totalCartItems);
}else{
$('#cartBodyWrapper').html('');
}

// Set the totals section
var cartTotalsHtml = `
<div class="row">
<div class="cart-contents-shipping col-md-12 no-pad-right">
<div class="text-right">
Shipping: ${shippingTotal}
</div>
<div class="text-right">
Total:
<strong id="total-cart-amount">${result.currencySymbol}${totalAmount}</strong>
</div>
</div>
</div>`;

var cartTotalsEmptyHtml = `
<div id="cart-empty" class="row">
<div class="cart-contents-shipping col-md-12 no-pad-right">
Cart empty
</div>
</div>`;

// Set depending on cart contents
if(cart){
$('#cartTotalsWrapper').html(cartTotalsHtml);
$('#cart-buttons').removeClass('d-none');
}else{
$('#cartTotalsWrapper').html(cartTotalsEmptyHtml);
$('#cart-buttons').addClass('d-none');
}
})
.fail(function(result){
showNotification(result.responseJSON.message, 'danger');
});
}

function upperFirst(value){
return value.replace(/^\w/, (chr) => {
return chr.toUpperCase();
});
}
2 changes: 1 addition & 1 deletion public/javascripts/expressCart.min.js

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ router.get('/checkout/shipping', async (req, res, next) => {
session: req.session,
cartSize: 'part',
cartClose: false,
cartReadOnly: true,
page: 'checkout-shipping',
countryList,
message: clearSessionValue(req.session, 'message'),
Expand All @@ -146,7 +147,7 @@ router.get('/checkout/cart', (req, res) => {
res.render(`${config.themeViews}checkout-cart`, {
page: req.query.path,
cartSize: 'full',
config: req.app.config,
config,
session: req.session,
message: clearSessionValue(req.session, 'message'),
messageType: clearSessionValue(req.session, 'messageType'),
Expand All @@ -156,7 +157,13 @@ router.get('/checkout/cart', (req, res) => {
});

router.get('/checkout/cartdata', (req, res) => {
res.status(200).json(req.session.cart);
const config = req.app.config;

res.status(200).json({
cart: req.session.cart,
session: req.session,
currencySymbol: config.currencySymbol || '$'
});
});

router.get('/checkout/payment', (req, res) => {
Expand Down
5 changes: 2 additions & 3 deletions views/layouts/layout.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.20.2/mode/css/css.min.js" integrity="sha256-D5oJ11cOmRhXSYWELwG2U/XYH3YveZJr9taRYLZ2DSM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.20.2/mode/xml/xml.min.js" integrity="sha256-ERFGS58tayDq5kkyNwd/89iZZ+HglMH7eYXxG1hxTvA=" crossorigin="anonymous"></script>
{{/if}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js" integrity="sha256-LlHVI5rUauudM5ZcZaD6hHPHKrA7CSefHHnKgq+/AZc=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.7/js/tether.min.js" integrity="sha256-4lietOiwRDBKx1goZZbRiwB06L+/bPYEGDIKZt82bgg=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.9/validator.min.js"></script>
<script src="/javascripts/jquery.bootpag.min.js"></script>
Expand Down Expand Up @@ -138,12 +139,10 @@
<div id="cart" class="col-md-12">
{{> (getTheme 'cart')}}
<div class="row">
{{#if @root.session.cart}}
<div class="col-sm-12">
<div id="cart-buttons" class="col-sm-12 {{showCartButtons @root.session.cart}}">
<button class="btn btn-outline-danger float-left" id="empty-cart" type="button">{{ @root.__ "Empty cart" }}</button>
<a href="/checkout/information" class="btn btn-outline-primary float-right">Checkout</a>
</div>
{{/if}}
</div>
</div>
</div>
Expand Down
24 changes: 11 additions & 13 deletions views/themes/Cloth/cart.hbs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@

<div class="card top-marg-15 bottom-marg-15">
<div class="card-body cart-body">
<h5 class="card-title">{{ @root.__ "Cart contents" }}</h5>
<div id="cartBodyWrapper">
{{#each @root.session.cart}}
<div class="d-flex flex-row bottom-pad-15">
<div class="col-xs-4 col-md-3">
<div class="col-4 col-md-3">
{{#if productImage}}
<img class="img-fluid" src="{{this.productImage}}" alt="{{this.title}} product image"> {{else}}
<img class="img-fluid" src="/uploads/placeholder.png" alt="{{this.title}} product image"> {{/if}}
</div>
<div class="col-sm-12 col-md-7">
<div class="col-12 col-md-7">
<div class="row h-200">
<div class="col-sm-12 text-left no-pad-left">
<h6><a href="/product/{{this.link}}">{{this.title}}</a></h6>
Expand All @@ -20,18 +19,17 @@
{{#if @last}}
<strong>{{#upperFirst this.name}}{{/upperFirst}}</strong>: {{this.value}}
{{else}}
<strong>{{#upperFirst this.name}}{{/upperFirst}}:</strong> {{this.value}} /
<strong>{{#upperFirst this.name}}{{/upperFirst}}:</strong> {{this.value}} /
{{/if}}
{{/each}}
</div>
{{#ifCond cartReadOnly '!=' true}}
{{#ifCond @root.cartReadOnly '!=' true}}
<div class="col-md-8 no-pad-left">
<div class="input-group">
<div class="input-group-prepend">
<button class="btn btn-outline-primary btn-qty-minus" type="button">-</button>
</div>
<input type="number" class="form-control cart-product-quantity text-center" data-id="{{../this.productId}}" data-index="{{@key}}"
maxlength="2" value="{{../this.quantity}}">
<input type="number" class="form-control cart-product-quantity text-center" id="{{../this.productId}}-qty" data-id="{{../this.productId}}" maxlength="2" value="{{../this.quantity}}">
<div class="input-group-append">
<button class="btn btn-outline-primary btn-qty-add" type="button">+</button>
</div>
Expand All @@ -43,35 +41,35 @@
{{/ifCond}}
</div>
</div>
<div class="align-self-center col-sm-12 col-md-2 text-right no-pad-right">
<div class="col-12 col-md-2 align-self-center text-right no-pad-right">
<strong class="my-auto">{{currencySymbol @root.config.currencySymbol}}{{formatAmount this.totalItemPrice}}</strong>
</div>
</div>
{{/each}}
</div>
<div class="container-fluid">
<div id="cartTotalsWrapper" class="container-fluid">
{{#if @root.session.cart}}
<div class="row">
<div class="cart-contents-shipping col-md-12 no-pad-right">
{{#ifCond @root.session.shippingCostApplied '===' true}}
<div class="text-right">
{{ @root.__ "Shipping" }}
<strong>{{currencySymbol @root.config.currencySymbol}}{{formatAmount @root.session.totalCartShipping}}</strong>
<strong id="shipping-amount">{{currencySymbol @root.config.currencySymbol}}{{formatAmount @root.session.totalCartShipping}}</strong>
</div>
{{else}}
<div class="text-right">
{{ @root.__ "Shipping" }}
<strong>FREE</strong>
<strong id="shipping-amount">FREE</strong>
</div>
{{/ifCond}}
<div class="text-right">
Total:
<strong>{{currencySymbol @root.config.currencySymbol}}{{formatAmount @root.session.totalCartAmount}}</strong>
<strong id="total-cart-amount">{{currencySymbol @root.config.currencySymbol}}{{formatAmount @root.session.totalCartAmount}}</strong>
</div>
</div>
</div>
{{else}}
<div class="row">
<div id="cart-empty" class="row">
<div class="cart-contents-shipping col-md-12 no-pad-right">
Cart empty
</div>
Expand Down
4 changes: 1 addition & 3 deletions views/themes/Cloth/checkout-cart.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
<div id="cart" class="col-md-12">
{{> (getTheme 'cart')}}
<div class="row">
{{#if @root.session.cart}}
<div class="col-sm-12">
<div id="cart-buttons" class="col-sm-12 {{showCartButtons @root.session.cart}}">
<button class="btn btn-outline-danger float-left" id="empty-cart" type="button">{{ @root.__ "Empty cart" }}</button>
<a href="/checkout/information" class="btn btn-outline-danger float-right">Checkout</a>
</div>
{{/if}}
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion views/themes/Cloth/checkout-information.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
{{> (getTheme 'cart')}}
{{#if @root.session.cart}}
<div class="row">
<div class="col-sm-12">
<div id="cart-buttons" class="col-sm-12 {{showCartButtons @root.session.cart}}">
<button class="btn btn-outline-danger float-right" id="empty-cart" type="button">{{ @root.__ "Empty cart" }}</button>
</div>
{{/if}}
Expand Down
Loading

0 comments on commit 3373a60

Please sign in to comment.