What is the most effective method to implement a toggle function using only JavaScript, without any reliance on jQuery?

Recently, I had a navigation bar in the form of an unordered list (ul) with multiple list items (li), and the last li element was labeled 'more' which had its own sub-menu in the form of another ul. To toggle this sub-menu between visible and hidden states when clicking on the 'more' li, I utilized JavaScript along with a counter in an if statement. Despite my success in achieving the desired functionality, I found it necessary to use the counter as an intermediary step since directly checking for visibility didn't produce the toggle effect.

Here are the queries that arose from this implementation:

  1. Would employing this toggle method be considered acceptable within a professional front-end developer workspace?

  2. Is there a more efficient way to accomplish toggling between visible and hidden states solely using JavaScript? (I aim to enhance my JavaScript skills)

For reference, below is the relevant code snippets:

HTML

<ol id = "leftNav" class = "bothNavs">
    <li class = "navs" id = "more">More<div class = "arrow"></div>
        <ul class = "subMenu">
            <li>One</li>
            <li>Two</li>
            <li>Three</li>
        </ul>
    </li>
</ol>

CSS

.subMenu {
    width: 160%;
    padding: 5px 0px;
    padding-left: 7px;
    margin-left: 6px;
    position: absolute;
    top: 100%;
    left: 0;
    visibility: hidden;
    box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2);
    background: #2D2D2D;
    list-style: none;
    z-index: 1001;
}

JavaScript

var more = document.querySelector('#more');
var subMenu = document.querySelector('.subMenu');
var counter = 0;

more.addEventListener("click", toggle);

function toggle() {
    if (counter === 0) {
        subMenu.style.visibility = "visible";
        counter += 1;
    } else {
        subMenu.style.visibility = "hidden";
        counter -= 1;
    }
};

Awaiting your valuable insights and suggestions. Thank you.

Answer №1

I believe a more efficient way to handle visibility toggling (or any style change) is by using class toggling.

Try incorporating something similar to this in your CSS:

.dropdownMenu.is-shown {
    display: block;
}

Then your JavaScript function can be simplified like so:

var dropdown = document.querySelector('.dropdownMenu');
document.getElementById('showMore').addEventListener('click', function ()  {
    dropdown.classList.toggle('is-shown');
}, false);

Answer №2

When implementing a toggle functionality, it is recommended to use a boolean value instead of an integer:

var more = document.querySelector('#more');
var subMenu = document.querySelector('.subMenu');
var clicked = false;

more.addEventListener("click", function(evt) {
  // Utilize the ternary operator for a simple if/else statement
  subMenu.style.visibility = (clicked) ? "visible" : "hidden";

  // Toggle the boolean value of 'clicked' from true to false or vice versa
  clicked = !clicked;
});

Additionally, it would be beneficial to review (and upvote) this question on Stack Overflow - What is the difference between visibility:hidden and display:none?

Answer №3

Avoid placing a <ul> within an <li> element as it can disrupt the document hierarchy and diminish the semantic value of the HTML.

In a previous instance, I encountered a similar issue which led me to implement the following solution:

var submenu = document.querySelector('.submenu');
if (clicked) {
    submenu.style.visibility = "visible";
} else {
    submenu.style.visibility = "hidden";
}

It may be beneficial to utilize an id instead of a class if there are other submenus that could be affected.

Answer №4

If you find that a counter is unnecessary, consider using a boolean instead:

var more = document.querySelector('#more');
var subMenu = document.querySelector('.subMenu');

more.addEventListener("click", toggle);

function toggle () {    
    subMenu.style.visibility = subMenu.style.visibility != "hidden" ? "hidden" : "visible";
    
};
.subMenu {
    width: 60%;
    background: #2D2D2D;
    list-style: outside none none;
    color: white
}
<ol id = "leftNav" class = "bothNavs">
    <li class = "navs" id = "more">More<div class = "arrow"></div>
        <ul class = "subMenu" style="visibility: hidden">
            <li>One</li>
            <li>Two</li>
            <li>Three</li>
        </ul>
    </li>
</ol>

To improve this code, consider modifying it to toggle a class rather than an inline CSS style, as suggested by James in his response.

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

The div above the footer seems to be interfering with the styling of the footer. Is there a solution to

I am currently working on implementing a Help functionality for our users. In order to do this, I have placed a div right above my footer. However, I am facing an issue where the styling of my div is affecting the footer in ways that I cannot figure out. ...

Need a tool for validating forms?

I am currently facing some confusion with the UI Validation plugin that we are using. Within our application, we employ Spring MVC, Jquery & Bootstrap. As we delve into UI development, we have encountered uncertainty in selecting an appropriate Validation ...

