Corey Ogburn
Corey Ogburn

Reputation: 24717

Call checkbox's click event seems erroneous?

I'm using jQuery 1.6.1 and I have checkbox that I want to programmatically check while also calling it's click event. Normally I just make this call:

$('#my_checkbox').click();

When the webpage first loads, the checkbox is not checked. When I make the above call, it does set off the click event as expected, but inside the click event this.checked will still return false. When the click event is completed, the checkbox is then checked. It seems the click event (when programmatically triggered) is executed before the state change of the checkbox. If I actually click on the checkbox, this.checked properly reflects the new state of the checkbox, i.e. it changes the state before firing the event.

Why when I programmatically call the click event does the event fire before the state change and what can I do to get around it?

Upvotes: 2

Views: 347

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074465

It's an interesting problem (which I've replicated here). The temptation, of course, would be to use change handlers rather than click handlers (example), but the problem is that change doesn't fire at all on IE when you use click to toggle the state. Which might be a good reason not to do that.

I suppose you could define your own mechanism that doesn't rely on click performing the default action — a teeny little plug-in, or just a function you call and pass in a jQuery object. Here's a teeny plug-in version:

(function($) {
  $.fn.flip = function() {
    this.prop("checked", !this.prop("checked"));
    this.triggerHandler("click");
    this.triggerHandler("change");
  };
})(jQuery);

Usage:

$('my_checkbox').flip();

Live example | source

Note that that off-the-cuff version will, if applied to jQuery object containing multiple checkboxes, force them all to the same value. You could loop if you want them to be independent:

(function($) {
  $.fn.flip = function() {
    this.each(function() {
        this.checked = !this.checked;
    });
    this.triggerHandler("click");
    this.triggerHandler("change");
  };
})(jQuery);

Live example | source

By using triggerHandler rather than trigger, we avoid causing the default action.

The alternative would be for all of your click handlers for checkboxes to use a timeout:

$("my_checkbox").click(function() {
    var $this = $(this);
    setTimeout(function() {
        // Actually do something with $this
    }, 0);
});

...which just seems like a maintenance nightmare.

Upvotes: 3

Related Questions