(
titleText,
type = "indicator",
options = {},
)
| 29 | * @returns {Collapsible} |
| 30 | */ |
| 31 | export default function collapsableList( |
| 32 | titleText, |
| 33 | type = "indicator", |
| 34 | options = {}, |
| 35 | ) { |
| 36 | let onscroll = null; |
| 37 | const $ul = tag("ul", { |
| 38 | className: "scroll", |
| 39 | onscroll: onUlScroll, |
| 40 | }); |
| 41 | const $collapseIndicator = tag("span", { |
| 42 | className: `icon ${type}`, |
| 43 | }); |
| 44 | const $title = tile({ |
| 45 | lead: $collapseIndicator, |
| 46 | type: "div", |
| 47 | text: options.allCaps ? titleText.toUpperCase() : titleText, |
| 48 | tail: options.tail, |
| 49 | }); |
| 50 | const $mainWrapper = tag(options.type || "div", { |
| 51 | className: "list collapsible hidden", |
| 52 | children: [$title, $ul], |
| 53 | }); |
| 54 | |
| 55 | let collapse = () => { |
| 56 | $mainWrapper.classList.add("hidden"); |
| 57 | if ($mainWrapper.ontoggle) $mainWrapper.ontoggle.call($mainWrapper); |
| 58 | delete $ul.dataset.scrollTop; |
| 59 | }; |
| 60 | |
| 61 | let expand = () => { |
| 62 | $mainWrapper.classList.remove("hidden"); |
| 63 | if ($mainWrapper.ontoggle) $mainWrapper.ontoggle.call($mainWrapper); |
| 64 | }; |
| 65 | |
| 66 | $title.classList.add("light"); |
| 67 | $title.addEventListener("click", toggle); |
| 68 | |
| 69 | [$title, $mainWrapper].forEach(defineProperties); |
| 70 | |
| 71 | $mainWrapper.dataset.id = `${Math.random().toString(36).substring(2, 15)}`; |
| 72 | |
| 73 | return $mainWrapper; |
| 74 | |
| 75 | function onUlScroll() { |
| 76 | if (onscroll) onscroll.call($ul); |
| 77 | $ul.dataset.scrollTop = $ul.scrollTop; |
| 78 | } |
| 79 | |
| 80 | function toggle() { |
| 81 | if ($title.collapsed) { |
| 82 | expand(); |
| 83 | } else { |
| 84 | collapse(); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | function defineProperties($el) { |
no test coverage detected