1document.addEventListener("DOMContentLoaded", () => { 2 const listWrappers = document.querySelectorAll( 3 "[data-show-more-list-wrapper]", 4 ); 5 6 listWrappers.forEach((listWrapper) => { 7 const list = listWrapper.querySelector("[data-show-more-list]"); 8 const listId = list.getAttribute("data-show-more-list-id"); 9 const listElements = list.querySelectorAll("[data-show-more-item]"); 10 const amountOfListElements = parseInt(listElements.length, 10); 11 const listShowMoreButton = listWrapper.querySelector( 12 "[data-show-more-button]", 13 ); 14 15 if (!list || !listShowMoreButton || !listElements || !listId) { 16 const missingElements = []; 17 if (!list) missingElements.push("list"); 18 if (!listShowMoreButton) missingElements.push("listShowMoreButton"); 19 if (!listElements.length) missingElements.push("listElements"); 20 if (!listId) missingElements.push("listId"); 21 22 console.debug( 23 `show-more.js: Missing required elements: ${missingElements.join(", ")}`, 24 ); 25 return; 26 } 27 28 // Add listId & aria attributes to list and buttons 29 list.setAttribute("id", `list-id-${listId}`); 30 listShowMoreButton.setAttribute("aria-controls", `list-id-${listId}`); 31 32 const initialVisibleItems = parseInt( 33 list.getAttribute("data-initial-visible-items") || amountOfListElements, 34 10, 35 ); 36 37 // Stacked items (e.g. stacked event instances) follow their parent and 38 // should not count toward the initial visible count. 39 // @todo: clear this with the client! 40 const isStacked = (item) => 41 item.hasAttribute("data-show-more-item-stacked"); 42 const countableElements = Array.from(listElements).filter( 43 (item) => !isStacked(item), 44 ); 45 46 // Hide button if there are fewer countable items than the initial visible items 47 if (initialVisibleItems >= countableElements.length) { 48 listShowMoreButton.classList.add("show-more__hidden"); 49 return; 50 } 51 52 // Hide items beyond the initial visible items, ignoring stacked items 53 // when counting. 54 let shownCountable = 0; 55 listElements.forEach((listItem) => { 56 if (!isStacked(listItem)) shownCountable += 1; 57 if (shownCountable > initialVisibleItems) 58 listItem.classList.add("show-more__hidden"); 59 }); 60 61 const showMoreText = listShowMoreButton.getAttribute("data-show-more-text"); 62 const showLessText = listShowMoreButton.getAttribute("data-show-less-text"); 63 const hideListButtonAfterExpand = list.getAttribute( 64 "data-hide-list-button-after-expand", 65 ); 66 67 listShowMoreButton.addEventListener("click", () => { 68 let toggledCountable = 0; 69 listElements.forEach((listItem) => { 70 if (!isStacked(listItem)) toggledCountable += 1; 71 if (toggledCountable > initialVisibleItems) 72 listItem.classList.toggle("show-more__hidden"); 73 }); 74 75 const isAriaExpanded = 76 listShowMoreButton.getAttribute("aria-expanded") === "true"; 77 listShowMoreButton.setAttribute("aria-expanded", !isAriaExpanded); 78 79 listShowMoreButton.innerText = isAriaExpanded 80 ? showMoreText 81 : showLessText; 82 83 if (hideListButtonAfterExpand === "true" && !isAriaExpanded) { 84 listShowMoreButton.classList.add("show-more__hidden"); 85 } 86 }); 87 }); 88});
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.