2

I'm trying to output a <script> element in an innerHTML:

<script type="text/javascript">
    function fileManager()
    {
        data = document.getElementById("FM");
        data.innerHTML = "<script type='text/javascript' src='functions.js'></script>";
    }
</script>
    <div id="FM"></div>
    <ul id="show-menu">
        <li onClick="fileManager()">File Manager
    </ul>

The innerHTML bit of the script works perfectly, it's just that there's a problem with escaping characters inside the double quotes ("). The whole <script type='text/javascript' src='functions.js'></script> seems to be broken/written incorrectly and I can't seem to figure out what's wrong with it.

In case you're wondering, the functions.js file contains only document.write("test"); for testing purposes.

For some unknown reason this does not work. The result is a broken page, I see bits of other functions in the script and it doesn't make sense. How do I escape it correctly?

Onion
  • 1,714
  • 1
  • 23
  • 42

2 Answers2

4

The literal <script>/</script> inside the script is actually breaking the html tag that contains the script itself. There is also the problem that .innerHTML does not execute or load scripts. So I suggest:

function fileManager()
{
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = 'functions.js';
    document.getElementById("FM").appendChild(script);
}
Community
  • 1
  • 1
Esailija
  • 138,174
  • 23
  • 272
  • 326
  • I'll try this code. But the innerHTML isn't supposed to execute a script. It's purpose is to put the – Onion Jul 13 '12 at 20:52
  • @user1020567 I don't understand, you either want the script to execute or you don't. But it seems you want to it both, to execute and not execute? Script elements created with `.innerHTML` will not execute so I don't understand. And the whole purpose of creating a script element is to execute its `src` or its contents, which you cannot do with `.innerHTML`. Man am I confused now :D – Esailija Jul 13 '12 at 20:53
  • That's not what I meant. innerHTML will put anything I write within double quotes into the
    element. Theoretically, it should be possible to pass on the
    – Onion Jul 13 '12 at 20:57
  • @user1020567 the browser will not execute scripts that you create with `.innerHTML`. And if it doesn't work, please see if there are any errors. Also, replace `document.write` with `console.log` :p – Esailija Jul 13 '12 at 20:59
  • But aren't the scripts "created" with innerHTML just a simple HTML code output inside a
    element? I mean, it's practically the same as outputting some html inside a document.write - the document.write itself doesn't execute that html code, it just places it on the page so that the browser can actually interpret it.
    – Onion Jul 13 '12 at 21:04
  • @user1020567 scripts created with `document.write` are loaded and executed, I said that scripts created with `.innerHTML` are not. It is stated in the [specification](http://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0): *script elements inserted using innerHTML do not execute when they are inserted.* – Esailija Jul 13 '12 at 21:05
  • Also, if your functions.js script uses document.write then an async load like this will blank out your page since it'll probably load up after the DOM is ready. If that's the case and you are unable to modify your functions.js - you might have to go for a document.write over ride. Is your page coming up blank with this code ? – Ashray Baruah Jul 13 '12 at 21:07
  • Alright, I can see that you don't fully understand what I meant. Lets say we do this: data.innerHTML = "" <-- this will result in the img.jpg image being displayed inside that
    element, right? So why not any other HTML element in the world such as
    – Onion Jul 13 '12 at 21:08
  • 1
    @user1020567 the limitations are that script elements are not executed and invalid html is usually handled "unexpectedly" – Esailija Jul 13 '12 at 21:09
  • I've just re-checked the code and it still doesn't work. I literally copy-pasted your code and replaced my own function with it, but nothing happens when I invoke the fileManager() function. – Onion Jul 13 '12 at 21:12
  • @user1020567 did you check the network tab if the script is being loaded? Did you check the console for errors? – Esailija Jul 13 '12 at 21:16
  • Yes, the script IS being loaded and the console outputs the text successfully – Onion Jul 13 '12 at 21:18
  • @user1020567 then what is the problem? – Esailija Jul 13 '12 at 21:20
  • When I invoke the function fileManager() the
    element is not changed. The network tab shows that the script is loaded successfully but the console.log("text") simply doesn't output any text. In the Console tab I can see that the text "text" is being output, but that doesn't happen within the page
    – Onion Jul 13 '12 at 21:22
  • @user1020567 yes, `console.log` prints in the console not on the page. If you want to do something with the page, then you can use methods like `.innerHTML` etc. If the text is logged, then the script was loaded and is working properly. Script tags are not printed on the page. You can [inspect element](https://developers.google.com/chrome-developer-tools/docs/elements) on the div to see it has a `script` child though. – Esailija Jul 13 '12 at 21:23
  • Well that was the idea, I wanted to use innerHTML to change the contents of the
    element with an external script (which initially included document.write("text")
    – Onion Jul 13 '12 at 21:25
  • @user1020567 in the `functions.js` file , write `document.getElementById("FM").innerHTML = "text";` instead of `console.log` – Esailija Jul 13 '12 at 21:26
  • I already did that and was surprised it that it doesn't work :/ EDIT: I've restarted the browser and it works now. It appears that the browser had cached an old version of the page and it needed a restart. – Onion Jul 13 '12 at 21:28
  • @user1020567 are you sure you are not using a cached file? If the script loads and executes without errors, there are probably not many other explanations :D – Esailija Jul 13 '12 at 21:30
  • Thanks for the help, everything works now! (check the edit on the comment above) – Onion Jul 13 '12 at 21:31
0

There is a bug in certain browsers that will mess up when you try to insert script tags using javascript. What you need to do is break up the script tags like this:

"<scr"+"ipt..........</scr"+"ipt>"

This will work.

Ashray Baruah
  • 1,585
  • 11
  • 7