====== AJAX Pitfalls in Crossbrowser Compatibility ======
While [[wp>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 [[wiki:Spell Checker]] for [[wiki: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 [[http://twilightuniverse.com/2005/05/sack-of-ajax/|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 available((This fix is already included in [[http://twilightuniverse.com/2005/05/sack-of-ajax/|SACK]])):
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 ((See [[http://dev.splitbrain.org/reference/dokuwiki/lib/scripts/spellcheck.js.source.html|spellcheck.js]] and [[ http://dev.splitbrain.org/reference/dokuwiki/lib/exe/spellcheck.php.source.html|spellcheck.php]] )).
^ 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.