Skip to content

Instantly share code, notes, and snippets.

@diegoversiani
Last active February 15, 2024 12:32
Show Gist options
  • Save diegoversiani/9d4086b8031f3f10c91ebace608092e9 to your computer and use it in GitHub Desktop.
Save diegoversiani/9d4086b8031f3f10c91ebace608092e9 to your computer and use it in GitHub Desktop.
Detect quantity field updates (redacted for brevity)
/**
* Manage cart items ajax actions.
*
* DEPENDS ON:
* - jQuery // Interact with WooCommerce events
*/
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define([], factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.CartAjax = factory(root);
}
})(typeof global !== 'undefined' ? global : this.window || this.global, function (root) {
'use strict';
var $ = jQuery;
var _hasJQuery = ( $ != null );
var _publicMethods = {};
var _settings = {
quantityInputSelector: '.cart_item input.qty',
quantitySpinnerButtonSelector: '.cart_item .fc-number-spin-button',
quantityAttribute: 'data-quantity',
updateWaitTime: 500,
fragmentsUpdateEvent: 'wc_fragment_refresh',
fragmentsReplacedEvent: 'wc_fragments_refreshed',
};
/**
* METHODS
*/
/**
* Returns a function, that, as long as it continues to be invoked, will not
* be triggered. The function will be called after it stops being called for
* N milliseconds. If `immediate` is passed, trigger the function on the
* leading edge, instead of the trailing.
*
* @param {[type]} func Function to be executed.
* @param {[type]} wait Wait time in milliseconds.
* @param {[type]} immediate Trigger the function on the leading edge.
*
* @return function Function to be executed, incapsulated in a timed function.
*/
var debounce = function ( func, wait, immediate ) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply( context, args );
};
var callNow = immediate && !timeout;
clearTimeout( timeout );
timeout = setTimeout( later, wait );
if ( callNow ) func.apply( context, args );
};
};
/**
* Set the quantity attribute value for quantity fields.
*/
var setAllQuantityAttributes = function() {
var quantityFields = document.querySelectorAll( _settings.quantityInputSelector );
for ( var i = 0; i < quantityFields.length; i++ ) {
var input = quantityFields[ i ];
input.setAttribute( _settings.quantityAttribute, input.value );
}
};
/**
* Check whether the product quantity field value has changed.
*
* @param HTMLElement qtyField The product quantity field.
*
* @return bool Whether the product quantity value has changed.
*/
var hasQuantityChanged = function( qtyField ) {
if ( qtyField.getAttribute( _settings.quantityAttribute ) != qtyField.value ) {
return true;
}
return false;
}
/**
* Maybe update cart items quantity and other attributes for all products in cart.
*/
var debouncedMaybeUpdateQuantities;
var maybeUpdateCartItemQuantities = function( e ) {
// Bail if target is not a quantity field or buttons
if ( ! e.target.matches( _settings.quantityInputSelector ) && ! e.target.matches( _settings.quantitySpinnerButtonSelector ) ) { return; }
var allQuantityFields = document.querySelectorAll( _settings.quantityInputSelector );
for ( var i = 0; i < allQuantityFields.length; i++ ) {
var qtyField = allQuantityFields[i];
// Maybe trigger update item
if ( hasQuantityChanged( qtyField ) ) {
// PROCESS UPDATE
}
}
}
/**
* Initialize component and set related handlers.
*/
_publicMethods.init = function( ) {
// Set quantity attribute for quantity fields at initialization
setAllQuantityAttributes();
// Add event listeners for quantity updates
debouncedMaybeUpdateQuantities = debounce( maybeUpdateCartItemQuantities, _settings.updateWaitTime );
document.addEventListener( 'click', debouncedMaybeUpdateQuantities, true );
document.addEventListener( 'keydown', debouncedMaybeUpdateQuantities, true );
document.addEventListener( 'change', debouncedMaybeUpdateQuantities, true );
// After fragments has been updated
if ( _hasJQuery ) {
$( document.body ).on( _settings.fragmentsReplacedEvent, setAllQuantityAttributes );
}
};
//
// Public APIs
//
return _publicMethods;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment