JQuery stop event from starting
I have a simple script as shown in the fiddle which is on
Initially, the event is binded
for only one button A and the click
event is triggered manually in both buttons (A and B).
The event handler for Button A now has an event handler for Button B attached to it. It is not expected to call B's callback because it is bound after the event has fired.
But the callback is still executing. 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');
});
EDIT:
I have this scenario in my project and now I knew why this is happening :). But how can I stop the event from propagating?
source to share
$('button').trigger('click');
fires a click event on both buttons in the order in which they appear in the markup in the document. Because the bubbling event occurs synchronously, the for event is .b
bound before the click event is triggered on that button. Here's the breakdown:
-
$('button')
creates a collection of buttons.a
and a button.b
. -
.trigger('click');
iterates through each button in the collection and fires a click event. Button -
.a
receives a click event and fires the event handler you registered for it on page load. - The event handler for is
.b
registered in the event handler callback for.a
. Button -
.b
receives a click event from.trigger('click');
as it is second in the collection. - The event listener callback for the button
.b
raises a popup warning.
Since you only want to click a button .a
, click any of the following for your current document:
-
$('.a').trigger('click');
-
$('button.a').trigger('click');
(although this is redundant) -
$('button').get(0).trigger('click');
(since it.a
is the 0th indexed element of the button)
EDIT While this is unrelated to the question, you might have wanted to register the event for .b
just one time by doing the following:
$('.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 the propagation of events, you need to add another event listener, for example:
$(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>
source to share
Perhaps this is because the click is triggered in all instances of buttons in sequence ...
button a
the click is fired first ... in your callback you are binding the button b
click callback ...
... then ... the button b
click is triggered ... so the callback for b is executed ...
All this happens in one call: $('button').trigger('click');
Edit: Others have probably answered this before I have it ... but iteration triggers a click on the correct element:
$('.a').trigger('click');
source to share
Execution order:
- bind.a
- trigger start button (say a)
- callback for: bind b
- trigger start button (b)
- callback for b
Even $("button").trigger("click")
- it's one line, it's kind of a loop that works as if it were:
var buttonElms = $("button");
for (var index in buttonElms) {
buttonElms[index].trigger("click");
}
source to share