1// 2// accordion 3// 4// Local copy of kk/panda-core's accordion component, scoped to the timetable 5// plugin: the page level accordions are already initialized by the accordion of 6// the sitepackage bundle, so everything outside `scope` must stay untouched - 7// a second click handler would toggle each item twice. 8// 9 10const selectors = { 11 scope: '.content-element.timetable', 12 component: '.accordion', 13 trigger: '.toggle-trigger', 14 item: '.accordion-item', 15 content: '.content-section', 16}; 17 18const attributes = { 19 data: { 20 activeBehavior: 'data-active-behavior', 21 }, 22}; 23 24const states = { 25 open: 'accordion-item--open', 26}; 27 28function accordion() { 29 30 const components = document.querySelectorAll(`${selectors.scope} ${selectors.component}`); 31 components.forEach((component) => { 32 initializeToggleClickHandler(component); 33 }); 34} 35 36function initializeToggleClickHandler(component) { 37 const accordionItems = component.querySelectorAll(selectors.item); 38 accordionItems.forEach(function (accordionItem) { 39 const trigger = accordionItem.querySelector(selectors.trigger); 40 trigger.addEventListener('click', (event) => { 41 event.preventDefault(); 42 toggleAccordionItem(accordionItem); 43 }); 44 }); 45} 46 47function toggleAccordionItem(accordionItem) { 48 if (accordionItem.classList.contains(states.open)) { 49 closeAccordionItem(accordionItem) 50 } else { 51 openAccordionItem(accordionItem) 52 } 53} 54 55function closeAllAccordionItems(accordionItems) { 56 accordionItems.forEach(function (accordionItem) { 57 closeAccordionItem(accordionItem); 58 }); 59} 60 61function closeAccordionItem(accordionItem) { 62 const content = accordionItem.querySelector(selectors.content); 63 accordionItem.classList.remove(states.open); 64 content.style.height = content.scrollHeight + 'px'; 65 setTimeout( function (){ 66 content.style.height = 0; 67 }, 10); 68} 69 70function openAccordionItem(accordionItem) { 71 const content = accordionItem.querySelector(selectors.content); 72 73 // check the active behavior setting 74 if (accordionItem.closest(selectors.component).getAttribute(attributes.data.activeBehavior) === 'single') { 75 let accordionItems = accordionItem.closest(selectors.component).querySelectorAll(selectors.item); 76 const index = Array.from(accordionItems).indexOf(accordionItem); 77 accordionItems = Array.from(accordionItems).filter((item, i) => i !== index); 78 closeAllAccordionItems(accordionItems); 79 } 80 accordionItem.classList.add(states.open); 81 content.style.height = content.scrollHeight + 'px'; 82 /*content.addEventListener('transitionend', function() { 83 if (content.offsetHeight > 0) { 84 content.style.height = 'auto'; 85 } 86 });*/ 87} 88 89window.addEventListener('DOMContentLoaded', function () { 90 return { 91 accordion: accordion(), 92 }; 93}); 94 95export { accordion };
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.