1/** 2 * Accordion organism - expand/collapse & toggle behavior. 3 * 4 * Manages: 5 * - Expand all / Collapse all toggle button (label + icon + aria-controls) 6 * - Syncing aria-expanded on each <details> element with its open state, 7 * whether toggled via the "Expand/Collapse all" button or on click. 8 * 9 * Supports multiple accordion instances on the same page - each toggle 10 * button only affects the <details> elements inside the region referenced 11 * by its own aria-controls id. 12 */ 13 14(function (Drupal) { 15 'use strict'; 16 17 Drupal.behaviors.mtAccordion = { 18 attach: function (context) { 19 once('mtAccordion', '.mt-accordion', context).forEach(function (accordion) { 20 // Keep aria-expanded in sync with each <details> element's open 21 // state, regardless of what triggered the change. Uses its own 22 // once() id (distinct from accordion-item.js's 'mtAccordionItem') 23 // so both behaviors get to register their own 'toggle' listener 24 // on the same <details> elements instead of one skipping the other. 25 once('mtAccordionAriaExpanded', 'details', accordion).forEach(function (details) { 26 details.setAttribute('aria-expanded', details.open ? 'true' : 'false'); 27 details.addEventListener('toggle', function () { 28 details.setAttribute('aria-expanded', details.open ? 'true' : 'false'); 29 }); 30 }); 31 32 const toggleButton = accordion.querySelector('.mt-accordion__toggle-button'); 33 if (!toggleButton) { 34 return; 35 } 36 37 const toggleLabel = toggleButton.querySelector('.mt-text'); 38 const toggleIcon = toggleButton.querySelector('.mt-accordion__toggle-icon .mt-icon'); 39 40 let isExpanded = false; 41 42 function updateToggleUI() { 43 if (toggleLabel) { 44 toggleLabel.textContent = isExpanded ? Drupal.t('Collapse all') : Drupal.t('Expand all'); 45 } 46 if (toggleIcon) { 47 toggleIcon.textContent = isExpanded ? 'remove' : 'add'; 48 } 49 } 50 51 toggleButton.addEventListener('click', function () { 52 isExpanded = !isExpanded; 53 54 const controlsId = toggleButton.getAttribute('aria-controls'); 55 const controlledRegion = controlsId ? document.getElementById(controlsId) : null; 56 57 if (controlledRegion) { 58 controlledRegion.querySelectorAll('details').forEach(function (details) { 59 details.open = isExpanded; 60 details.setAttribute('aria-expanded', isExpanded ? 'true' : 'false'); 61 }); 62 } 63 64 updateToggleUI(); 65 }); 66 }); 67 } 68 }; 69})(Drupal);
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.