How do I hide the dropdown of a navbar when a user clicks elsewhere?

Viewed 163

I'm building a new website with a navbar with a dropdown menu and want to have the dropdown disappear when I click on another button or other part of the site. How do I code that?

The code below is my latest experiment in trying to get this to work. It worked fine when it was one button, but I've been unable to scale it to multiple buttons. I'm very new to this and trying to learn.

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.navbar {
  overflow: hidden;
  background-color: #333;
  font-family: Arial, Helvetica, sans-serif;
}

.navbar a {
  float: left;
  font-size: 16px;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

.dropdown {
  float: left;
  overflow: hidden;
}

.dropdown .dropbtn {
  cursor: pointer;
  font-size: 16px;  
  border: none;
  outline: none;
  color: white;
  padding: 14px 16px;
  background-color: inherit;
  font-family: inherit;
  margin: 0;
}

.navbar a:hover, .dropdown:hover .dropbtn, .dropbtn:focus {
  background-color: red;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  float: none;
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
}

.dropdown-content a:hover {
  background-color: #ddd;
}

.show {
  display: block;
}

.wrapper {
  min-width: 800px;
  margin: auto;
}
</style>
</head>
<body>

<div class="wrapper">
<div class="navbar">

  <a href="#home">Company name</a>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(1)">Our Methods
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown1">
    <a href="#link">Insurance</a>
    <a href="#link">Divorce</a>
    <a href="#link">Financial Planning</a>
    <a href="#link">Mortgage</a>
    <a href="#link">Stocks</a>
    <a href="#link">Pension</a>
  </div>
  </div>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(2)">Who we are
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown2">
    <a href="#link">About the Team</a>
    <a href="#link">Awards</a>
    <a href="#link">Interesting articles</a>
  </div>
  </div>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(3)">Business info
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown3">
    <a href="#link">Prices</a>
    <a href="#link">Privacy</a>
    <a href="#link">Methods</a>
  </div>
  </div> 

  <a href="#home">Recommendations</a>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(4)">Advice Evenings
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown4">
    <a href="#link">Succesful Pensions</a>
    <a href="#link">Casestudie Pension</a>
    <a href="#link">Business Contacts</a>
  </div>
  </div> 
</div>
</div>

<script>
/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
function myFunction(num) {

  document.getElementById("myDropdown" + num).classList.toggle("show");
}



// Close the dropdown if the user clicks outside of it
window.onclick = function(e) {
  if (!e.target.matches('.dropbtn')) {
  var myDropdown1 = document.getElementById("myDropdown1");
    if (myDropdown1.classList.contains('show')) {
      myDropdown1.classList.remove('show');
    }
  var myDropdown2 = document.getElementById("myDropdown2");
    if (myDropdown2.classList.contains('show')) {
      myDropdown2.classList.remove('show');
    } 
  var myDropdown3 = document.getElementById("myDropdown3");
    if (myDropdown3.classList.contains('show')) {
      myDropdown3.classList.remove('show');
    } 
  var myDropdown4 = document.getElementById("myDropdown4");
    if (myDropdown4.classList.contains('show')) {
      myDropdown4.classList.remove('show');
    } 
  }
}

</script>
</body>
</html>

I expected all buttons to be hidden when I click elsewhere, but somehow that isn't happening. (you can see the code in action here: http://growtricks.com/dropdown/dropdown4.html ).

I've tried including this line at the beginning of MyFunction:

document.getElementsByClassName('dropdown-content').forEach(function(dropdown) { dropdown.classList.remove('show'); });

But that just completely stops ever showing the dropdown-content.

  1. How do I make the dropdown content disappear when I click elsewhere?
  2. How do I make the dropdown content disappear when I click another one?
  3. This is a bonus question and non-essential: How do I clean up the window.onclick at the end to a way where I'm not repeating the same code n times?
3 Answers

There are multiple ways. I kind a like to have separate function variable for clearing previous action:

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.navbar {
  overflow: hidden;
  background-color: #333;
  font-family: Arial, Helvetica, sans-serif;
}

.navbar a {
  float: left;
  font-size: 16px;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

.dropdown {
  float: left;
  overflow: hidden;
}

.dropdown .dropbtn {
  cursor: pointer;
  font-size: 16px;  
  border: none;
  outline: none;
  color: white;
  padding: 14px 16px;
  background-color: inherit;
  font-family: inherit;
  margin: 0;
}

.navbar a:hover, .dropdown:hover .dropbtn, .dropbtn:focus {
  background-color: red;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  float: none;
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
}

.dropdown-content a:hover {
  background-color: #ddd;
}

.show {
  display: block;
}

.wrapper {
  min-width: 800px;
  margin: auto;
}
</style>
</head>
<body>

<div class="wrapper">
<div class="navbar">

  <a href="#home" onclick="myFunction('home')">Company name</a>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(1)">Our Methods
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown1">
    <a href="#link">Insurance</a>
    <a href="#link">Divorce</a>
    <a href="#link">Financial Planning</a>
    <a href="#link">Mortgage</a>
    <a href="#link">Stocks</a>
    <a href="#link">Pension</a>
  </div>
  </div>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(2)">Who we are
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown2">
    <a href="#link">About the Team</a>
    <a href="#link">Awards</a>
    <a href="#link">Interesting articles</a>
  </div>
  </div>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(3)">Business info
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown3">
    <a href="#link">Prices</a>
    <a href="#link">Privacy</a>
    <a href="#link">Methods</a>
  </div>
  </div> 

  <a href="#home" onclick="myFunction('home')">Recommendations</a>

  <div class="dropdown">
  <button class="dropbtn" onclick="myFunction(4)">Advice Evenings
    <i class="fa fa-caret-down"></i>
  </button>
  <div class="dropdown-content" id="myDropdown4">
    <a href="#link">Succesful Pensions</a>
    <a href="#link">Casestudie Pension</a>
    <a href="#link">Business Contacts</a>
  </div>
  </div> 
</div>
</div>

<script>
/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
let closeDropdown = function() {

}
function myFunction(num) {
  closeDropdown();
  let el = document.getElementById("myDropdown" + num);  
  if (el) {
    el.classList.toggle("show");
    closeDropdown = function() {
        el.classList.remove("show");
    }
  } else {
    closeDropdown = function() {
    } 
  }
}



</script>
</body>
</html>

The one thing the other answer did not address was how to also hide the dropdowns if one clicks elsewhere on the page. I found that adding the code below solved that issue:

window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {
    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}

There is already css solution given. Given below is my javascript solution. Just replace your javascript code with mine.

<script>
/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
let closeDropdown = function() {

}
var oldselection = 0;
function myFunction(num) {
  if(oldselection != 0){
  document.getElementById('myDropdown'+oldselection).classList.remove("show");
// hiding the old dropdown
}
  closeDropdown();
  let el = document.getElementById("myDropdown" + num);  
  if (el) {
    el.classList.toggle("show");
    closeDropdown = function() {
        el.classList.remove("show");
    }
  } else {
    closeDropdown = function() {
    } 
  }
oldselection = num;
}    

</script>

In this code i have jus added 1 variable called "oldselection" and i m storing the previously selected dropdowns "num" value. And during the next selection i m just using the old selected value to hide its associated content.

Related