October 25, 2010
jQuery 1.4.3 was recently
released. If you
upgrade to jQuery 1.4.3 you will notice that the behavior of return false
has
changed in this version. First let's see what return false
does.
$("a").click(function () {
console.log("clicked");
return false;
});
First ensure that above code is executed on domready. Now if I click on any link then two things will happen.
e.preventDefault() will be called .
e.stopPropagation() will be called .
As the name suggests, calling e.preventDefault()
will make sure that the
default behavior is not executed.
<a href='www.google.com'>click me</a>
If above link is clicked then the default behavior of the browser is to take you
to www.google.com
. However by invoking e.preventDefault()
browser will not
go ahead with default behavior and I will <strong>not</strong> be taken to
www.google.com
.
When a link is clicked then an event "click event" is created. And this event
bubbles all the way up to the top. By invoking e.stopPropagation
I am asking
browser to not to propagate the event. In other words the event will stop
bubbling.
<div class="first">
<div class="two">
<a href="www.google.com">click me</a>
</div>
</div>
If I click on "click me" then "click event" will start bubbling. Now let's say
that I catch this event at .two
and if I call e.stopPropagation()
then this
event will never reach to .first
.
First note that you can bind more than one event to an element. Take a look at following case.
<a class="one">one</a>
I am going to bind three events to the above element.
$("a").bind("click", function (e) {
console.log("first");
});
$("a").bind("click", function (e) {
console.log("second");
e.stopImmediatePropagation();
});
$("a").bind("click", function (e) {
console.log("third");
});
In this case there are three events bound to the same element. Notice that
second event binding invokes e.stopImmediatePropagation()
. Calling
e.stopImmediatePropagation
does two things.
Just like stopPropagation
it will stop the bubbling of the event. So any
parent of this element will not get this event.
However stopImmdiatePropagation
stops the event bubbling even to the siblings.
It kills the event right then and there. That's it. End of the event.
Once again calling stopPropagation
means stop this event going to parent. And
calling stopImmediatePropagation
means stop passing this event to other event
handlers bound to itself.
If you are interested here is link to DOM Level 3 Events spec.
Now that I have described what preventDefault
, stopPropagation
and
stopImmediatePropagation
does lets see what changed in jQuery 1.4.3.
In jQuery 1.4.2 when I execute "return false" then that action was same as executing:
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
Now e.stopImmediatePropagation
internally calls e.stopPragation
but I have
added here for visual clarity.
Fact that return false
was calling e.stopImmeidatePropagation
was a bug. Get
that. It was a bug which got fixed in jquery 1.4.3.
So in jquery 1.4.3 e.stopImmediatePropagation
is not called. Checkout this
piece of code from events.js
of jquery code base.
if (ret !== undefined) {
event.result = ret;
if (ret === false) {
event.preventDefault();
event.stopPropagation();
}
}
As you can see when return false
is invoked then e.stopImmediatePropagation
is <strong>not</strong> called.
To make the case complicated, jQuery 1.4.3 has a bug in which
e.preventStopImmediatePropagation
doest not work. Here is
a link to this bug
I reported.
To understand the bug take a look at following code:
<a href='' class='first'>click me</a>
$('a.first').live('click', function(e){
alert('hello');
e.preventDefault();
e.stopImmediatePropagation();
});
$('a.first').live('click', function(){
alert('world');
});
Since I am invoking e.stopImmediatePropagation
I should never see
alert world
. However you will see that alert if you are using jQuery 1.4.3.
You can play with it here .
This bug has been fixed as per this commit . Note that the commit mentioned was done after the release of jQuery 1.4.3. To get the fix you will have to wait for jQuery 1.4.4 release or use jQuery edge.
As I have shown "return false" does not work in jQuery 1.4.3 . However I would
have to like have as much backward compatibility in jquery-ujs
as much
possible so that the same code base works with jQuery 1.4 through 1.4.3 since
not every one upgrades immediately.
This commit
should make jquery-ujs
jquery 1.4.3 compatible.
Many issues have been logged at
jquery-ujs and I will take a look at all of them one by one. Please do provide
your feedback.
If this blog was helpful, check out our full blog archive.