PageSourceSearch

https://www.moonliner.ch/_assets/187c25ce80055c161a2e884abecefef3/…=88f18b678bf4c06a301f7a92708d6738e3380368

js moonliner.ch collected 2026-10-02 19:23:32 UTC 2,934 bytes, 95 lines download raw bytes

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.