Utilize JavaScript to create a toggle menu feature that can target multiple variables with just one click function

I am attempting to create a collapsing menu on click functionality with additional modifications. One of the changes I would like to implement is altering the background of another element when the menu collapses.

Currently, the code snippet only works for the first link, while the second toggleable link remains untargeted.

var pill = document.querySelector(".navpill");
var sub = document.querySelector(".submenu");
pill.onclick = () => {
    sub.classList.toggle("collapse");
    pill.classList.toggle("active");
}
.mainmenu {
  background-color: #1f1f1f;
}
.navpill {
  padding: 15px;
}
.navpill.active {
  background: red;
}
.navpill a {
  text-decoration: none;
  color: white;
}
.submenu {
  display: none;
}
.submenu.collapse {
  display: block;
}
<div>
  <ul class="mainmenu">
    <li class="navpill"><a href="#">Link collapse 1</a>
        <ul class="submenu">
            <li class="navpill"><a href="#">sub Link 1</a></li>
            <li class="navpill"><a href="#">sub Link 2</a></li>
            <li class="navpill"><a href="#">sub Link 3</a></li>
            <li class="navpill"><a href="#">sub Link 4</a></li>
        </ul>
    </li>
    <li class="navpill"><a href="#">Link collapse 2</a>
        <ul class="submenu">
            <li class="navpill"><a href="#">sub Link 1</a></li>
            <li class="navpill"><a href="#">sub Link 2</a></li>
            <li class="navpill"><a href="#">sub Link 3</a></li>
        </ul>
    </li>
    <li class="navpill"><a href="#">no link</a></li>
    <li class="navpill"><a href="#">no link</a></li>
  </ul>
</div>

An earlier solution I received helps the functionality work for all links, but I'm unsure how to introduce more variables and toggles to the function.

var pills = document.querySelectorAll(".expand");

pills.forEach(function(pill) {
  pill.onclick = () => {
    var sub = pill.querySelector(".submenu");
    sub.classList.toggle("collapse");
  }
});

I attempted adding this extra piece of code, but it was ineffective.

    var navpill = pill.querySelector(".navpill");
    navpill.classList.toggle("active");

If feasible, I would also appreciate a method to reset the actions taken when clicking on a different submenu.

Currently, using the aforementioned code does not close out the first link when the second is clicked, resulting in both remaining open simultaneously. My objective is to have only one link expand at a time.

Answer №1

This solution should be more in line with your requirements.

