1(function () { 2 function closePanel(wrapper, trigger, panel) { 3 trigger.setAttribute("aria-expanded", "false"); 4 panel.classList.add("hidden"); 5 const icon = trigger.querySelector("[data-accordion-icon]"); 6 if (icon) icon.classList.remove("rotate-180"); 7 } 8 9 function openPanel(wrapper, trigger, panel, allowMultiple) { 10 if (!allowMultiple) { 11 // Close all others 12 wrapper 13 .querySelectorAll("[data-accordion-trigger]") 14 .forEach(function (btn) { 15 // Only act on triggers that belong to this wrapper level 16 if (btn.closest("[data-accordion]") !== wrapper) return; 17 if (btn !== trigger) { 18 const otherPanelId = btn.getAttribute("aria-controls"); 19 const otherPanel = 20 otherPanelId && document.getElementById(otherPanelId); 21 if (otherPanel) closePanel(wrapper, btn, otherPanel); 22 } 23 }); 24 } 25 trigger.setAttribute("aria-expanded", "true"); 26 panel.classList.remove("hidden"); 27 const icon = trigger.querySelector("[data-accordion-icon]"); 28 if (icon) icon.classList.add("rotate-180"); 29 } 30 31 function initAccordion(wrapper) { 32 const allowMultiple = 33 wrapper.getAttribute("data-allow-multiple") === "true"; 34 wrapper 35 .querySelectorAll("[data-accordion-trigger]") 36 .forEach(function (trigger) { 37 // Skip triggers that belong to nested accordions 38 if (trigger.closest("[data-accordion]") !== wrapper) return; 39 const panelId = trigger.getAttribute("aria-controls"); 40 const panel = panelId && document.getElementById(panelId); 41 if (!panel) { 42 try { 43 console.warn("[accordion] panel not found for trigger", { 44 trigger, 45 panelId, 46 }); 47 } catch (e) {} 48 return; 49 } 50 51 trigger.addEventListener("click", function () { 52 const expanded = trigger.getAttribute("aria-expanded") === "true"; 53 if (expanded) { 54 closePanel(wrapper, trigger, panel); 55 } else { 56 openPanel(wrapper, trigger, panel, allowMultiple); 57 } 58 }); 59 60 }); 61 } 62 63 function initAllAccordions() { 64 const nodes = document.querySelectorAll("[data-accordion]"); 65 nodes.forEach(initAccordion); 66 } 67 68 if (document.readyState === "loading") { 69 document.addEventListener("DOMContentLoaded", function () { 70 initAllAccordions(); 71 }); 72 } else { 73 // DOM is already parsed (interactive or complete) when script is loaded in footer 74 initAllAccordions(); 75 } 76})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.