feat: initial release of CommerceKit Floating Cart add-on v1.0.0
This commit is contained in:
147
assets/js/floating-cart.js
Normal file
147
assets/js/floating-cart.js
Normal file
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* 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 );
|
||||
Reference in New Issue
Block a user