views:

1226

answers:

4

I am writing small JavaScript code which will load external js files at html page loading.

I tested 2 ways.

Case 1: Used document.write to add <script> tag. It worked for all browsers (IE, FF, Safari, Chrome, Opera).

Case 2: Used DOMElement.appendChild to add <script> tag to the <haed> element.

Only worked for IE, FF, and Opera. Did NOT work for Safari and Chrome.

In both cases, I expected new <script> tag is being inserted before <head> closing tag. So the new <script> tag is evaluated before processing <body>, and by the time window.onload is called, "success" variable should be true.

But it wasn't for Safari and Chrome.

Can anyone tell if this should or shouldn't work? Thank you.

<html>
  <head>
    <title>JavaScript loading test</title>
    <script type="text/javascript">
      var success = false;

      window.onload = function()
      {
        document.getElementById("result").innerHTML = success? "OK": "ERROR!";
      }

      // TEST CASE 1.
      // Works for all browsers.
      document.write('<script type="text/javascript" src="foo.js"></' + 'script>');

      // TEST CASE 2.
      // Only works for Opera, FireFox, Opera.
      // var scriptElem = document.createElement("script");
      // scriptElem.setAttribute("type", "text/javascript");
      // scriptElem.setAttribute("src", "foo.js");
      // var headElem = document.getElementsByTagName("head")[0];
      // headElem.appendChild(scriptElem);
    </script>
    <!-- expected new scrip tag being inserted here. -->
  </head>
  <body>
    Testing...<br/>
    <span id="result"></span>
  </body>
</html>

"foo.js" is just one line of code.

success = true;
+1  A: 

At the time when your javascript is evaluated, the DOM isn't fully built, the head element is not even finished. You normally cannot access or manipulate the DOM ( getElementsByTagName and appendChild, etc. ) before the HTML page is fully loaded.

Leventix
You can access the DOM before the page is loaded, but indeed you can't access elements below the current script block, and it's highly unreliable to do manipulations like inserts inside elements whose close-tag has not yet been encountered.
bobince
+1  A: 

Try this instead:

var s = document.createElement('SCRIPT');
s.charset = 'UTF-8';
s.src ='foo.js';
document.getElementsByTagName('HEAD')[0].appendChild(s);

But place this in a SCRIPT tag at the beginning of the BODY tag

Mic
Thanks Mic.But Safari and Chrome still showing the same error...
3rensho
A: 

Thanks everyone.

I changed my code as below. I added script.onload event handler.

This is the result for Safari and Chrome.

Page loaded.

Number of script elements is 2

ERROR! (success = false)

Script loaded.

Number of script elements is 2

There are 2 <script> elements at the time of page load, but "success" variable is still false (meaning that the external JS file "foo.js" is not yet evaluated).

So I think I can conclude that if <script> element is added by DOMElement.appendChild, Safari and Chrome append <script> element right after the current code block, but read the external JS file asynchronously.

<html>
  <head>
    <title>JavaScript loading test</title>
    <script type="text/javascript">
      var success = false;
      var logs = [""];

      function showLog(msg)
      {
        logs.push(msg);

        var spanElem = document.getElementById("result");
        if (spanElem)
        {
          spanElem.innerHTML += logs.join("<br/>");
          logs = [""];
        }
      }

      window.onload = function()
      {
        showLog("Page loaded.");
        var scriptElemCount = document.getElementsByTagName("head")[0].getElementsByTagName("script").length;
        showLog("Number of script elements is " + scriptElemCount);
        showLog(success? "OK (success = true)": "ERROR! (success = false)");
      }

      var scriptElem = document.createElement("script");
      scriptElem.setAttribute("type", "text/javascript");
      scriptElem.setAttribute("src", "foo.js");
      scriptElem.onload = function()
      {
        showLog("Script loaded.");
        var scriptElemCount = document.getElementsByTagName("head")[0].getElementsByTagName("script").length;
        showLog("Number of script elements is " + scriptElemCount);
      };

      var headElem = document.getElementsByTagName("head")[0];
      headElem.appendChild(scriptElem);
    </script>
    <!-- expected new scrip tag being inserted here. -->
  </head>
  <body>
    Testing...<br/>
    <span id="result"></span>
  </body>
</html>
3rensho
The files are loaded sequentially when you hardcode them in the page HEAD. But if you add them dynamically, they are loaded asynchronously. An easy cross browser technique is to add a call to a function at the end of the js file you load. This function will be executed when the file is fully parsed and loaded. Or you can wrap your js code into a function that will be executed as well when the file is loaded. I think you should avoid all those onload handlers.
Mic
A: 

O método document.write não funcionou comigo.

gadarf