document.addEventListener("DOMContentLoaded", () => { let activateTimeout = null; let timeoutWarning = null; let currentPageLoad = null; let safetyTimeout = null; // Timeout de sécurité pour éviter que le loader reste bloqué /** * Active le loader et le rend visible * Affiche un message d'annulation après 8 secondes */ window.showLoader = function() { const loader = document.getElementById("loader-overlay"); if (!loader) return; // Protection : si l'élément n'existe pas, on ne fait rien const timeoutMessage = document.getElementById("timeout-message"); const errorMessage = document.getElementById("error-message"); // Nettoyer les timeouts précédents clearTimeout(activateTimeout); clearTimeout(timeoutWarning); // Réinitialiser l'affichage if (errorMessage) errorMessage.style.display = "none"; if (timeoutMessage) timeoutMessage.style.display = "none"; loader.classList.remove("hidden"); // Afficher le loader après 500ms (évite le flash sur les chargements rapides) activateTimeout = setTimeout(() => { if (loader && !loader.classList.contains("hidden")) { loader.classList.add("active"); } }, 500); // Afficher le message de timeout après 8 secondes timeoutWarning = setTimeout(() => { if (loader && loader.classList.contains("active") && !loader.classList.contains("hidden")) { if (timeoutMessage) { timeoutMessage.style.display = "block"; } } }, 8000); // Protection : cacher automatiquement le loader après 30 secondes maximum // Au cas où hideLoader ne serait jamais appelé (page qui ne charge pas, erreur, etc.) if (safetyTimeout) clearTimeout(safetyTimeout); safetyTimeout = setTimeout(() => { if (loader && !loader.classList.contains("hidden")) { hideLoader(); } }, 30000); // 30 secondes max }; /** * Désactive et cache le loader */ window.hideLoader = function() { const loader = document.getElementById("loader-overlay"); if (!loader) return; // Protection : si l'élément n'existe pas, on ne fait rien const timeoutMessage = document.getElementById("timeout-message"); clearTimeout(activateTimeout); clearTimeout(timeoutWarning); if (safetyTimeout) { clearTimeout(safetyTimeout); safetyTimeout = null; } loader.classList.remove("active"); if (timeoutMessage) timeoutMessage.style.display = "none"; setTimeout(() => { if (loader) { loader.classList.add("hidden"); } }, 500); }; /** * Affiche un message d'erreur dans le loader * @param {string} msg - Message d'erreur à afficher */ window.showError = function(msg) { const errorMessage = document.getElementById("error-message"); const timeoutMessage = document.getElementById("timeout-message"); if (!errorMessage) return; // Protection : si l'élément n'existe pas, on ne fait rien clearTimeout(activateTimeout); clearTimeout(timeoutWarning); if (timeoutMessage) timeoutMessage.style.display = "none"; errorMessage.textContent = msg; errorMessage.style.display = "block"; }; /** * Annule le chargement en cours et cache le loader */ const cancelLoadingLink = document.getElementById("cancel-loading-link"); if (cancelLoadingLink) { cancelLoadingLink.addEventListener("click", () => { // Annuler le chargement de la page en cours si possible if (currentPageLoad && currentPageLoad.abort) { currentPageLoad.abort(); } hideLoader(); // Afficher une notification discrète if (typeof M !== 'undefined' && M.toast) { M.toast({ html: 'Chargement annulé', classes: 'rounded grey darken-3', displayLength: 2500 }); } }); } /** * Permet de stocker l'abort controller du chargement en cours * @param {AbortController} controller - Controller de la requête fetch */ window.setCurrentPageLoad = function(controller) { currentPageLoad = controller; }; });