74
votes

I am trying to load a certain script after page load executes, something like this:

function downloadJSAtOnload(){
            var element = document.createElement("script");
            element.src = "scriptSrc";
            document.body.appendChild(element);
        }

         if (window.addEventListener)
                  window.addEventListener("load", downloadJSAtOnload, false);
            else if (window.attachEvent)
                  window.attachEvent("onload", downloadJSAtOnload);
            else window.onload = downloadJSAtOnload;

And while this script seems to execute and download 'scriptSrc', and append it right before the end of the body tag, it yields the following message (not an error) in the console (chrome)

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

What does this even mean? And am I supposed to do something differently? Even though I get the expected behavior?

3
It means the script you are loading executes document.write, which is not supported when you add it to the page via a <script> tag. You should probably look at what the script is doing and change the script to not use document.write.univerio
got it, but I can't change that script. Call it bureaucracy. Can I get the script to load synchronously? No right, cause it happens after page load.Parijat Kalia
Yes, you can load the script contents synchronously with AJAX, then eval it, though I'm not 100% sure whether that would work.univerio
recently found a fantastic library on github that gets around this "restriction" nicely: github.com/krux/postscribeRandy L
@univerio I am also facing same issue. document.write('\x3Cscript type="text/javascript" src="http://ads.appnexus.com/ttj?id=xyzpqr&cb=${CACHEBUSTER}">\x3C/script>'); this is working perfectly but when I create a script using createElement('script') I am facing same issue. Can you suggest something here?RockStar

3 Answers

90
votes

An asynchronously loaded script is likely going to run AFTER the document has been fully parsed and closed. Thus, you can't use document.write() from such a script (well technically you can, but it won't do what you want).

You will need to replace any document.write() statements in that script with explicit DOM manipulations by creating the DOM elements and then inserting them into a particular parent with .appendChild() or .insertBefore() or setting .innerHTML or some mechanism for direct DOM manipulation like that.

For example, instead of this type of code in an inline script:

<div id="container">
<script>
document.write('<span style="color:red;">Hello</span>');
</script>
</div>

You would use this to replace the inline script above in a dynamically loaded script:

var container = document.getElementById("container");
var content = document.createElement("span");
content.style.color = "red";
content.innerHTML = "Hello";
container.appendChild(content);

Or, if there was no other content in the container that you needed to just append to, you could simply do this:

var container = document.getElementById("container");
container.innerHTML = '<span style="color:red;">Hello</span>';
24
votes

A bit late to the party, but Krux has created a script for this, called Postscribe. We were able to use this to get past this issue.

2
votes

In case this is useful to anyone I had this same issue. I was bringing in a footer into a web page via jQuery. Inside that footer were some Google scripts for ads and retargeting. I had to move those scripts from the footer and place them directly in the page and that eliminated the notice.