Skip to content

Instantly share code, notes, and snippets.

@stevomccormack
Last active May 15, 2018 18:58
Show Gist options
  • Save stevomccormack/a97856cc5fa85dec8466039d664d5871 to your computer and use it in GitHub Desktop.
Save stevomccormack/a97856cc5fa85dec8466039d664d5871 to your computer and use it in GitHub Desktop.
KASE.com AJAX Cart Scripting using Immediately Invoked Function Expression (IIFE)
/*!
Theme Name: Kase Shopify Development
Author URI: https://mwebsolutions.com.au
Description: Developed by Steve McCormack for MWeb Solutions
Version: 1.1
Author: Steve McCormack
*/
// IIFE - Immediately Invoked Function Expression
(function(library) {
library(window.jQuery, window, document);
}(function($, window, document) {
/*---------------------------------------------------------------------------
Cart Functions
-----------------------------------------------------------------------------*/
var validateQty = function(qty) {
if((parseFloat(qty) == parseInt(qty)) && !isNaN(qty) && parseInt(qty) > 0) {
return qty;
}
else if (parseInt(qty) <= 0){
return 0;
}
else {
return 1;
}
};
var ajaxUpdateCart = function(lineId, quantity, $parent) {
var qty = validateQty(quantity);
var params = { quantity: qty, line: lineId };
$.ajax({
url: '/cart/change.js',
dataType: 'json',
type: 'post',
data: params,
success: function (cart) {
if (qty === 0){
var lineIndex = parseInt(lineId) - 1;
$('form[action="/cart"] .cart-table tbody tr:eq(' + lineIndex +')').remove();
}
refreshCart(cart);
}
});
}
var refreshCart = function(cart) {
var $cartForm = $('form[action="/cart"]');
var $cartEmptyContainer = $('#cart-empty-container');
var $cartBtn = $('#cart-link .cart_count');
var cartBtnText = $cartBtn.text() || '0';
var cart_subtotal_html = '';
var discounted_price_total = 0;
var total_savings = 0;
$cartBtn.text(cartBtnText.replace(/[0-9]+/, cart.item_count));
if (cart.item_count == 0)
{
$cartForm.addClass('hidden').fadeOut().hide();
$cartEmptyContainer.removeClass('hidden');
}
else
{
$cartForm.removeClass('hidden').fadeIn().show();
$cartEmptyContainer.addClass('hidden');
$.each(cart.items, function(index, item)
{
$.ajax({
dataType: "json",
async: false,
url: "/products/" + item.handle + ".js",
success: function(data)
{
var variant_id = item.variant_id;
var variant = $.grep(data.variants, function(v)
{
return v.id == variant_id;
});
if(variant[0] && variant[0].compare_at_price > item.price)
{
discounted_price_total += item.price * item.quantity;
total_savings += variant[0].compare_at_price * item.quantity;
}
var lineTotal = item.price * item.quantity;
var lineHtml = Shopify.formatMoney(lineTotal, $cartForm.data('money-format'));//
$cartForm.find('.cart-table tbody tr:eq(' + index +') td[data-label="{{ 'cart.label.total' | t }}"] .cart-item__total').html(lineHtml);
}
});
//update line id
$cartForm.find('.cart-table tbody tr:eq(' + index +') td[data-label="{{ 'cart.label.quantity' | t }}"] input[data-line-id]').data('line-id', index + 1);
});
cart_subtotal_html = Shopify.formatMoney(cart.total_price, $cartForm.data('money-format'));
if( total_savings > 0 )
{
//data-money-format="<span class=money>${{amount}} AUD</span>
//cart_savings_html = '{{ 'cart.general.savings_html' | t | escape }}' + Shopify.formatMoney(total_savings - discounted_price_total, $cartForm.data('money-format'));
cart_savings_html = 'Your saving ' + Shopify.formatMoney(total_savings - discounted_price_total, $cartForm.data('money-format'));
}
else
{
cart_savings_html = '';
}
}
$('.cart-container .cart__subtotal').html(cart_subtotal_html);
$('.cart-container .cart-subtotal__savings').html(cart_savings_html);
{% comment %} {% if settings.show_multiple_currencies %}
convertCurrencies();
{% endif %} {% endcomment %}
if (typeof BOLD.common.eventEmitter === "object")
BOLD.common.eventEmitter.emit('BOLD_CURRENCY_double_check');
}
var initCart = function()
{
$(document).on('change', 'form[action="/cart"] input[type="number"]', function(e)
{
var $self = $(e.currentTarget);
var lineId = $self.data('line-id');
var qty = $self.val();
var $cartForm = $self.closest('form[action="/cart"]');
ajaxUpdateCart( lineId, qty, $cartForm );
return false;
});
$(document).on('click', 'form[action="/cart"] .number-input button', function(e)
{
var $self = $(e.currentTarget);
var $numberInput = $self.closest('.number-input').find('input[type="number"]');
var lineId = $numberInput.data('line-id');
var qty = $numberInput.val();
var $cartForm = $self.closest('form[action="/cart"]');
ajaxUpdateCart( lineId, qty, $cartForm );
return false;
});
}
//--------------------------------------------------------------
// --- Window Scoping
//--------------------------------------------------------------
window.initCart = initCart();
//--------------------------------------------------------------
// --- Init
//--------------------------------------------------------------
var init = function() {
//cart ajax
initCart();
};
//--------------------------------------------------------------
// --- Dom Ready
//--------------------------------------------------------------
$(function() {
//dom is ready!
var pageInit = function() {
init();
}();
});
}));
@stevomccormack
Copy link
Author

