Stop propagation for a specific handler

Let's say I have a custom dropdown (). When the button is clicked, I want to open the menu, and when the user clicks outside the menu, I want it to close. So I am doing something like this:

$(myDropDown).mousedown(dropDownMouseDown); $("html").mousedown(htmlMouseDown,myDropDown); function dropDownMouseDown(event) { event.target.open(); event.stopPropagation();//I need this line or else htmlMouseDown will be called immediately causing the dropDown-menu to close right before its opened } function htmlMouseDown() { this.close(); } 

Well, that works. But what if I add two of them? If I click to open the first, then the same on the second, then both will be open, because dropDownMouseDown stops the distribution, so htmlMouseDown will never be called for the first. How do I get around this? If I had only these two, then adding some logic for this would, of course, be easy, but if the quantity is dynamic? Also, maybe I do not want to call event.stopPropagation (), because it will do strange things in other libraries that I use that also listen to this event? I also tried putting this line: $ ("HTML"). MouseDown (htmlMouseDown, myDropDown) inside the dropDownMouseDown handler, but it will be called immediately anyway as soon as the bubbles reach the html element.

+4
source share
3 answers

How to use a variable containing the last opened? There are probably many other ways to do this, but here is a way I could think of:

 var lastOpened = null; // initially nothing is open (unless something is) 

Then:

 function dropDownMouseDown(event) { if (lastOpened != null) { // if one is still open lastOpened.close(); // close it lastOpened = null; // nothing is open anymore } event.target.open(); lastOpened = event.target; // now this one is open event.stopPropagation(); } function htmlMouseDown() { this.close(); lastOpened = null; // nothing is open } 

This should work so that the last open always closes before opening a new one.

+1
source

Assuming you have a selector for your dropdows, (say " .dropdown "), I would try using " .not() "

 $('.dropdown').mousedown(dropDownMouseDown); $("html").on('mousedown', htmlMouseDown); function dropDownMouseDown(event) { event.target.open(); } function htmlMouseDown(event) { $('.dropdown').not($(event.target)).close(); } 

Here is the fiddle in the same idea with css classes: http://jsfiddle.net/eFEL6/4/

+1
source

Thanks for answers. They are really appreciated. I figured out how to do this and I am satisfied. Here's how:

 $(myDropDown).mousedown(dropDownMouseDown); $("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler function dropDownMouseDown(event) { event.target.open(); } function htmlMouseDown(event) { if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can... event.data.close();///close the dropdown this handler was added for } 

I canโ€™t believe that I didnโ€™t think about it. In my case, although the element that opens / closes has children, therefore, event.target may be one of the children, not the element to which the handler is bound. So I changed my html-element handler:

  function htmlMouseDown(event) { var element=event.target; while (element) { if (element==event.data) return; element=element.parentElement; } event.data.hide(); } 
0
source

Source: https://habr.com/ru/post/1482984/


All Articles