Automatically close dropdown when clicking on another option

Currently, I'm working on creating a responsive dropdown navigation bar using vanilla JavaScript. My goal is to have only one dropdown menu open at a time when clicked in mobile view. Here's the JavaScript code snippet:

dropbtns.forEach(link => {
  link.addEventListener("click", function(e) {
    e.currentTarget.nextElementSibling.classList.toggle("showdd");
  });
});

This code snippet will toggle the visibility of the dropdown menu:

  .showdd {
    height: auto;
  }

Below is the HTML code structure for the navigation bar:

<div class="nav-container">
    <div class="brand">
        <a href="#!">Logo</a>
    </div>
    <nav>
        <div class="nav-mobile"><a id="nav-toggle" href="#!"><span></span></a></div>
        <ul id="nav-list">
            <li>
                <a href="#!">Home</a>
            </li>
            <li>
                <a href="#!">About</a>
            </li>
            <li class="dropdown">
                <a href="#!" class='dropbtn'>Services <i class="fas fa-sort-down"></i></a>
                <ul class="nav-dropdown">
                    <li>
                        <a href="#!">Web Design</a>
                    </li>
                    <li>
                        <a href="#!">Web Development</a>
                    </li>
                    <li>
                        <a href="#!">Graphic Design</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#!">Pricing</a>
            </li>
            <li class="dropdown">
                <a href="#!" class='dropbtn'>Portfolio <i class="fas fa-sort-down"></i></a>
                <ul class="nav-dropdown">
                    <li>
                        <a href="#!">Web Design</a>
                    </li>
                    <li>
                        <a href="#!">Web Development</a>
                    </li>
                    <li>
                        <a href="#!">Graphic Design</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#!">Contact</a>
            </li>
        </ul>
    </nav>
</div>

You can access the full code here.

Answer №1

If you wish to collapse all other .nav-dropdown menus when one is clicked on, follow these steps:

  1. Store the current element's .nav-dropdown reference for comparison later.
  2. Toggle its class as you are already doing.
  3. Iterate through all other .nav-dropdown elements in your document and check if they match the stored reference. If not, remove the class.

Here is the code snippet implementing the above logic:

dropbtns.forEach(link => {
  link.addEventListener('click', e => {
    const ownDropdown = e.currentTarget.nextElementSibling;
    ownDropdown.classList.toggle('showdd');

    document.querySelectorAll('.dropbtn + .nav-dropdown').forEach(el => {
      if (el !== ownDropdown)
        el.classList.remove('showdd');
    });
  });
});

Answer №2

After making a few adjustments, your Codepen is now functioning perfectly.

links.forEach(link => {
  link.addEventListener("click", function(e) {
    links.forEach(link => {
      link.nextElementSibling.classList.remove("display"); // This line has been modified
    });
    e.currentTarget.nextElementSibling.classList.toggle("show");
  });
});

On another note, can you explain what the "display" class does?

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

How can one properly test the functionality of an AngularJS directive in a way that is commonly accepted and

What is the recommended approach for conducting in-memory integration testing of a directive? For instance, if there is a directive with a button that changes color when clicked, would the following method be considered standard practice for a DOM integra ...

Ways to incorporate a background image using CSS

I tried to add a background image using CSS, but unfortunately, I was unsuccessful in my attempts. body { font-family: Arial, Helvetica, sans-serif; } /* .login-form{ width: 400px; } */ /* Full-width input fields */ input[type=text], input[type ...

Text affected by mix-blend-mode glitch

Currently, I am experimenting with knockout text using the mix-blend-mode property. An interesting issue arises when I examine the responsiveness of my design by utilizing Developer tools in the browser console - there are faint lines that momentarily appe ...

Unable to transfer information from a PHP form to a MYSQL database when registering

Currently struggling to troubleshoot a piece of code that is not functioning as expected. I have all the necessary HTML, JS, and PHP in place, but after submitting the form, the data does not get sent to the SQL database as intended. Any assistance would b ...

Maintain tab state in AngularJS during page refresh

Here's the coffee script code I'm currently working with: window.AddressGridController = [ "$scope", "$rootScope", "$http" ($scope, $rootScope, $http) -> init = window.angularInit $scope.countryNames = init.countryNames $scop ...

Edge allows conversion of Canvas to Blob

Encountering an issue specifically on Microsoft Edge browser while attempting to convert an Html canvas element to a blob. The process works seamlessly on other browsers without any hiccups. Exception: SCRIPT438: Object doesn't support property or ...

The @emit event in vue.js is not being received by the parent component

Within my application, there is a form located in the ManageCards component. This form includes a child component called ImageUpload, which emits an image file and its local URL to the parent component: <form class="mb-3"> <div class ...

Filtering data in DataTables using button selection based on HTML attributes

Utilizing the DataTables plugin for a dynamic bootstrap 4 table with data retrieved from various APIs (https://datatables.net/). The process involves constructing an object and adding it to the table. While everything is functioning correctly, I am intere ...

Having an issue with the OBJLoader.js not loading properly in three.js

Encountering an error using OBJLoader.js to load an obj model with the following message: Resource "https://cdnjs.cloudflare.com/ajax/libs/three.js/r119/OBJLoader.js" blocked due to mismatch (X-Content-Type-Options: nosniff) MIME type ("text ...

Is there a way for me to track the number of times the local HTML document has been accessed?

Imagine we have a standalone HTML file that is sent to someone. Is there a way, possibly using third-party services, to track if the document has been opened without the user knowing? I thought about placing a PHP script on a "friendly" server and making ...

Showing a loading image before an Action is completed in ASP.Net MVC 5 can greatly enhance the user experience

This project is developed using ASP.Net MVC 5. The following code snippet demonstrates a simple integration of javascript/jQuery: <script> $(document).ready(function () { $("#textBox").focusout(function () { var phrase= $("#textBox").va ...

Experience a login page similar to Google's with a fully functional back button

I'm currently working on a login page that requires the user to enter their username and have it validated before proceeding. Once the username is confirmed as valid, a new input field for password entry should appear. However, I'm facing an issu ...

Transform the MySQL query to fetch the highest date for each user ID and then convert it into a sequelize query

Below is the MySQL query I'm working with: SELECT a.id, a.name, a.pname, b.skill, date_add(a.end_date, interval 1 DAY) AS available_date FROM (SELECT user.id, concat(user.first_name, " ", user.last_nam ...

Troubleshooting problem with Electron and sqlite3 post application packaging

I've been facing various challenges with Node and databases lately, hence the numerous questions I've posted here recently. Here's some background: I have an Electron app with an AngularJS frontend. On the electron side, I run an express s ...

Creating registration and login forms using an express server

Currently, I'm in the process of creating a basic website on my localhost that incorporates a signup form along with other essential HTML elements. The setup for the signup procedure went smoothly as planned. When a user completes the form and submits ...

Creating a paragraph from text inputs using React

I'm currently working on code that retrieves input from two textboxes - one for a string value and one for a number value. I want this data to be displayed in real-time within a paragraph without the need for a submit button. I've been struggling ...

Unlocking the secrets of retrieving the URL query string in Angular2

I'm struggling to extract the URL query string returned by the security API, resulting in a URL format like this: www.mysite.com/profile#code=xxxx&id_token=xxx. My goal is to retrieve the values of code and id_token. In my ngOnInit() function, I ...

Extend and retract within a row of a table

I need help with modifying a dynamically generated table to meet specific requirements. The table currently looks like this. The task involves hiding all columns related to Category B, eliminating duplicate rows for Category A, and displaying entries from ...

Leverage ngFor to loop through a "highly intricate" data structure

In my project, I have stored data in a JSON file structured as follows: { "name": { "source1": ____, "source2": ____, "source3": ____ }, "xcoord": { "source1": ____, "source2": ____, "source3": _ ...

After introducing input from the DOM with jQuery, the scrolling functionality in Bootstrap 4 Modal has ceased to

My current setup involves utilizing Bootstrap 4 Modal, resulting in a user interface similar to the following: https://i.sstatic.net/nTqZ5.png The design showcases a "Questions" label and an "Add Question" button. By clicking on "Add Question", I am able ...