1

I have a dropdown menu that does not work properly. When i click one of the buttons, a dropdown menu will appear. But when i click the button again it should close, but it dosn't. I know it has something to do with closeAll function, but i still need that function to close another dropdown menu when the first one is already open.

 /* When the user clicks on the button, 
    toggle between hiding and showing the dropdown content */
    function myFunction() {
    closeAll();
        document.getElementById("myDropdown").classList.toggle("show");
       }

       function myFunction2() {
        closeAll();
        document.getElementById("myDropdown2").classList.toggle("show"); 
    }

    function closeAll(){
     var dropdowns = document.getElementsByClassName("dropdown-content");
     var i;
     for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
       openDropdown.classList.remove('show');
     }
    }

    // Close the dropdown menu if the user clicks outside of it
    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');
  
          }
        }
      }
    }
/* Dropdown Button */
    .dropbtn {
    background-color: #4CAF50;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
    }

    /* Dropdown button on hover & focus */
    .dropbtn:hover, .dropbtn:focus {
        background-color: #3e8e41;
    }

    /* The container <div> - needed to position the dropdown content */
    .dropdown {
        position: relative;
        display: inline-block;
    }

    /* Dropdown Content (Hidden by Default) */
    .dropdown-content {
        display: none;
        position: absolute;
        background-color: #f9f9f9;
        min-width: 150px;
        box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
        z-index: 1;
    }

    /* Links inside the dropdown */
    .dropdown-content a {
        color: black;
        padding: 12px 16px;
        text-decoration: none;
        display: block;
    }

    /* Change color of dropdown links on hover */
    #myDropdown a:hover {background-color: #f1f1f1}

    /* Show the dropdown menu (use JS to add this class to the .dropdown-content 
    container when the user clicks on the dropdown button) */
    .show {display:block;}

    #myDropdown2{
     min-width:200px;
     border:4px solid red;
 
    }

    #myDropdown2 a:hover{
     color:red;
    }

    .left-bar{
     float:left;
    }

    .right-bar{
     float:left;
    }
    

    <div class="dropdown">
      <button onclick="myFunction()" class="dropbtn">Dropdown</button>
      <div id="myDropdown" class="dropdown-content">
        <a href="#">Link 1</a>
        <a href="#">Link 2</a>
        <a href="#">Link 3</a>
      </div>
    </div>

    <div class="dropdown">
      <button onclick="myFunction2()" class="dropbtn">Dropdown</button>
      <div id="myDropdown2" class="dropdown-content">
     <div class="left-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
     </div>
 
     <div class="right-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
     </div>
      </div>
    </div>
Anurag Awasthi
  • 6,115
  • 2
  • 18
  • 32
Pleinair
  • 437
  • 9
  • 21

5 Answers5

3

your Functions (myFunction() and myFunction2()) first close all dropdown menu using closeAll(); and next line document.getElementById("myDropdown").classList.toggle("show"); shows it again.So,when you click the button againو It does not close.

For Fix it :

Just remove Function closeAll(); and change your code Like this :

function myFunction() {
    document.getElementById("myDropdown2").classList.remove("show");
    document.getElementById("myDropdown").classList.toggle("show");
}

function myFunction2() {
    document.getElementById("myDropdown").classList.remove("show");
    document.getElementById("myDropdown2").classList.toggle("show");
}

Full code :

function myFunction() {
  document.getElementById("myDropdown2").classList.remove("show");
  document.getElementById("myDropdown").classList.toggle("show");
}

function myFunction2() {
  document.getElementById("myDropdown").classList.remove("show");
  document.getElementById("myDropdown2").classList.toggle("show");
}

// Close the dropdown menu if the user clicks outside of it
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: #4CAF50;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}


/* Dropdown button on hover & focus */

.dropbtn:hover,
.dropbtn:focus {
  background-color: #3e8e41;
}


/* The container <div> - needed to position the dropdown content */

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


/* Dropdown Content (Hidden by Default) */

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


/* Links inside the dropdown */

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


/* Change color of dropdown links on hover */

#myDropdown a:hover {
  background-color: #f1f1f1
}


/* Show the dropdown menu (use JS to add this class to the .dropdown-content 
    container when the user clicks on the dropdown button) */

.show {
  display: block;
}

