Browse Source

util.js: fix dynamic script load on IE 9 (again).

Use a mechanism described here to serialize the execution of scripts
under IE: http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
Basically, we set the src attribute but do not append the script to
the body/head until after readyState is "loaded". Unfortunately, Opera
uses readyState but in a different way (always "loaded" for both load
and execution).

This is related to (and hopefully fixes) these issues:
https://github.com/kanaka/noVNC/issues/194,
https://github.com/kanaka/noVNC/issues/205,
https://github.com/kanaka/noVNC/issues/208.
Joel Martin 12 years ago
parent
commit
73ee4fa7cc
1 changed files with 33 additions and 29 deletions
  1. 33 29
      include/util.js

+ 33 - 29
include/util.js

@@ -217,38 +217,30 @@ Util.conf_defaults = function(cfg, api, defaults, arr) {
 Util.get_include_uri = function() {
 Util.get_include_uri = function() {
     return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/";
     return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/";
 }
 }
+Util._loading_scripts = [];
 Util._pending_scripts = [];
 Util._pending_scripts = [];
-Util.load_script = function(file, onload) {
-    var head = document.getElementsByTagName('head')[0];
-    var script = document.createElement('script');
-    script.type = 'text/javascript';
-    script.src = Util.get_include_uri() + file;
-    // In order script execution for webkit and firefox    
-    // https://developer.mozilla.org/en-US/docs/HTML/Element/script
-    script.async = false;
-    if (Util.Engine.trident) {
-        // In order script execution for IE 9
-        // http://ui.cognifide.com/slides/async-js/template/#26
-        script.defer = true;
-    }
-    //console.log("loading script: " + Util.get_include_uri() +  files[f]);
-    head.appendChild(script);
-    if (typeof onload !== "undefined") {
-        script.onload = script.onreadystatechange = onload;
-    }
-    return script;
-};
 Util.load_scripts = function(files) {
 Util.load_scripts = function(files) {
-    var head = document.getElementsByTagName('head')[0],
-        ps = Util._pending_scripts;
+    var head = document.getElementsByTagName('head')[0], script,
+        ls = Util._loading_scripts, ps = Util._pending_scripts;
     for (var f=0; f<files.length; f++) {
     for (var f=0; f<files.length; f++) {
-        var script = Util.load_script(files[f], function (e) {
-            if (!this.readyState || 
-                this.readyState == 'complete' ||
-                this.readyState == 'loaded') {
-                this.onload = this.onreadystatechange = null;
+        script = document.createElement('script');
+        script.type = 'text/javascript';
+        script.src = Util.get_include_uri() + files[f];
+        //console.log("loading script: " + script.src);
+        script.onload = script.onreadystatechange = function (e) {
+            while (ls.length > 0 && (ls[0].readyState === 'loaded' ||
+                                     ls[0].readyState === 'complete')) {
+                // For IE, append the script to trigger execution
+                var s = ls.shift();
+                //console.log("loaded script: " + s.src);
+                head.appendChild(s);
+            }
+            if (!this.readyState ||
+                (Util.Engine.presto && this.readyState === 'loaded') ||
+                this.readyState === 'complete') {
                 if (ps.indexOf(this) >= 0) {
                 if (ps.indexOf(this) >= 0) {
-                    //console.log("loaded script: " + this.src);
+                    this.onload = this.onreadystatechange = null;
+                    //console.log("completed script: " + this.src);
                     ps.splice(ps.indexOf(this), 1);
                     ps.splice(ps.indexOf(this), 1);
                 }
                 }
                 // Call window.onscriptsload after last script loads
                 // Call window.onscriptsload after last script loads
@@ -256,7 +248,19 @@ Util.load_scripts = function(files) {
                     window.onscriptsload();
                     window.onscriptsload();
                 }
                 }
             }
             }
-        });
+        };
+        // In-order script execution tricks
+        if (Util.Engine.trident) {
+            // For IE wait until readyState is 'loaded' before
+            // appending it which will trigger execution
+            // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
+            ls.push(script);
+        } else {
+            // For webkit and firefox set async=false and append now
+            // https://developer.mozilla.org/en-US/docs/HTML/Element/script
+            script.async = false;
+            head.appendChild(script);
+        }
         ps.push(script);
         ps.push(script);
     }
     }
 }
 }