Return false has changed in jquery 1.4.3

 
 

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.

return false

$('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 .

e.preventDefault()

As the name suggets, calling e.preventDefault() will make sure that the default beahvior 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 not be taken to www.google.com.

e.stopPropagation

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 .

e.stopImmediatePropagation

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 even to other evevent handlers bound to itself.

If you are interested here is link to DOM Level 3 Events sepc.

Back to original problem

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 not called.

I tried to find which commit made this change but I could not go far because of this issue.

It gets complicated with live and a bug in jQuery 1.4.3

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.

I am using rails.js (jquery-ujs). What do I do?

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. Pleaes do provide your feedback.

 
Neeraj Singh's profile picture

Comments