JSFiddle - React, Tailwind, and code Playground
by amindunited
JavaScript
// Create a class for the element
class ExpandingList extends HTMLUListElement {
constructor() {
// Always call super first in constructor
// Return value from super() is a reference to this element
self = super();
}
connectedCallback() {
// Get ul and li elements that are a child of this custom ul element
// li elements can be containers if they have uls within them
const uls = Array.from(self.querySelectorAll("ul"));
const lis = Array.from(self.querySelectorAll("li"));
// Hide all child uls
// These lists will be shown when the user clicks a higher level container
uls.forEach((ul) => {
ul.style.display = "none";
});
// Look through each li element in the ul
lis.forEach((li) => {
// If this li has a ul as a child, decorate it and add a click handler
if (li.querySelectorAll("ul").length > 0) {
// Add an attribute which can be used by the style
// to show an open or closed icon
li.setAttribute("class", "closed");
// Wrap the li element's text in a new span element
// so we can assign style and event handlers to the span
const childText = li.childNodes[0];
const newSpan = document.createElement("span");
// Copy text from li to span, set cursor style
newSpan.textContent = childText.textContent;
newSpan.style.cursor = "pointer";
// Add click handler to this span
newSpan.addEventListener("click", (e) => {
// next sibling to the span should be the ul
const nextul = e.target.nextElementSibling;
// Toggle visible state and update class attribute on ul
if (nextul.style.display == "block") {
nextul.style.display = "none";
nextul.parentNode.setAttribute("class", "closed");
} else {
nextul.style.display = "block";
nextul.parentNode.setAttribute("class", "open");
}
});
// Add...