/* Feedback de chargement pour FullCalendar et spinner sur le bouton Enregistrer du modal */ (function () { function setDisabled(containerSelector, disabled) { try { var container = document.querySelector(containerSelector); if (!container) return; var els = container.querySelectorAll('button, input, select, textarea'); els.forEach(function (el) { el.disabled = !!disabled; }); } catch (e) {} } function showIndicator(id, show) { try { var el = document.getElementById(id); if (el) { el.style.display = show ? 'block' : 'none'; } } catch (e) {} } function attachLoading(calendar, indicatorId, filtersSelector) { try { if (!calendar || typeof calendar.setOption !== 'function') return; calendar.setOption('loading', function (isLoading) { showIndicator(indicatorId, isLoading); // Ne pas désactiver les filtres pendant le chargement, uniquement overlay sur le calendrier try { var calEl = document.getElementById('agenda-calendar') || (calendar.el || null); if (calEl && window.CRVI_OVERLAY) { if (isLoading) { window.CRVI_OVERLAY.show(calEl); } else { window.CRVI_OVERLAY.hide(calEl); } } } catch (e) {} }); } catch (e) {} } // Gestionnaire de chargement global, pour couvrir les appels AJAX génériques (création, update, delete, etc.) // Usage: window.CRVI_LOADING.start(); ... finally window.CRVI_LOADING.end(); (function initGlobalLoading() { var counter = 0; var defaultIndicatorId = 'loading-indicator'; // Ne pas désactiver automatiquement les zones de filtres var defaultDisableSelectors = []; function updateUi() { var isLoading = counter > 0; try { showIndicator(defaultIndicatorId, isLoading); // Désactiver quelques containers communs si présents defaultDisableSelectors.forEach(function (sel) { setDisabled(sel, isLoading); }); } catch (e) {} } if (!window.CRVI_LOADING) { window.CRVI_LOADING = { start: function () { counter++; updateUi(); }, end: function () { if (counter > 0) counter--; updateUi(); }, // Permet d'ajuster la cible si besoin ailleurs configure: function (opts) { if (opts && typeof opts.indicatorId === 'string') { defaultIndicatorId = opts.indicatorId; } if (opts && Array.isArray(opts.disableSelectors)) { defaultDisableSelectors = opts.disableSelectors.slice(); } updateUi(); }, // Pour diagnostics _getCount: function () { return counter; } }; } })(); // Overlay ciblé par élément: window.CRVI_OVERLAY.show(elementOrSelector), .hide(...) (function initElementOverlay() { function getTarget(elOrSelector) { if (!elOrSelector) return null; if (typeof elOrSelector === 'string') return document.querySelector(elOrSelector); return elOrSelector.nodeType === 1 ? elOrSelector : null; } function ensurePositioned(target) { var style = window.getComputedStyle(target); if (style.position === 'static' || !style.position) { target.style.position = 'relative'; } } function createOverlay(target) { var overlay = document.createElement('div'); overlay.className = 'crvi-overlay'; overlay.style.position = 'absolute'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.right = '0'; overlay.style.bottom = '0'; overlay.style.background = 'rgba(255,255,255,0.6)'; overlay.style.display = 'flex'; overlay.style.alignItems = 'center'; overlay.style.justifyContent = 'center'; overlay.style.zIndex = '20'; var spinner = document.createElement('div'); spinner.className = 'spinner-border text-primary'; spinner.setAttribute('role', 'status'); spinner.setAttribute('aria-hidden', 'true'); overlay.appendChild(spinner); return overlay; } function getCount(target) { var c = parseInt(target.getAttribute('data-overlay-count') || '0', 10); return isNaN(c) ? 0 : c; } function setCount(target, c) { target.setAttribute('data-overlay-count', String(c)); } function show(elOrSelector) { var target = getTarget(elOrSelector); if (!target) return; ensurePositioned(target); var count = getCount(target); setCount(target, count + 1); if (count > 0 && target.querySelector(':scope > .crvi-overlay')) { return; } var overlay = createOverlay(target); target.appendChild(overlay); } function hide(elOrSelector) { var target = getTarget(elOrSelector); if (!target) return; var count = getCount(target); count = Math.max(0, count - 1); setCount(target, count); if (count === 0) { var overlay = target.querySelector(':scope > .crvi-overlay'); if (overlay) { overlay.remove(); } } } if (!window.CRVI_OVERLAY) { window.CRVI_OVERLAY = { show: show, hide: hide }; } })(); function tryAttach() { if (window.currentCalendar) { attachLoading(window.currentCalendar, 'loading-indicator', '.filters'); } if (window.currentColleaguesCalendar) { attachLoading( window.currentColleaguesCalendar, 'loading-indicator-colleagues', '.filters-colleagues' ); } } document.addEventListener('DOMContentLoaded', function () { // Essayer d'attacher au démarrage puis quelques tentatives (calendriers init asynchrones) tryAttach(); var iv = setInterval(tryAttach, 500); setTimeout(function () { clearInterval(iv); }, 10000); // Spinner + désactivation sur le bouton Enregistrer du modal document.addEventListener( 'click', function (e) { var btn = e.target && (e.target.closest ? e.target.closest('#saveEvent') : null); if (!btn) return; if (btn.dataset.loading === '1') return; btn.dataset.loading = '1'; btn.disabled = true; if (!btn.dataset.originalHtml) { btn.dataset.originalHtml = btn.innerHTML; } btn.innerHTML = 'Enregistrer'; var onDone = function () { btn.disabled = false; btn.dataset.loading = '0'; if (btn.dataset.originalHtml) { btn.innerHTML = btn.dataset.originalHtml; } }; // Réactiver à la fermeture du modal ou après un timeout de secours var modal = document.getElementById('eventModal'); if (modal) { var handler = function () { modal.removeEventListener('hidden.bs.modal', handler); onDone(); }; modal.addEventListener('hidden.bs.modal', handler); } setTimeout(onDone, 8000); }, true ); }); })();