views:

54

answers:

1

My website dynamically embeds an external Javascript file into the head tag. The external Javascript defines a global variable myString = "data". At what point does myString become accessible to Javascript within the website?

<html>
<head>
    <script type="text/javascript">
        myString = null;
        external = document.createElement("script");
        //externalScript.js is one line, containing the following:
        //myString = "data";
        external.setAttribute("src", "externalScript.js");
        external.setAttribute("type", "text/javascript");
        document.getElementsByTagName("head")[0].append(external);
        alert(myString);
    <script>
</head>
<body>
</body>
</html>

This code alerts null (when I thought it would alert "data") in Chrome and IE, even though the DOM has loaded in externalScript.js at this point. When is externalScript.js actually evaluated by the browser and at what point do I have access to the new value of myString?

+4  A: 

You can access it when the onload event fires for that script element, like this:

external = document.createElement("script");
external.onload = function() { alert(myString); };
script.onreadystatechange= function () { //for IE, the special kid...
  if (this.readyState == 'complete') alert(myString);
}
external.setAttribute("src", "externalScript.js");
external.setAttribute("type", "text/javascript");
document.getElementsByTagName("head")[0].appendChild(external);

This just attaches a function to run once that script has loaded, execute any code that depends upon the script in there. Correction to previous answer: as seanmonstar points out in comments (thanks!), you do indeed need an IE exception here again, because it's a bit "special"...

Nick Craver
Ooh, I like that much better. Answer removed. Will injecting the external script even work at all, though, if we're acting inside `<head>`? I haven't dealt with this one much...
Matchu
@Matchu - It should, as long as the element's been opened it'll work...browsers I would *assume* know that this kind of thing happens. When an element is opened, most browser implementations treat it as a closed element, adding the children into that parent as it finds them, but the parent itself is fair game as soon as it's opened.
Nick Craver
I think I've hit issues with scripts at the end of `<body>` being able to add things... time to test!
Matchu
You'll also need to check onreadystatechange for IE. like so: http://stackoverflow.com/questions/903012/waiting-on-lazy-loaded-objects-without-lockup/903087#903087
seanmonstar
@Matchu - I setup a test you can play with here: http://jsfiddle.net/qJVCu/
Nick Craver
@seanmonstar: Thanks - updated to include this with a shoutout. This is once again why I use an abstraction layer...I guess you can't assume anything will work in IE like the rest of the browser world...
Nick Craver
@Nick Craver - Thanks for the answer. I just have one small problem. The W3C DOM API does not seem to mention attribute onload for elements or nodes. Where can I find documentation on how this works?
Mark
@Mark - [You can use MSDN for some of this](http://msdn.microsoft.com/en-us/library/cc197055.aspx) I'm not sure it is in the API (not where I can pull it up at the moment)...which would explain the discrepancy with IE. For not really an API description, but a good run-down of how it works, take a look here: http://unixpapa.com/js/dyna.html
Nick Craver
@Nick Craver - The first link was helpful and shows a way to mimic an event listener without using onload. Just a note on the MSDN, it also suggests that <script ... onload="handler">...</script> will fire once the script is loaded. This suggests you would also be able to do this: external.setAttribute("onload", "alert('myString');");Scripts, however, cannot have an onload attribute according to the XHTML dtds, so things this way would actually break the XHTML validity of a document. If external.onload is a shortcut to external.getAttribute("onload"), your way invalidates XHTML.
Mark
contd: However, if element.onload is just a method that browsers call once elements are loaded, there is no problem. So I was just wondering if the onload of the Javascript object is tied to the DOM.
Mark
@Mark - attributes and event handlers are 2 very different things, for example `onclick` isn't an attribute, it may be an event handler declared the same way an attribute is in markup (though this is bad practice, and another discussion altogether), but they are separate things. You would never attach event handlers in the attribute manner, so don't go by which attributes are allowed...attributes, event handlers and DOM methods are 3 separate though overlapping concepts.
Nick Craver
@Nick Craver - Okay gotchya. Declaring an event handler through markup is a wonky way of declaring an event handler. (And it invalidates your XHTML).
Mark