(loading = false), 300)"
x-init="
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => (loading = false), 300);
});
window.addEventListener('beforeunload', () => {
loading = true;
setTimeout(() => {
loading = false;
}, 3000);
});
const handleNavigation = (element) => {
const link = element.closest('a');
if (
!link ||
!link.href ||
link.hasAttribute('target') ||
link.href.startsWith('tel:') ||
link.href.startsWith('sms:') ||
link.href.startsWith('mailto:') ||
link.href.startsWith('javascript:') ||
link.hasAttribute('download') ||
link.classList.contains('no-loader')
) {
return;
}
const location = window.location;
// Sólo origen + path + search: un enlace que únicamente cambia el hash (el skip link a
// `#main`) es una navegación en el mismo documento — el navegador salta sin recargar,
// así que el overlay no recibiría nunca su `pageshow`/`DOMContentLoaded`, se quedaría
// tapando la página y, con `loading` en true, el listener de click se tragaría todos
// los clicks siguientes. El origen va incluido: sin él, un enlace externo con el mismo
// path+search pasaría por «mismo documento» y no pintaría el loader.
const currentPath = location.origin + location.pathname + location.search;
const url = new URL(link.href);
const path = url.origin + url.pathname + url.search;
if (currentPath === path) {
return;
}
loading = true;
setTimeout(() => {
window.location.href = link.href;
}, 300);
};
document.addEventListener('click', (e) => {
// Una superficie reactiva (p. ej. el explorador, que reemplaza sólo los rieles y los
// resultados) ya resolvió esta navegación y llamó a preventDefault. Secuestrarla aquí
// con `window.location.href` la convertiría en una recarga completa y anularía su
// pushState. Sin JS el evento llega sin cancelar y el loader sigue navegando igual.
if (e.defaultPrevented) {
return;
}
handleNavigation(e.target);
if (loading) {
e.preventDefault();
}
});
"
>