I have an element as show below:
<div id="treeTable123" class="collapsed">
<div id="test"></div>
</div>
I have binded on click function to div with id 'test' using jquery.
function1:
$(document).delegate('#test', 'click', function(e){
....
});
I have another binded click function to other elements as:
function2:
$('[id^="treeTable"]').delegate('.collapsed', 'click', function(e){
});
When I click div with id 'test' both events are fired. So I want to prevent the event in the function 2 on clicking on event inside function 1. How can i do that?
$('[id^="treeTable"]').delegate('.collapsed', 'click', function(e){
if($(e.target).closest('#test').length === 0) {
// code placed inside this condition is not executed on clicking the element #test
}
});
Just call the e.stopPropagation() form the first callback. Here is a demo http://jsfiddle.net/eyXT7/2/.
you can simple use e.stopPropagation()
More Info
As you have it, its not possible. You can do it if you don't use delegation as the event has to bubble up to the delegate target for the event handler to fire. So function2 will fire before function1 and you can't prevent a it from firing after it fired.
$('#test').on('click', function(e){
e.stopPropagation();
....
});
http://jsfiddle.net/r5JaL/
Related
I have simple scenario as shown in fiddle which is
Initially event is binded on only one button A and click event is triggered in both the buttons(A & B) manually.
Now in event handler of button A the event handler for button B is binded. It is expected not to execute the callback of B as it is binded after the event is triggered.
But the callback is still executed. Where am i going wrong?
HTML:
<div>
<button class="a">botton A</button>
<button class="b">button B</button>
</div>
JS:
$(function () {
$('div').on('click', '.a', function (e) {
e.preventDefault();
$('div').on('click', '.b', function () {
alert('Can"t see me')
});
});
$('button').trigger('click');
});
FIDDLE LINK
EDIT:
I have this scenario in my project and
now I knew why is this happening :). But how can i stop event from propagating?
$('button').trigger('click'); triggers a click event on both buttons in the order they appear in the document markup. Since event bubbling is synchronous, the event for .b is binded before the click event is triggered on that button. Here's the breakdown:
$('button') creates a collection of button .a and button .b.
.trigger('click'); iterates through each button in the collection and generates a click event.
button .a receives the click event and runs its event handler you registered for it on page load.
The event handler for .b is registered within the callback of the event handler for .a.
button .b receives the click event from .trigger('click'); since it's second in the collection.
The callback of the event listener for button .b triggers the popup alert.
Since you only want to trigger button .a to be clicked, any of the following will work on your current document:
$('.a').trigger('click');
$('button.a').trigger('click'); (though this is redundant)
$('button').get(0).trigger('click'); (since .a is the 0th indexed button element)
EDIT Although this is unrelated to the question, Perhaps you meant to register the event for .b only once, doing this:
$('.a').one('click', function (e) {
$(function() {
$('.a').one('click', function(e) {
e.preventDefault();
$('div').on('click', '.b', function() {
alert('Can\'t see me');
});
});
$('.a').trigger('click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button class="a">button A</button>
<button class="b">button B</button>
</div>
SECOND EDIT If you want to stop event propagation, you need to add another event listener, like this:
$(function() {
$('.a').one('click', function() {
$('.b').on('click', function(e) {
e.stopPropagation();
alert('Can see me');
});
$('div').on('click', '.b', function() {
alert('Can\'t see me');
});
});
$('button').trigger('click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button class="a">button A</button>
<button class="b">button B</button>
</div>
It's because of $('button').trigger('click');.
This triggers a click on every button - first it clicks on .a, which binds the click handler to .b, then it clicks on .b.
In my experiment, simply putting button .b first fixed this, but I wouldn't rely on that.
This is probably because the click is being triggered on all button instances serially...
button a click gets executed first...in its callback you bind button b click callback...
...then...button b click gets executed...hence callback for b gets executed...
All of this happens in that one call: $('button').trigger('click');
Edit: others have probably answered this before I have...but to iterate trigger the click on the correct element :
$('.a').trigger('click');
The order of the execution is:
bind .a
trigger first button (say, a)
callback for a: bind b
trigger second button (b)
callback for b
Even $("button").trigger("click") is a single line, it is a kind of loop, works like if it were:
var buttonElms = $("button");
for (var index in buttonElms) {
buttonElms[index].trigger("click");
}
How do I stop the infinite recursion here so that a mousedown event can be triggered just once? should it be in a separate method?
$(document).on('mouseover',function (e) {
$(e.target).mousedown(function(e){
e.stopPropagation();
console.log('clicked');
$(e.target).trigger('mousedown'); //use hello(e); instead?
return;
})
});
$(document).on('mousedown', 'a', function(e){
hello(e);
});
function hello(e){
console.log('got it');
}
This seems to trigger a never ending loop. Basically I need to bind a mousedown handler on the currently element under the mouse, which will fire a mousedown event that another handler will be able to handle.
The reason I am doing this is because the mouseover works on dynamically generated element so when this happens I need to bind a handler again as the on handler is not able to catch the newly generated element.
You are making it complicated. Imagine everytime a user move his mouse an event will be added dynamically?
Why not design your element with class names and use it in your mousedown event? This way a sure call to mousedown will trigger always.
$(".className").mousedown(function(e){
console.log('clicked');
return;
})
--The reason I am doing this is because the mouseover works on dynamically generated element so when this happens I need to bind a handler again as the on handler is not able to catch the newly generated element.
If you say so then, add a className to your dynamically generated element to have your mousedown event bind to it.
try like this:
$(document).on('mouseover',function (e) {
$(e.target).trigger('mousedown'); //use hello(e); instead?
return;
});
$(document).on('mousedown','a', function(e){
hello(e);
});
function hello(e){
alert('got it');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
hello
How can I listen to a change event on a checkbox without triggering a click event on its container?
<label><input type="checkbox"> Hello world</label>
I want to trigger an action on the checkbox's change event, but I don't want it to bubble up to a click event on the label.
(function ($) {
$('input').change(function (v) {
v.stopPropagation();
});
$('label').click(function () {
alert('You should not see this message if you click the checkbox itself!');
});
})(jQuery);
http://jsfiddle.net/r49PA/
Any ideas? Thanks!
The issue is that two events are triggered when you click the checkbox -- a change and a click. You're only catching the change, so the click isn't ever being told to stop propagation. You need to either add a second handler on the checkbox for click events, or combine one handler to catch both types, like this:
$('input').on('change, click', function (v) {
v.stopPropagation();
});
Here's a jsFiddle demonstrating a combined handler: http://jsfiddle.net/r49PA/4/
You can stop propagation on click event instead of change event since you bind click event for the parent label:
$('input').click(function (v) {
v.stopPropagation();
});
Updated Fiddle
With plain javascript you can do something like this:
var stopPropagation = false;
selector.addEventListener('mousedown', function(event) {
// simulating hold event
setTimeout(function() {
stopPropagation = true;
// do whatever you want on the `hold` event
})
}
selector.addEventListener('click', function(event) {
if (stopPropagation) { event.stopPropagation(); return false; }
// regular event code continues here...
}
Since mousedown and click events are overlapping, we want the click event to not be triggered when we are trying to get the hold state. This little helper flag variable stopPropagation does the trick.
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 click event I wired up on a div on my page.
Once the click event has fired, I want to unbind the event on that div.
How can I do this? Can I unbind it in the click event handler itself?
Use the "one" function:
$("#only_once").one("click", function() {
alert('this only happens once');
});
Taken from the jQuery documentation found here:
$("#unbind").click(function () {
$("#theone").unbind('click', aClick)
.text("Does nothing...");
});
In plain JavaScript:
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener('click', clicked, false);
function clicked()
{
// Process event here...
myDiv.removeEventListener('click', clicked, false);
}
Steve
There's the unbind function documented here:
http://docs.jquery.com/Events/unbind
Fits your example :)