Enhance button and form interaction handling to prevent conflicts with Livewire and Alpine states
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
// Optimized app.js
|
||||
const passiveOptions = { passive: true };
|
||||
// Non-passive options for handlers that need to call preventDefault()
|
||||
const activeOptions = { passive: false };
|
||||
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.hook('request', ({ fail }) => {
|
||||
@@ -148,11 +150,21 @@ function initRevealAnimations() {
|
||||
}
|
||||
|
||||
const buttonClickStates = new WeakMap();
|
||||
const buttonClickHandlers = new WeakMap();
|
||||
|
||||
function preventDoubleClick(selector) {
|
||||
const buttons = document.querySelectorAll(selector);
|
||||
|
||||
buttons.forEach(button => {
|
||||
if (buttonClickStates.has(button)) return;
|
||||
// Skip if already has a handler attached
|
||||
if (buttonClickHandlers.has(button)) return;
|
||||
|
||||
// Skip Livewire/Alpine handled elements - let them handle their own state
|
||||
if (button.hasAttribute('wire:click') ||
|
||||
button.hasAttribute('x-on:click') ||
|
||||
button.hasAttribute('@click')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clickHandler = function(e) {
|
||||
if (buttonClickStates.get(button)) {
|
||||
@@ -176,8 +188,10 @@ function preventDoubleClick(selector) {
|
||||
}
|
||||
};
|
||||
|
||||
button.addEventListener('click', clickHandler, passiveOptions);
|
||||
// Use non-passive listener since we need to call preventDefault()
|
||||
button.addEventListener('click', clickHandler, activeOptions);
|
||||
buttonClickStates.set(button, false);
|
||||
buttonClickHandlers.set(button, clickHandler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -228,10 +242,20 @@ function getDevicePerformance() {
|
||||
return devicePerformanceLevel;
|
||||
}
|
||||
|
||||
const formSubmitHandlers = new WeakMap();
|
||||
|
||||
function optimizeFormInteractions() {
|
||||
const forms = document.querySelectorAll('form');
|
||||
|
||||
forms.forEach(form => {
|
||||
// Skip if already has a handler attached
|
||||
if (formSubmitHandlers.has(form)) return;
|
||||
|
||||
// Skip Livewire forms - they handle their own submit state
|
||||
if (form.hasAttribute('wire:submit') || form.closest('[wire\\:id]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const submitBtn = form.querySelector('button[type="submit"], input[type="submit"]');
|
||||
if (!submitBtn) return;
|
||||
|
||||
@@ -246,6 +270,7 @@ function optimizeFormInteractions() {
|
||||
};
|
||||
|
||||
form.addEventListener('submit', submitHandler, passiveOptions);
|
||||
formSubmitHandlers.set(form, submitHandler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -361,6 +386,26 @@ if (document.readyState === 'loading') {
|
||||
initializeApp();
|
||||
}
|
||||
|
||||
// Reinitialize after Livewire navigation (wire:navigate)
|
||||
document.addEventListener('livewire:navigated', () => {
|
||||
// Re-run initialization for dynamically loaded content
|
||||
updateDateTime();
|
||||
|
||||
const performance = getDevicePerformance();
|
||||
|
||||
if (performance === 'high') {
|
||||
initRevealAnimations();
|
||||
initLazyLoading();
|
||||
} else {
|
||||
document.querySelectorAll('.reveal-on-scroll').forEach(el => {
|
||||
el.classList.add('revealed');
|
||||
});
|
||||
}
|
||||
|
||||
preventDoubleClick('.btn-primary, [href*="checkout"], [href*="add-to-cart"]');
|
||||
optimizeFormInteractions();
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', () => {
|
||||
if (timeUpdateInterval) clearInterval(timeUpdateInterval);
|
||||
if (revealObserver) revealObserver.disconnect();
|
||||
|
||||
@@ -329,6 +329,15 @@
|
||||
}
|
||||
|
||||
document.addEventListener('click', function(e) {
|
||||
// Skip Livewire/Alpine handled buttons - they manage their own loading states
|
||||
if (e.target.hasAttribute('wire:click') ||
|
||||
e.target.hasAttribute('wire:submit') ||
|
||||
e.target.hasAttribute('x-on:click') ||
|
||||
e.target.hasAttribute('@click') ||
|
||||
e.target.closest('[wire\\:submit]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.target.matches('button[type="submit"], .btn-submit')) {
|
||||
e.target.classList.add('btn-loading');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user