Warning: A call to document.write() from an asynchronously-loaded external script was ignored. How is this fixed?
Asked Answered
N

3

6

In my Ruby on Rails application I am using the Facebox plugin for an Ajax pop up window. I have 2 pages called add_retail_stores/new.html.erb and add_retail_stores/new.js. The new.js page inherits all elements from the new.html.erb page so it looks exactly alike. I have a Google map script on the HTML page that works as it should. But the new.js page that pops up on my different page called add_store_prices.html.erb page(<%= link_to add_retail_store_path, :remote => true %>)

I get the error:

Warning: A call to document.write() from an asynchronously-loaded external script was ignored. Source File: http://localhost:3000/add_store_prices Line: 0

I believe because it's trying to go through 2 functions/scripts. The first one for the Facebox and then the Google script. Anyone know how to handle this error?

EDIT:

I believe the Facebox plugin is using document.write but I am not sure where, perhaps in one of these 2 lines on my page?

new.js:

$.facebox('<%= escape_javascript(render :template => 'business_retail_stores/new.html') %>')
$('#facebox form').data('remote','true');
Nogas answered 18/10, 2011 at 18:31 Comment(0)
L
11

Don't use document.write. The script is being loaded asynchronously, which means it's detached from the document parsing state. There is quite literally NO WAY for the JS engine to know WHERE the document.write should be executed in the page.

The external script could load instantaneously and the document.write executes where the <script src="..."> tag is, or it could hit a net.burp and load an hour later, which means the document.write gets tagged at the end of the page. It's quite literally a race condition, so JS engines will ignore document.writes from scripts loaded asynchronously.

Convert the document.write to use regular DOM operations, guarded by a document.onload type handler.

Lukelukens answered 18/10, 2011 at 18:51 Comment(3)
Its strange, document.write doesn't exist anywhere in my application. I am using the the script to get Google maps to run along with the code in my edit above. Do you see anything issues with the above code?Nogas
Looks ok. Maybe it's one of those two other scripts you mention: facebox or google's.... can't see google using doc.write, so most likely faceboxLukelukens
Actually, yes, Google's async scripts do use document.write if you don't pass a callback. You can just append &callback=isNaN to the Google Maps v3 script URL and it won't use document.write anymore. Total WTF from Google on this one.Springhead
E
4

If you have access to the .js file in question, your best solution is going to be to modify the "document.write()" method and replace it with whatever makes sense in order to distribute the content contained within.

The reasons for this are very well described above.

If you are using document.write to write html tags to the page:

document.write("<script src=...></script>");

or

document.write("<img href=... />");

Consider using the same sort of asynchronous format you've already been using:

// Add/Remove/Sugar these components to taste
script = document.createElement("script");
script.onload = function () { namespaced.func.init(); };    
script.src = "http://...";
document.getElementsByTagName("script")[0].parentNode.appendChild(script);

If you're looking to append DOM elements that are for the user to see and interact with, then you're better off either:

a) Grabbing a specific containter (section/div) by id, and appending your content:

document.getElementById("price").innerHTML = "<span>$39.95</span>";

b) Building content off-DOM and injecting it into your container:

var frag = document.createDocumentFragment(),
    span = document.createElement("span");
span.innerText = "39.95";
frag.appendChild(span);
document.getElementById("price").appendChild(frag);

Again, Sugar to your liking.

If you DON'T have access to mod this second .js file, I'd suggest taking it up with them.

Ejection answered 18/10, 2011 at 19:49 Comment(0)
P
1

I had the same problem loading google maps with the places library. I temporarily override the write function to create a new script element in the head.

(function() {
  var docWrite = document.write;
  document.write = function(text) {
    var res = /^<script[^>]*src="([^"]*)"[^>]*><\/script>$/.exec(text);
    if (res) {
      console.log("Adding script " + res[1]);
      var head = document.getElementsByTagName('head')[0];
      var script = document.createElement("script");
      script.src = res[1];
      head.appendChild(script);
    } else {
      docWrite(text);
    }
  }
})();

Now all I have to do to load a script asynchronously is

document.write('<script src="http://maps.googleapis.com/maps/api/js?libraries=places"></script>');
Phillie answered 22/10, 2014 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.