I recently developed a sign-up form for a client that includes on-page price total calculation using JavaScript (jQuery). The premise is simple: the user provides information and specify options, then clicks a radio button to choose a specific price plan. The initial total price calculation is triggered by the change() event for the radio button elements. But, the client was concerned (and with user testing, it turned out rightly so) because in IE, the price calculation didn’t happen until the user clicked somewhere else on the page. In cases where they first clicked one option, then a different one, the price would seemingly lag behind because of IE’s delayed change event firing. It was confusing to the user, but worse—confusing for me to “fix” IE’s implementation.
The awesome news is that this has been fixed in jQuery 1.4, but the concern is still valid for older versions (which my application was using) and straight-JavaScript implementations.
The problem
In Internet Explorer, the change event fires when focus leaves the form element (an event know as blur). That means that the event happens only once a user has clicked on—or used the keyboard to navigate to—another element on the page (form or other). In cases like mine, where a user is expecting instant feedback to their click, this causes issues with user experience. Unfortunately, this isn’t exactly a “bug,” as it’s how IE handles this event in 6, 7 and 8.
In other browsers—Firefox, Webkit-based (Safari/Chrome) and Opera—the event fires off immediately, so in order to have consistent, intelligent operation, we have to hack IE’s basic behavior. The easiest solution is to bind your function to a different event, such as the click event, but that’s generally not the right solution. There is a better one.
Why using the click event is wrong
One word: accessibility. Users—whether they have a disability that restricts their use of the mouse or like to tab about the page with the keyboard for speed—don’t always use the mouse to move from form element to form element. So, if you bind your functionality to the click event, you may end up messing with a user’s workflow, which makes for unhappy visitors. In some cases, it may even make a user unable to use your application. So don’t use that as your solution.
The real solution
If IE needs a blur event to know that the change event should fire, give it one when the element is clicked. In jQuery, that looks something like:
$("#element").click(function(){
// In IE, we need to do blur then focus to trigger a change event
if ($.browser.msie) {
this.blur();
this.focus();
}
}).change(function(){ actionIWantOnChange(); });
This code tricks IE into thinking that focus has been changed away from the element when it is clicked. But since the change
event is also triggered, the actions attached to that event also happen. Keyboard navigability still works, because even though there is no click, the change
event will fire when they use the keyboard to move to another field meaning the feedback is instantaneous.
Now, you can probably improve my above example by using better feature-sniffing to test for IE instead of the browser
object in jQuery, but my time for creating a fix was limited—and this code gets the job done.