Created
September 2, 2021 17:12
-
-
Save influxweb/85cce583ba974468474fca6cdfcdc2f8 to your computer and use it in GitHub Desktop.
Colossus: Add to Cart with GA Universal Enhanced Ecommerce
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* When called from a `theme.js` file on a product page, this extension will | |
* work with the default page code to add a product to the cart utilizing an | |
* AJAX call to the form processor. | |
* | |
* The function contains internal error checking as well as a check to see which | |
* page was reached and displaying messages accordingly. If the store is also | |
* utilizing the `mini-basket` extension, said extension will be triggered for | |
* display upon successfully adding a product to the cart. | |
*/ | |
(function (window, document, undefined) { | |
'use strict'; | |
var purchaseButton = document.querySelector('[data-hook="add-to-cart"]'); | |
if (!document.body.contains(purchaseButton)) { | |
return; | |
} | |
var purchaseButtonText = (purchaseButton.nodeName.toLowerCase() === 'input') ? purchaseButton.value : purchaseButton.textContent; | |
var purchaseForm = document.querySelector('[data-hook="purchase"]'); | |
var purchaseFormActionInput = purchaseForm.querySelector('input[name="Action"]'); | |
var responseMessage = document.querySelector('[data-hook="purchase-message"]'); | |
var miniBasketCount = document.querySelectorAll('[data-hook~="mini-basket-count"]'); | |
var miniBasketAmount = document.querySelectorAll('[data-hook~="mini-basket-amount"]'); | |
var requiredFields = purchaseForm.querySelectorAll('[required]'); | |
purchaseButton.addEventListener('click', function (evt) { | |
if (purchaseFormActionInput.value !== 'ADPR') { | |
return; | |
} | |
evt.preventDefault(); | |
evt.stopImmediatePropagation(); | |
purchaseForm.action = purchaseButton.getAttribute('data-action'); | |
purchaseFormActionInput.value = 'ADPR'; | |
var data = new FormData(purchaseForm); | |
var request = new XMLHttpRequest(); // Set up our HTTP request | |
purchaseForm.setAttribute('data-status', 'idle'); | |
for (let i = 0; i < requiredFields.length; i++) { | |
let field = requiredFields[i]; | |
field.setCustomValidity(''); | |
if (!field.validity.valid) { | |
if (field.type === 'checkbox') { | |
field.focus(); | |
field.setCustomValidity('Please check this box if you want to proceed.'); | |
field.reportValidity(); | |
purchaseForm.setAttribute('data-status', 'submitting'); | |
break; | |
} | |
else if (field.type === 'radio') { | |
field.focus(); | |
field.setCustomValidity('Please select one of these options.'); | |
field.reportValidity(); | |
purchaseForm.setAttribute('data-status', 'submitting'); | |
break; | |
} | |
else if (field.type.indexOf('select') !== -1) { | |
field.focus(); | |
field.setCustomValidity('Please select an item in the list.'); | |
field.reportValidity(); | |
purchaseForm.setAttribute('data-status', 'submitting'); | |
break; | |
} | |
else if (field.type === 'text' || field.type === 'textarea') { | |
field.focus(); | |
field.setCustomValidity('Please fill out this field.'); | |
field.reportValidity(); | |
purchaseForm.setAttribute('data-status', 'submitting'); | |
break; | |
} | |
} | |
} | |
if (purchaseForm.getAttribute('data-status') !== 'submitting') { | |
purchaseForm.setAttribute('data-status', 'submitting'); | |
purchaseButton.classList.add('is-disabled'); | |
if (purchaseButton.nodeName.toLowerCase() === 'input') { | |
purchaseButton.value = 'Processing...'; | |
} | |
else { | |
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) { | |
return; | |
} | |
// Process our return data | |
if (request.status === 200) { | |
// What do when the request is successful | |
var response = request.response; | |
if (response.body.id === 'js-BASK') { | |
var basketData = response.querySelector('[data-hook="mini-basket"]'); | |
var basketCount = basketData.getAttribute('data-item-count'); | |
var basketSubtotal = basketData.getAttribute('data-subtotal'); | |
if (miniBasketCount) { | |
for (var mbcID = 0; mbcID < miniBasketCount.length; mbcID++) { | |
miniBasketCount[mbcID].textContent = basketCount; // Update mini-basket quantity (display only) | |
} | |
} | |
if (miniBasketAmount) { | |
for (var 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 () { | |
document.querySelector('[data-hook="open-mini-basket"]').click(); | |
}, 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') { | |
attrMachCall.Initialize(); | |
} | |
} | |
else if (response.body.id === 'js-PATR') { | |
var findRequired = purchaseForm.querySelectorAll('.is-required'); | |
var missingAttributes = []; | |
for (var 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 (response.body.id === '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 (response.body.id === '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 | |
purchaseButton.classList.remove('is-disabled'); | |
purchaseButton.style.backgroundColor = '#307962'; | |
purchaseButton.style.color = '#fff'; | |
if (purchaseButton.nodeName.toLowerCase() === 'input') { | |
purchaseButton.value = 'Product Added'; | |
} | |
else { | |
purchaseButton.textContent = 'Product Added'; | |
} | |
setTimeout(function () { | |
if (purchaseButton.nodeName.toLowerCase() === 'input') { | |
purchaseButton.value = purchaseButtonText; | |
} | |
else { | |
purchaseButton.textContent = purchaseButtonText; | |
} | |
purchaseButton.removeAttribute('style'); | |
}, 3000); | |
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 | |
*/ | |
request.open(purchaseForm.method, purchaseForm.action, true); | |
request.responseType = 'document'; | |
request.send(data); | |
} | |
}, false); | |
})(window, document); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment