Another confusion in IE
April 12, 2011 Leave a comment
It is well-known fact that there are a lot of staff that are implemented illogically in IE. I found another one, cost of which was three successive days of rewriting + debugging and a month of background warring + thinking for me…
I have implemented dynamic loading of .js content in my web application. It had problem in IE for a long time. Once it came time to fix it. I rewrite all the staff that was related to it. Originally it was in a single file. I rewrite it in three files with three different classes (App, Manager, Loader) to make it as simple and as clear as possible with a lot of comments. Loader class is responsible for file downloading and this was the most suspected place. After exploring during three successive days I found the problem. Originally the key method was written like this: (I use ExtJs):
/* Loads .js file from specified URL */ Loader.prototype.loadScript = function(src, callBack){ var script; !this.head && (this.head = document.getElementsByTagName("head")[0]); script = document.createElement('script'); script.type = 'text/javascript'; if(Ext.isIE){ //listener for IE script.setAttribute('onreadystatechange', function() { if (script.readyState == 'complete'){ callBack(); } }); }else{ //listener for other browsers than IE. script.onload = callBack; } script.setAttribute('src', src); this.head.appendChild(script); };
Problem was in bolded line. There are two cases:
- When the file is not in the cache then onreadystatechange is fired two times: firstly, script.readyState == ‘loading’ and secondly, script.readyState == ‘loaded’. script.readyState never equals to “complete”!!!.
- When the file is in the cache then onreadystatechange is fired only once and script.readyState == ‘complete’.
So, I rewrite if condition like this: (script.readyState == ‘complete’ || script.readyState == ‘loaded’). It is very easy solution but it was quite time-consuming to get to it for me.
The first thing is to discover that script.onload doesn’t work in IE and you have to use script.onreadystatechange instead and the socond thing is to debug and pray for discovering how onreadystatechange works 😀