Files
CommerceKit-FloatingCart/assets/js/floating-cart.js

148 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* CommerceKit Floating Cart frontend script
*
* Responsibilities:
* 1. Open the CommerceKit / Shoptimizer minicart when the floating button is clicked.
* 2. Automatically open the minicart after a successful add-to-cart (AJAX or standard).
* 3. Play a small badge-bump animation when the item count changes.
*
* All selectors and feature flags come from the `cgkitFC` object localised by PHP.
*/
( function ( $ ) {
'use strict';
/* -----------------------------------------------------------------------
* Module
* --------------------------------------------------------------------- */
var FloatingCart = {
$btn: null,
$count: null,
prevCount: 0,
/** Bootstrap */
init: function () {
if ( typeof cgkitFC === 'undefined' ) {
return;
}
this.$btn = $( '#cgkit-floating-cart .cgkit-floating-cart__btn' );
this.$count = $( '#cgkit-fc-count' );
if ( ! this.$btn.length ) {
return;
}
this.prevCount = parseInt( this.$count.text(), 10 ) || 0;
this.bindEvents();
},
/** Attach event listeners */
bindEvents: function () {
var self = this;
// --- Floating button click → open minicart -----------------------
this.$btn.on( 'click', function ( e ) {
e.preventDefault();
self.openMinicart();
} );
// --- Auto-open after AJAX add-to-cart ----------------------------
if ( cgkitFC.autoOpen === 'yes' ) {
$( document.body ).on( 'added_to_cart', function () {
setTimeout( function () {
self.openMinicart();
self.pulseBtn();
}, parseInt( cgkitFC.autoOpenDelay, 10 ) || 400 );
} );
}
// --- Badge bump when WooCommerce refreshes fragments -------------
$( document.body ).on(
'wc_fragments_refreshed wc_fragments_loaded',
function () {
self.maybeBumpBadge();
}
);
},
/**
* Trigger the theme's minicart open mechanism.
*
* Strategy:
* 1. Try clicking the first element matching the configured selector.
* 2. If that element has no jQuery click handlers registered, dispatch
* a native 'click' so themes that use addEventListener also fire.
* 3. Last resort: navigate to the cart URL.
*/
openMinicart: function () {
var selectors = ( cgkitFC.minicartTrigger || '' ).split( ',' );
var $trigger = null;
for ( var i = 0; i < selectors.length; i++ ) {
var $el = $( $.trim( selectors[ i ] ) ).first();
if ( $el.length ) {
$trigger = $el;
break;
}
}
if ( $trigger && $trigger.length ) {
// Fire both jQuery and native click so all listeners catch it.
$trigger.trigger( 'click' );
var nativeEl = $trigger.get( 0 );
if ( nativeEl && typeof nativeEl.click === 'function' ) {
nativeEl.click();
}
return;
}
// No trigger found → fall back to cart page
if ( cgkitFC.cartUrl ) {
window.location.href = cgkitFC.cartUrl;
}
},
/**
* Add a pulse ring on the button after add-to-cart.
*/
pulseBtn: function () {
var self = this;
this.$btn.addClass( 'cgkit-fc--pulse' );
setTimeout( function () {
self.$btn.removeClass( 'cgkit-fc--pulse' );
}, 600 );
},
/**
* If the item count increased, animate the badge.
*/
maybeBumpBadge: function () {
var $freshCount = $( '#cgkit-fc-count' );
// Re-query in case the fragment replaced the element.
if ( ! $freshCount.length ) {
return;
}
this.$count = $freshCount;
var newCount = parseInt( this.$count.text(), 10 ) || 0;
if ( newCount !== this.prevCount ) {
this.prevCount = newCount;
this.$count.removeClass( 'cgkit-floating-cart__count--bump' );
// Force reflow so removing + re-adding the class restarts the animation.
void this.$count[ 0 ].offsetWidth; // eslint-disable-line no-unused-expressions
this.$count.addClass( 'cgkit-floating-cart__count--bump' );
}
}
};
/* -----------------------------------------------------------------------
* Boot
* --------------------------------------------------------------------- */
$( document ).ready( function () {
FloatingCart.init();
} );
} )( jQuery );