I want to bind a click function to the document when open some menu via click.
The problem is that when trigger the first event 'click on the menu', the function attached to the document has been triggered by the same event and close the menu. How to solve that issue. My code is something like that:
$('#openMenu').bind('click touchend', function(e){
e.preventDefault();
$('.openMobMenu').removeClass('openMobMenu');//Close All elements
var _this=$('#headMenu')
_this.addClass('openMobMenu');
$(document).bind('click touchend',{elem:_this},hideElementMob);
});
// bind click event listner to the document
function hideElementMob(e){
var th=e.data.elem;//Get the open element
var target=$(e.target);//Get the clicked target
//Check the target and close the element if need
if(target.parents('.openMobMenu').length==0) {
th.removeClass('openMobMenu');//close the element if need
//Unbind listner after closing the element
$(document).unbind('click touchend');
}
}
Thank you in advance!
Try adding the close handler with a little delay:
setTimeout(function(){
$(document).bind('click touchend',{elem:_this},hideElementMob);
}, 10);
And as Jan Dvorak suggested, you should use .on() to attach events.
UPDATE
I realized I did not answer the whole question, so here is some improvement to the "why does it behave like this" part:
When the click event occurs on #openMenu, the associated handler is executed first. This binds a click event to the document body itself.
After this, the event gets bubbled, so the parents of the #openMenu also recieves a click event, and since document.body is a parent of the #openMenu, it also recieves a click event and closes the popup immediatley.
To cancel the event bubbling, you can also call e.stopPropagation(); anywhere in your event handler. (maybe its a cleaner solution compared to setTimeout)
Related
I have a situation where the response of a click is handled like this:
//File A
$(document).on("click", function(evt) {
if (validateEvent(evt)) {submitEvent(evt.target); return(false);};
});
And I need to programmatically click an element on the document:
//File B
$('#myButton').click();
But unfortunately the .click() on the element does not trigger the $(document).on("click") code, solely the click handler of the element.
How could I either
Click the element, capture that event, and send the event to the validateEvent() function.
Create a click event on the element to send to the validateEvent()
function.
Trigger the document's click handler and tell it that the event belongs to the #myButton element?
You could use dispatchEvent to dispatch an event on the element #myButton like so:
var clickEvent = new Event('click');
$('#myButton')[0].dispatchEvent(clickEvent);
I slightly modified FU thumbnail template to hook a click event on it. I also display a delete button (the provided one).
The problem is that when I click on the delete button, the click event bubbles to the rest of the javascript stack.
How can I prevent the delete button to propagate the click event??
(usually you do something like event.stopPropagation()...).
Thanks for your help
If you'd like to prevent any DOM event from bubbling, simply attach an event handler to the element where you would like it to terminate and call stopPropagation() on the Event object. For example, for a click event:
someElement.addEventListener('click', function(event) {
event.stopPropagation();
});
The above code will not work in IE8 and older since addEventListener and stopPropagation were first introduced in IE9.
I wonder how do I change the order of events.
Because I have to check when I took a focusOut with a click, if the click was inside the parent div, I can not let it happen the focusOut.
The problem, which is called first event focusOut the click event.
Is it possible to reverse the order of events? (Click - focusOut)?
http://jsfiddle.net/eL19p27L/5/
$(document).ready(function(){
$(".clean").click(function(){
$(".alert").html("");
});
$(document).on({
click: function(e){
$(".alert").append("<p>click</p>");
},
focusin: function(e){
$(".alert").append("<p>focusin</p>");
},
focusout: function(e){
$(".alert").append("<p>focusout</p>");
}
})
});
It would be even better. If I could detect what the event might turn out to generate the fucusout. Hence check if it happened within the parent div, if not a focusIn, it leaves not give a focusOut.
ATT
No, the way you have your event handler set up on a common parent, you can't change the order of the events.
But, you can attach your event handlers to the specific objects you want to watch and then you can see events for that object only.
Or, you can look at the target of the event and see which object is which and you will see that the focusOut event is on a different object than the click event.
You can see the source of the event with e.target.
Example of looking at the object that is the source of the event: http://jsfiddle.net/jfriend00/u5tLhes7/
Need to get info from any element, which was clicked.
Example:
<div>text1<section>text2</section></div>
and JS
$(function(){
$('body *').click(function(){
alert($(this).get(0).tagName.toLowerCase());
});
});
If I click text2, parent element throw alert too. I need only first alert from section. How I can block next alerts from all parent elements of section.
Use event.stopPropagation() to prevent the event from firing on the containing elements.
$(function(){
$('body *').click(function(e){
e.stopPropagation();
alert($(this).get(0).tagName.toLowerCase());
});
});
Just wanted to expand on Kooilnc answer - Using on with event delegation is another option.
Event delegation would be nice if you have an event listener bound before or after on a node that needs to listen to a click handler that has bubbled up. If you stopPropagation, this obviously would be an issue.
Here's a fiddle with a demo:
http://jsfiddle.net/ahgtLjbn/
Let's say a buddy of yours has bound an event listener to a node higher up in the DOM tree. He expects any events that bubble up to it, to be handled by his script.
Using event delegation, the event still bubbles up (so your buddies code will still fire), but it will only alert once (since we called e.stopPropagation).
Calling on without event delegation, or binding the event directly using click (which, under the hood, is just calling on) will prevent the event from bubbling, so your buddies code will never run.
Is there any specificity associated with event callback with jQuery. Say, I register a mousedown event callback on a div element, and also on the document. Which one would trigger if I click on the div? Does the order of registration matters? or the specificity (like css) matters?
thanks.
It will bubble up the DOM tree and call all other events of that type.
You can stop this with event.stopPropagation().
Your example
If you assigned the events like so...
$(document).mousedown(function() { alert('document'); });
$('div').mousedown(function() { alert('div'); });
Mouse down anywhere will trigger document's handler, and get one alert dialog with document.
Mouse down on any div will trigger the div's handler, and then bubble up the DOM all the way to document where it will trigger its event handler. You will get two alert dialogs; first the div one and then the document one.
Both events will be triggered, first the div, and then the document click.
It will execute both, from inside out. Clicking in the div will fire the div event then the document. Example on jsFiddle
$(window.document).click(function(e){
alert("doc");
});
$("div").click(function(e){
alert("div");
});
You can avoid it firing other events with e.stopImmediatePropagation(). See this example
$(window.document).click(function(e){
alert("doc");
});
$("div").click(function(e){
alert("div");
e.stopImmediatePropagation(); // prevents $(doc) from rising
});