I am building a dropdown menu. As is, when I open one submenu, it stays open, even if I open a second submenu. When I open the second submenu, it should close any other open menus.
const submenuLinks = document.querySelectorAll('.has-submenu > a');
submenuLinks.forEach(element => element.addEventListener('click', function(e) {
var submenu = element.nextElementSibling;
if (submenu.classList.contains('menu-hide')) {
submenu.classList.add('menu-show');
submenu.classList.remove('menu-hide');
} else {
submenu.classList.add('menu-hide');
submenu.classList.remove('menu-show');
}
}));
.menu-hide {
display: none;
}
.menu-show {
display: block;
}
<nav>
<ul class="menu">
<li>
<a href="#">Menu Item 1</a>
</li>
<li class="has-submenu">
<a href="#">Menu Item 2 »</a>
<ul class="menu-sub menu-hide">
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 2</a></li>
<li><a href="#">Submenu Item 3</a></li>
</ul>
</li>
<li class="has-submenu">
<a href="#">Menu Item 3 »</a>
<ul class="menu-sub menu-hide">
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 2</a></li>
<li><a href="#">Submenu Item 3</a></li>
</ul>
</li>
</ul>
</nav>
.menu-showTry this
const submenuLinks = document.querySelectorAll('.has-submenu > a');
submenuLinks.forEach(element => element.addEventListener('click', function(e) {
var submenu = element.nextElementSibling;
if (submenu.classList.contains('menu-show')) {
submenu.classList.remove('menu-show');
} else {
submenuLinks.forEach(a => a.nextElementSibling.classList.remove('menu-show'));
submenu.classList.add('menu-show');
}
}));
.menu-sub {
display: none;
}
.menu-show {
display: block;
}
<nav>
<ul class="menu">
<li>
<a href="#">Menu Item 1</a>
</li>
<li class="has-submenu">
<a href="#">Menu Item 2 »</a>
<ul class="menu-sub">
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 2</a></li>
<li><a href="#">Submenu Item 3</a></li>
</ul>
</li>
<li class="has-submenu">
<a href="#">Menu Item 3 »</a>
<ul class="menu-sub">
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 2</a></li>
<li><a href="#">Submenu Item 3</a></li>
</ul>
</li>
</ul>
</nav>
before your logic that hides the current submenu, you can hide every submenu (ul with class 'menu-sub'). In this way, only the current submenu will be expanded. Here's the edited javascript code:
const submenuLinks = document.querySelectorAll('.has-submenu > a');
submenuLinks.forEach((element) =>
element.addEventListener('click', function (e) {
var allSubmenus = document.querySelectorAll('.menu-sub');
allSubmenus.forEach((submenu) => {
submenu.classList.remove(...submenu.classList);
submenu.classList.add('menu-sub');
submenu.classList.add('menu-hide');
});
var currentSubmenu = element.nextElementSibling;
if (currentSubmenu.classList.contains('menu-hide')) {
currentSubmenu.classList.add('menu-show');
currentSubmenu.classList.remove('menu-hide');
} else {
currentSubmenu.classList.add('menu-hide');
currentSubmenu.classList.remove('menu-show');
}
})
);
What I did there extra was to remove all the classes from the submenus, add back the 'menu-sub' and 'menu-hide' classes.
You must loop over all ul's to check the classes. I commented what i add to you js code.
const uls = document.querySelectorAll('.menu-sub');
uls.forEach(a => {
if (a.classList.contains('menu-show')) {
a.classList.remove('menu-show')
a.classList.add('menu-hide')
}
})
const submenuLinks = document.querySelectorAll('.has-submenu > a');
submenuLinks.forEach(element => element.addEventListener('click', function(e) {
/* start */
const uls = document.querySelectorAll('.menu-sub');
uls.forEach(a => {
if (a.classList.contains('menu-show')) {
a.classList.remove('menu-show')
a.classList.add('menu-hide')
}
})
/* end */
var submenu = element.nextElementSibling;
if (submenu.classList.contains('menu-hide')) {
submenu.classList.add('menu-show');
submenu.classList.remove('menu-hide');
} else {
submenu.classList.add('menu-hide');
submenu.classList.remove('menu-show');
}
}));
.menu-hide {
display: none;
}
.menu-show {
display: block;
}
<nav>
<ul class="menu">
<li>
<a href="#">Menu Item 1</a>
</li>
<li class="has-submenu">
<a href="#">Menu Item 2 »</a>
<ul class="menu-sub menu-hide">
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 2</a></li>
<li><a href="#">Submenu Item 3</a></li>
</ul>
</li>
<li class="has-submenu">
<a href="#">Menu Item 3 »</a>
<ul class="menu-sub menu-hide">
<li><a href="#">Submenu Item 1</a></li>
<li><a href="#">Submenu Item 2</a></li>
<li><a href="#">Submenu Item 3</a></li>
</ul>
</li>
</ul>
</nav>