(It is not clear if you wanted the submenu items to become highlighted upon clicking them - currently, clicking only collapses the menu so the highlighting wouldn't be visible. Also, I have removed the hrefs as they were not serving any useful purpose.)

var pills = document.querySelectorAll(".expand");
var subs = document.querySelectorAll(".submenu");

pills.forEach(function(pill) {
  pill.addEventListener("click", function() {
    var sub = pill.querySelector(".submenu");
    
    var alreadyOpen = false;
    if (sub.classList.contains("collapse")) alreadyOpen = true;
    
    pills.forEach(function(pill2) {
      pill2.classList.remove("active"); 
    });

    subs.forEach(function(sub2) {
      sub2.classList.remove("collapse"); 
    });

    if (!alreadyOpen) { 
      sub.classList.toggle("collapse");
      this.classList.add("active");
    }
  });
});
.expand.active {
  background-color: red;
}

.expand.active > .submenu
{
  background-color: #1f1f1f;
}

.mainmenu {
  background-color: #1f1f1f;
}

.navpill {
  padding: 15px;
  color: white;
}

.submenu {
  display: none;
}

.submenu.collapse {
  display: block;
}
<div>
  <ul class="mainmenu">
    <li class="navpill expand">Link collapse 1
      <ul class="submenu">
        <li class="navpill">sub Link 1</li>
        <li class="navpill">sub Link 1</li>
        <li class="navpill">sub Link 1</li>
        <li class="navpill">sub Link 1</li>
      </ul>
    </li>
    <li class="navpill expand">Link collapse 2
      <ul class="submenu">
        <li class="navpill">sub Link 1</li>
        <li class="navpill">sub Link 1</li>
        <li class="navpill">sub Link 1</li>
        <li class="navpill">sub Link 1</li>
      </ul>
    </li>
    <li class="navpill">no link</li>
    <li class="navpill">no link</li>
  </ul>
</div>

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

Bespoke Video Player using HTML5 with "Nerdy Stats" Feature

I have been given the task of creating a streaming video testing framework for internal metrics and measurement purposes. Essentially, I am looking to develop an HTML5 player that can handle streams and provide performance data related to: - Average Bitr ...

AngularJS - Changing Views with Templates

At the moment, I am changing my directives in the following manner. Within my directive: (function(){ 'use strict'; var controller = ['$scope', function ($scope) { }]; angular .module('moduleName' ...

Vue function displays 'undefined' message

Although many posts on this topic exist already, I am struggling to understand what is going wrong (even after searching extensively here and on Google). I have created my interceptor like this, but I keep receiving an error message stating "This is undef ...

ways to display view without page refresh in mvc3

@using (Html.BeginForm("Index", "HRBankInfo", FormMethod.Get)) { <div align="center" class="display-label"> @ViewBag.message <br /><input type="submit" value="Ok" /> </div> } This particular partial view is display ...

Unable to access model content in multiple AngularJS controllers

My question is clear and straightforward. Let me explain in detail: 1. I have created a module. var ang = angular.module('myApp', []); I have a controller named controller1, which includes the 'campaign' factory. //controllero ...

Having trouble importing Bootstrap into Next.js? It seems like the issue may be related to the

I am currently facing an issue with importing bootstrap 5.3.2 (not react-bootstrap) into my NextJS 14.1.0 project that utilizes the new App Router. My goal is to strategically utilize individual Bootstrap components (not through data-attrs). I managed to ...

Using React to Identify the Chosen Option on a Custom Toggle Button

I have successfully implemented a toggle switch using HTML and CSS in my React app. I am now looking for a way to detect the selected option whenever it changes. For instance, if OR is chosen, I would like it to be saved in the selectedOption state, and if ...

How can I incorporate Bootstrap multi-select into the jQuery DataTables DOM?

Having trouble implementing a bootstrap multi-select inside a jQuery datatable DOM. I followed this example to add a custom element within the jQuery datatable container. It works fine for normal bootstrap select, but when trying to add a bootstrap multi-s ...

What is the best way to insert an object at a particular position within an array containing numerous nested objects?

This is the given Object: [ { "id": "1709408412689", "name": "WB1", "children": [ { "id": "1709408412690", "n ...

Retrieve the image and insert it using an img tag

Working on a project, I want to include Instagram profile pictures by embedding them. Although I have the image URL, I am struggling to integrate it into my HTML page. Take a look at this sample: This provided link displays the Instagram profile picture. ...

Spacing applied to content within a fresh Vue application

Having been assigned the task of developing a Vue page for my team, I am facing an issue with a persistent white border surrounding the entire page. <script setup lang="ts"> </script> <template> <body> <div>&l ...

Having trouble with CSS basics? Seeing properties change across multiple classes?

My CSS skills are still in the beginner stage and I am currently struggling to troubleshoot an issue with my code. The HTML: <div id="loginForm"> <span class="dottedLink"><a href="resetlogin">Recover login details</a></span ...

Enhancing button functionality using jQuery and JavaScript for toggling behavior

I am facing a challenge with this code. The goal is to have a single script that can handle multiple audio elements on the page and toggle between PLAY and PAUSE buttons by adding or removing classes. Can anyone suggest any changes or additions that coul ...

Exploring the depths of time travel in Redux without the aid of developer

Has anyone successfully achieved time traveling capabilities with Redux core? It seems that this feature is limited to the devtools and not advised for production use. I had planned on implementing Redux in a multiplayer game to assist with managing clie ...

What could be causing the image file input to appear sideways or flipped?

I am currently working on a Vuejs component that allows users to select a file from their local system. Once the user selects an image, it is previewed in a div. However, I have noticed that some images appear 'flipped' sideways automatically, es ...

Here's a unique version: "A guide on using jQuery to dynamically adjust the background color of table

I need some assistance with changing the background color of td elements based on the th class. Specifically, I want to target all td elements under the bots class in the HTML code provided below. <table border="1" class="CSSTableGenerator" id="myTab ...

Customizing the main icon in the Windows 10 Action Center through a notification from Microsoft Edge

I am facing an issue with setting the top icon of a notification sent from a website in Microsoft Edge. Let's consider this code as an example: Notification.requestPermission(function (permission) { if (permission == "granted") { new ...

Toggle a Vue.js method to display responses for a particular question

Currently, I am in the process of developing a simple toggle feature for a FAQ section. The idea is that when a user clicks on an icon associated with a specific question, only that question's answer should be displayed. Although the function is oper ...

Is the custom attribute event being triggered too soon?

My Unique Component Creation Journey I have meticulously crafted a custom component to enhance the navigation of my application. The core structure consists of an ul element, with each li item dynamically generated based on the contents of the router&apo ...

Tips for effectively utilizing v-model and v-select in a dynamic manner

Is it possible to have a group of select elements in Vue.js that work independently with v-model without needing separate data properties for each one? For example, select 1 and select 2 should be treated as one group, while select 3 and select 4 are anot ...