Struggling with your Dropdown Menu onclick functionality in Javascript? Let me lend

I am seeking assistance with implementing a Javascript onclick Dropdown Menu. The current issue I am facing is that when one menu is opened and another menu is clicked, the previous menu remains open. My desired solution is to have the previously open menu close automatically when a new menu is opened.

<!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>

Answer №1

To simplify dropdown button functionality, consider using a generic event listener instead of individual onclick events like my1Function.

  1. Hide any currently displayed dropdown content to manage visibility when clicking outside.
  2. Show the specific dropdown content related 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>

Answer №2

If I were to implement a dropdown menu, I would use the following structure:

<nav>
    <ul class="my-nav">
        <li>
            <details class="dropdown">
                <summary>Click here for more options</summary>
                <ul>
                    <li><a href="#option1">Option 1</a></li>
                    <li><a href="#option2">Option 2</a></li>
                </ul>
            </details>
        </li>
        <li>
            <details class="dropdown">
                <summary>Another dropdown menu</summary>
                <ul>
                    <li><a href="#menu-item1">Menu Item 1</a></li>
                    <li><a href="#menu-item2">Menu Item 2</a></li>
                </ul>
            </details>
        </li>
    </ul>
</nav>

Of course, each dropdown would have its own unique content and links. Here is the accompanying JavaScript code:

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

    // Only execute if dropdown is being opened
    if (!event.target.open) return;

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

}, true);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered "Function undefined error when invoking within a map in TypeScript"

In my function, there is a map that looks like this: mainFunc(){ // other logics data.map(function (item) { item.number = Math.round(item.number); item.total = item.last - item.first; item.quantity= item?.quantity ? quantityRange(ite ...

Quiz application features various button states for optimal user interaction

I am in the process of creating a quiz that resembles the popular BuzzFeed quizzes such as THIS ONE. Although I have mapped out the logic and have an idea of how to code it to function similarly to the one provided in the link, I am encountering issues wit ...

How Can You Change the Position of a Threejs Vector3?

I'm attempting to create bones and then manipulate the vertices of each bone, but I am struggling with the correct syntax. Here is an example of what I have tried: var v = new THREE.Vector3(0,0,0); var b = new THREE.Bone(); b.position.x = 5; b.positi ...

Experimenting with a loader component in AngularJS

This is a test for a $resource with a loader describe('Service: MultiCalculationsLoader', function(){ beforeEach(module('clientApp')); var MultiCalculationLoader, mockBackend, calculation; beforeEach(inject(function (_ ...

How come my justify-content property isn't functioning properly with Flexbox?

I've been racking my brain trying to solve this. The goal is to have all the boxes neatly grouped together, but for some reason there's a massive gap between the main content and footer. Could someone lend a hand? CSS Below is the CSS code rele ...

Having trouble getting the CSS Hover state to function properly?

I am currently working with a code snippet that looks like this: <div style="position: absolute; margin-left: -22px; margin-top: -22px; left: 502px; top: 379px; z-index: 380; display: block;" class="maptimize_marker_0 f st">1<span class="pinlabel ...

What is the best way to align the content of a <ul> in the center while keeping the text left-aligned and setting a max-width

UPDATE: Including an image for better visualization: [![Check out the image link][1]][1] To understand more clearly, refer to this fiddle: https://jsfiddle.net/c7jazc9z/2/ Currently, I have a list with items aligned to the left. The goal is to center th ...

What is the relationship between font size adjustments and the dimensions of the surrounding parent div element?

I've come across an issue that involves having the following code snippet in the body of an HTML file: html, body { width: 99%; height: 99%; margin: 0px; overflow: hidden; } #container1 { display: flex; gap: 2%; width: 90%; heigh ...

There are two borders in place, with the second border present only on the right and bottom

Can someone help me achieve borders like the ones in this image? https://i.sstatic.net/qZHbK.png I tried using the after pseudo-element as shown below, but after learning from this discussion: Why can't an element with a z-index value cover its child ...

Getting the value of dynamically generated buttons when they are clicked in PHP - a simple guide

In my PHP code, I have successfully created dynamic buttons. However, I am facing an issue where I need to retrieve the value of a specific button when it is clicked, and populate all the information in a form. Below is the code snippet for handling the b ...

Strategies for identifying CSS properties within a div element

I am attempting to identify the CSS property display of a div. If it is set to display:block, I want to change the icon to -. If it is set to display:none, I want to change the icon to +. I have tried using the following code but it does not seem to work: ...

Unable to organize list of entities based on numerical values

I am working with an array of objects structured like this: [ { "value": 351.68474, "o_p": [ "$.text" ] }, { "value": 348.0095, "o_p": [ ...

Python scripts are unable to perform file uploads through an HTTP form, unlike PHP scripts which are compatible

Currently, I am working on a Python project where I need to upload a text file through HTTP to my server. Initially, I used an HTTP form for convenience and the upload process was successful. However, now I want to automate the file selection process by ha ...

Generating a preview image for a three.js environment

I am currently working on a website dedicated to visualizing the biological neurons found in animals. I have a comprehensive list of neuron names, and I use THREE JS to draw the neuron when the user clicks on its name. However, with hundreds of neurons to ...

What could be causing AngularJS to truncate my URL in the search bar?

Currently, I am in the process of setting up a state provider for a CRUD website. One issue I encountered is that when I navigate to www.mysite.com/posts/mypost, the URL gets shortened to www.mysite.com/mypost and does not trigger the controller as intend ...

Enhance the numerical worth of the variable through the implementation of the function

I'm working on a JavaScript timer but I'm struggling with assigning the value of a parameter to a global variable. Currently, I can achieve this without using parameters, but I really want to streamline my code and reduce the number of lines. He ...

Determining the precise spacing needed for a personalized cursor

Currently, I'm facing an obstacle in my attempt to design a custom cursor/crosshair inside a canvas. The problem lies in the Length, Width, and Gap dimensions assigned to the four rectangles that make up the cursor, as it is resulting in an incorrect ...

How to Round Decimals in DataTables

I am encountering an issue with my data table's footer, which is supposed to display the sum of each column. However, while the values within the table are rounded to two decimal places, the values in the footer do not always adhere to this formatting ...

Convert text to bold when checkbox is selected and alter color upon selecting a radio button

Having just started learning HTML, CSS, and PHP, I find myself in need of assistance. Despite extensive research online, I have hit a dead end and cannot seem to find any productive solutions. Any guidance or suggestions would be greatly appreciated! I am ...

Saving asp.net strings in different formats to datetime fields in a database

Can someone please assist me with saving the string value of textbox to the database as a datetime, and for updating/editing purposes, display it again in the textbox as a string? The reason for this is that the datetime input will be copied from Outlook a ...