Home > Software design >  Closing dropdown button in Vanilla JS
Closing dropdown button in Vanilla JS

Time:05-27

How do I close the dropdown button in Vanilla JS? I currently have a method to open the dropdown button but no way in which the close the button. I would like to keep the for loop in place but am unsure as to how to achieve the close. What is the proper way to handle the problem? Help would be appreciated. HTML

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <script
  src="https://code.jquery.com/jquery-3.6.0.js"
  integrity="sha256-H K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
  crossorigin="anonymous"></script>
    <script src="https://kit.fontawesome.com/36947df53d.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
  <div >
    <p id="logo">Logo</p>
    <button id="btn"><i ></i></button>
  </div>
   <nav class ="">
     <ul class ="">
       <li><a href="#" >Link 1</a></li>
       <li><a href="#" >Link 2</a></li>
       <li><a href="#" >Link 3</a></li>
     </ul>
   </nav>
    <script src="script.js"></script>
  </body>
</html>

JS

let btnn = document.getElementById("btn");
btnn.addEventListener("click", changeBtn);

function changeBtn() { 
    let links = document.getElementsByClassName('link');
    for (let i = 0; i < links.length; i  ) {
        document.getElementsByClassName('link')[i].style.display = "block";
    } 
}

CSS


body {
    height: 100vh;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

.logo {
    display: block;
    text-align: left;
    background: red;
    height: 10vh;
}

.logo #logo {
    display: inline;
    line-height: 10vh;
    font-size: 3em;
    margin-left: 0.8em;
    
}

button#btn {
    display: inline;
    float: right;
    margin-right: 2em;
    line-height: 10vh;
    margin-top: 0;
    margin-bottom: 0;
    border: none;
    background-color: red;
    padding: 0;
}

nav {
    display: block;
    background-color: black;
    width: 100vw;
}

nav ul {
    display: block;
    list-style-type: none;
    margin: 0;
    padding-left: 0;
}

nav ul li {
    text-align: center; 
}

.link {
    display: none;
    color: white;
    font-size: 2.4em;
    background-color: blue;
    text-decoration: none;
    width: 100vw;
    height: 7vh;
    line-height: 7vh;
    border-bottom: 2px solid black;
    text-align: center;
}

CodePudding user response:

You just need to add one function for the close button in javascript where the display is set to none on clicking the button again. You can do the same by clicking anywhere by window object.


Below is the code after the correction of the javascript part for closing the menu after clicking the button again. Hope you understand well. Please upvote if you like.

let btnn = document.getElementById("btn");
btnn.addEventListener("click", changeBtn);

function changeBtn() {
    let links = document.getElementsByClassName('link');
    for (let i = 0; i < links.length; i  ) {
        document.getElementsByClassName('link')[i].style.display = "block";
    }
    // close the menu after clicking again
    btnn.removeEventListener("click", changeBtn);
    btnn.addEventListener("click", closeBtn);
}

function closeBtn() {
    let links = document.getElementsByClassName('link');
    for (let i = 0; i < links.length; i  ) {
        document.getElementsByClassName('link')[i].style.display = "none";
    }
    // open the menu after clicking again
    btnn.removeEventListener("click", closeBtn);
    btnn.addEventListener("click", changeBtn);
}
body {
  height: 100vh;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.logo {
  display: block;
  text-align: left;
  background: red;
  height: 10vh;
}

.logo #logo {
  display: inline;
  line-height: 10vh;
  font-size: 3em;
  margin-left: 0.8em;
}

button#btn {
  display: inline;
  float: right;
  margin-right: 2em;
  line-height: 10vh;
  margin-top: 0;
  margin-bottom: 0;
  border: none;
  background-color: red;
  padding: 0;
}

nav {
  display: block;
  background-color: black;
  width: 100vw;
}

nav ul {
  display: block;
  list-style-type: none;
  margin: 0;
  padding-left: 0;
}

nav ul li {
  text-align: center;
}

.link {
  display: none;
  color: white;
  font-size: 2.4em;
  background-color: blue;
  text-decoration: none;
  width: 100vw;
  height: 7vh;
  line-height: 7vh;
  border-bottom: 2px solid black;
  text-align: center;
}
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <script
      src="https://code.jquery.com/jquery-3.6.0.js"
      integrity="sha256-H K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
      crossorigin="anonymous"
    ></script>
    <script
      src="https://kit.fontawesome.com/36947df53d.js"
      crossorigin="anonymous"
    ></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
    <div >
      <p id="logo">Logo</p>
      <button id="btn"><i ></i></button>
    </div>
    <nav >
      <ul >
        <li><a href="#" >Link 1</a></li>
        <li><a href="#" >Link 2</a></li>
        <li><a href="#" >Link 3</a></li>
      </ul>
    </nav>
    <script src="script.js"></script>
  </body>
