jQuery's Event Triggering, Order Of Default Behavior, And triggerHandler()
Posted March 12, 2009 at 10:20 AM
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 | Permalink | Other Searches | Print Page
Newer Post
Converting A Single CSS Element Selector To XPath Using ColdFusion
Older Post
Ask Ben: Using jQuery's triggerHandler() To Skip Default Behaviors
Reader 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?
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.
@Mohammed,
Glad to help out :)
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();
});
});
sorry,it seems not work correctly when actually click the checkbox.
Exactly the information I was looking for.
Toggling the checked state, then using triggerHandler() worked perfectly.
Thanks for this.
@llade,
No worries my man. It's a weird situation.
@Jeff,
Glad to help out.




