I would like a treeview that users can update (add, delete, and rename nodes), but I ran into an issue.
I'm starting from the process described here: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_treeview. You can see how I'm trying to update a node here: https://jsfiddle.net/mervius68/4of5ung0/2/. If I replace the outerHTML of an element using Javascript, the class inside that text (necessary for opening and closing tree nodes) is no longer recognized. How do I get the CSS to apply to the Javascript-created HTML? The node called "Tea" gets successfully renamed to "BEAR," but is then no longer able to toggle between collapsed and open.
I can get this to work when just changing the innerHTML, but I need to add entire new nodes, so I think I need to get the outerHTML option working. Please help?
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
ul, #myUL {
list-style-type: none;
}
#myUL {
margin: 0;
padding: 0;
}
span.caret {
cursor: pointer;
-webkit-user-select: none; /* Safari 3.1+ */
-moz-user-select: none; /* Firefox 2+ */
-ms-user-select: none; /* IE 10+ */
user-select: none;
}
span.caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
span.caret-down::before {
-ms-transform: rotate(90deg); /* IE 9 */
-webkit-transform: rotate(90deg); /* Safari */'
transform: rotate(90deg);
}
.nested {
display: none;
}
.active {
display: block;
}
</style>
</head>
<body>
<h2>Tree View</h2>
<p>A tree view represents a hierarchical view of information, where each item can have a number of subitems.</p>
<p>Click on the arrow(s) to open or close the tree branches.</p>
<ul id="myUL">
<li><span class="caret">Beverages</span>
<ul class="nested">
<li>Water</li>
<li>Coffee</li>
<li><span id="test" class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>Green Tea</li>
</ul>
</li>
</ul>
</li>
</ul>
<button onclick="myFunction()">Click me</button>
<script>
function myFunction() {
document.getElementById("test").outerHTML = `<li><span id="test2"
class="caret">BEAR</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>Green Tea</li>
</ul>
</li>`
}
</script>
<script>
var toggler = document.getElementsByClassName("caret");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
</script>
</body>
</html>
The problem isn't class not being recognized. The problem, as @A Haworth mentioned in the comments, is that you haven't attached any event listeners to the newly created element. The script you have that attaches event listeners to all caret
class only runs once when it is loaded. Afterwards, if you're creating new elements, you must attach a new event listener to this new element.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
ul, #myUL {
list-style-type: none;
}
#myUL {
margin: 0;
padding: 0;
}
span.caret {
cursor: pointer;
-webkit-user-select: none; /* Safari 3.1+ */
-moz-user-select: none; /* Firefox 2+ */
-ms-user-select: none; /* IE 10+ */
user-select: none;
}
span.caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
span.caret-down::before {
-ms-transform: rotate(90deg); /* IE 9 */
-webkit-transform: rotate(90deg); /* Safari */'
transform: rotate(90deg);
}
.nested {
display: none;
}
.active {
display: block;
}
</style>
</head>
<body>
<h2>Tree View</h2>
<p>A tree view represents a hierarchical view of information, where each item can have a number of subitems.</p>
<p>Click on the arrow(s) to open or close the tree branches.</p>
<ul id="myUL">
<li><span class="caret">Beverages</span>
<ul class="nested">
<li>Water</li>
<li>Coffee</li>
<li><span id="test" class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>Green Tea</li>
</ul>
</li>
</ul>
</li>
</ul>
<button onclick="myFunction()">Click me</button>
<script>
function myFunction() {
document.getElementById("test").outerHTML = `<li><span id="test2"
class="caret">BEAR</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>Green Tea</li>
</ul>
</li>`
document.getElementById("test2").addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
</script>
<script>
var toggler = document.getElementsByClassName("caret");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
</script>
</body>
</html>