jQuery's Event Triggering, Order Of Default Behavior, And triggerHandler()

Posted March 12, 2009 at 10:20 AM

Tags: Javascript / DHTML

I ran into a strange, rather undesirable behavior this morning when dealing with jQuery's manual event triggering. It seems that when you trigger the click event on a checkbox, the default behavior (toggling the checked attribute) takes place after event handlers fire. This is opposite of what happens when the browser naturally handles the checkbox click event - the checked attribute is toggled and then the event handlers are executed.

This difference in the order of operations between inherent clicking and jQuery's event triggering can cause a big problem if the event handler depends on the status of checkbox in anyway (which, if you have a click handler on a checkbox to begin with means it probably does).

To see this in action, take a look at this simple code:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>jQuery Trigger and Default Behavior Demo</title>
  •  
  • <script type="text/javascript" src="jquery-1.3.2.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM is ready, initialize.
  • $(
  • function(){
  •  
  • $( "input" ).click(
  • function( objEvent ){
  •  
  • // Alert the checkboxed status.
  • alert( this.checked );
  •  
  • }
  • );
  •  
  •  
  • $( "button" ).click(
  • function( objEvent ){
  •  
  • // Trigger click on the checkbox.
  • $( "input" ).click();
  •  
  • }
  • );
  •  
  • }
  • );
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery Trigger and Default Behavior Demo
  • </h1>
  •  
  • <form>
  • <input type="checkbox" />
  • <button>click checkbox</button>
  • </form>
  •  
  • </body>
  • </html>

If I refresh this above code and click on the checkbox directly, it alerts:

true

... because the checkbox's checked attribute is toggled before the click handler executes. If, however, I refresh the page (hard refresh to reset form) and click on the button to manually trigger the click handler on the checkbox, it alerts:

false

This is because the manually triggered event handlers fire before the default behavior takes place.

To get around this, I had to manually change the checkbox and then trigger ONLY the event handlers:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>jQuery Trigger and Default Behavior Demo</title>
  •  
  • <script type="text/javascript" src="jquery-1.3.2.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM is ready, initialize.
  • $(
  • function(){
  •  
  • $( "input" ).click(
  • function( objEvent ){
  •  
  • // Alert the checkboxed status.
  • alert( this.checked );
  •  
  • }
  • );
  •  
  •  
  • $( "button" ).click(
  • function( objEvent ){
  •  
  • // Toggle checkbox checked status.
  • $( "input" )[ 0 ].checked = !$( "input" )[ 0 ].checked;
  •  
  • // Trigger ONLY click event hanlders on the checkbox.
  • $( "input" ).triggerHandler( "click" );
  •  
  • }
  • );
  •  
  • }
  • );
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery Trigger and Default Behavior Demo
  • </h1>
  •  
  • <form>
  • <input type="checkbox" />
  • <button>click checkbox</button>
  • </form>
  •  
  • </body>
  • </html>

jQuery's triggerHandler() method allows us to trigger the jQuery-bound event handlers without triggering the default behavior of the browser (toggle checked status). In doing so, the click handler on the checkbox itself can now function uniformly no matter how it is triggered.

I love jQuery event binding and triggering; I think this is the only place where this anomaly will actually matter as this is the only event type that I can think of that has to change the DOM before it executes its handlers.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page





Reader Comments

Mar 18, 2009 at 10:18 AM // reply »
1 Comments

Hi,

Thanks I think that's exactly what I need. I guess nobody is aware of a jQuery plugin solution to this problem so far?


Mar 21, 2009 at 5:58 AM // reply »
1 Comments

Hi,

Thanks for sharing this precious information, I was banging my head against the wall to solve this nagging problem. I think that's exactly what I needed.

Thanks once again!

Mohammed.


Mar 21, 2009 at 2:00 PM // reply »
7,488 Comments

@Mohammed,

Glad to help out :)


Mar 28, 2009 at 6:51 AM // reply »
2 Comments

another way:

$(document).ready(function(e){
$("body").append("<input type='checkbox'/>");

$(":checkbox").click(function(e){
this.checked=!this.checked;
}).click(function(e){
alert(this.checked);
}).click(function(e){
this.checked=!this.checked;
});

$("body").append("<input type='button' value='toggle'/>");
$(":button").click(function(e){
$(":checkbox").click();
});
});


