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

153 lines
4.5 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 (stops at the first approach that succeeds):
* 1. Find the header cart button via the configured selector list and
* fire ONE native click on it. Using native click (not jQuery trigger
* + native) avoids the double-fire / toggle-closed bug.
* 2. If no button is found, try to show the Shoptimizer cart panel
* directly by toggling the body class the theme uses.
* 3. Last resort: navigate to the cart URL.
*
* NOTE: never call both $el.trigger('click') AND el.click() — that
* fires two events and the toggle cancels itself immediately.
*/
openMinicart: function () {
// --- 1. Try clicking the configured header cart button ------------
var selectors = ( cgkitFC.minicartTrigger || '' ).split( ',' );
for ( var i = 0; i < selectors.length; i++ ) {
var $el = $( $.trim( selectors[ i ] ) ).first();
if ( $el.length ) {
// One native click reaches both jQuery and native listeners.
$el[ 0 ].click();
return;
}
}
// --- 2. Shoptimizer direct panel toggle --------------------------
// Shoptimizer's cart anchor is a.cart-contents inside .shoptimizer-cart.
// If the selector loop above somehow missed it, grab it directly.
var $directBtn = $( '.shoptimizer-cart a.cart-contents' );
if ( $directBtn.length ) {
$directBtn[ 0 ].click();
return;
}
// --- 3. 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 );