Can a <Link> be customized with a specific condition?

On the webpage, there is a list of elements retrieved from a database. When clicking on the last displayed element, I want to link to '/upload' if it shows "Carica Referto", or link to '/consensi/{this.$state.item.hash_consenso}' if it ...

What is the functionality of Google Chrome's "New Tab" iframes?

Have you ever wondered about those 8 small iframes displaying your most visited websites? How do they capture snapshots of the websites? How are the websites chosen for display? And most importantly, how do they actually work? Edit: I want to learn how to ...

What is the most effective method for updating a className in Next.js using CSS Modules when a button is activated?

Looking to create a responsive navigation bar that transforms based on screen size? When the width reaches 600px, I'd like to hide the links and instead show a clickable nav button that reveals those options. Upon inspecting my list elements in the c ...

"Troubleshooting: Why are errors not appearing in ts-node

Whenever I encounter an error in my code while compiling with ts-node, the error does not seem to appear in the console. For instance:let data = await fs.readFileSync(path); In the following code snippet, I am using "fs" to read a file by passing a path ...

The hovering event trail feature is not functioning in tsParticles, unlike in particlejs

I have two questions regarding the implementation of tsParticles in my React application. First question: <Particles id="tsparticles" options={{ background: { color: { value: "black&quo ...

Tips for modifying the language of an Angular Application's OneTrust Cookie Banner

I'm currently developing an Angular application and utilizing OneTrust for managing cookie consent. The issue I'm encountering is that while the rest of the components on the login page are properly translated into the target language, the OneTru ...

Is there a software available that can transform <style> blocks into inline CSS code?

Is there a tool available that can convert <style> blocks to the corresponding style attributes in an HTML file? For instance, if we have the following input file: <html> <head> <style> .myclass { color:red; } </style> &l ...

Transforming Button style in jQuery Mobile version 1.3.0

There are reports of a new function in jQuery Mobile 1.3.0 that allows for dynamically changing button themes using JavaScript: http://jquerymobile.com/blog/2013/02/20/jquery-mobile-1-3-0-released/ However, upon attempting to run the provided code snippe ...

Ensuring a div remains perfectly centered

Currently, I am new to HTML and still in the process of learning. I am facing a challenge in centering a button within a div, and I have been using margins to position it. While this method works well when the window is fullscreen, the button's positi ...

RTL in TextInput only functions properly every other time it is rendered

I am facing a strange problem with RTL where everything seems to be flipped correctly except for TextInput, which only works about half of the time. Check out this gif that demonstrates the issue as I switch between English and Hebrew: (click to view a la ...

Discovering the mean value from a data set in a spreadsheet

I have been tasked with creating an HTML page for a car dealership using JQuery and Bootstrap 5. The goal is to utilize Bootstrap 5 to accomplish the following: Set up a table with appropriate form input elements that allow users to input four (4) quarter ...

"Unlocking the potential of AngularJS: A guide to accessing multiple controllers

I am trying to set a variable in one instance of a controller and read it in another. The variable I need to set is within the object vm (so $scope cannot be used). This is the code for the controller: app.controller("AppController", function(){ var ...

A guide to extracting iFrame information (specifically the referring URL) using JavaScript

Is there a way to retrieve the information from an iFrame (right-click on an iFrame in the browser -> This Frame -> View frame info)? I'm particularly interested in obtaining the referring URL. So far, I managed to retrieve the address using co ...

The webpack development server refreshes the page just one time

I've been searching through various issues on Stack Overflow but haven't had any luck. It seems like most solutions are for an older version of webpack-dev-server. Despite trying numerous things, my app just won't reload or rebuild more tha ...

What are the steps for incorporating a linear-gradient hue into a Slider?

Is it possible to apply a linear-gradient as color to Material-UI Slider? I have tried everything but can't seem to make it work. color: 'linear-gradient(180deg, #29ABE2 0%, #00EAA6 100%)' ...

Customize your error messages in AJAX requests

The form on my index.php page submits to process.php, triggering the execution of the code below: $(document).ready(function() { $('#login_button').click(function() { event.preventDefault(); var formData = { 'email' ...

aligning columns within a flexible element that has a maximum height

Within this flex element, I have set flex: column wrap; and max-height: 150px;. The issue I'm facing is that justify-content doesn't seem to be working. However, when I switch to using height: 150px, the alignment works fine. This problem arises ...

Dealing with performance issues in VueJS and Vuetify's data-table component, especially when trying to implement

In my VueJS and Vuetify project, I encountered an issue. I am trying to create a table with expandable rows for displaying orders and their associated products. The table needs to show at least 100 rows of orders on one page. To achieve this, I utilized th ...