function wireAdminDropdowns() { const reposition = (toggle, menu) => { const rect = toggle.getBoundingClientRect(); const gutter = 8; const menuWidth = menu.offsetWidth || 220; const menuHeight = menu.offsetHeight || 0; // Prefer placing the menu to the right of the toggle; clamp within viewport. let left = rect.right + gutter; if (left + menuWidth > window.innerWidth - gutter) { left = Math.max(gutter, window.innerWidth - menuWidth - gutter); } let top = Math.max(gutter, Math.min(rect.top, window.innerHeight - menuHeight - gutter)); menu.style.position = 'fixed'; menu.style.transform = 'none'; menu.style.top = `${top}px`; menu.style.left = `${left}px`; menu.style.right = 'auto'; menu.style.minWidth = `${Math.max(rect.width, 160)}px`; menu.style.maxWidth = '260px'; menu.style.display = 'block'; menu.dataset.dropdownOpen = '1'; menu.classList.add('show'); }; const resetMenu = (menu) => { menu.style.position = ''; menu.style.transform = ''; menu.style.top = ''; menu.style.left = ''; menu.style.right = ''; menu.style.minWidth = ''; menu.style.maxWidth = ''; menu.style.display = ''; menu.classList.remove('show'); delete menu.dataset.dropdownOpen; }; document.querySelectorAll('.admin-nav .dropdown-toggle').forEach((toggle) => { if (toggle.dataset.dropdownWired) return; toggle.dataset.dropdownWired = '1'; const menu = toggle.nextElementSibling; if (!menu) return; toggle.addEventListener('shown.bs.dropdown', () => reposition(toggle, menu)); toggle.addEventListener('hide.bs.dropdown', () => resetMenu(menu)); window.addEventListener('scroll', () => { if (menu.dataset.dropdownOpen) reposition(toggle, menu); }, { passive: true }); window.addEventListener('resize', () => { if (menu.dataset.dropdownOpen) reposition(toggle, menu); }); }); } if (document.readyState === 'complete' || document.readyState === 'interactive') { wireAdminDropdowns(); } else { document.addEventListener('DOMContentLoaded', wireAdminDropdowns); } // 1) Delegate clicks on any .toggle-icon, now or in the future: document.addEventListener('click', function(e) { // Find the closest .toggle-icon ancestor of the click target, if any if (!e.target.classList.contains('toggle-icon')) return; var icon = e.target; // Prevent clicks on the icon from bubbling further if you want e.stopPropagation(); // Locate its .card-body.collapsable in the same card var card = icon.closest('.card'); if (!card) return; var body = card.querySelector('.card-body.collapsable'); if (!body) return; // Toggle the 'show' class and swap +/– text if (body.classList.contains('show')) { // Collapse: remove show, update icon, remove from set body.classList.remove('show'); icon.textContent = '+'; icon.setAttribute('aria-expanded', 'false'); openCards.add(key); } else { // Expand: add show, update icon, add to set body.classList.add('show'); icon.textContent = '–'; icon.setAttribute('aria-expanded', 'true'); openCards.add(key); } });