Bug Tracker

Opened 14 years ago

Closed 14 years ago

Last modified 13 years ago

#399 closed bug (worksforme)

Second handler firing after first returned false

Reported by: avaly2k@… 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.

Change History (6)

comment:1 Changed 14 years ago by john

Milestone: 1.1
Version: 1.01.1

comment:2 Changed 14 years ago by blair

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.

comment:3 Changed 14 years ago by andrea ercol

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"

comment:4 Changed 14 years ago by Dave

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.

comment:5 Changed 14 years ago by paul.bakaus@…

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.

comment:6 Changed 14 years ago by joern

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 );
Note: See TracTickets for help on using tickets.