Table of Contents

AJAX Pitfalls in Crossbrowser Compatibility

While AJAX should work in pretty much every modern Browser there are some little things that don't work. I encountered them while working on the Spell Checker for DokuWiki and want to list these problems and their solutions here.

I will not address how to create a XMLHttpRequest object in different Browsers. There are plenty of Toolkits available already - my favourite is Simple AJAX Code Kit (SACK).

Opera 8 and missing setRequestHeader

Opera 8.0 does not support the setRequestHeader method needed to specify the content type of the request. This will cause an exception in Opera if it encounters this method.

The solution is to check for the availability for the method and to omit it if not available1):

try {
  xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
} catch (e) {}
try {
  xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
} catch (Exception e) {System.out.println("hey");}

Unfortunately this causes PHP (and possibly other Languages) to ignore the posted data. So you have to extract the data yourself:

if(!count($_POST) && $HTTP_RAW_POST_DATA){
  parse_str($HTTP_RAW_POST_DATA, $_POST);
}

Instead of $HTTP_RAW_POST_DATA you can also use php://input in PHP 4.3+

Broken UTF-8 in Konqueror

Konqueror usually works okay with UTF-8 encoded pages. However in my experience it fails to handle it correctly in a XMLHttpRequest answer and ignores the charset header.

The workaround isn't that simple. You need to check if the Browser does UTF-8 correctly by using an AJAX request to send a UTF-8 char and compare the result. If the UTF-8 is broken you need to send this info to the backend and let it encode all UTF-8 chars as entities. On the receiving JavaScript end you can decode the entities back to UTF-8 again.

Detailed code is available in my Spellchecker implementation 2).

Step Client JavaScript Backend PHP
1 Send UTF-8 char
2 Send Back UTF-8 as received
3 sent != received ? utf8ok=false
4 send Workload and utf8ok
5 handle workload → $result
$utf8ok == false ? utf8_to_entities($result)
send $result
6 utf8ok == false ? decode($result)
repeat steps 4 to 6 as needed

This bug appears to be fixed in version 3.5 of Konqueror/KDE.fixed

Memory Leaks in Microsoft Internet Explorer

In MSIE, XmlHttpRequest is an ActiveX (COM) object, but function which is passed to onreadystatechange is a Javascript (or VBScript) function. These are different worlds. So req.onreadystatechange contains an indirect circle-link: (COM) req depends on (JS) function through onreadystatechange, and the (JS) function sees a (COM) req through a variable visibility scope.

All Microsoft Internet Explorers until IE7 March, 2007 are incapable to detect and remove such link, so all data (including request, reply, parsed reply, function) lost in memory until browser restart.

There is one possible well-known workaround: do not set onreadystatechange at all, checking readystate with timing events, for example, every 10 ms. Then there aren't any link from COM object to the javascript and so there is no leak.

1)
This fix is already included in SACK