I have a treeview with accordion which is working, but I want to collapse all previously opened items when a different one is clicked.
For example, in my jsFiddle, clicking on 'Beverages' will expand it. Then clicking on 'Food' will expand that one. I want 'Beverages' to collapse when 'Food' is clicked on, and vice versa.
I tried adding a new class in addition to the caret
class thinking to remove all caret-down
classes prior to the toggler function but I couldn't figure out how to call it before that click function. Would someone please explain how to close all previous expanded items and then expand the one that was clicked on?
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");
});
}
ul,
#myUL {
list-style-type: none;
}
#myUL {
margin: 0;
padding: 0;
}
.box {
cursor: pointer;
-webkit-user-select: none;
/* Safari 3.1+ */
-moz-user-select: none;
/* Firefox 2+ */
-ms-user-select: none;
/* IE 10+ */
user-select: none;
}
.box::before {
content: "\2610";
color: black;
display: inline-block;
margin-right: 6px;
}
.check-box::before {
content: "\2611";
color: dodgerblue;
}
.nested {
display: none;
}
.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li>
<span class="caret">Beverages</span>
<ul class="nested">
<li>Water</li>
<li>Coffee</li>
<li>
<span class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>
<span class="caret">Green Tea</span>
<ul class="nested">
<li>Sencha</li>
<li>Gyokuro</li>
<li>Matcha</li>
<li>Pi Lo Chun</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span class="caret">Food</span>
<ul class="nested">
<li>Water</li>
<li>Coffee</li>
<li>
<span class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>
<span class="caret">Green Tea</span>
<ul class="nested">
<li>Sencha</li>
<li>Gyokuro</li>
<li>Matcha</li>
<li>Pi Lo Chun</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
For this to work you need to remove the relevant classes from any .caret
and its sibling ul.nested
which is not a parent of the .caret
which is clicked. This can be done most simply using a combination of jQuery's closest()
, children()
, ,parents()
and find()
methods. Try this:
let $carets = $('.caret').on('click', e => {
let $caret = $(e.target);
// display the clicked item
$caret.toggleClass('caret-down');
$caret.closest('li').children('.nested').toggleClass('active');
// hide the rest
let $parentCarets = $caret.parents('li').children('.caret');
$carets.not($parentCarets).removeClass('caret-down').closest('li').find('.nested').removeClass('active');
});
ul,
#myUL {
list-style-type: none;
}
#myUL {
margin: 0;
padding: 0;
}
.box {
cursor: pointer;
-webkit-user-select: none;
/* Safari 3.1+ */
-moz-user-select: none;
/* Firefox 2+ */
-ms-user-select: none;
/* IE 10+ */
user-select: none;
}
.box::before {
content: "\2610";
color: black;
display: inline-block;
margin-right: 6px;
}
.check-box::before {
content: "\2611";
color: dodgerblue;
}
.nested {
display: none;
}
.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<span class="caret">Beverages</span>
<ul class="nested">
<li>Water</li>
<li>Coffee</li>
<li>
<span class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>
<span class="caret">Green Tea</span>
<ul class="nested">
<li>Sencha</li>
<li>Gyokuro</li>
<li>Matcha</li>
<li>Pi Lo Chun</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span class="caret">Food</span>
<ul class="nested">
<li>Water</li>
<li>Coffee</li>
<li>
<span class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li>
<span class="caret">Green Tea</span>
<ul class="nested">
<li>Sencha</li>
<li>Gyokuro</li>
<li>Matcha</li>
<li>Pi Lo Chun</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>