In this tutorial we'll be adding an ajax cart to create more seamless user experience for our Shopify store. The tutorial assumes you have a working shopify theme and some knowledge of CSS and HTML. If you're not there yet, please take a look at our learning roadmap or jump straight to Setting Up a Shopify Theme in a Development Store

Make sure jQuery is installed

Add this line to in the head section of the theme.liquid file.



{{ '//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.js' | script_tag }}

Modal setup - markup, styles and jQuery

Markup

First we need to add the initial markup for the modal. Place the following code at the top of the product.liquid template.





Styles


.modal {
   max-width: 575px;
   background: white;
   border: 5px solid #111;
   padding: 50px 65px;
   position: fixed;
   z-index: 1000;
}
.modal .close {
   position: absolute;
   top: 10px;
   right: 20px;
   font-size: 20px;
   cursor: pointer;
}
.modal--overlay {
   position: fixed;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
   z-index: 100;
   background-color: rgba(0, 0, 0, 0.4);
}
.hidden {
   display: none;
}

jQuery

Here we're creating some jquery functions to open, close, and center the modal. Place this code in script tags in the head section of the theme.liquid file.

These functions will be called upon later in this tutorial.


// layout/theme.liquid
//Modal Actions
//center modal based on window size
function centerModal(){
   var modal = $('.modal.open');
   var mWidth = modal.outerWidth()
   var mHeight = modal.outerHeight();
   var width = $(window).width();
   var height = $(window).height();
   if((width % 1) != 0){
      width = Math.round(width)
   }
   if((height % 1) != 0){
      height = Math.round(height)
   }
   var topPos = (height / 2) - (mHeight / 2);
   var leftPos = (width / 2) - (mWidth / 2); 
   modal.css({top: topPos, left:leftPos})
}
//open modal and overlay
function openModal(){
   $('.modal').removeClass('hidden').addClass('open');
   $('.modal--overlay').removeClass('hidden').addClass('open');
   $('body').css('overflow', 'hidden');
   centerModal();
}

//close modal and overlay
function closeModal(overlay){
   $(overlay).addClass('hidden').removeClass('open');
   $('.modal.open').addClass('hidden').removeClass('open');
   $('body').css('overflow', 'auto');
}

The product form

In the product.liquid file, you have a form with a submit. We'll be modifying this form in two ways.

1. Add an onclick event to the submit

First we'll be adding a onclick event in order to perform the ajax call.

Modify the current input, something similar to this:



by adding the onclick event:



Note that we've added a function call to addItem with the argument 'add-to-cart'.

Also, note that we've added return false; after the function call. This is to prevent the normal action of the submit button, which is the page redirecting to the cart page.

2. Add an id to the form

Next, we'll add an id to the form. This should match the argument we placed in the addItem function call in the step above.

The form opening tag should look similar to this (not in comments though)



Displaying the number of items in the cart

This tutorial assumes that you will be displaying the total number of items in the cart in the nav menu. Somewhere in your nav bar you should have a link to the cart like this:



For the purposes of this tutorial it'll need to have the id="cart-number"

Then, just inside the script tag in the head section add the following code:


var cartCount = {{ cart.item_count }};

$(document).ready(function(){   
{% if cart.item_count != 0 %}  
$('#cart-number').replaceWith("View cart (" + cartCount + ")");
{% endif %}
});

Here we're immediately setting the number of items in the cart at the time that the page loads. We're using the #cart-number to select the a tag and replace the contents with the current number if there are any items.

Making the AJAX call

Everything up until now has been preparation for the the big event. Now we're here, the ajax call. It's going to look like this:


function addItem(form_id) {
   $.ajax({
      type: 'POST', 
      url: '/cart/add.js',
      dataType: 'json', 
      data: $('#'+form_id).serialize(),
      success: addToCartOk,
      error: addToCartFail
   });
}

This code should be placed in the script tags in the theme.liquid file, just below the code we added in the previous step.

Ajax allows the javascript to run asyncronously.

Key Value Description
type POST the method the request uses, post implies data will be changed on the server
url /cart/add.js An endpoint provided by Shopify for the purpose of adding to cart. For more info go here
dataType json Tells the request the info sent will be in the format of json.
data $('#'+form_id).serialize() This takes the data provided by the form and turns it into json.
success addToCartOk This is a function that we will be defining that will account for a successful ajax call.
error addToCartFail This is a function that we will be defining that will account for a failed ajax call.

addToCartOk Function

This function increases the cartCount by one, adds the product (that comes from the form) to the cart. Then it creates a little message about the product and replaces the cartCount on the page and opens the modal with the message. It's added in between the script tags in theme.liquid


function addToCartOk(product) { 
   cartCount++; 
   $('.modal').html(product.title + ' was added to the cart!'); 
   $('#cart-number').replaceWith("View cart (" + cartCount + ")");
   openModal();
} 

addToCartFail Function

This function creates a little message about the product not being available and opens the modal with the message. It's also added in between the script tags in theme.liquid


function addToCartFail(obj, status) { 
   $('.modal').html('The product you are trying to add is out of stock.'); 
   openModal()
}

Closing the modal

And finally, to close the modal, this allows the user to click anywhere on the modal overlay. This code should be in the document ready area of the javascript as it's a listener.


$('.modal--overlay').on('click', function(){
   var overlay = $('.modal--overlay')
   closeModal(overlay)
})

All the Javascript

Just to prevent any confusion, I'll provide all the javascript here. It's should be placed in between script tags in the head section, found in the theme.liquid file.


var cartCount = {{ cart.item_count }};

$(document).ready(function(){   
   {% if cart.item_count != 0 %}  
      $('#cart-number').replaceWith("View cart (" + cartCount + ")");
   {% endif %}

   $('.modal--overlay').on('click', function(){
      var overlay = $('.modal--overlay')
      closeModal(overlay)
    })
});

function addItem(form_id) {
   $.ajax({
      type: 'POST', 
      url: '/cart/add.js',
      dataType: 'json', 
      data: $('#'+form_id).serialize(),
      success: addToCartOk,
      error: addToCartFail
    });
}

function addToCartOk(product) { 
   cartCount++; 
   $('.modal').html('' + product.title + ' was added to the cart!'); 
   $('#cart-number').replaceWith("View cart (" + cartCount + ")");
   openModal();
} 

function addToCartFail(obj, status) { 
    $('.modal').html(' The product you are trying to add is out of stock.'); 
   openModal()
 } 

//Modal Actions
//center modal based on window size
function centerModal(){
   var modal = $('.modal.open');
   var mWidth = modal.outerWidth()
   var mHeight = modal.outerHeight();
   var width = $(window).width();
   var height = $(window).height();
   if((width % 1) != 0){
      width = Math.round(width)
    }
   if((height % 1) != 0){
      height = Math.round(height)
   }
   var topPos = (height / 2) - (mHeight / 2);
   var leftPos = (width / 2) - (mWidth / 2);
   modal.css({top: topPos, left:leftPos})

 }

//open modal and overlay
function openModal(){
   $('.modal').removeClass('hidden').addClass('open');
   $('.modal--overlay').removeClass('hidden').addClass('open');
   $('body').css('overflow', 'hidden');
   centerModal();
}

//close modal and overlay
function closeModal(overlay){
   $(overlay).addClass('hidden').removeClass('open');
   $('.modal.open').addClass('hidden').removeClass('open');
   $('body').css('overflow', 'auto');
}