It’s just data

That’s Not Write

I learned something new today.  I’ve known for a while that pretty much all the browsers don’t implement document.write when found in the context of XHTML documents — even in the case where both the enclosing document and string are separately well formed.  Because Google AdSense depends on document.write, the net result is that I only serve ads to users of browsers that don’t support XHTML, which increasingly means that only IE users see ads.

The solution is to use createElementNS instead.  So far, so good.  The only piece left to the puzzle is where to append the child that you created.  If you simply do a document.appendChild, the new element ends up at the end of the document.  There doesn’t seem to be a property which indicates the current node in the tree at the time of the parse.  But in cases like adsense, you generally want the widget put in place.

Not seeing an answer online, and not finding the answer in the DOM, I sought out Ian Hickson in IRC.  When I posed the question, he answered without a moment hesitation:

var e = document.getElementsByTagName('*'); var pos = e[e.length-1]; pos.parentNode.appendChild(...);

The reason this works is the difference between a stream of bytes and a tree, namely the DOM.  Appending a child to the root effectively places the node after the body.  You need to drill down to find the last node based on an in-order traversal of the DOM, and append the child to the right of that one.

Now that I understand it, the following seems both more clear, and more scalable for large documents:

var pos = document;
while (pos.lastChild.nodeType == 1) pos = pos.lastChild;