11

Update: This only applies to jQuery 1.8 and below. This was fixed in jQuery 1.9.

Here is my minimal jsfiddle example: http://jsfiddle.net/8fuEJ/. I'm using Google Chrome, if that makes a difference.

I have a checkbox:

<input type="checkbox" id="wtf">

And I have a jquery event handler:

$('#wtf').click(function(ev) { alert(this.checked); });

So far, so good. When I click the checkbox, I first see the checkmark appear, then the alert "true" (in that order). When I click it again, I see the checkmark disappear, then the alert "false".

The problem comes when I programmatically trigger the click event. Like this:

$('#wtf').click(function(ev) { alert(this.checked); });
$('#wtf').click();

In this case, first I see the alert "false" (with the checkmark still not visible), then after dismissing the alert, the checkmark appears.

Why the difference in order here?

Also note that if I use the event handler change, it works as expected.

$('#wtf').change(function(ev) { alert(this.checked); });
$('#wtf').click();

Here, I see the checkmark appear, then the alert "true".

Ben Lee
  • 52,489
  • 13
  • 125
  • 145

2 Answers2

12

There are three types of actions going on here:

  1. Manually clicking it changes the state. That is all it does by itself; the trigger then fires because it is realizing that it has been clicked. This is a matter of browser behavior before scripting behavior.
  2. Calling the Click() event calls the javascript event first. jQuery prioritizes the function you provided, as it may very well cancel that click or perform some other action. After that is completed, javascript changes the status of the checkbox.
  3. Lastly the Change() event is mimicking the manual clicking by telling the browser to click it. That means that the item is being changed by the browser, which then in turn is calling your triggered event.

Essentially the difference is that the Click() is a straight javascript call. It can do things the others cannot, such as cancel the change and do all sorts of other zany stuff, so it is delaying the change of state for as long as it can.

PCasagrande
  • 5,302
  • 3
  • 27
  • 36
4

The click event fires before the default action. It does this to allow you to prevent the default action from occurring by returning false from the handler.

In your example, this means that you alert the old value as the default action of changing the checkbox state has not yet occurred.

a'r
  • 35,921
  • 7
  • 66
  • 67
  • …by returning false from the handler *or calling .preventDefault() on the event object* – Gareth Oct 06 '11 at 17:27
  • I know about default actions and `preventDefault`, but this doesn't answer my question. I asked about the difference in order. Why does clicking on it manually check it first, then run my event handler, whereas calling `click` on it programatically first call my event handler, then check it? – Ben Lee Oct 06 '11 at 17:32
  • To see what I mean, if I throw in an `ev.preventDefault()` into the event handler, it still alerts "true" when I check it. In that case, I would see the checkmark appear, then the alert "true", then the checkmark disappears. See: http://jsfiddle.net/csPzu/ – Ben Lee Oct 06 '11 at 17:34
  • In other words, where you say "In your example, this means that you alert the old value as the default action of changing the checkbox state has not yet occurred.", that's only true for the programmatic case. For the manual case, I am alerting the *new* value. Why? – Ben Lee Oct 06 '11 at 17:37