Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple dropdown buttons – only one open at a time (JS/jQuery)

I've been trying to create two language selection dropdown buttons. I succeeded using this W3Schools template. However, this solution has two drawbacks: 1. you need (?) one script per dropdown button or modification of that script; 2. you can have two dropdown buttons open at the same time, which I don't want.

I found a solution to a similar problem here, but I cannot seem to be able to adapt it to dropdown buttons. I tried to rework it step-by-step, but I cannot get rid of nested in .

How can I create multiple dropdown buttons, so that they use one JS/jQuery script (preferably without Bootstrap), and so that opening one dropdown closes any other currently open dropdown?

Edit: This is the code in my page I have now:

<div class="dropdown">
    <button onclick="myFunction(this)" class="dropbtn"><img src="img/flags/en.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">English</span>&nbsp;<i class="fas fa-caret-down"></i></button>
    <div id="lang2" class="dropdown-content">
        <a href="#"><img src="img/flags/en.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">English</span></a>
        <a href="#"><img src="img/flags/fr.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">French</span></a>
        <a href="#"><img src="img/flags/de.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">German</span></a>
        <a href="#"><img src="img/flags/ru.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">Russian</span></a>
        <a href="#"><img src="img/flags/pl.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">Polish</span></a>
        <a href="#"><img src="img/flags/cz.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">Czech</span></a>
        <a href="#"><img src="img/flags/zh.png" class="langmenu">&nbsp;&nbsp;<span class="langmenu">Mandarin</span></a>
    </div>
</div>

This is the furthest I ever got without breaking the dropdowns. I tried replacing the outside <ul>s with and update the css accordingly, but somehow it didn't work as intended. I also tried applying is-open where dropdown-content is.

like image 528
MrVocabulary Avatar asked Feb 21 '18 19:02

MrVocabulary


1 Answers

I modified the W3Schools template to make it work with 2 dropdowns menus that can't be opened at the same time with just a little modification of the script.
This solution works with vanilla JavaScript. Some could prefer jQuery.

Please see below the code, I commented some parts:

/* When the user clicks on the button, 
closes every dropdowns and open the only one passed as argument */

/* Javascript only */
function myFunction(element) {
  var dropdowns = document.getElementsByClassName("dropdown-content");
  
  // element.nextSibling is the carriage return… The dropdown menu is the next next.
  var thisDropdown = element.nextSibling.nextSibling;
  
  if (!thisDropdown.classList.contains('show')) {  // Added to hide dropdown if clicking on the one already open
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      dropdowns[i].classList.remove('show');
    }
  }
  
  // Toggle the dropdown on the element clicked
  thisDropdown.classList.toggle("show");
}

/* W3Schools function to close the dropdown when clicked outside. */
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');
      }
    }
  }
}
.dropbtn {
  background-color: #3498DB;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}

.dropbtn:hover,
.dropbtn:focus {
  background-color: #2980B9;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  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;
}
<div class="dropdown">
  <button onclick="myFunction(this);" class="dropbtn">Dropdown1</button>
  <div id="myDropdown1" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div>
<!-- Added 2nd dropdown ! -->
<div class="dropdown">
  <button onclick="myFunction(this);" class="dropbtn">Dropdown2</button>
  <div id="myDropdown2" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div>

I added a proposition of utilisation of this using nextSibling, as an example.

⋅ ⋅ ⋅

A jQuery solution, for those who prefer.

/* When the user clicks on the button, 
closes every dropdowns and open the only one passed as argument */

/* jQuery */
function myFunction(element) {
  var elements = ".dropdown-content";
  $(elements).removeClass('show');
  $(element).next(elements).toggleClass("show");
}

/* W3Schools function to close the dropdown when clicked outside. */
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');
      }
    }
  }
}
.dropbtn {
  background-color: #3498DB;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}

.dropbtn:hover,
.dropbtn:focus {
  background-color: #2980B9;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dropdown">
  <button onclick="myFunction(this);" class="dropbtn">Dropdown1</button>
  <div id="myDropdown1" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div>
<div class="dropdown">
  <button onclick="myFunction(this);" class="dropbtn">Dropdown2</button>
  <div id="myDropdown2" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div>

Hope it helps !

like image 141
Takit Isy Avatar answered Oct 13 '22 23:10

Takit Isy