201 Ways to Toggle Submenus with JavaScript

Just dipping my toes into the world of javascript and web development, I'm currently struggling to make my submenu's in the sidebar navigation area appear when clicked. Opening them individually with repetitive javascript felt clunky, so I'm searching for a better way (perhaps using a loop?). However, even after getting this far, I can't figure out how to close them back up efficiently. Here's a snippet of the HTML code I'm working with:


    <ul id="sidebarNavUl">

        <li class="sidebarLi">Main Topic:
            <ul>
                <li><a href="#">Sub Topic</a></li>
            </ul>
        </li>

        <li class="sidebarLi">Main Topic:
            <ul>
                <li><a href="#">Sub Topic</a></li>
            </ul>
        </li>

        <li class="sidebarLi">Main Topic:
            <ul>
                <li><a href="#">Sub Topic</a></li>
            </ul>
        </li>

    </ul>

Here's a glimpse at my CSS as well:


    .sidebarLi ul {
        padding-left: 10px;
        position: absolute;
        right: 9000em;
    }

    .sidebarLi ul li a {
        color: #003354;
    }

    .sidebarLi ul li a:hover {
        color: #003354;
        padding: 0 10px;
        width: auto;
        height: auto;
        background-color: #edf3f6;
        border-radius: 5px;
    }

I'm starting with the submenus in an absolute position, planning to use javascript to toggle them between positions when clicked. However, my current script is far from ideal. If anyone could provide guidance on writing efficient javascript code to manage the submenu visibility, it would be greatly appreciated. Thank you.

In case you're curious, here's the flawed javascript attempt I made:


    var mainSidebarLi = document.getElementsByClassName("sidebarLi");

    mainSidebarLi[0].onclick = function () {
        mainSidebarLi[0].getElementsByTagName("ul")[0].style.position = "static";
        mainSidebarLi[0].getElementsByTagName("ul")[0].style.right = "0";
    };

    var mainSidebarLi = document.getElementsByClassName("sidebarLi");

    mainSidebarLi[1].onclick = function () {
        mainSidebarLi[1].getElementsByTagName("ul")[0].style.position = "static";
        mainSidebarLi[1].getElementsByTagName("ul")[0].style.right = "0";
    };

This process needs to be repeated for all elements in the li array.

Answer №1

Here is another solution from a different discussion to incorporate a tag within an li tag:

$('.expandingNav').on('click', function (e) {
    if ($(e.target).closest('ul').parent('nav.sidebar').length) {
        if ($(this).hasClass('expanded')) {
            $(this).children('.hidden').slideUp();
            $(this).removeClass('expanded');
        } else {
            $(this).children('.hidden').slideDown();
            $(this).addClass('expanded');
        }
    }
});

Check out the fiddle here

Answer №2

There are a couple of ways you can approach this task. One easy method is to utilize jQuery toggleClass. Simply add an active class to the ul tag and toggle that class upon click event.

Include this CSS style:

.sidebarLi ul.active {
position: relative;
left: 0;    

}

Add this snippet of jQuery:

$('#sidebarNavUl li').click(function() {
$(this).children('ul').toggleClass('active');
});

If you are unfamiliar with adding jQuery, simply insert this code right before your </body> tag:

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$('#sidebarNavUl li').click(function() {
$(this).children('ul').toggleClass('active');
});
</script>

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

Tips for showcasing the latest Google Map InfoWindows above previous ones

I have a dynamic Google Map with InfoWindows being added dynamically, but I am facing an issue where overlapping InfoWindows do not always display the most recent one on top of older ones. Is there a way to ensure that the latest InfoWindow always shows u ...

Strategies for simulating a flexible back end with maximum versatility, using the URL string, parameters, response codes, and JSON responses

Currently, I am working on the UI development in React while another team is handling the backend. So far, only 15% of the API is available for me to work with. I wish to create a mock backend that offers maximum flexibility. Here are some key requirement ...

Mini-navigation bar scrolling

I am trying to create a menu where I want to hide elements if the length of either class a or class b is larger than the entire container. I want to achieve a similar effect to what Facebook has. How can I make this happen? I have thought about one approac ...

Bidirectional Data Flow with rxjs in Angular

