Skip to main content

Bug Tracker

Side navigation

#399 closed bug (worksforme)

Opened November 16, 2006 03:28PM UTC

Closed December 02, 2006 01:14PM UTC

Last modified June 19, 2007 07:00AM UTC

Second handler firing after first returned false

Reported by: avaly2k@hotmail.com Owned by:
Priority: major Milestone: 1.1a
Component: core Version: 1.1a
Keywords: event stop Cc:
Blocked by: Blocking:
Description

When registering two functions to an event on the same element and the first executed function returns false, jQuery stops the propagation of the event, but it should also stop executing the second registered function on that event.

Example:

$('a.test').click(function(){
	return false;
});
$('a.test').click(function(){
	alert("This shouldn't show!");
});

This can be achieved easily by placing a "break" statement in the jQuery.event.handle function.

Attachments (0)
Change History (6)

Changed November 17, 2006 08:02PM UTC by john comment:1

milestone: → 1.1
version: 1.01.1

Changed November 29, 2006 10:52PM UTC by blair comment:2

I disagree. Two points:

  • In more complex code there is no way to know or control the order of the events attached to an element
  • This is usually an undesirable behaviour anyway - e.g. when plugins are adding events that you aren't aware of

Situations where this behaviour is needed are the exceptions not the rule.

Changed November 30, 2006 02:05AM UTC by andrea ercol comment:3

could be an option, maybe called break

even if I do not totally control the page, I have practically exclusive control on my elements, the ones that I'm adding/handling, so if I need to register more than one handler on the same event on the same elements and the first decides that the chain is to be broken, then if there is no option I have to find a workarond, but I can see that soon it gets dirty and complicated; on the contary a break option lets me get the most out of the event handling engine of jQuery

in a shared environment, I mean if there could be handlers registered by others on that same event on those same elements, the option could make use of an id, rather than a boolean, defined when binding and referenced when triggering, like this

$( ".aClass" ).bind( "click", fn1, {break: "myID1"} );

code I don't control...

$( ".aClass" ).bind( "click", fn2, {break: "myID2"} );

$( ".aClass" ).bind( "click", fn3 );

code I do control...

$( ".aClass" ).bind( "click", fn4, {break: "myID1"} );

$( ".aClass" ).trigger( "click", {break: "myID1"} );

which would mean that if fn1 returns false, then fn4 is not to be called, but fn2 and fn3 would not be influenced by the result of fn1

the default for bind should be undefined and for trigger {break: false}, which means "any false event won't break propagation"

and could exist the opposite for trigger {break: true}, which means "the first false event will break propagation"

Changed November 30, 2006 04:00AM UTC by Dave comment:4

avaly2k, what was the scenario in your code where delivering the second click broke something? Maybe the goal can be accomplished in some other way.

Right now, the jQuery handler calls all the handlers and remembers whether any returned false. If one or more did, the jQuery handler returns false. If you had two submit or change handlers, for example, that seems like the right behavior. Perhaps all it needs is to be documented to work that way?

A page with plugins and page-specific jQuery code could have multiple handlers of the same type attached to an element. Handlers can be attached while the page is in use; attempting to control the initialization order in a .ready() handler is futile. No handler can reliably be the first called, return false, and shut out the others.

Changed November 30, 2006 07:57AM UTC by paul.bakaus@ comment:5

If you add your events via addEventListener, I'm quite sure that it behaves like actual jQuery, so it continues with the second event.

I think it's very important to strictly seperate these events in functionality, so one event cannot stop another.

Changed December 02, 2006 01:14PM UTC by joern comment:6

resolution: → worksforme
status: newclosed

I agree with Paul: The behaviour of calling events should stick to the one of addEventListener.

It should be possible to workaround this feature by using an external context:

var allowOthers = true;
$('a.test').click(function(){
  allowOthers = false;
});
$('a.test').click(function(){
  if(allowOthers)
    alert("This shouldn't show!");
});

With jQuery 1.1 it's possible to avoid that external context, eg.:

var data = { allowOthers: true };
$('a.test').click(function(event, data){
  data.allowOthers = false;
}, data );
$('a.test').click(function(event, data){
  if(data.allowOthers)
    alert("This shouldn't show!");
}, data );