Categories
HTML Technical The Sky Is Falling

Disappearing content in MSIE7 using AJAX

I write web applications for a living. I enjoy it immensely.

Webkit-based browsers (FireFox, Mozilla, Chrome, and Safari) are a pleasure to work with – they render closely to what you design with stylesheets, their JavaScript engines perform quickly and what you’d expect, and the final rendering of sites is generally pleasing.

Internet Explorer 6 (IE6) and Internet Explorer 7 (IE7), however, are slime mold.

Well, IE7 not so much, but IE6 has caused me hours and hours of work, from its peekaboo bug, to its non-standards support to … well, pretty much everything.

That said, in a new version of the marketing tracking tool product I work on (due out any fricking second now) a customer encountered a bug in MSIE7 which I had not seen.

The quick and dirty:

  • Render a page
  • Part of page updates using jquery $.get
  • Poof! That part of page disappears in IE7 upon update.

What? I wrote some simple tests for it and was shocked at the results.

Here’s some tips when working with MSIE7 and AJAX.

Return valid (X)HTML

Ok, ok, this was my error, really, but come on! It renders okay as part of the page but not in an AJAX call?

The above problem with the disappearing content was because I had an extra “div” at the end of the dynamic content. In short, doing:

$.get('data.php', function (data) { $('#content').html(data); });

upon our page, where data.php contains:

<div id="something">Boo!</div></div>

Makes MSIE7 replace it with … a blank space.

I thank the faithful engineers at Microsoft for keeping me honest and finding this bug.

Make sure you’re not caching

Of course, in the process of determining what the problem was, I had a few “Huh?” moments where I updated my test, and it still didn’t work as expected.

That is, MSIE7 likes to cache your content. While Firefox seems to actually make the request when you do the above $.get call, MSIE7 seems to just pull it straight from the cache unless it has a good reason not to. That said, there are a few ways to force non-caching of content in calls like this, as follows:

Method 1: Use, like 27, non-caching headers in your code

Ok, there aren’t 27 non-caching headers, but I’ve seen incarnations of this which have up to 4 or 5 headers destined to avoid the edge cases of each and every proxy server.

However, the following headers generally will help avoid caching by browsers:

Cache-Control: no-cache
Pragma: no-cache
Expires: -1

In PHP, you can just pass the above strings to the header function before you output any content in your script. MSIE7 will not cache the AJAX content as long as it hasn’t been cached already. That is, if you return the content once without the headers (say, while testing), then later with the headers, MSIE7 will cache it. To “uncache” it, just visit the URL in question to refresh the cache status in MSIE7.

Method 2: Using Math.random() to force each call

This, I like slightly better because it works even in aggressive caching situations (like once when I had Satellite internet). Just make each request unique. Instead of the above JavaScript, try the following:

$.get('data.php?_r=' + Math.random(), function (data) { $('#content').html(data); });

Where the _r parameter is ignored by the accessing script, but each request is made because the browser thinks each one is unique.