document.addEventListener("DOMContentLoaded", function () {
const jsonData = [
{ text: "TITLE 1", children: [
{ text: "subtitle 1", children: [
{ text: "sub subtitle 1a" },
{ text: "sub subtitle 1b" } ] },
{ text: "subtitle 2", children: [
{ text: "sub subtitle 2a"},
{ text: "sub subtitle 2b"}
] },
{ text: "subtitle 3" }
] },
{ text: "TITLE 2", children: [
{ text: "subtitle 1" },
{ text: "subtitle 2" },
{ text: "subtitle 3" } ] },
{ text: "TITLE 3", children: [
{ text: "subtitle 1", children: [
{ text: "sub subtitle 1a" },
{ text: "sub subtitle 1b" } ] },
{ text: "subtitle 2" }
]
}
];
const treeContainer = document.getElementById("tree");
function createTree(treeData, parentElement) {
treeData.forEach(item => {
const listItem = document.createElement("li");
const toggleButton = document.createElement("button");
toggleButton.innerText = item.text;
let sublist; // Define sublist variable here
if (item.children) { // still have children
sublist = document.createElement("ul");
// toggleButton.style.content = "▼";
createTree(item.children, sublist);
listItem.appendChild(toggleButton);
listItem.appendChild(sublist);
} else { // no more children
const toggleButton2 = document.createElement("button");
toggleButton2.innerText = item.text;
listItem.appendChild(toggleButton2);
}
toggleButton.addEventListener("click", () => {
if (sublist) {
toggleButton.classList.toggle("toggled");
if(sublist.style.maxHeight){
sublist.style.maxHeight = null;
} else {
sublist.style.maxHeight = sublist.scrollHeight + "px";
}
}
});
parentElement.appendChild(listItem);
});
}
createTree(jsonData, treeContainer);
});
/* Apply basic styling */
ul {
list-style-type: none;
padding-left: 20px;
margin: 0px;
overflow: hidden;
max-height: 0;
transition: max-height 0.2s ease-out;
}
li {
list-style-type: none;
padding-left: 20px;
margin: 0px;
}
li > button {
background: blue;
border: none;
border-radius: 3px;
cursor: pointer;
padding: 10px;
}
li > ul > li > button {
background: yellow;
border: none;
cursor: pointer;
padding: 10px;
}
li > ul > li > ul > li > button {
background: green;
border: none;
cursor: pointer;
padding: 0;
}
button:focus {
outline: none;
}
/* Add icon for the toggle button */
button:has(+ ul)::after {
content: "25BC";
padding-right: 5px;
}
/* Style the button when it's toggled */
button.toggled:has(+ ul)::after {
content: "25B2";
}
<!DOCTYPE html>
<html>
<head>
<title>My Site </title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="tree"></div>
<script src="script.js"></script>
</body>
</html>
I have the html ,css js codes as above.
when i click the title 1, it expands using the maxheight attributes
when i click the subtitle 1, it still expand its content but the subtitle 3 is being cut out from the view.
how to make the subtitle 3 still in view after expanding subtitle 1, etc
ive tried chatgpt / bard, but no use.
2
Answers
You can simply adjust the maxHeight with the
calc
functionsublist.style.maxHeight = `calc(100% - 100px)`
Here’s a working Demo:
You need to take into account the scroll height of the sublist’s child nodes, as well as the scroll height of the toggle button. So, you have to change the line:
with the following:
You can test the result here.
Try adding more list items to a sublist to test if it’s responding correctly.