What is the best way to hide the drop down menu after it has been opened by clicking on the same element

My attempt to create a code that toggles a drop-down menu on every click and closes any other open menus is not working as expected. The menu doesn't close upon clicking it again.

$(document).ready(function(){ 
    "use strict";
    $(".dropdown").hide();
    $("#smpg-cat-list li span").click(function() {

      $(".dropdown").hide();

      $("#smpg-cat-list li span").html('<i class="fa fa-plus" aria-hidden="true"></i>');

      if( $(this).next('.dropdown').css('display') == 'none' ){

         $(this).next('.dropdown').show();

         $(this).html('<i class="fa fa-minus" aria-hidden="true"></i>');

      }else{

        $(this).next('.dropdown').hide();

        $(this).html('<i class="fa fa-plus" aria-hidden="true"></i>');
      }

  });
});

I intend for the code to:

  1. Hide all instances of the class .dropdown.
  2. When #smpg-cat-list li span is clicked, close any open menus.
  3. Change the hidden elements' HTML to display a plus icon.
  4. Determine if the next .dropdown element has a display of none.
  5. If true, display the element and change the icon to minus.
  6. If false, hide the element and change the icon to plus.

The issue remains where the element shows but does not hide when clicked again.

HTML

<ul id="smpg-cat-list">
<li><a href="/web-design/">Web Design</a>
</li>
<li><a href="/robots/">Robots</a></li>
<li>
    <a href="/programming/">Programming</a>
    <span class="toggle" style="cursor:pointer"><i class="fa fa-plus" aria-hidden="true"></i></span>
    <ul class="dropdown">
        <li><a href="/programming/php/">PHP</a></li>
        <li><a href="/programming/c/">C#</a></li>
    </ul>
</li>
<li>
    <a href="/frameworks/">Frameworks</a>
    <span class="toggle" style="cursor:pointer"><i class="fa fa-plus" aria-hidden="true"></i></span>
    <ul class="dropdown">
        <li><a href="/frameworks/laravel/">Laravel</a></li>
    </ul>
</li>
<li><a href="/data-analysis/">Data Analysis</a></li>
<li>
    <a href="/cms/">CMS</a>
    <span class="toggle" style="cursor:pointer"><i class="fa fa-plus" aria-hidden="true"></i></span>
    <ul class="dropdown">
        <li><a href="/cms/wordpress/">WordPress</a></li>
        <li><a href="/cms/joomla/">Joomla</a></li>
    </ul>
</li>
</ul>

No special CSS involved.

Answer №1

After selecting a span element in the code snippet below, I utilized the [.find()][1] function to locate the i tag and verify if it contains a specific class using [.hasClass()][1]. Following this, I replaced the class from fa-plus to fa-minus, or vice versa, and then displayed the adjacent dropdown menu.

This script should guide you:

$(document).ready(function() {
  "use strict";
  $(".dropdown").hide();
  $("#smpg-cat-list li span").click(function() {
    
    $(".dropdown").hide();
   
    var $element = $(this).find("i");
    console.log($element);
    if ($element.hasClass("fa-plus")) {
      $element.removeClass("fa-plus").addClass("fa-minus");
      $(this).next('.dropdown').show();
    } else {
      $element.removeClass("fa-minus").addClass("fa-plus");
      $(this).next('.dropdown').hide();
    }
  });
});
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="smpg-cat-list">
  <li><a href="#">Web Design</a>
  </li>
  <li><a href="#">Robots</a></li>
  <li>
    <a href="#">Programming</a>
    <span class="toggle" style="cursor:pointer"><i class="fa fa-plus" aria-hidden="true"></i></span>
    <ul class="dropdown">
      <li><a href="#">PHP</a></li>
      <li><a href="#">C#</a></li>
    </ul>
  </li>
  <li>
    <a href="#">Frameworks</a>
    <span class="toggle" style="cursor:pointer"><i class="fa fa-plus" aria-hidden="true"></i></span>
    <ul class="dropdown">
      <li><a href="#">Laravel</a></li>
    </ul>
  </li>
  <li><a href="#">Data Analysis</a></li>
  <li>
    <a href="#">CMS</a>
    <span class="toggle" style="cursor:pointer"><i class="fa fa-plus" aria-hidden="true"></i></span>
    <ul class="dropdown">
      <li><a href="#">WordPress</a></li>
      <li><a href="#">Joomla</a></li>
    </ul>
  </li>
</ul>

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

Enlarge the font size without changing the location of the input field

Imagine having an input field with a set height of 25px. If you decide to increase the font size within that text field, even though the dimensions remain constant, it may seem like extra padding has been added. Initially, at a normal font size, it appears ...

Navigating through each segment

I'm currently working on a website with sections that are set to be 100% height of the window, but at least 800px tall. My goal is to implement a smooth scrolling functionality where one scroll moves the view from section to section. However, if the ...

Remain concealed once the lights dim

Looking for a way to fade out a logo in a preloader div after a call, but having issues with it becoming visible again once fully faded out. Ideally, I would like to keep it faded out or set it to display none using only CSS, although I can use jQuery if n ...

Conceal the standard style class of the p:selectOneRadio element

On my xhtml page, I've implemented p:selectOneRadio. However, I'm struggling to remove the default style class .ui-helper-hidden-accessible, resulting in the radio button icons not being visible. Here's a snippet of my code: <p:selectOne ...

Send the form to the webpage and display various div elements based on the entered information

I have created a form that is designed to display one of four hidden divs on a page, depending on the input provided. Here is the form: <form> <input id="place" name="place" type="text"> <input name="datepicker" type="text" id="datepicker" ...

Enhance the current model in backbone.js by incorporating additional data

When a user selects an item on the webpage, more details need to be fetched and displayed. The API function /api/full_details has been implemented to return the additional data for that item. Challenge: How can I retrieve the additional data and append it ...

Tips on moving down the `<li><span>` elements with the jQuery `.slidedown()` method

I'm struggling to articulate my question clearly, so please bear with me. Essentially, I have a jquery script that reveals content within a div nested in an li. When I click on the header, the content drops down and visually pushes the next header do ...

I desire my grid to exhibit an identical appearance to that of the jquery datepicker

I have an interactive element called the "open grid" that, when clicked on, reveals a grid of buttons. I'm looking for help with coding it so that instead of being displayed below the textbox, the grid of buttons can be hovered over the "open grid" li ...

What could be the reason that my d3.tooltip is not functioning properly for these specific two lines on the chart?

I am currently experiencing issues with the d3.tool tip for my line charts. Additionally, I would like to adjust the y-axis scale to create larger gaps between the lines. Below are the codes used to generate the line charts: <!DOCTYPE html> <meta ...

Organize your table with CSS styling

Looking for a way to rearrange a table with 2 columns after every 2 rows so that the lines continue on the right side? Check out the example below: [1][2] [1][2][5][6] [3][4] => [3][4][7][8] [5][6] [7][8] Wondering if this can be achieved using o ...

Has a newly created element been styled or are all values set to default since it is outside of the DOM?

First, I begin by creating an element: let link = document.createElement('a'); After my document is fully loaded and all styles and scripts are applied. The styles may look something like this: a { background-color: salmon; } Therefore, it w ...

Utilize the JQuery range slider within an ASP.NET MVC Razor project

After finding an answer to a question on creating a simple range slider in ASP.NET MVC 3, I decided to implement a jQuery range slider for my ASP.NET MVC Razor view website. Although I managed to get the slider working on the frontend, I encountered issues ...

"Utilizing the datepicker functionality in Rails with jQuery UI

I am looking to integrate the datepicker widget into one of my select fields within a Rails 3.2.13 application with Ruby 1.9.3.p325 installed. To achieve this, I have incorporated the 'jquery_datepicker' gem along with 'jquery-rails' an ...

Using Vue3 to conditionally display a child div based on the class of its parent div

Just starting out with Vue, I'm currently experimenting with the active classes feature from this Vue3 carousel plugin. My goal is to only show the text and link divs for the carousel__slide--active class, but at the moment, all carousel__items are di ...

What causes the disappearance of CSS styles when attempting to modify the className in react js?

I am currently working on a basic react application, and I am trying to dynamically change the name of a div element using the following code snippet - <div className={'changeTab ' + (page.login ? 'leftSide' : 'rightSide')} ...

What is causing my CSS grid items to overlap instead of aligning neatly in rows and columns?

I am encountering an issue with CSS grid where items are stacking on top of each other when I assign them to grid template areas. As a newcomer to CSS grid, I suspect that I may be overlooking some key principles. You can view my playground here: https:// ...

What is the best way to retrieve response data from php using ajax in a single file?

Trying to retrieve PHP response data using AJAX has been a challenge for me. My goal is to search for a specific string in testing.txt based on user input. If the string is found, PHP should output "1", but no matter what I attempt, AJAX consistently retur ...

Is it feasible to set a default value in an HTML input field that is not editable using JavaScript?

Is there a way to set a default value in an input field of HTML that is not editable, and then allow users to add additional text to it? For example, having 'AB' as the default and uneditable starting characters, followed by any numbers such as A ...

Every time I reopen Fancybox, my custom Ajax function is triggered multiple times

Utilizing an input field and a list within Fancybox to search and retrieve clients using 2 custom Ajax functions. Everything is functioning properly, but upon reopening the same Fancybox, the Ajax functions are triggered multiple times. The first ajax ...

Basic click event triggered every second click in JavaScript and HTML

onclick="HandleAction(\'playnow\');HandleAction(\'stop\');" This element performs two functions simultaneously. However, it only executes the actions \playnow\ and then \stop\ immediately after. ...