No announcement yet.

Shadows ReadyTheme, Add To Cart On CTGY Trigger Ajax Add To Cart

  • Filter
  • Time
  • Show
Clear All
new posts

    Shadows ReadyTheme, Add To Cart On CTGY Trigger Ajax Add To Cart

    As the title reads, anyone have a quick hit process for enabling the ajax add to cart button on the CTGY page within the Shadows theme? I have it set so it's triggering, but it's erroring out. Can't figure out the right medley of settings with all the moving parts. So if anyone abroad or at Miva has a quick hit how to, that would be pretty awesome for me so I don't have to hurt my brain figuring it out.
    Ted Hust

    Celebrating 13 Years of Outstanding Service & Support
    Miva Merchant Design

    As far as I'm aware there isn't an easy out of the box solution. I've implemented this functionality on a couple of sites made with Shadows... It requires editing a few templates and a separate script for the CTGY page. I also like to update the cart via AJAX on page load, and upon clicking the cart button – so it incorporates that as well. None of the Readythemes update the cart after a user uses the back button, which is a major problem with Chromium browsers.

    Honestly, you might try posting this on the Shadows forum first. Hopefully, Matt can chime in with a solution / add this functionality to the core theme. Otherwise, shoot me a message and I'll try to walk you through it via email.

    You can see an example of this working here:



      I'm tagging in on this - I've been trying to get something like this working for quite some time now, but for different ReadyThemes (Trying to get it working in Colossus here ). Ryan, I might be reaching out too.
      Leslie Kirk
      Miva Certified Developer
      Miva Merchant Specialist since 1997
      Previously of Webs Your Way
      (aka Leslie Nord leslienord)

      Email me: [email protected]

      Follow me: Twitter | Facebook | FourSquare | Pinterest | Flickr


        The default ajax-add-to-cart function is designed to be used on a page with a single product add form. I do have extension for other ways to use it in the works [ ]. Here is a possible framework you can use to start building your own function for the category page. It is completely untested and may blow-up.
        (function (window, document, undefined) {
            'use strict';
            let purchaseForms = document.querySelectorAll('[data-hook="purchase"]');
            let responseMessage = document.querySelector('[data-hook="purchase-message"]');
            let miniBasketCount = document.querySelectorAll('[data-hook~="mini-basket-count"]');
            let miniBasketAmount = document.querySelectorAll('[data-hook~="mini-basket-amount"]');
            Array.from(purchaseForms).forEach(function (purchaseForm) {
                purchaseForm.addEventListener('submit', function (evt) {
                    let purchaseButton = purchaseForm.querySelector('[data-hook="add-to-cart"]');
                    let purchaseButtonText = (purchaseButton.nodeName.toLowerCase() === 'input') ? purchaseButton.value : purchaseButton.textContent;
                    let purchaseFormActionInput = purchaseForm.querySelector('input[name="Action"]');
                    if (purchaseFormActionInput.value !== 'ADPR') {
                    purchaseForm.action = purchaseButton.getAttribute('data-action');
                    purchaseFormActionInput.value = 'ADPR';
                    let data = new FormData(purchaseForm);
                    let request = new XMLHttpRequest(); // Set up our HTTP request
                    purchaseForm.setAttribute('data-status', 'idle');
                    if (purchaseForm.getAttribute('data-status') !== 'submitting') {
                        purchaseForm.setAttribute('data-status', 'submitting');
                        purchaseButton.setAttribute('disabled', 'disabled');
                        if (purchaseButton.nodeName.toLowerCase() === 'input') {
                            purchaseButton.value = 'Processing...';
                            purchaseButton.textContent = 'Processing...';
                        responseMessage.innerHTML = '';
                        // Setup our listener to process completed requests
                        request.onreadystatechange = function () {
                            // Only run if the request is complete
                            if (request.readyState !== 4) {
                            // Process our return data
                            if (request.status === 200) {
                                // What do when the request is successful
                                let response = request.response;
                                if ( === 'js-BASK') {
                                    let basketData = response.querySelector('[data-hook="mini-basket"]');
                                    let basketCount = basketData.getAttribute('data-item-count');
                                    let basketSubtotal = basketData.getAttribute('data-subtotal');
                                    if (miniBasketCount) {
                                        for (let mbcID = 0; mbcID < miniBasketCount.length; mbcID++) {
                                            miniBasketCount[mbcID].textContent = basketCount; // Update mini-basket quantity (display only)
                                    if (miniBasketAmount) {
                                        for (let mbaID = 0; mbaID < miniBasketAmount.length; mbaID++) {
                                            miniBasketAmount[mbaID].textContent = basketSubtotal; // Update mini-basket subtotal (display only)
                                    if (typeof miniBasket !== 'undefined') {
                                        document.querySelector('[data-hook="mini-basket"]').innerHTML = response.querySelector('[data-hook="mini-basket"]').innerHTML;
                                        setTimeout(function () {
                                        }, 100);
                                    else {
                                        responseMessage.innerHTML = '<div class="x-messages x-messages--success"><span class="u-icon-check"></span> Added to cart.</div>';
                                    // Re-Initialize Attribute Machine (if it is active)
                                    if (typeof attrMachCall !== 'undefined') {
                                else if( === 'js-PATR') {
                                    let findRequired = purchaseForm.querySelectorAll('.is-required');
                                    let missingAttributes = [];
                                    for (let id = 0; id < findRequired.length; id++) {
                                        missingAttributes.push(' ' + findRequired[id].title);
                                    responseMessage.innerHTML = '<div class="x-messages x-messages--warning">All <em class="u-color-red">Required</em> options have not been selected.<br />Please review the following options: <span class="u-color-red">' + missingAttributes + '</span>.</div>';
                                else if( === 'js-PLMT') {
                                    responseMessage.innerHTML = '<div class="x-messages x-messages--warning">We do not have enough of the combination you have selected.<br />Please adjust your quantity.</div>';
                                else if( === 'js-POUT') {
                                    responseMessage.innerHTML = '<div class="x-messages x-messages--warning">The combination you have selected is out of stock.<br />Please review your options or check back later.</div>';
                                else {
                                    responseMessage.innerHTML = '<div class="x-messages x-messages--warning">Please review your selection.</div>';
                                // Reset button text and form status
                                if (purchaseButton.nodeName.toLowerCase() === 'input') {
                                    purchaseButton.value = purchaseButtonText;
                                    purchaseButton.textContent = purchaseButtonText;
                                purchaseForm.setAttribute('data-status', 'idle');
                            else {
                                // What do when the request fails
                                console.log('The request failed!');
                                purchaseForm.setAttribute('data-status', 'idle');
                         * Create and send a request
                         * The first argument is the post type (GET, POST, PUT, DELETE, etc.)
                         * The second argument is the endpoint URL
              , purchaseForm.action, true);
                        request.responseType = 'document';
                }, false);
        })(window, document);
        Matt Zimmermann
        Director of UI/UX
        / Miva, Inc.


          Thanks for the link Matt! Good resource to have.