Home > Blockchain >  Need Javascript help Dropdown Menu onclick issue
Need Javascript help Dropdown Menu onclick issue

Time:11-26

I need the help with Javascript onclick Dropdown Menu. The menu opens when I click the button and closes when I click outside. The problem is that when I open one menu and click on another, the previous menu stays open. I want the solution that when I open one menu when I open another menu the previous menu closes. enter image description here

<!DOCTYPE HTML>
<html>

<head>
  <style>
    * {
      box-sizing: border-box;
    }
    
    body {
      margin: 0;
    }
    
    .navbar {
      width: 100%;
      padding: 0 10% 0 10%;
      overflow: hidden;
      box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
    }
    
    .dropbtn {
      font-size: 16px;
      border: none;
      outline: none;
      padding: 21.5px 20px;
      background-color: inherit;
      margin: 0;
      cursor: pointer;
      font-weight: bolder;
      color: #2d3436;
    }
    
    .dropdown {
      float: left;
    }
    
    .dropdown-content {
      display: none;
      position: absolute;
      background-color: #fff;
      min-width: 460px;
      box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
      height: 450px;
    }
    
    .show {
      display: block
    }
  </style>
</head>

<body>
  <div class="navbar">
    <div class="dropdown">
      <button onclick="my1Function()" class="dropbtn dropbtn1">Dropdown <i class="fas fa-caret-down"></i></button>
      <div id="myDropdown1" class="dropdown-content dropdown-content1">

      </div>
    </div>

    <div class="dropdown">
      <button onclick="my2Function()" class="dropbtn dropbtn2">Dropdown <i class="fas fa-caret-down"></i></button>
      <div id="myDropdown2" class="dropdown-content dropdown-content2">

      </div>
    </div>

    <div class="dropdown">
      <button onclick="my3Function()" class="dropbtn dropbtn3">Dropdown <i class="fas fa-caret-down"></i></button>
      <div id="myDropdown3" class="dropdown-content dropdown-content2">

      </div>
    </div>
  </div>
  <script>
    function my1Function() {
      document.getElementById("myDropdown1").classList.toggle("show");
    }

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

    function my3Function() {
      document.getElementById("myDropdown3").classList.toggle("show");
    }
    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');
          }
        }
      }
    }
  </script>
</body>

</html>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You may not need specific onclick event like my1Function for each dropdown button, instead use a generic event listener.

  1. Hide any open dropdown content. (This takes care of hiding the dropdown content when clicked outside)
  2. Show the dropdown content specific to the clicked button.

<!DOCTYPE HTML>
<html>

<head>
  <style>
    * {
      box-sizing: border-box;
    }
    
    body {
      margin: 0;
    }
    
    .navbar {
      width: 100%;
      padding: 0 10% 0 10%;
      overflow: hidden;
      box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
    }
    
    .dropbtn {
      font-size: 16px;
      border: none;
      outline: none;
      padding: 21.5px 20px;
      background-color: inherit;
      margin: 0;
      cursor: pointer;
      font-weight: bolder;
      color: #2d3436;
    }
    
    .dropdown {
      float: left;
    }
    
    .dropdown-content {
      display: none;
      position: absolute;
      background-color: #fff;
      min-width: 460px;
      box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
      height: 450px;
    }
    
    .show {
      display: block
    }
  </style>
</head>

<body>
  <div class="navbar">
    <div class="dropdown">
      <button class="dropbtn dropbtn1">Dropdown 1<i class="fas fa-caret-down"></i></button>
      <div id="myDropdown1" class="dropdown-content dropdown-content1">
      </div>
    </div>

    <div class="dropdown">
      <button class="dropbtn dropbtn2">Dropdown 2<i class="fas fa-caret-down"></i></button>
      <div id="myDropdown2" class="dropdown-content dropdown-content2">

      </div>
    </div>

    <div class="dropdown">
      <button class="dropbtn dropbtn3">Dropdown 3<i class="fas fa-caret-down"></i></button>
      <div id="myDropdown3" class="dropdown-content dropdown-content2">

      </div>
    </div>
  </div>
  <script>
    window.addEventListener('click', function(event) {
      // Hide any open dropdown content
      const dropdownContents = document.querySelectorAll('.dropdown-content')
      dropdownContents.forEach(content => {
        content.classList.remove('show');
      });

      // Show the dropdown content respective to the clicked button
      if (event.target.matches('.dropbtn')) {
        event.target.nextElementSibling.classList.add('show');
      }
    })
  </script>
</body>

</html>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I would do the dropdown as a details tag like this:

<nav>
    <ul class="my-nav">
        <li>
            <details class="dropdown">
                <summary>This has dropdown items</summary>
                <ul>
                    <li><a href="#hi">Hi</a></li>
                    <li><a href="#universe">Universe</a></li>
                </ul>
            </details>
        </li>
        <li>
            <details class="dropdown">
                <summary>Another dropdown</summary>
                <ul>
                    <li><a href="#goodbye">Goodbye</a></li>
                    <li><a href="#universe">Universe</a></li>
                </ul>
            </details>
        </li>
    </ul>
</nav>

Granted you would have different summaries/links, and here is the corresponding js:

var nav = document.querySelector('.my-nav');
nav.addEventListener('toggle', function (event) {

    // Only run if the dropdown is open
    if (!event.target.open) return;

    // Get all other open dropdowns and close them
    var dropdowns = nav.querySelectorAll('.dropdown[open]');
    Array.prototype.forEach.call(dropdowns, function (dropdown) {
        if (dropdown === event.target) return;
        dropdown.removeAttribute('open');
    });

}, true);
  • Related