#myDropdown2 {
  min-width: 200px;
  border: 4px solid red;
}

#myDropdown2 a:hover {
  color: red;
}

.left-bar {
  float: left;
}

.right-bar {
  float: left;
}
<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>

<div class="dropdown">
  <button onclick="myFunction2()" class="dropbtn">Dropdown</button>
  <div id="myDropdown2" class="dropdown-content">
    <div class="left-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>

    <div class="right-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>
  </div>
</div>
Community
  • 1
  • 1
Ehsan
  • 12,655
  • 3
  • 25
  • 44
-1

Remove this Function for myFunction() & myFunction2() closeAll();

you already use ToggleClass

/* When the user clicks on the button, 
    toggle between hiding and showing the dropdown content */
function myFunction() {
  
  document.getElementById("myDropdown").classList.toggle("show");
}

function myFunction2() {
  
  document.getElementById("myDropdown2").classList.toggle("show");
}

function closeAll() {
  var dropdowns = document.getElementsByClassName("dropdown-content");
  var i;
  for (i = 0; i < dropdowns.length; i++) {
    var openDropdown = dropdowns[i];
    openDropdown.classList.remove('show');
  }
}

// Close the dropdown menu if the user clicks outside of it
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');

      }
    }
  }
}
/* Dropdown Button */

.dropbtn {
  background-color: #4CAF50;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}


/* Dropdown button on hover & focus */

.dropbtn:hover,
.dropbtn:focus {
  background-color: #3e8e41;
}


/* The container <div> - needed to position the dropdown content */

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


/* Dropdown Content (Hidden by Default) */

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


/* Links inside the dropdown */

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


/* Change color of dropdown links on hover */

#myDropdown a:hover {
  background-color: #f1f1f1
}


/* Show the dropdown menu (use JS to add this class to the .dropdown-content 
    container when the user clicks on the dropdown button) */

.show {
  display: block;
}

#myDropdown2 {
  min-width: 200px;
  border: 4px solid red;
}

#myDropdown2 a:hover {
  color: red;
}

.left-bar {
  float: left;
}

.right-bar {
  float: left;
}
<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>

<div class="dropdown">
  <button onclick="myFunction2()" class="dropbtn">Dropdown</button>
  <div id="myDropdown2" class="dropdown-content">
    <div class="left-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>

    <div class="right-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>
  </div>
</div>
Lalji Tadhani
  • 14,041
  • 3
  • 23
  • 40
-1

In the first step you close all dropdowns and after that toggle the current one which then will be reopened. If you want to change this behaviour you have to change the closeAll() function to receive one parameter which would be the current dropdown or button and only close all but this one.

closeAll(currentDropdown){
    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
        var openDropdown = dropdowns[i];
        if(openDropdown != currentDropdown){
            openDropdown.classList.remove('show');
        }
    }
}

You could save the states the elements should have in an array and apply all these every time one is clicked.

// executed once on page load
var dropdowns = new array();
var tmpdropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < tmpdropdowns.length; i++) {
    dropdowns[tmpdropdowns[i].id] = 0;
}


// executed on click of one button
for (i = 0; i < dropdowns.length; i++) {
    dropdowns[i] = 0;
}
dropdowns[/*clicked id*/] = (dropdowns[/*clicked id*/] + 1) % 2;
for (var key in dropdowns) {
   if(dropdowns[key] == 0) {
       document.getElementById[key].classList.remove("show");
   } else {
       document.getElementById[key].classList.add("show");
   }
}
Jonathan
  • 177
  • 1
  • 11
  • Would you mind telling me why you downvoted? I answered because I want to help you and if this answer didn't help or wasn't detailed enough or whatever I can improve it if you tell me what is missing or wrong. – Jonathan Jun 01 '17 at 12:58
-1

The problem is that after you call closeAll(), you then toggle the dropdown that the user clicked on, which opens that one again.

You need to test whether the current one is already open, and not re-open it.

/* When the user clicks on the button, 
    toggle between hiding and showing the dropdown content */
function myFunction() {
  var isOpen = document.getElementById("myDropdown").classList.contains("show");
  closeAll();
  if (!isOpen) {
    document.getElementById("myDropdown").classList.add("show");
  }
}

function myFunction2() {
  var isOpen = document.getElementById("myDropdown2").classList.contains("show");
  closeAll();
  if (!isOpen) {
    document.getElementById("myDropdown2").classList.toggle("show");
  }
}