After adapting an Angular template and component from Angular Material's dashboard schematic, I wanted to manipulate the properties on the "cards" object using events and two-way data binding. Initially, it seemed like two-way data binding was working ...

Extract a property from a JSON object

Is there a way to access the href properties and use them to create multiple img elements with their sources set as the extracted href properties? I'm looking for a solution in either javascript or jQuery. I attempted the following code, but it didn& ...

Meteor: The call stack has surpassed its maximum size limit

I attempted to perform an action that I have done several times before without encountering any errors. My goal is to retrieve all documents where the X field matches the value Y in my Meteor app: JS: (template helper) 'friendPictures' : funct ...

What is the best way to delete a dynamically generated div element through JavaScript?

function addDiv { var content = document.getElementById('area1').value; var newDivElement = document.createElement("div"); newDivElement.id = "myNewDiv"; newDivElement.className = "newDivClass"; newDivElement.innerHTML = cont ...

"Exploring the Backbone collection object in our browser's developer console

When I log one of my Backbone collections, the object summary shows that the length is 0 and the models array is empty. However, in the dropdown detail, it displays the correct length and model array. When I run console.log(this.collection.models), it re ...

Logic in ReactJS for displaying the application

Struggling a bit with React here. Currently working on an application that fetches user data from an external endpoint and saves it in local storage. I've noticed that my react-app is rendering the html before the state for that data is updated, resul ...

Update all unique symbols excluding the initial instance of the addition symbol

I need a solution to replace all non-numeric characters in a string, excluding any leading "+" signs. For example: 1234++!@#$%^&*()_+=-;',.><:" becomes 1234 +1234 becomes +1234 ++++1234 becomes +1234 +1234++!@#$%^&*()_+=-;',.&g ...

obtain the position of an element within an array

After entering a value in the input field, an array is generated with a length based on that input. For example, if I enter 3 in the input field, I will have var input = 3 and var sir = [0,1,2]. Can someone please help me figure out why my attempt to find ...

How can one properly incorporate static CSS and JavaScript into a VueJS application?

There have been numerous inquiries regarding the proper way to incorporate static CSS, but I still find myself puzzled. Is placing the static CSS in the "static" folder the right approach? Various suggestions I stumbled upon online include: Importing th ...

When I try to hover my mouse over the element for the first time, the style.cursor of 'hand' is not functioning as expected

Just delving into the world of programming, I recently attempted to change the cursor style to hand during the onmouseover event. Oddly enough, upon the initial page load, the border style changed as intended but the cursor style remained unaffected. It wa ...

retrieve a string from a given array

I need to retrieve a string from an array in vue and display it on the screen. Here is the method I created for this purpose: displayFixturesName() { const result = this.selectedFixture.toString(); document.getElementById(& ...

What could be causing my page to suddenly disappear?

After saving my changes in the IDE and refreshing the browser to test the prompt() function in my index.js file, the entire page goes blank, showing only a white screen. I double-checked the syntax of my function and it seems correct. Everything else on th ...

What could be causing my ul list to not be populated by ajax?

To populate the ul list with data from PHP code on page load, you can use the following ajax function. I appreciate any help in advance, and please forgive me if my explanation is not precise as I'm new here. This post contains mostly code snippets. ...

Incorporate a Font Awesome button in front of the content of each list group item in Pug/Jade

I'm struggling to insert a Font Awesome icon before the list-group-item content within a Pug loop, but I can't seem to make it work. Adding the icon at the end of the list-group-item content is straightforward. How do I position it in front (I h ...

"Controlling Selected Options in Bootstrap Dual Listbox: A Guide to Limiting Choices

I am utilizing the Bootstrap Dual Listbox plugin to assist users in selecting specific options. I have successfully integrated this plugin into my project. However, I encountered an issue when attempting to impose a limit on the number of options a user ...

Unable to mark as 'touched'

Currently, I am working on creating a custom Formik <Field />. This involves using an <input type = file /> with opacity set to 0. Depending on the values provided, I style my <Error /> component and another <input type = text />. ...

Difficulties encountered when trying to create a basic timeline using Moment JS

I'm in the process of developing a straightforward report that retrieves entries through an ajax request and I aim to organize my entries by the day of the week. My desired output would look something like this: ---------------------------------- Mon ...