Replacing document.write

When JavaScript was first created it did not have much ability to interact with the actual web page. With the versions of JavaScript available in Netscape 2 and 3 and JScript in Internet Explorer 3 the only way to output something to the web page itself from a script was to use a document.write statement. As these statements wrote to the spot in the web page immediately after the script that included it you had to jumble the scripts through the HTML where ever you wanted to be able to insert content from JavaScript. The other limitation with using document.write is that if it was called after the web page finished loading then it would start creating a completely new web page overwiting the current page completely.

Netscape 4 and Internet Explorer 4 each introduced their own proprietary document object model (DOM) that allowed scripts to interact far more easily with the web page without needing to use document.write at all. Unfortunately these DOM were incompatible with one another butr this was resolved by all subsequent browsers incorporating at least the first portion of the W3C standard DOM. As all browsers to not support the standard DOM died out by approximately 2005 there has been no reason to use either document.write or either of the proprietary DOM since that time. The DOM are a little complicated for a beginner to understand and so browsers soon introduced another simpler way to interface with web pages called innerHTML. While there are a few limitations on where you can use innerHTML they are far fewer than the restrictions on using document.write and so if none of the prior replacements for document.write could be considered to have made document.write completely obsolete then the introduction of innerHTML certainly did.

Unfortunately there are still a lot of people teaching the obsolete document.write command to JavaScript beginners. Also there are still many scripts that use this command that have to be jumbled with the HTML instead of being called from the bottom of the web page the way almost all properly written modern scripts can be (the exception being scripts that redirect to another page which need to go in the head instead).

Where you have document.write statements in your own script you can easily rewrite the script to use innerHTML instead. Simply place a div with an id in the place where you had the script and move the script itself to the bottom of the page. Declare a new variable at the top of the script to hold the values to be written out and replace all of the document.write statements with commands to concatenate to that variable instead. Then at the end of the script simply use document.getElementById to reference the div you added and innerHTML to insert the values that the document.write statements were outputting.

For example if your original script reads:

for (i = 1; i < 6; i++)

Then you'd place the following HTML in plave of that script:

<div id="list"></div>

and move the script to the bottom of the page and change it to read:

var msg = '';
msg += '<ul>';
for (i = 1; i < 6; i++)
  msg += '<li>'+i+'</li>';
msg += '</ul>';
document.getElementById('list').innerHTML = msg;

This conversion can be applied no matter what document.write statements you have in the original obsolete code, you simply need to specify a different id for each spot where something needs to be output.

Things are a lot more complicated where the script is one written by someone else where you are not allowed to rewrite their code to replace the obsolete calls. Some years ago John Resig started developing an HTML parser JavaScript which could examine the HTML contained in document.write statements and dynamically convert them so that the HTML can be inserted into the page later (if that name looks familiar it is probably because of another JavaScript that he also wrote called JQuery). By writing your own code to pass the script containing the document.write statements into the parser script you could get it to run the script with the output of those document.write directly referenced in the script being inserted at the spot of your choice within the page. Unfortunately with more complicated scripts (which includes most of the scripts that you are not allowed to change such as ad scripts) means that a simple call to the parser is insufficient as nested content calling document.write ends up outputting after the script you call the parser from instead of after the spot where you inserted the script.

A number of people have collaborated on finding a solution to this problem and the result is a script called postscribe. Using this script you can take any script that contains document.write statements and attach it to the bottom of your web page. The only restrction on using this to move scripts to the bottom of the web page that I have found is that you can't combine the scripts together if they are supposed to be outputting to different spots in the page.

For example if you are using AdSense to display ads supplied by Google in your web page then instead of posting the code they supply directly in the spot where you want the ad to appear you can place a div with an id in that spot instead and use postscribe to attach the ad code to it from the bottom of the web page. The JavaScript for your Google ad will look something like this:

google_ad_client = "pub-9999999999999999";
google_ad_slot = "9999999999";
google_ad_width = 300;
google_ad_height = 250;
postscribe('#adv1','<script type="text/javascript" src=""><\/script>');

Note that the only change we have made is to incorporate the call to the Google script into the same script as the one assigning the parameters for it to use with that script tag as the second parameter to a postscribe call and with the id where we want the ad to be inserted defined in the first parameter. The code in the second parameter needs to coded in the same way as if we were using a document.write statement and so the </script> in the code needs to be escaped so that it is treated as data and not as the HTML tag at the end of the script.

Let's assume that code is in a script that we call ad1.js. So now we just need copies of the htmlParser.js and postscribe.js files which we can get from GIThub and by including calls to those two files at the bottom of our page we can then follow that with the call to our ad script.

<script type="text/javascript" src="postscribe.js"></script>
<script type="text/javascript" src="htmlParser.js"></script>
<script type="text/javascript" src="ad1.js"></script>

To add a second Google ad we'd add a new div where we want the second ad to appear and create another script to contain the Google code for that ad with the postscribe call identifying where that ad is to appear and then add a call to that script after the ones we just added (we only need toe postscribe and htmlParser scripts to be included once and we need each ad script to be separate).

Now we can have all of our JavaScript where it belongs at the bottom of our web page even if the code does use obsolete document.write calls. The only disadvantage is that we have added two relatively large scripts into our web page in order to fix this problem which would not have been necessary had the script owner updated their code to get rid of the document.write statements. We have also complied with the requirement that we not change the supplied script with its antiquated code, all we have done is to change the way we use the supplied code in order to overcome the limitations that the obsolete calls in the supplied code would otherwise impose.


This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow