A few drop-down lists: how to handle them correctly?

I need to create a small drop down system that starts with clicks. I managed to handle the "click from div" question (thanks to this previously posted question).

I can hide the current drop-down list by clicking on another trigger of the drop-down list or by clicking outside the drop-down list itself. So the problems are:

  • Click the current drop down trigger, which is useless; the dropdown does not disappear while other things are working fine
  • A click inside the current drop-down list (for example: a .divider element) causes the drop-down list to be disabled.

So here is the html code (let's say I have some dropdowns in the header)

... <div id="header" class="navbar"> <div class="line"> <a href="#" class="logo">Site Name</a> <ul class="nav right"> <li> <a href="#" class="has-drop">Item 1</span> <ul class="dropdown-menu"> <li><a href="#">Action A</a></li> <li><a href="#">Action B</a></li> <li><a href="#">Action C</a></li> <li class="divider"></li> <li><span>Inline note</span></li> </ul> </li> <li> <a class="has-drop" href="#">Item 2</a> <ul class="dropdown-menu"> <li><a href="#">Action D</a></li> <li><a href="#">Action E</a></li> <li><a href="#">Action F</a></li> <li class="divider"></li> <li><a href="#">Action G</a></li> </ul> </li> </ul> </div> </div> <!-- end #header --> ... 

And this is actually the JS code I'm using in the highlighted file

  $(document).ready(function(){ $("html").on({ click: function(e) { $(".dropdown-menu.opened").toggleClass("opened"); } }); $(".nav > li > a").on({ click: function(e){ e.stopPropagation(); $(".dropdown-menu.opened").toggleClass("opened"); // should close each .dropdowns before opening the current one $(e.target).siblings(".dropdown-menu").toggleClass("opened"); } }); }); 

Why do you think that the dropdown menu will not disappear when I again click on its trigger? Because inside $(".nav > li > a").on() is almost the same thing done?

Also, is there a way to prevent the pop-up menu when some of its children are clicked? But perhaps this is more related to another issue, I do not know.

And last but not least, is this, in your opinion, the right way to do all this?

Thanks to everyone in advance.


EDIT : thanks to @ Beetroot-Beetroot I was able to solve the problem, so here is the current working code $ (Document) .ready (function () {

  $("html").on("click", function(e) { $(".dropdown-menu.opened").removeClass("opened"); }); $(".nav").find("li :first-child").on("click", function(e) { e.preventDefault(); e.stopPropagation(); var $thisMenu = $(this).siblings(".dropdown-menu").toggleClass("opened"); $(".dropdown-menu").not($thisMenu).removeClass("opened"); }); }); 

The "secret" is the clever use of .not (), which I now understand more.

I just changed the goal (which can <a> or <span> ) to a more general one. Not sure about the performances in the long run, but certainly a good starting point.

WITH

 $(".nav").find("a.has-drop").on(... 

For

 $(".nav").find("li :first-child").on(... 

Also here

$ (this) .closest ("nav"). Find (". Drop-down menu"). No (... I made it more general like this $ (Drop-down menu). No (... This is because I want to hide all open drop-down lists. The previous behavior considered only one type of target and only one area of ​​origin (for example: maybe I need these drop-down lists, as well as in the title and inside any toolbar in the content).


EDIT 2 : @ Beetroot-Beetroot helped me again. As he suggested, while I was porting the current code to jsFiddle, the solution unexpectedly turned out by itself. So now the part of $("html").on("click", ... looks like

  $("html").on("click", function(e) { if ( $(e.target).hasClass("dropdown-menu") || $(e.target).parents(".dropdown-menu").length ) { // do nothing, basically } else { $(".dropdown-menu.opened").removeClass("opened"); } }); 

Basically, I'm just looking to see if there is a click from $("html") to make the width of the dropdown list. If so, do nothing. If not, it means that I clicked anywere, but not where it fell out.

+4
source share
1 answer

I think something like this should do:

 $(document).ready(function() { $("html").on('click', function(e) { $(".dropdown-menu.opened").removeClass("opened"); }); $(".nav").find("a.has-drop").on('click', function(e) { e.preventDefault(); e.stopPropagation(); var $thisMenu = $(this).siblings(".dropdown-menu").toggleClass("opened"); $(this).closest(".nav").find(".dropdown-menu").not($thisMenu).removeClass("opened"); }); }); 

untested

Notes:

  • removeClass() replaces toggleClass() in several places.
  • the secret is to switch $thisMenu first and then use not($thisMenu) on the next line to ensure that $thisMenu remains in any of the states it was switched to.
+2
source

All Articles