</html>


CodePudding user response:

You can use a simple classList.toggle function in JS by assigning a base class and then a "visible" class and just toggle between the two on click. See: https://www.w3schools.com/howto/howto_js_toggle_class.asp

Edit: added in the forEach just in case you wanted multiple buttons

let btnn = document.querySelectorAll(".btn");
btnn.forEach(btnn => btnn.addEventListener('click', function() {
  let links = document.getElementById('links');
  links.classList.toggle("visible");
}))
body {
  height: 100vh;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.logo {
  display: block;
  text-align: left;
  background: red;
  height: 10vh;
}

.logo #logo {
  display: inline;
  line-height: 10vh;
  font-size: 3em;
  margin-left: 0.8em;
}

button#btn {
  display: inline;
  float: right;
  margin-right: 2em;
  line-height: 10vh;
  margin-top: 0;
  margin-bottom: 0;
  border: none;
  background-color: red;
  padding: 0;
}

nav {
  display: block;
  background-color: black;
  width: 100vw;
}

nav ul {
  display: block;
  list-style-type: none;
  margin: 0;
  padding-left: 0;
}

nav ul li {
  text-align: center;
}

.link {
  display: block;
  color: white;
  font-size: 2.4em;
  background-color: blue;
  text-decoration: none;
  width: 100vw;
  height: 7vh;
  line-height: 7vh;
  border-bottom: 2px solid black;
  text-align: center;
}

.links {
  display: none;
}

.links.visible {
  display: block;
}
<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
  <script src="https://kit.fontawesome.com/36947df53d.js" crossorigin="anonymous"></script>
  <link rel="stylesheet" type="text/css" href="style.css" />
</head>

<body>
  <div >
    <p id="logo">Logo</p>
    <button  id="btn"><i ></i></button>
  </div>
  <nav >
    <ul  id="links">
      <li><a href="#" >Link 1</a></li>
      <li><a href="#" >Link 2</a></li>
      <li><a href="#" >Link 3</a></li>
    </ul>
  </nav>
  <script src="script.js"></script>
</body>

</html>

CodePudding user response:

A more simple approach would be to add a class to the nav element and then toggle the visibility of nav element using the changeBtn function

I have highlighted the changes to the code using comments

HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <script
  src="https://code.jquery.com/jquery-3.6.0.js"
  integrity="sha256-H K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
  crossorigin="anonymous"></script>
    <script src="https://kit.fontawesome.com/36947df53d.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
  <div >
    <p id="logo">Logo</p>
    <button id="btn"><i ></i></button>
  </div>
   <nav id="main_nav" class ="">  <!-- added id to nav element -->
     <ul class ="">
       <li><a href="#" >Link 1</a></li>
       <li><a href="#" >Link 2</a></li>
       <li><a href="#" >Link 3</a></li>
     </ul>
   </nav>
    <script src="script.js"></script>
  </body>
</html>

CSS:

body {
    height: 100vh;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

.logo {
    display: block;
    text-align: left;
    background: red;
    height: 10vh;
}

.logo #logo {
    display: inline;
    line-height: 10vh;
    font-size: 3em;
    margin-left: 0.8em;
    
}

button#btn {
    display: inline;
    float: right;
    margin-right: 2em;
    line-height: 10vh;
    margin-top: 0;
    margin-bottom: 0;
    border: none;
    background-color: red;
    padding: 0;
}

nav {
    display: none;
    background-color: black;
    width: 100vw;
}

nav ul {
    display: block;
    list-style-type: none;
    margin: 0;
    padding-left: 0;
}

nav ul li {
    text-align: center; 
}

.link {
    display: block;  /* Changed display: none to display: block */
    color: white;
    font-size: 2.4em;
    background-color: blue;
    text-decoration: none;
    width: 100vw;
    height: 7vh;
    line-height: 7vh;
    border-bottom: 2px solid black;
    text-align: center;
}

Js:

let btnn = document.getElementById("btn");
btnn.addEventListener("click", changeBtn);

function changeBtn() {   //changes to function
    
    let main_nav = document.getElementById("main_nav");   
   
    if (main_nav.classList.contains("nav_active")) {  
        //when element has nav_active class, hide the nav element and remove
        //the "nav-active" class

        main_nav.style.display = "none";      
        main_nav.classList.remove("nav_active");
    } else {
        //when element doesn't have nav_active class, show the nav element
        //and add the "nav-active" class
        main_nav.style.display = "block";
        main_nav.classList.add("nav_active");
    }
}
  • Related