jQuery, .change() notification, and IE

Volume 12, Issue 7; 24 Mar 2009; last modified 08 Oct 2010

I'd like to know when this radio button changes, ok? What's that, you're not going to tell me when it changes exactly, you're going to tell me the next time an event occurs? Gee, thanks.

Here's the thing. I've got some JavaScript code that's part of an application. When the user changes a radio button, I want to be notified so that I can change other parts of the page. Easy, right?

$(document).ready(function(){
    $("input[name='custom-format']:radio").change(function() {
	alert("Option changed!");
    });
});

(I'm building on top of jQuery 1.3.1; here's a full test case: ietest.zip.)

That works fine in Firefox and Safari and I bet it would work fine in Opera too. Heck, it would probably work fine in Links if JavaScript was supported.

On IE(7)? Not so much.

Changing the radio button causes nothing to happen. Except that if you click anywhere on the page after you've changed the radio button, then you get the popup.

Someone please tell me I'm doing something stupid. Or tell me how to fix the stupid thing IE is doing. Or something.

Comments

http://webbugtrack.blogspot.com/2007/11/bug-193-onchange-does-not-fire-properly.html

"The onchange event can be attached (inline or as an event handler) to any form element. It fires whenever the value of the form field changes. Unfortunately, the behavior is a bit strange in IE, in that for a checkbox, or a radio button field, the event doesn't fire when it is supposed to (right when you click the option you want to choose), but instead it only fires, when you click elsewhere on the page/form, or if you explicitly call blur(); on the field."

—Posted by Bryan on 24 Mar 2009 @ 10:25 UTC #

I don't know the historical reasons but in IE5->IE8 you're best bet with <input> & @type=radio or @type=checkbox is to use the click event. I believe it is also possible to use change, if you fire the blur event yourself.

If anyone knows the historical reasons for this, I'd love to know... I'm on vacation or I do the list archaeology myself.

—Posted by Shawn Medero on 25 Mar 2009 @ 06:21 UTC #

just use the click event - same thing

—Posted by Rob Koberg on 25 Mar 2009 @ 10:43 UTC #

Click is not the same thing. Click fires even if you click on the same radio button. So either I have to accept that that is uncommon enough not to care or I have to track the current state of all the buttons separately.

Not that it looks like I have much choice.

[expletives deleted --ed]

—Posted by Norman Walsh on 25 Mar 2009 @ 11:59 UTC #

Can you do onclick=this.blur()? (syntax uncertain) This could lead to the right onchange events, if I understand the other comments right.

—Posted by Jacek on 25 Mar 2009 @ 02:46 UTC #

"Click is not the same thing. Click fires even if you click on the same radio button."

Which is what you want. A click should change/toggle a radio button or checkbox.

—Posted by Rob Koberg on 27 Mar 2009 @ 10:47 UTC #

No, it isn't what I want. Luckily, it turns out in this application that it's close enough.

Consider three mutually exclusive options A, B, and C represented by a group of radio buttons. Initially A is selected.

I click on B: the radio button changes and both the onClick and onChange events fire.

I click on B again: the radio button doesn't change and the onClick event fires, but the onChange event does not.

Since it's only the change of a radio button that I care about, I'd prefer to hang my code off the onChange event.

Except that in yet another bit of IE buggyness, the onChange event doesn't fire until the focus leaves the button group.

%$#@?!

—Posted by Norman Walsh on 27 Mar 2009 @ 11:38 UTC #

Just came across this myself in IE8. You'd have thought Microsoft would have fixed this bug by now......

—Posted by Mark Sheppard on 18 Jun 2009 @ 04:39 UTC #

To all those saying "use click, it's the same":

a) It's obviously not the same; it wouldn't exist if it were

b) Using click breaks all UI methods that are NOT moving a mouse pointer over the element and clicking the button. Most significantly, this breaks keyboard accessibility. 'change' has the wonderful property that, in half-decent browsers, it does exactly what it says: fires if the value changes, however that change might occur (e.g. I hope - although haven't tested - that it would also fire if the value was programatically changed)

I thought jQuery was supposed to solve all these horrible cross-browser problems! Do you know if anyone's working on fixing this? It seems as if whatever fix can be applied by all of us (however insufficient that fix might be), can also be applied in the jQuery library, saving us the bother.

Cheers,

- Bobby

—Posted by Five Minute Argument on 09 Jul 2009 @ 11:23 UTC #

Click could be an alternative in some cases but here's a case where click does not apply. I am trying to use Ben Nadel's example of listening for changes in the browser location object -- see Binding Events To Non-DOM Objects With jQuery, and using this to adjust html element classes.

This works nicely in Firefox, Safari, and Chrome, but in IE it only works in the "forward" direction, when changes to the window location (specifically, the hash value) are the result of clicks. When I use the browser's back button, the hash values change, but IE does not execute the function that I have bound to that change.

Now I have to waste another day figuring out a workaround. I hate IE.

—Posted by Chris Loosley on 18 Jul 2009 @ 10:59 UTC #
If you click on a radio button, IE seems to wait with firing the change event until you leave the button, which is consistent with the behavior on other input fields (like text), but kinda unintuitive. The following piece of code fixes this behavior for me:
$(function () {
    if ($.browser.msie) {
        $('input:radio').click(function () {
            this.blur();
            this.focus();
        });
    }
});
—Posted by Alexander M. Turek on 16 Sep 2009 @ 09:06 UTC #

Alexander, you saved me hours of endless tweaking with IE! That click handler works just fine.

Thanks.

—Posted by marco on 24 Sep 2009 @ 08:30 UTC #

@Alexander M. Turek Thank you so much for this, as marco has mentioned above, this works perfectly and has saved me *hours* of trouble!

I'm surprised that jQuery doesn't have this feature built into the core, this is certainly one of those cross browser issues that should be addressed by the library.

—Posted by Hectic Jeff on 06 Nov 2009 @ 04:28 UTC #

Another pat on the back for Alexander M. Turek, that kludge did the trick for me.

And a kick in the teeth to the IE team at Microsoft for making us suffer so much.

I also noticed that IE8 (and probably seven) doesn't seem to understand label tags whose content is an image so I'm off to write a click handler for my image labels...

—Posted by Eric Howe on 09 Nov 2009 @ 02:07 UTC #

Thanks Alexander! This saved my tail on a huge project :D

—Posted by Dennis Monsewicz on 01 Dec 2009 @ 10:58 UTC #

Alexander, perfect fix! This seems to be working perfectly in all the IE browsers. Very clever.

—Posted by Vince on 02 Dec 2009 @ 06:02 UTC #

Wish I would have found this a few hours ago ;-) Better late than never I guess. Now I can move on to more important things. Alexander's code is perfect!

—Posted by Jermaine Maree on 14 Dec 2009 @ 09:19 UTC #

WOW!!! Well done!!!

—Posted by Izik on 16 Feb 2010 @ 01:25 UTC #

Thanks!

Works also well for checkboxes...

Unfortunately, in my case the next checkbox happened to be hidden, so I got an error:

Can't move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus.

Agrgrh!

IE Sucks. Why do we continue trying to waist so much time, money and effort getting things sort of working in this piece of crap. This only causes the world to keep using IE. So that we have to go on supporting IE, so that the world keeps using it, so that ...

Martijn

—Posted by Martijn Bak on 26 Feb 2010 @ 02:15 UTC #

Thanks, saved my day.

—Posted by Milhouse on 04 Mar 2010 @ 09:16 UTC #

wow, saved me some time there, could not figure out why IE8 would not focus on a post-page load created DOM element (while safari and FF do just fine).

We have a have a multiple choice survey [single page for admins] with @70 multi-checkbox response questions.

Workaround in my case was to focus on the first unchecked checkbox in target group, and then blur() on that element. At this point IE now responds to further event. We then focus on the post-page load created DOM element (positioned above the question text) and remove() it.

No more need to pop an alert in IE in order to get the focus() working.

I concur with everyone here re: the utter piece of trash-edness that is IE...

—Posted by ThanksAlex on 20 Apr 2010 @ 05:58 UTC #

http://msdn.microsoft.com/en-us/library/ms536912%28VS.85%29.aspx

They seem to think it's not a bug but a feature.

—Posted by Erik on 27 Apr 2010 @ 08:05 UTC #

I almost thought Alexander's jQuery solution didn't work...but it's because I was still using the "onclick" event for the radio button. Make sure to use "onchange" in the radio button.

BTW, I understand that Microsoft was trying to be consistent with the other elements. However, this goes to show why I disagree with UI experts who have concrete rules like "strict consistency" and "shortest mouse distance". My #1 rule is that rules should be broken if they don't feel right...and in this case, I can't think of a single use-case for Microsoft's implementation. In every use case I've run into, Microsoft's implementation was just wrong.

That being said, I think Microsoft actually chose a better Box Model. The standard box model makes it impossible to use percentage widths totaling 100% while using fixed pixel paddings (your total width will be 100% plus all of the paddings). Of course CSS3 solves this in two ways: letting us choose the box model, or using expressions. I guess IE is like a broken clock...it's still right twice a day.

—Posted by Hank on 01 Jun 2010 @ 09:04 UTC #

Thank goodness for the memory of the Internet!
This issue bit me with jQuery 1.5.1 and IE8.

If you ever see this...THANK YOU, Alex! You saved me boatloads of time.

—Posted by Glenn on 11 Oct 2012 @ 02:29 UTC #