function closeAll() {
  var dropdowns = document.getElementsByClassName("dropdown-content");
  var i;
  for (i = 0; i < dropdowns.length; i++) {
    var openDropdown = dropdowns[i];
    openDropdown.classList.remove('show');
  }
}

// Close the dropdown menu if the user clicks outside of it
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');

      }
    }
  }
}
/* Dropdown Button */

.dropbtn {
  background-color: #4CAF50;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}


/* Dropdown button on hover & focus */

.dropbtn:hover,
.dropbtn:focus {
  background-color: #3e8e41;
}


/* The container <div> - needed to position the dropdown content */

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


/* Dropdown Content (Hidden by Default) */

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


/* Links inside the dropdown */

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


/* Change color of dropdown links on hover */

#myDropdown a:hover {
  background-color: #f1f1f1
}


/* Show the dropdown menu (use JS to add this class to the .dropdown-content 
    container when the user clicks on the dropdown button) */

.show {
  display: block;
}

#myDropdown2 {
  min-width: 200px;
  border: 4px solid red;
}

#myDropdown2 a:hover {
  color: red;
}

.left-bar {
  float: left;
}

.right-bar {
  float: left;
}
<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>

<div class="dropdown">
  <button onclick="myFunction2()" class="dropbtn">Dropdown</button>
  <div id="myDropdown2" class="dropdown-content">
    <div class="left-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>

    <div class="right-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>
  </div>
</div>
Barmar
  • 741,623
  • 53
  • 500
  • 612
-1

Try this: remove the classshowof another dropdown when hasClass of show element clicked dropdown .because each time of you click closeAll was remove the show in all dropdown .So you could validate only remove the hasClass ofshow element .It prevent the toggle event of dropdown also

Array.prototype.indexOf.call(document.getElementById("myDropdown").classList, 'show')

Its used to find the hasClass

/* When the user clicks on the button, 
    toggle between hiding and showing the dropdown content */
function myFunction() {
if(Array.prototype.indexOf.call(document.getElementById("myDropdown").classList, 'show')){
  document.getElementById("myDropdown").classList.toggle("show");
   document.getElementById("myDropdown2").classList.remove("show");
  }
  else{
  closeAll();
  }
  
}

function myFunction2() {if(Array.prototype.indexOf.call(document.getElementById("myDropdown2").classList, 'show')){
  document.getElementById("myDropdown2").classList.toggle("show");
     document.getElementById("myDropdown").classList.remove("show");
  }
  else{
  closeAll()
  }
  
}

function closeAll() {
  var dropdowns = document.getElementsByClassName("dropdown-content");
  var i;
  for (i = 0; i < dropdowns.length; i++) {
    var openDropdown = dropdowns[i];
    openDropdown.classList.remove('show');
  }
}

// Close the dropdown menu if the user clicks outside of it
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');

      }
    }
  }
}
/* Dropdown Button */

.dropbtn {
  background-color: #4CAF50;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}


/* Dropdown button on hover & focus */

.dropbtn:hover,
.dropbtn:focus {
  background-color: #3e8e41;
}


/* The container <div> - needed to position the dropdown content */

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


/* Dropdown Content (Hidden by Default) */

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


/* Links inside the dropdown */

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


/* Change color of dropdown links on hover */

#myDropdown a:hover {
  background-color: #f1f1f1
}


/* Show the dropdown menu (use JS to add this class to the .dropdown-content 
    container when the user clicks on the dropdown button) */

.show {
  display: block;
}

#myDropdown2 {
  min-width: 200px;
  border: 4px solid red;
}

#myDropdown2 a:hover {
  color: red;
}

.left-bar {
  float: left;
}

.right-bar {
  float: left;
}
<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <a href="#">Link 3</a>
  </div>
</div>

<div class="dropdown">
  <button onclick="myFunction2()" class="dropbtn">Dropdown</button>
  <div id="myDropdown2" class="dropdown-content">
    <div class="left-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>

    <div class="right-bar">
      <a href="#">Link 1</a>
      <a href="#">Link 2</a>
      <a href="#">Link 3</a>
    </div>
  </div>
</div>
prasanth
  • 22,145
  • 4
  • 29
  • 53