i am trying to create a menu with JS, when i click on the first menu item and it is open, then i want when i click on the next item i want the first one to close and the second one to open and when i am clicking on the open menu item i want it to close. also when i click anywhere if i can make it close as well...
here the code i have
HTML
<div class="container-header">
<div class="navbar">
<ul>
<li>
<a onclick="dropdownToggle(event)"><span>Products</span></a>
<div class="dropdown">
<ul class="submenu-img">
<li><a><img src="2015_images/img.png">title</a></li>
<li><a><img src="2015_images/img.png">title</a></li>
<li><a><img src="2015_images/img.png">title</a></li>
<li><a><img src="2015_images/img.png">title</a></li>
<li><a><img src="2015_images/img.png">title</a></li>
</ul>
</div>
</li>
<li><a onclick="dropdownToggle(event)"><span>Services</span></a>
<div class="dropdown">
<ul class="submenu">
<li><a>item</a></li>
<li><a>item</a></li>
<li><a>item</a></li>
<li><a>item</a></li>
</ul>
</div>
</li>
<li><a onclick="dropdownToggle(event)"> <span>Softwares</span></a>
<div class="dropdown">
<ul class="submenu">
<li><a>item</a></li>
<li><a>item</a></li>
<li><a>item</a></li>
<li><a>item</a></li>
</ul>
</div>
</li>
</ul>
</div>
CSS
* {
box-sizing: border-box;
}
ul {
list-style: none;
}
.navbar {
width: 100%;
text-align: center;
position: absolute;
top: -500px;
background-color: #585859;
transition: top 0.3s;
z-index: 1;
}
#media screen and (min-width: 768px) {
.navbar {
line-height: 65px;
width: auto;
position: static;
}
}
.navbar ul {
margin: 0;
padding: 0;
}
.navbar li {
vertical-align: middle;
color: #fff;
padding: 10px;
border-bottom: 5px solid #fff;
}
#media screen and (min-width: 768px) {
.navbar li {
display: inline-block;
margin-right: 10px;
border: none;
padding: 0;
}
}
.dropdown {
display: none;
}
.dropdown-open {
display: block;
position: absolute;
top: 70px;
left: 0;
background: rgba(88, 88, 89, 0.7);
width: 100%;
}
.submenu {
width: 100%;
display: flex;
align-items: center;
flex-flow: row;
justify-content: center;
padding: 10px 0 !important;
}
.submenu li {
margin: 0 2px;
flex: 0 0 12%;
line-height: normal;
}
and JS
function dropdownToggle(event) {
var dropdownItem = event.target.parentElement.parentElement.getElementsByClassName("dropdown")[0];
if (dropdownItem.classList.contains("dropdown-open")) {
var dropdowns = document.querySelectorAll(".dropdown");
var arrayLength = dropdowns.length;
for (var i = 0; i < arrayLength; i++) {
dropdowns[i].classList.remove("dropdown-open");
}
}
else {
dropdownItem.classList.toggle("dropdown-open");
}
}
I tried on JSFiddle but it is not working so here is a codepen as well..
http://codepen.io/nnns/pen/rLvdgE
The best way will be to put
var dropdowns = document.querySelectorAll(".dropdown");
var arrayLength = dropdowns.length;
for (var i = 0; i < arrayLength; i++) {
dropdowns[i].classList.remove("dropdown-open");
}
in a function and call it at the beginning of your function dropdownToggle(event) so like that every time you call your function you close everything and can open what you want.
EDIT
Do this:
function dropdownToggle(event) {
var dropdownItem =event.target.parentElement.parentElement.getElementsByClassName("dropdown")[0];
var dropdowns = document.querySelectorAll(".dropdown");
var arrayLength = dropdowns.length;
for (var i = 0; i < arrayLength; i++) {
dropdowns[i].classList.remove("dropdown-open");
}
dropdownItem.classList.add("dropdown-open");
}
function dropdownToggle(event) {
var dropdownItem = event.target.parentElement.getElementsByClassName("dropdown")[0];
dropdownItem.classList.remove("dropdown");
var dropdowns = document.querySelectorAll(".dropdown");
var arrayLength = dropdowns.length;
for (var i = 0; i < arrayLength; i++) {
dropdowns[i].classList.remove("dropdown-open");
}
dropdownItem.classList.toggle("dropdown-open");
dropdownItem.classList.add("dropdown");
}
This removes all dropdown open classes and toggles the dropdown that is found in the parent(li) of the a.
To close on body click:
document.all.body.onclick=dropdownToggle(document.all.body);
Related
With the help of Michael M. I edited my WordPress menu code in the previous question nicely.
Now I want to open the submenu slowly whenever every li is clicked if there is a ul under it, which I wrote this code but in addition to opening the sub menu, I want the right direction sign (→) to the down direction sign (↓ ) to change.
I have put all the code of this professional menu below, but my problem is only related to the last script code.
let icon = document.querySelector(".icon_menu");
let nav = document.querySelector(".main_menu");
$('.back').hide();
$('.back').click(function() {
if ($(this).is(':hidden')) return;
$(this).toggle();
icon.classList = "bi bi-grid-fill icon_menu";
icon.style.left = "2%";
icon.style.color = "#a66fff";
icon.style.fontSize = "40px";
nav.style.left = '-300px';
});
icon.addEventListener("click", function() {
if (this.classList.contains("bi-grid-fill")) {
this.classList = "bi bi-x-circle-fill icon_menu";
icon.style.left = "21%";
icon.style.color = "#ff6f6f";
icon.style.fontSize = "30px";
nav.style.left = 0;
} else {
this.classList = "bi bi-grid-fill icon_menu";
icon.style.left = "2%";
icon.style.color = "#a66fff";
icon.style.fontSize = "40px";
nav.style.left = "-300px";
}
$('.back').toggle();
});
//********************** **A script that needs editing** *********************
$('.main_menu').find('li').click(function(sub_menu) {
sub_menu.stopPropagation();
sub_menu.preventDefault();
$(this).children('ul').slideToggle();
if ($(this).is(style.content = ' → ')) {
this.style.content = " ↓ ";
};
});
.main_menu {
position: absolute;
top: 0;
left: -300px;
bottom: 0;
z-index: 999;
background: #eee;
padding-right: 2rem;
transition: all 1s ease;
}
.icon_menu {
position: fixed;
top: 10%;
left: 2%;
font-size: 40px;
color: #a66fff;
cursor: pointer;
z-index: 99999;
transition: all 1.1s ease;
}
.main_menu ul {
list-style: none;
line-height: 60px;
font-size: 35px;
}
.main_menu ul li a {
color: #000000;
text-decoration: none;
padding-right: 15px;
padding-left: 40px;
margin-left: -60px;
margin-bottom: 10px;
}
.back {
width: 100%;
height: 100%;
position: fixed;
z-index: 9 !important;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #00000056;
}
.main_menu ul li ul {
display: none;
}
.main_menu ul li>a::after {
content: ' → ';
}
.main_menu ul li:first-child>a::after {
content: ' → ';
}
.main_menu ul li>a:only-child::after {
content: ' ';
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.10.3/font/bootstrap-icons.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
<nav id="nav">
<span class="bi bi-grid-fill icon_menu"></span>
<aside class="main_menu">
<ul>
<li>
home
</li>
<li>
our articles
<ul>
<li>
social
</li>
<li>
Academic
</li>
<li>
historical
</li>
</ul>
</li>
<li>about us</li>
</ul>
</aside>
</nav>
</section>
<div class="back"></div>
It's probably best to do this with CSS instead of JavaScript. Just add the submenu class to any <li> elements that hold sub-menus. Then, create an open class that will be toggled from the JavaScript. From your click handler, all you need to do is toggle the open class.
Because you're using WordPress and can't give elements classes directly, you can use some JavaScript trickery to assign the submenu class to each li in the main_menu that has a ul child.
Like this:
let icon = document.querySelector(".icon_menu");
let nav = document.querySelector(".main_menu");
$('.back').hide();
$('.back').click(function() {
if ($(this).is(':hidden')) return;
$(this).toggle();
icon.classList = "bi bi-grid-fill icon_menu";
icon.style.left = "2%";
icon.style.color = "#a66fff";
icon.style.fontSize = "40px";
nav.style.left = '-300px';
});
icon.addEventListener("click", function() {
if (this.classList.contains("bi-grid-fill")) {
this.classList = "bi bi-x-circle-fill icon_menu";
icon.style.left = "21%";
icon.style.color = "#ff6f6f";
icon.style.fontSize = "30px";
nav.style.left = 0;
} else {
this.classList = "bi bi-grid-fill icon_menu";
icon.style.left = "2%";
icon.style.color = "#a66fff";
icon.style.fontSize = "40px";
nav.style.left = "-300px";
}
$('.back').toggle();
});
//********************** **A script that needs editing** *********************
// hack to give the 'submenu' class
$('.main_menu li ul').each(function() {
$(this).parent().addClass('submenu')
})
$('.submenu').click(function(sub_menu) {
sub_menu.stopPropagation();
sub_menu.preventDefault();
$(this).children('ul').slideToggle();
$(this).toggleClass('open');
});
.main_menu {
position: absolute;
top: 0;
left: -300px;
bottom: 0;
z-index: 999;
background: #eee;
padding-right: 2rem;
transition: all 1s ease;
}
.icon_menu {
position: fixed;
top: 10%;
left: 2%;
font-size: 40px;
color: #a66fff;
cursor: pointer;
z-index: 99999;
transition: all 1.1s ease;
}
.main_menu ul {
list-style: none;
line-height: 60px;
font-size: 35px;
}
.main_menu ul li a {
color: #000000;
text-decoration: none;
padding-right: 15px;
padding-left: 40px;
margin-left: -60px;
margin-bottom: 10px;
}
.back {
width: 100%;
height: 100%;
position: fixed;
z-index: 9 !important;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #00000056;
}
.main_menu ul li ul {
display: none;
}
.main_menu .submenu > a::after {
content: ' → ';
}
.main_menu .open > a::after {
content: ' ↓ ' !important;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.10.3/font/bootstrap-icons.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
<nav id="nav">
<span class="bi bi-grid-fill icon_menu"></span>
<aside class="main_menu">
<ul>
<li>
home
</li>
<li>
our articles
<ul>
<li>
social
</li>
<li>
Academic
</li>
<li>
historical
</li>
</ul>
</li>
<li>about us</li>
</ul>
</aside>
</nav>
</section>
<div class="back"></div>
Apologies if this is a repeat question. I've scanned the internet but haven't found a viable solution to this. My website has varying background colours, blue and white. My nav's copy is primarily set to white but I'd like it to change to black when over a div with a white background.
Initially, I found this bit of JS on here:
$(document).ready(function(){
$(window).scroll(function(){
var lightPos = $('#light').offset().top;
var lightHeight = $('#light').height();
var menuPos = $('.desktop-menu').offset().top;
var menuHeight = $('.desktop-menu').height();
var menuPos = $('.logo').offset().top;
var menuHeight = $('.logo').height();
var scroll = $(window).scrollTop();
if(menuPos > lightPos && menuPos < (lightPos + lightHeight)) {
$('.desktop-menu').addClass('menu-secondary');
$('.desktop-menu').removeClass('menu-primary');
}
else {
$('.desktop-menu').removeClass('menu-secondary');
$('.desktop-menu').addClass('menu-primary');
}
})
})
But this seems to not work beyond 3 containers. If I continue scrolling to other divs, no matter what id I attach to a div (#light or #dark), the text stops changing after the first 3 div containers on a page.
Thanks to anyone who can help!
EDIT:
Struggled to get codepen to work so here's an example below.
Example HTML:
<div class="container">
<header>
<nav>
<ul class="menu">
<li>Page 1</li>
<li>Page 2</li>
<li>Page 3</li>
</ul>
</nav>
</header>
<div class="hero-container dark-background">
</div>
<div class="content-container light-background" id="light">
</div>
<div class="content-container dark-background">
</div>
<div class="content-container light-background" id="light">
</div>
<div class="content-container dark-background">
</div>
<div class="content-container light-background" id="light">
</div>
<div class="content-container dark-background">
</div>
</div>
Example CSS:
body {
margin: 0;
font-family: 'Poppins', sans-serif;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
header {
display: flex;
}
.container {
text-align: center;
}
/*-------------------- COLORS */
.dark-background {
background: #313747;
}
.light-background {
background: #f4f4f4;
}
.dark-color {
color: #303030;
}
.light-color {
color: #f4f4f4;
}
/*-------------------- NAVIGATION */
nav {
position: fixed;
height: auto;
width: 100%;
margin: auto;
z-index: 10;
}
.menu {
display: flex;
padding: 2em 0 2em 3em;
text-align: left;
float: left;
}
.menu li a {
margin-right: 2em;
font-size: 1.2em;
font-weight: 700;
text-decoration: none;
}
/*-------------------- HERO CONTAINER */
.hero-container {
position: relative;
height: 100vh;
width: 100%;
}
/*-------------------- CONTENT CONTAINER */
.content-container {
position: relative;
display: flex;
width: 100%;
height: 100vh;
margin: auto;
}
Example JS:
$(document).ready(function(){
$(window).scroll(function(){
var lightPos = $('#light').offset().top;
var lightHeight = $('#light').height();
var menuPos = $('.menu-btn').offset().top;
var menuHeight = $('.menu-btn').height();
var scroll = $(window).scrollTop();
if(menuPos > lightPos && menuPos < (lightPos + lightHeight)) {
$('.menu-btn').addClass('dark-color');
$('.menu-btn').removeClass('light-color');
}
else {
$('.menu-btn').removeClass('dark-color');
$('.menu-btn').addClass('light-color');
}
})
})
Ok, I had to change a bit your code because you were checking on ids (you shouldn't have multiple elements with the same ID),
This should be ok for your case,
so basically i create an array of light-sections and then check if scroll position is inside one of them
var $ = jQuery;
$(document).ready(function () {
var lightPos = [];
$(".light-background").each(function () {
lightPos.push({
start: $(this).offset().top,
end: $(this).offset().top + $(this).height()
});
});
$(window).scroll(function () {
var menuPos = $(".menu-btn").offset().top;
var isInLight = !!lightPos.some((light) => {
return light.start < menuPos && light.end > menuPos;
});
if (isInLight) {
$(".menu-btn").addClass("dark-color");
$(".menu-btn").removeClass("light-color");
} else {
$(".menu-btn").removeClass("dark-color");
$(".menu-btn").addClass("light-color");
}
});
});
body {
margin: 0;
font-family: "Poppins", sans-serif;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
header {
display: flex;
}
.container {
text-align: center;
}
/*-------------------- COLORS */
.dark-background {
background: #313747;
}
.light-background {
background: #f4f4f4;
}
.dark-color {
color: #303030;
}
.light-color {
color: #f4f4f4;
}
/*-------------------- NAVIGATION */
nav {
position: fixed;
height: auto;
width: 100%;
margin: auto;
z-index: 10;
}
.menu {
display: flex;
padding: 2em 0 2em 3em;
text-align: left;
float: left;
}
.menu li a {
margin-right: 2em;
font-size: 1.2em;
font-weight: 700;
text-decoration: none;
}
/*-------------------- HERO CONTAINER */
.hero-container {
position: relative;
height: 100vh;
width: 100%;
}
/*-------------------- CONTENT CONTAINER */
.content-container {
position: relative;
display: flex;
width: 100%;
height: 100vh;
margin: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<header>
<nav>
<ul class="menu">
<li>Page 1</li>
<li>Page 2</li>
<li>Page 3</li>
</ul>
</nav>
</header>
<div class="hero-container dark-background"></div>
<div class="content-container light-background"></div>
<div class="content-container dark-background"></div>
<div class="content-container light-background"></div>
<div class="content-container dark-background"></div>
<div class="content-container light-background"></div>
<div class="content-container dark-background"></div>
</div>
https://ataqfuel.com/pages/home-page-v2
I am trying to get button 2 and 3 to close like button 1 does when clicking outside of the dropdown menu. I tried adding myFunction1 code to myFunction2 and myFunction3 code but I'm not sure if I messed up the naming or what because all the dropdowns stopped functioning then.
function myFunction1() {
document.getElementById("myDropdown1").classList.toggle("show");
document.getElementById("myDropdown1").addEventListener('click', function(event) {
event.stopPropagation();
});
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn1')) {
var dropdowns = document.getElementsByClassName("dropdown-content1");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
document.getElementById("dropbtn1").addEventListener('click', function(event) {
event.stopPropagation();
});
function myFunction2() {
document.getElementById("myDropdown2").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn2')) {
var dropdowns = document.getElementsByClassName("dropdown-content2");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
function myFunction3() {
document.getElementById("myDropdown3").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn3')) {
var dropdowns = document.getElementsByClassName("dropdown-content3");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
CSS : .dropbtn {
margin: 5%;
background-color: #d3d3d3;
color: gray;
padding: 16px;
font-size: 16px;
font-weight: 500;
border: none;
cursor: pointer;
}
.dropbtn:hover,
.dropbtn:focus {
background-color: #edeb3f;
}
.dropdown {
position: relative;
display: inline;
min-width: 160px;
}
.dropdown-content {
display: none;
background-color: #f1f1f1;
min-width: 160px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {
background-color: #ddd;
}
.show {
display: block;
}
$('.moderate .button').on('click', (event) => {
$(event.target).siblings('.dropdown')
.toggleClass('is-open');
});
$(document).click(function(e) {
$('.moderate')
.not($('.moderate').has($(e.target)))
.children('.dropdown')
.removeClass('is-open');
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.0/css/bulma.css" rel="stylesheet" />
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<style>
.dropdown {
box-shadow: 0 0 2px #777;
display: none;
left: 0;
position: absolute;
padding: 2px;
z-index: 10;
}
.dropdown a {
font-size: 12px;
padding: 4px;
}
.dropdown.is-open {
display: block;
}
</style>
<div class="control moderate">
<button class="button is-small" type="button">
moderate
</button>
<div class="box dropdown">
<ul>
<li><a class="nav-item">edit</a></li>
<li><a class="nav-item">delete</a></li>
<li><a class="nav-item">block user</a> </li>
</ul>
</div>
</div>
<div class="control moderate">
<button class="button is-small" type="button">
moderate
</button>
<div class="box dropdown">
<ul>
<li><a class="nav-item">edit</a></li>
<li><a class="nav-item">delete</a></li>
<li><a class="nav-item">block user</a></li>
</ul>
</div>
</div>
You can use full screen width and height fixed backdrop for that. And after backdrop click close menu. It should be something like this:
jQuery(".backdrop").click(function(){
jQuery("#menu").toggleClass("open");
});
I have a navigation of 8 items (li), and when resolution gets smaller items drop in a new line. I need to make it so that when an item doesn't fit on a navigation anymore it should put a "MORE" dropdown button on the right side of nav and put the item that doesn't fit in a dropdown.
I don't know how I can do it with the Angular project, I don't need JQuery code.
This is my code:
<div id="mainMenu" class="main-menu">
<ul id="autoNav" class="main-nav">
<li>
home
</li>
<li>
about us
</li>
<li>
portfolio
</li>
<li>
team
</li>
<li>
blog
</li>
<li>
contact
</li>
<li id="autoNavMore" class="auto-nav-more">
more
<ul id="autoNavMoreList" class="auto-nav-more-list">
<li>
policy
</li>
</ul>
</li>
</ul>
</div>
Javascript Code:
const $mainMenu = $("#mainMenu");
const $autoNav = $("#autoNav");
const $autoNavMore = $("#autoNavMore");
const $autoNavMoreList = $("#autoNavMoreList");
autoNavMore = () => {
let childNumber = 2;
if($(window).width() >= 320) {
// GET MENU AND NAV WIDTH
const $menuWidth = $mainMenu.width();
const $autoNavWidth = $autoNav.width();
if($autoNavWidth > $menuWidth) {
// CODE FIRES WHEN WINDOW SIZE GOES DOWN
$autoNav.children(`li:nth-last-child(${childNumber})`).prependTo($autoNavMoreList);
autoNavMore();
} else {
// CODE FIRES WHEN WINDOW SIZE GOES UP
const $autoNavMoreFirst = $autoNavMoreList.children('li:first-child').width();
// CHECK IF ITEM HAS ENOUGH SPACE TO PLACE IN MENU
if(($autoNavWidth + $autoNavMoreFirst) < $menuWidth) {
$autoNavMoreList.children('li:first-child').insertBefore($autoNavMore);
}
}
if($autoNavMoreList.children().length > 0) {
$autoNavMore.show();
childNumber = 2;
} else {
$autoNavMore.hide();
childNumber = 1;
}
}
}
// INIT
autoNavMore();
$(window).resize(autoNavMore);
CSS Code:
.main-menu {
max-width: 800px;
}
.main-nav {
display: inline-flex;
padding: 0;
list-style: none;
}
.main-nav li a {
padding: 10px;
text-transform: capitalize;
white-space: nowrap;
font-size: 30px;
font-family: sans-serif;
text-decoration: none;
}
.more-btn {
color: red;
}
.auto-nav-more {
position: relative;
}
.auto-nav-more-list {
position: absolute;
right: 0;
opacity: 0;
visibility: hidden;
transition: 0.2s;
text-align: right;
padding: 0;
list-style: none;
background: grey;
border-radius: 4px;
}
.auto-nav-more:hover .auto-nav-more-list {
opacity: 1;
visibility: visible;
}
Any help to how I can do it with the Angular project (Typescript)?.
You can use the ng-repeat-start (ngRepeat directive)
https://docs.angularjs.org/api/ng/directive/ngRepeat
Example
<header ng-repeat-start="item in items">
Header {{ item }}
</header>
<div class="body">
Body {{ item }}
</div>
<footer ng-repeat-end>
Footer {{ item }}
</footer>
I am trying to do a side navigation that:
Just have ONE open sublist (close other)
Select only the clicked link in sublist
There are tons of examples out there, but I have not found any good sample in Vanilla Javascript.
HTML
<div class="sidenav">
Home
<button class="btn">Module 1</button>
<div class="list">
Link 1
Link 2
Link 3
</div>
<button class="btn">Module 2</button>
<div class="list">
Link 1
Link 2
Link 3
</div>
</div>
Javascript
var dropdown = document.getElementsByClassName("btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
The complete CSS is found on this Fiddle:
http://jsfiddle.net/q2en6djg/1/
Any clue, hint or help is appreciated.
You can consider an active CSS class to make it easier:
var dropdown = document.getElementsByClassName("btn");
var l = dropdown.length;
var i;
for (i = 0; i < l; i++) {
dropdown[i].addEventListener("click", function() {
for (var j = 0; j < l; j++) {
if (this != dropdown[j])
dropdown[j].classList.remove('active')
}
this.classList.toggle('active');
});
}
/*To select the sub item*/
var sub = document.querySelectorAll(".list a");
for (var i = 0; i < sub.length; i++) {
sub[i].addEventListener("click", function() {
this.classList.toggle('active');
});
}
* {
font-family: "Trebuchet MS", sans-serif;
font-size: 7em;
}
.sidenav {
margin-top: 0px;
height: auto;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #555;
overflow-x: hidden;
}
.sidenav a,
.btn {
padding: 10px 10px 10px 20px;
text-decoration: none;
font-size: 17px;
color: #fff;
display: block;
text-align: left;
border: none;
background: none;
width: 100%;
cursor: pointer;
outline: none;
border-bottom: 1px solid #777;
box-sizing:border-box;
}
.sidenav a:hover,
.sidenav a.active,
.btn:hover,
.btn.active {
background-color: #777;
}
.list {
display: none;
background-color: #999;
padding-left: 0px;
}
.active+.list {
display: block;
}
<div class="sidenav">
Home
<button class="btn">Module 1</button>
<div class="list">
Link 1
Link 2
Link 3
</div>
<button class="btn">Module 2</button>
<div class="list">
Link 1
Link 2
Link 3
</div>
</div>