wgallop wgallop - 6 months ago 81
HTML Question

Vanilla JS remove class from all other elements besides 'active' class

I'm trying to build a dropdown menu with Vanilla JavaScript and I can't figure out the best way to add a class of active to the clicked dropdown menu, and then at the same time remove all other active classes from the sibling elements.

so far this is what I have as far as JS:

var _dropdowns = [].slice.call(document.getElementsByClassName('main-menu-li_dropdown'));

_dropdowns.forEach(function(dropdowns) {
dropdowns.addEventListener('click', function( event ){
event.preventDefault();
console.log(this !== event.target);
this.classList.toggle('active');
});
});


And here is my markup:

<nav id="main-nav">
<ul>
<li class="main-menu-li_dropdown">
<a href="">link</a>
<ul class="sub-nav">
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
</ul>
</li>
<li class="main-menu-li_dropdown">
<a href="">link</a>
<ul class="sub-nav">
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
</ul>
</li>
<li class="main-menu-li_dropdown">
<a href="">link</a>
<ul class="sub-nav">
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
</ul>
</li>
<li class="main-menu-li_dropdown">
<a href="">link</a>
<ul class="sub-nav">
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
</ul>
</li>
<li class="main-menu-li_dropdown">
<a href="">link</a>
<ul class="sub-nav">
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
<li><a href="">link</a></li>
</ul>
</li>
</ul>
</nav>

Answer

You can loop through all of the items and remove the class, then add the class to the item that was clicked.

Here is an example:

http://jsbin.com/rivogelaqu/edit?html,js,output

let dropDowns = Array.from(document.querySelectorAll('.main-menu-li_dropdown'));

const handleClick = (e) => {
  e.preventDefault();
  dropDowns.forEach(node => {
    node.classList.remove('active');
  });
  e.currentTarget.classList.add('active');

}

dropDowns.forEach(node => {
  node.addEventListener('click', handleClick)
});

Edit: Alternative Click Handler

Here is an alternative click handler that avoids a loop on each click and just checks for the element. May be more performant.

const handleClick = (e) => {
  e.preventDefault();
  const active = document.querySelector('.active');
  if(active){
    active.classList.remove('active');
  }
  e.currentTarget.classList.add('active');
}