What are alternatives to document.write?

The reason that your HTML is replaced is because of an evil JavaScript function: document.write().

It is most definitely "bad form." It only works with webpages if you use it on the page load; and if you use it during runtime, it will replace your entire document with the input. And if you're applying it as strict XHTML structure it's not even valid code.


the problem:

document.write writes to the document stream. Calling document.write on a closed (or loaded) document automatically calls document.open which will clear the document.

-- quote from the MDN

document.write() has two henchmen, document.open(), and document.close(). When the HTML document is loading, the document is "open". When the document has finished loading, the document has "closed". Using document.write() at this point will erase your entire (closed) HTML document and replace it with a new (open) document. This means your webpage has erased itself and started writing a new page - from scratch.

I believe document.write() causes the browser to have a performance decrease as well (correct me if I am wrong).


an example:

This example writes output to the HTML document after the page has loaded. Watch document.write()'s evil powers clear the entire document when you press the "exterminate" button:

I am an ordinary HTML page.  I am innocent, and purely for informational purposes. Please do not <input type="button" onclick="document.write('This HTML page has been succesfully exterminated.')" value="exterminate"/>
me!

the alternatives:

  • .innerHTML This is a wonderful alternative, but this attribute has to be attached to the element where you want to put the text.

Example: document.getElementById('output1').innerHTML = 'Some text!';

  • .createTextNode() is the alternative recommended by the W3C.

Example: var para = document.createElement('p'); para.appendChild(document.createTextNode('Hello, '));

NOTE: This is known to have some performance decreases (slower than .innerHTML). I recommend using .innerHTML instead.


the example with the .innerHTML alternative:

I am an ordinary HTML page. 
I am innocent, and purely for informational purposes. 
Please do not 
<input type="button" onclick="document.getElementById('output1').innerHTML = 'There was an error exterminating this page. Please replace <code>.innerHTML</code> with <code>document.write()</code> to complete extermination.';" value="exterminate"/>
 me!
<p id="output1"></p>

You can combine insertAdjacentHTML method and document.currentScript property.

The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position:

  • 'beforebegin': Before the element itself.
  • 'afterbegin': Just inside the element, before its first child.
  • 'beforeend': Just inside the element, after its last child.
  • 'afterend': After the element itself.

The document.currentScript property returns the <script> element whose script is currently being processed. Best position will be beforebegin — new HTML will be inserted before <script> itself. To match document.write's native behavior, one would position the text afterend, but then the nodes from consecutive calls to the function aren't placed in the same order as you called them (like document.write does), but in reverse. The order in which your HTML appears is probably more important than where they're place relative to the <script> tag, hence the use of beforebegin.

document.currentScript.insertAdjacentHTML(
  'beforebegin', 
  'This is a document.write alternative'
)

Here is code that should replace document.write in-place:

document.write=function(s){
    var scripts = document.getElementsByTagName('script');
    var lastScript = scripts[scripts.length-1];
    lastScript.insertAdjacentHTML("beforebegin", s);
}