stevomccormack commented May 9, 2018

KASE.com
https://kase.com
After working with a Cronulla agency, Jack from KASE.com required a higher level of programming expertise and was referred to me.

  1. Immediately Invoked Function Expression used for scoping and to avoid namespace clashes.
  2. Reusable coding structure with IIFE - e.g. init, pageInit, window scoping (for external access)
  3. Click handlers all use $(document) scoping for best practices (there is use case, I think it is onsubmit forms where bindings are lost if not given document scoping, cannot recall specifically but is definitely the case! Thus the importance of reusable coding structure).

Other cool things on website:

  1. Lazy Loading Images - all images, backgrounds and videos are lazy loaded using all advanced techniques. That is, low resolution is loaded first for fast display and search optimisation/performance. The high resolution images (as well as backgrounds, videos) are loaded once page has finished all other tasks. Only images that are currently within screen viewport are loaded. This helps to improve the user experience as well as provided critical page speed for search performance (e.g. Google PageSpeed) and ranking. Mobile Case retailers are in a highly competitive sector so any ranking boost is critical to success and improved sales.

@stevomccormack
Copy link
Author

stevomccormack commented May 9, 2018

{% for image in product.images %} <img class="lazyload blur-up" src="{{ image.src | img_url: '100x' }}" data-src="{{ image.src | img_url: '2000x' }}" data-srcset="{{ image | img_url: '300x' }} 300w, {{ image | img_url: '400x' }} 400w, {{ image | img_url: '500x' }} 500w, {{ image | img_url: '600x' }} 600w, {{ image | img_url: '700x' }} 700w, {{ image | img_url: '800x' }} 800w, {{ image | img_url: '900x' }} 900w, {{ image | img_url: '1000x' }} 1000w, {{ image | img_url: '1100x' }} 1100w, {{ image | img_url: '1200x' }} 1200w, {{ image | img_url: '1300x' }} 1300w, {{ image | img_url: '1400x' }} 1400w, {{ image | img_url: '1500x' }} 1500w, {{ image | img_url: '1600x' }} 1600w, {{ image | img_url: '1700x' }} 1700w, {{ image | img_url: '1800x' }} 1800w, {{ image | img_url: '1900x' }} 1900w, {{ image | img_url: '2000x' }} 2000w, {{ image | img_url: '2048x' }} 2048w" data-widths="[180, 360, 540, 720, 900, 1080, 1296, 1512, 1728, 2048]" data-aspectratio="{{ image.aspect_ratio }}" data-sizes="auto" alt="{{ image.alt | escape }}" /> {% break %} {% endfor %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment