IE binds to id attributes, or “How I learned to love var”

I recently converted the LibraryHippo “Family Status” page to use AJAX to fetch individual card statuses, instead of having the server aggregate all the statuses and send the complete summary back to the user. It was fairly straightforward, with one notable exception – Internet Explorer.

AJAX LibraryHippoWhen using Firefox or Chrome, as soon as the page loaded, the user would see a list of cards that LibraryHippo was checking, complete with throbbers. As results came in, the matching progress line would disappear and other tables would fill in, holding the results – books that have to go back, holds ready for pickup, etc. I don't mind admitting that I was a little proud of my first foray into AJAXy web programming.

The morning after I finished the update, a co-worker signed up. Unlike everyone else I knew, she used Internet Explorer. She hit the summary page and everything stalled. The progress list was populated, the throbbers were throbbing, and… that’s it. They just kept going. Oh, and a little indicator woke up in the status bar, saying that there was an error on the page: “Object doesn’t support this property or method”. The reported line numbers didn’t match my source file, but via judicious application of alerts()s, I was able to isolate the problem to a callback that’s executed on a successful card check to update a span that holds a row count:

function refresh_table_count(table_selector)
{  
    count = $(table_selector + ' tbody tr').length;
    $(table_selector + ' thead #count').html(count);
}

That seemed pretty innocuous, and not dissimilar from code that I had elsewhere in the <script> block. Quick web searches revealed nothing, so I resorted to cutting and renaming bits until I could see what was going on. I was down to an HTML body with a single table definition, and the function above. The error persisted. Suspicious, I renamed the count variable to c, and the problem disappeared.

At this point, I was convinced that IE’s Javascript interpreter reserved the count keyword for itself. I made this claim to a friend, who was skeptical. Eager to show him, I whipped up a quick example, and… it worked. There were no problems with the word count. I was stymied again, but not for long: my sample HTML file didn’t include an element with a "count" id. Once I added the count id, the sample broke.

It turns out that IE is actually creating a global object that matches the item’s ID! As Rick Strahl explains, the problem is a little worse than that, because the assignment on line 3 above should’ve overwritten the variable reference, but there’s “some whacky scoping going on”.

Workarounds:

  1. do away with the temporary variable (possible in this case)
  2. rename the temporary variable (always possible, but lame)
  3. use more specific id attribute values (probably a good idea in any case)
  4. use the var statement to declare all variables – this is safest and probably the easiest to remember:
function refresh_table_count(table_selector)
{
    var count = $(table_selector + ' tbody tr').length;
    $(table_selector + ' thead #count').html(count);
}

Now everything is working on the new page, and I've every confidence that var will help keep it so.