Mar 28, 2009 at 6:56 AM // reply »
2 Comments

sorry,it seems not work correctly when actually click the checkbox.


Aug 28, 2009 at 10:29 AM // reply »
1 Comments

Exactly the information I was looking for.

Toggling the checked state, then using triggerHandler() worked perfectly.

Thanks for this.


Sep 2, 2009 at 9:38 AM // reply »
7,488 Comments

@llade,

No worries my man. It's a weird situation.

@Jeff,

Glad to help out.


Nov 24, 2009 at 11:50 AM // reply »
1 Comments

Thanks Ben, exactly the explanation I was looking for -- and not the first time you've helped me out here.


Nov 24, 2009 at 1:21 PM // reply »
7,488 Comments

@John,

Sweeeet. Always glad to help out.


Jan 12, 2010 at 6:03 AM // reply »
1 Comments

Thank you for clarification of this weird behavior.

However, since my case is using radio button and can't use yours approach (having to uncheck all other radio, not just toggle "checked" status)

=======================================

For folks who came across same problem. try this

$("yours_selector").each(function(){this.click()});

or

$("yours_selector")[0].click();

---------------------------------------------------------------------

it's click function as in "mouseclick in browser" and will behave as you would expected

=======================================


Jan 13, 2010 at 8:18 PM // reply »
7,488 Comments

@WallSky,

If you want to check the radio button, you can also just check it explicitly if you want:

$("yours_selector").attr( "checked", "true" );

... that should work for all of them. Of course, you lose the ability to perform additional logic in thee iteration.

You can also reach back into the raw DOM element:

$("yours_selector").each(function(){
this.checked = true;
});

Just presenting options (not saying any of them is any better). All depends on what you want to do.


Feb 4, 2010 at 3:19 PM // reply »
1 Comments

thanks for the tip! I run into the same problem.


Mar 3, 2010 at 6:43 PM // reply »
1 Comments

Has anyone else tried this under firefox? firefox resets the checkbox to false after the message box, IE works fine.

Great Article!


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 13, 2010 at 9:14 PM
The Magic Of Thinking Big By David Schwartz (Thanks Clark Valberg!)
Ben, COuld you plz tell me how to find the audio book version of The Magic of Thinking Big by David J. Schwartz, Ph.D Thanks ... read »
sun
Mar 13, 2010 at 6:21 PM
Sending (SMS) Picture Messages With ColdFusion And CFMail
MY BAD! @tmomail.net IS correct ... but, ONLY from pic taken W/ a cell -- NOT as attachment in an email ... (took ~4 min. for it to arrive ... then would NOT DL to my cell) ... read »
sun
Mar 13, 2010 at 6:16 PM
Sending (SMS) Picture Messages With ColdFusion And CFMail
@tmomail.net is NOT correct! IS t-mobile addy ... but, ONLY for a txt msg! ... read »
Mar 12, 2010 at 8:24 PM
Creating UI Elements With Low-Coupling And Conditional Event Handling
@Ben, Yes, that's exactly what's happening. That's the approach YUI has taken with custom events, you subscribe the handler to the Event object itself. I really like the event system in YUI, it's ... read »
Mar 12, 2010 at 7:34 PM
FLV 404 Error On Windows 2003 Server
I spent a good couple of hours on this today. What a pain. On my old server, everything was fine. I migrated the site to a new server, and suddenly, all the files with audio didn't work. Just got ... read »
Mar 12, 2010 at 7:26 PM
Creating UI Elements With Low-Coupling And Conditional Event Handling
@Ryan, I finally got around to reading that YUI blog post you linked (it took me a fews months, but I did it). I wanted to ask you something (rather than on his only cause it is so old), but from w ... read »
Mar 12, 2010 at 2:00 PM
Tim Cracked The GMail - CFMailPart Puzzle!
@Mik Muller, Exactly what I was encountering... complaints of empty emails. I'm really surprised no one else has reported this anywhere. I realize text emails may seem old school but there are a lot ... read »
Mar 12, 2010 at 1:50 PM
Using jQuery's SlideUp() and SlideDown() Methods With Bottom-Positioned Elements
That's exactly the situation that came to my mind the other day. Saved my life there! xoxo ... read »