I have some jQuery code to close my menu:
$('body').click(function(){
$('#menu').hide();
});
$("#menu").click(function(e) {
e.stopPropagation();
return false;
});
However on my #menu element I have some elements that have click events attached to them:
$('.menu_elem').live("click", function(){
//Do something
});
My problem is that the e.stopPropagation() is preventing my click events for my menu. How can I avoid this?
You can use e.target to include or exclude the element in condition for stopPropagation,
$("#menu").click(function(e) {
if(e.target.id == "menu")
{
e.stopPropagation();
return false;
}
});
I'm not sure I understand your HTML exactly, but if #menu is the root of your menu and .menu_elem are menu items in the menu, then you could change your delegated event handling to to be captures at #menu like this:
$("#menu").on("click", ".menu_elem", function () {
// do something
});
This has the following advantages:
It changes the delegated event handling to capture the bubbled events at #menu so it doesn't need propagation beyond #menu in order to work so you don't have to change your.stopPropagation() code.
It switches away from (the now deprecated) .live() to the replacement .on() which gives you more control over where the bubbled events are captured.
Write up your code that you want to execute and call it before you call stopPropagation..
$("#menu").click(function(e) {
// Your code here
e.stopPropagation();
return false;
});
Or use the target attribute to contain your click event
Related
I have:
$('#externalContactsGrid').on('mouseup', '.k-grid-content, tr', function(e) {
alert('test')
...
})
I want it to fire once if the mouse is up on either element, not twice. So I want it to fire on '.k-grid-content' OR 'tr', with 'tr' taking precedence.
tr elements are inside .k-grid-content.
I also need the browsers context menu to not show when e.which == 3.
Try to use .stopPropagation() to stop the event bubbling
$('#externalContactsGrid').on('mouseup', '.k-grid-content, tr', function(e) {
e.stopPropagation();
alert('test');
});
I want it to fire once if the mouse is up
What seems to me is either your alert is comming two times
or you want to bind the event for one time only
if case is 1 then probably you want to use .stopPropagation() because tr elements are inside .k-grid-content.
Because events are tend to bubble up the dom meaning whenever an event is bound to any child/grandchild element the event bubbles up to the parents of it. so if parent has any bound event then that would also get fired.
$('#externalContactsGrid').on('mouseup', '.k-grid-content, tr', function(e) {
e.stopPropagation(); // stops the event to bubbleup the dom
alert('test')
if case is 2 then probably you want to use .one()
$('#externalContactsGrid').one('mouseup', '.k-grid-content, tr', function(e) {
I also need the browsers context menu to not show when e.which == 3.
For this:
if(e.which == 3){
$(document).off('contextmenu');
}
How do I trigger click on a child element without letting the click event bubble upto the parent & thereby create a infinite trigger loop of click event.
For example I have like this:
<li>
<a> ... </a>
</li>
I want to trigger a click event on a whenever li is clicked, but to prevent infinite trigger loop, I should avoid event propagation upto parent. How do I do that ?
Something like this?
$('li').on('click','a', function(e) {
e.stopPropagation();
// your code here...
});
By using .stopPropagation() on the anchor you can stop the bubbling. You should be able to use something like:
$('a').click(function (e) {
e.stopPropagation();
console.log('link');
});
$('li').click(function () {
$('a').click();
});
jsFiddle example
You do not state exactly the behavior you want from the click on the link, but if you simply want to stop the click being handled at all, use preventDefault() on the event argument of click:
$('li').on('click','a', function(e) {
e.preventDefault();
});
If you just want to stop the parent seeing the event use stopPropagation() instead:
$('li').on('click','a', function(e) {
e.stopPropagation();
});
The other option is return false, which does the same as both preventDefault() and stopPropagation()
$('li').on('click','a', function(e) {
return false;
});
use event.stopPropagation()() in the event callback.
$('selector').click(function(event){
event.stopPropagation()();
})
Parse the tag name on the parent click handler. (You could also look at class name or ID, among other event filters.) If desirable child tag is detected, then stop the propagation and return true so that this event runs. If desirable child tag is not detected, then prevent default event and return false. Thus, clicking on LI will trigger the click on A without a runaway event loop, and clicking on A will proceed properly without a runaway event loop either. Note also that you can't just fire the .click() event on the tag. You need to send it deeper into the native DOM element, using [0].click(), as I have shown below.
$('LI').click(function(e){
var sTag = e.target.tagName.toUpperCase();
if (sTag == 'A') {
console.log('DEBUG: A click');
e.stopImmediatePropagation();
return true;
} else {
console.log('DEBUG: ' + sTag + ' click');
e.preventDefault();
// the following won't work without the [0]
$(this).find('A')[0].click();
return false;
});
I have a table cell that I want to be able to be clicked. But once it is clicked it will have the class ".clicked". When any table cell has this class, I do not want to be clickable. Is there any way to do this?
Also you can use .off() method to unbind any events.
$('td').on('click', function(){
$(this).addClass('clicked').off('click');
})
This is easily done by inserting some code at the top of the event handler.
$('td').click(function(e) {
if ($(this).hasClass('clicked')) {
e.stopPropagation();
e.preventDefault();
return;
}
// the rest of your code here
});
The other, more involved, way, is to use event delegation and only fire the function if the element doesn't have the class when it's clicked:
$('table').on('click', 'td:not(.clicked)', function() {
// your code here
});
You can use the .one() event registration method to do it, it will un-register the handler once the event is fired.
$('td').one('click', function(){
console.log('hanlded', this)
})
Another solution could be
$('table').on('click', ':not(.clicked)', function(){
console.log('hanlded', this)
})
Just add :not(.clicked) to whatever selector you're using to exclude clicked cells.
I am trying to make a swith on / off javascript, but I have a problem: I click always comes in my first class despite my class change.
I have always the same result : on->on or off->off. I check in Firebug my html is changed correctly...
Here my simplified code :
$('.off').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
alert('off');
$(this).removeClass('off');
$(this).addClass('on');
});
$('.on').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
alert('on');
$(this).removeClass('on');
$(this).addClass('off');
});
if anyone has a suggestion, I would be very grateful !!
The event handlers are bound on pageload, so changing the class won't change the event handlers, as they are attach to whatever elements existed at the time of binding. To attach them to future elements, i.e. when you change the classes, you'll need delegated event handlers, but an easier solution in my opinion is to just toggle the classes or use a flag:
$('.off').on('click', function(e) {
e.preventDefault();
var state = $(this).is('.off') ? 'on' : 'off';
alert(state);
$(this).toggleClass('off on');
});
FIDDLE
It can be confusing, but even if you remove the .off class, the event handler is still bound to the same element, as it had the .off class at the time of binding!
Either .off or .on does not exist when you first bind with .on. You need to use event delegation, or you can rewrite this so that it's bound to another class and maintain on/off state. I will show you both methods.
Delegation
$(document).on('click', '.off', function(e) {
$(this).removeClass('off').addClass('on');
}).on('click', '.on', function(e) {
$(this).removeClass('on').addClass('off');
});
http://jsfiddle.net/ExplosionPIlls/2PHJg/
Internal state
$(".switch").on('click', function () {
if ($(this).is('.off')) {
$(this).removeClass('off').addClass('on');
}
else {
$(this).removeClass('on').addClass('off');
}
});
http://jsfiddle.net/ExplosionPIlls/2PHJg/1/
This problem is caused because $('.on') and $('.off') only gets evaluated once, when your javascript code runs.
You have to use event delegation to solve the problem. Modify the code the following way. I describe below what it means.
$('#container').on('click', '.off', function(e) {
e.stopPropagation();
e.preventDefault();
alert('off');
$(this).removeClass('off');
$(this).addClass('on');
});
$('#container').on('click', '.on', function(e) {
e.stopPropagation();
e.preventDefault();
alert('on');
$(this).removeClass('on');
$(this).addClass('off');
});
In the place of #container use a selector which selects a parent of your .on / .off elements. In the second parameter of your on() call, youy have to specify the element for which you want to listen for events.
This way the event handler will run properly, even if the class of your elements change.
The problem is that the event handlers are bound when the code first runs, so when the class changes, the event handlers aren't rebound. One way to fix this is to assign the element a class that doesn't change, and use that for the event handler.
Example:
$('.button').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).toggleClass('off on');
});
You can see a working example at http://codepen.io/skimberk1/pen/GJhna.
I was trying to setup this "when you click outside of the element, close it" type of thing using some code I found on Stackoverflow:
$(document).click(function() {
$('.list-to-hide').hide();
});
$('.show-list-button').click(function(event) {
event.stopPropagation();
});
Could someone explain the later part with stopPropagation? I don't understand why it's needed.
Thanks!
Matt
Imagine this:
<div>
DIV
<span>
Span
</span>
<div>
and:
$('div').click(function() { alert('div clicked'); });
$('span').click(function() { alert('span clicked'); });
Check out what happens when you click each one
When you click the span, it happens to also trigger the div because your also clicking the div.
Now if we wanted to alert the span only we need to stop the div click from triggering when we click on the span so we do this:
$('div').click(function() { alert('div clicked'); });
$('span').click(function(e) { alert('span clicked'); e.stopPropagation(); });
See what happens now
Your example code is missing a vital part:
$(document).click(function() {
$('.list-to-hide').hide();
});
$('.show-list-button').click(function(event) {
event.stopPropagation();
$('.list-to-hide').show();
});
Without the event.stopPropagation(), it would show the list, and then hide it because the .show-list-button is inside the $(document) so both click handlers would fire. event.stopPropagation() basically says only apply this click event to THIS CHILD NODE and don't tell the parent containers anything because I don't want them to react.
Think about it this way - you rent a taxi for $100. The driver gives his company $80. event.stopPropagation() is like telling him to keep all $100 because the company doesn't need to know anything about the ride.
event.stopPropagation(); prevents the event from bubbling up the DOM. Without this line, clicking on .show-list-button the click handler for document will fire also. With it, the document click will not fire.
Have you read this ?
http://api.jquery.com/event.stopPropagation/
It prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
Example
Kill the bubbling on the click event.
$("p").click(function(event){
event.stopPropagation();
// do something
});