11

I'm trying to do the following (I'm using the prototype library):

var div = document.createElement('div');
div.innerHTML = '<script src="somescript.js"></script>';
$('banner').insert(div);

In IE, div.innerHTML property is always equal to "" after I set the property in the second line.

This snippet is inside a function which is overriding document.write() in an external vendor script, so that is why I am doing it this way rather than creating a script element and appending it to the div element directly.

Any help would really be appreciated, this is giving me grey hairs!

bitsprint
  • 897
  • 1
  • 11
  • 19

5 Answers5

12

This one had me stymied for a bit as well. It turns out that IE does not allow the insertion of JS directly via innerHTML unless you include the 'defer' property (see the second link below). This property is unique to IE and apparently allows IE to defer execution of any JS until after the other markup has been loaded. A warning, though...if you include two script tags (as I did), there is no guarantee which one will execute first, as the scripts appear to be loaded asynchronously. This should only be a problem if your scripts are dependent on one another (as mine were).

There is an additional caveat as well...you must insert non-script markup at the same time that you insert the script. I was unable to insert the script tags by themselves, with or without the 'defer' property. Finally, the script tags must be placed after all other non-script markup being inserted. Otherwise, the script tags are stripped out of the inserted HTML.

Here are a few references:

MS innerHTML Reference:

http://msdn.microsoft.com/en-us/library/ms533897%28v=vs.85%29.aspx

MS Defer Property Reference:

http://msdn.microsoft.com/en-us/library/ms533719%28v=vs.85%29.aspx

Example of Script Insert via code (yes, it actually does work):

http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/insertScript_2.htm

My Test Code:

// I downloaded the MS example file above and tweaked their script a bit, 
// resulting in this.  Using the proper approach to the defer property 
// (namely: defer="defer") did not provide me with consistent results, so 
// sticking with 'DEFER' may be necessary.
// Note:  Try moving the 'sHTML' variable to the end of the script string.
function insertScript2()
{
    var sHTML="<input type=button onclick=" + "go2()" + " value='Click Me'><BR>";
    var sScript = sHTML + "<SCRIPT DEFER type='text/javascript'> function go2(){ alert('Hello from inserted script.') } </SCRIPT" + ">";
    ScriptDiv.innerHTML = sScript;
}
7

Your script tag is probably managing to be interpreted independently. Try:

div.innerHTML = '<scr' + 'ipt src="somescript.js"></scr' + 'ipt>';
chaos
  • 122,029
  • 33
  • 303
  • 309
  • This is a common problem with using script tags in code and very likely the problem here – jcoder Jul 01 '09 at 11:17
  • This is interesting. Can you elaborate? – bitsprint Jul 01 '09 at 11:40
  • Quite a few browsers mangle obvious script injections like this. The work-around is correct, though - mangle it yourself in a way that still works. – Jeff Ober Jul 01 '09 at 12:04
  • Tried the following in IE - using IE8 in IE7 mode and developer Tools debugger, value does not end up in div:
    – bitsprint Jul 01 '09 at 12:10
  • I suspect you may need to set the innerHTML after the div is already in the DOM (after the appendChild) in order for the script to work. – chaos Jul 01 '09 at 12:56
  • that doesn't seem to make a difference in the above example. – bitsprint Jul 01 '09 at 13:37
  • Okay. I guess interpretation of the script tag isn't the issue, then. – chaos Jul 01 '09 at 14:10
6

You could try to do something like this instead:

function loadScript(src) {
       var script = document.createElement("script");
       script.type = "text/javascript";
       document.getElementsByTagName("head")[0].appendChild(script);
       script.src = src;
}

or do

..
div.innerHTML = "<script src=\"somescript.js\"></script>";
..
Juri
  • 32,424
  • 20
  • 102
  • 136
  • I also prefer the 1st one. It is much cleaner and reusable. They 2nd was just a "try-it" suggestion if he doesn't want to use the 1st approach :) – Juri Jul 01 '09 at 11:24
  • I have a vague feeling the OP's problem is actually a security feature at work and your first answer here is the conventional (and non-blocking!) solution. – annakata Jul 01 '09 at 11:28
  • 1
    Agreed, that is how I would normally do it but as I said there is an external vendor script that is doing: document.write(''); I don't know what the src will be. We are calling this script after a partial page refresh (ajax) and the document.write renders a new page, therefore I am overriding document.write in my script to try and append the script to the page rather than allow the document.write to happen. I should have been clearer about the circumstances. Does that all make sense? – bitsprint Jul 01 '09 at 11:38
  • I left the company where I had this issue. The issue was related to the external vendor script in the end but if it had not been I think the first solution would have been my preferred approach to this kind of issue. – bitsprint Mar 30 '11 at 07:49
  • -1, The first version will fail in modern browsers that disallow dynamic script loading. – Qix - MONICA WAS MISTREATED Apr 10 '14 at 17:27
6

you need to use escape char for the </script>

div.innerHTML = '<script src="somescript.js"><\/script>';

see why escaping / in javascript '<\/script>'?

Community
  • 1
  • 1
Scherbius.com
  • 3,396
  • 4
  • 24
  • 44
1

Have you tried to add inline JS instead of loading a .js file? I've done this in the past and it worked fine for me. Not sure if that would still work with the lastest browsers / security missery.

HTH.

Jonathan van de Veen
  • 1,016
  • 13
  • 27