document.write() fix for (real) XHTML [v0.5.1]

Please note that this page is being regularly updated as the script matures. Please check out the changelog to see what’s been added since it’s first release.

This is a solution to a niche problem. But even niche problems need solutions. A while back I started serving my pages with the application/xhtml+xml MIME type (in other words, as XML not HTML). The trouble was that all of the third party scripts on my site that used document.write() to output their content stopped working. (To learn more about this issue read: Does document.write work in XHTML? and Why document.write() doesn’t work in XML.)

The solution isn’t as pretty as I had originally hoped, but it works.

My first attempt only worked with one script tag. My second attempt also worked with only one script tag, just using a different technique.

I then toyed around with an early version of the script below and it was a lot more elegant than it is now. It was more elegant because every time a document.write was called it checked to see how far along the DOM was in being built by counting the number of script tags in the page. It then dumped its contents at the last known script tag’s position. Very clean. I wish I could have used that. It’s just that it only worked in text/html mode. As soon as I switched MIME types to application/xhtml+xml, the parser stopped cooperating and everything ended up bunched together at one location (the first script tag’s position). That’s because when using the text/html MIME type you’re in the standard DOM where script tags are parsed as the DOM is being built. Not so with application/xhtml+xml. The DOM is built first and then all scripts are run afterwards. The code that’s being executed has no idea where it’s being called from in the DOM (because in real XHTML you’re not supposed to run scripts that adjust the DOM directly in the body of the document) so there’s no reference for me to point to and say “build your nodeset here”. So seeing as how there was a huge disconnect between the scripts themselves and where they were supposed to dump their contents, I had no choice but to take the route that I took.

The code supports multiple script tags as well as script tags with multiple document.write()s, something I couldn’t have hoped to support in the first two tries. The code below basically does the following:

  1. Wires up document.write so that it dumps it’s output into a stack instead of the DOM.
  2. Builds node fragments out of the contents of the stack–it relies on manually entered signatures (ugly, I know) to know when to start building a new fragment. This is done in order to support scripts containing multiple document.write()s (see the code for the buzzboost section on my feeds page for an example of such a script).
  3. Cleans up the fragments because they contain HTML errors that will cause the XML DOM parser to bomb.
  4. Extracts, creates and re-inserts a <script> node out of any fragment containing one. This is the only way to ensure that it will be run once it’s inserted into the DOM. innerHTML doesn’t do it.
  5. Finds the script tags in the page via their IDs (which are also manually entered, yuk)
  6. Inserts the fragment next to the script tag

I suppose I could cut out the need for step four by identifying the script tags by the contents of their src attributes, but for now I’m just happy to get this thing working. Maybe in the next version. ;-)

So far I’ve tested it on Firefox 1.5(PC), IE 6(PC), Opera 8.5(PC), IE 5.2(Mac) and Safari 1.3.1(Mac) and they all seem to work fine. Take her for a spin and let me know how it works for you!

<head>

<script src="DocumentWriteOverride.js"></script>
<script>
	window.onload = DocumentWriteOverride.Show; // of course you can bind it however you wish as long as it's on load
</script>

DocumentWriteOverride.js

/*
Document Write Override v0.5
Written by Ara Pehlivanian (http://arapehlivanian.com)

This work is licensed under a Creative Commons Licence

http://creativecommons.org/licenses/by-nd/2.5/

*/

var DocumentWriteOverride = {
	Signatures : [
		["dw_technorati","<p id=\"te_l\"", ""],
		["dw_feedburner","<div class=\"feedburner", ""],
		["dw_measuremap","<script type='text/javascript' src='http://tracker.measuremap.com", ""]
	],

	Stack : [],

	Store : function(str){
		DocumentWriteOverride.Stack[DocumentWriteOverride.Stack.length] = str;
	},

	Show : function(){
		var signatures = DocumentWriteOverride.Signatures;
		var stack = DocumentWriteOverride.Stack;
		var scripts = document.documentElement.getElementsByTagName("body")[0].getElementsByTagName("script");
		var pointer = -1;
		for(var i=0; i<stack.length; i++){
			for(var j=0; j<signatures.length; j++){
				if(stack[i].toString().indexOf(signatures[j][1]) != -1) pointer=j;
			}
			signatures[pointer][2] += stack[i];
		}		

		for(var i=0; i<signatures.length; i++){
			var node = document.getElementById(signatures[i][0]);
			if(typeof node != "undefined"){
				var str = DocumentWriteOverride.Cleaner.Clean(signatures[i][2].toString());
				if(str.indexOf("<script") != -1){
					var parentNodeRef = node.parentNode; //referencing the parent node directly causes the script to bomb
					parentNodeRef.innerHTML += str.substring(0, str.indexOf("<script"));
					DocumentWriteOverride.AddScript(parentNodeRef, str.substring(str.indexOf("<script"), str.indexOf("</script")+9));
					parentNodeRef.innerHTML += str.substring(str.indexOf("</script")+9, str.length);
				}else if(str.length > 0){
					node.parentNode.innerHTML += str;
				}
			}
		}
	},

	AddScript : function(parentNodeRef, fragment){
		var delimiter = fragment.substr(fragment.indexOf("src=") + 4, 1);
		var start = fragment.indexOf("src=") + 5;
		var character = fragment.substr(start, 0);
		var src = "";
		while(character != delimiter){
			src += character;
			character = fragment.substr(start++, 1);
		}
		var script = document.createElement("script");
		script.type = "text/javascript";
		script.src = src;
		parentNodeRef.appendChild(script);
	},

	Cleaner : {
		Clean : function(str){
			var tmpStr = str;

			tmpStr = this.ReplaceAll(tmpStr, "&#187 ", "&amp;#187; ");			// Technorati fix
			tmpStr = this.ReplaceAll(tmpStr, "&#8230<", "&amp;#8230;<");		// FeedBurner fix
			tmpStr = this.ReplaceAll(tmpStr, "&repeat=", "&amp;repeat=");	// MeasureMap fix
			tmpStr = this.ReplaceAll(tmpStr, "&x=", "&amp;x=");				// MeasureMap fix
			return tmpStr
		},

		ReplaceAll : function(str, from, to){								// Hat tip to Mark for this algo (http://www.experts-exchange.com/M_1235249.html)
			var idx = str.indexOf(from);
			while(idx > -1){
				str = str.replace(from, to);
				idx = str.indexOf(from);
			}
			return str
		}
	}
}
document.write = DocumentWriteOverride.Store;

Changelog

Tags:


cialis 32
buy generic no online prescription viagra
viagra 50mg
100mg viagra
buy 10 mg cialis
cialis 1
cheapest place to buy viagra
buy cheap viagra cheap viagra online
viagra 50 mg
buy pfizer viagra
cheap viagra without prescription
buy levitra no prescription
buy generic viagra img
cheap levitra online
cheapest regalis viagra
generic cialis wholesale 100mg
viagra and cialis cheap
generic viagra 100mg
buy in uk viagra
buy cheap viagra online uk
buy pill price price viagra
buy cheap cialis
36 hour levitra
buy kamagra viagra india
cialis 36 hours
buy cialis no prescription
viagra buy oonline
canada pharmacy discounted viagra 100
cheap cialis canada
cheap cialis canada
buy online pill viagra
250 mg levitra
cheap pill pill sale viagra
buy now online viagra
cialis no prescription
free bingo
cialis 20mg reviews
buy levitra viagra
generic cialis 100mg
purchase levitra
100 mg levitra us pharmacy
buy cheap levitra
cheapest price for viagra and cialis
levitra 25 mg order
levitra brand levitra 100mg
cialis 10
buy site viagra
buy deal deal price viagra
buy levitra 50mg
buy cialis internet
buy viagra on the internet
buy real viagra online pharmacy
voagra online without prescription
cialis 50mg
levitra 25 mg
buy viagra no prescription
cialis 10
cialis brand cialis 100mg
50 mg levitra retail price
cheapest generic silagra viagra
cheapest generic price viagra
cheaper viagra levitra apcalis
cheep generic viagra
100mg cialis
cheapest uk supplier viagra
buy cost low viagra
viagra and cialas
cheapest brand viagra
purchase levitra online
buy cheapest online viagra
absolute poker
cialis no prescription
cialis reviews
viagra 25 mg
cheapest place to buy viagra online
buy cheap purchase uk viagra
order 50mg levitra
cheapest viagra
buy cheap viagra online u
cheapest in uk viagra
online slots
generic cialis 20mg pills erections
buy pharmaceutical viagra
buy in online uk viagra
cheap online purchase viagra
cialis 10mg 20mg
cheap pharmacy viagra
buy online purchase viagra
cheap viagra online
viagra 50mg online
cialis 10mg
50mg cialis
cialis 20
buy cheap deal pill viagra
buy in online usa viagra
tamiflu
buy viagra online alternative viagra
levitra 50 mg
buy free online sale viagra viagra
buy no online prescription viagra
cialis black reviews
10 generic levitra for 19.95
levitra 10mg 20mg
cialis 50 mg
voagra online without prescription
viagra brands
buy cheap viagra in uk
viagra by mail order
cialis online prescription
cheep viagra
buy online sale viagra viagra
viagra buy now pay later
viagra no prescription
buy deal herbal viagra viagra
buy real viagra online
50 mg viagra
national bingo night
cheap cialis canada
cialis without prescription
cheap levitra canada
10 generic viagra for 19.95
buy cheap viagra online
buy real viagra
buy file viagra
allegra
buy online prescription viagra
voagra online without prescription
buy online levitra cialis viagra
buy p viagra
viagra by mail canada
cheapest 4 quantity of viagra
viagra by the pill
cialis black 800mg
order levitra online
cheap websites for viagra
buy discount viagra
buy generic viagra viagra
canada pharmacy discounted levitra 100
generic viagra wholesale 100mg
40 grams of cialis
cialis 20
buy keyword online viagra
buy cheap viagra on
discount drugs levitra 100mg
viagra buy generic
20 mg cialis
cheap overnight viagra
buy discount levitra
10 generic cialis for 19.95
cheapest online viagra
buy cheap viagra on the net
canada pharmacy discounted cialis 100
discount drugs cialis 100mg
buy cheap uk viagra
buy cheap generic viagra
buy prescription viagra without
cheapest price viagra
cheapest site viagra
buy line viagra
cialis 100mg price
buy levitra online 50mg
100 mg viagra us pharmacy
viagra buy viagra online
buy prescription vaniqa viagra
buy pill viagra
cheap phizer viagra
cheap online price price viagra
buy cheap deal online viagra viagra
viagra and cialis and
viagra by overnight delivery
100mg levitra
cheap 25mg viagra
buy online order viagra
viagra 125 mg
cialis without prescription
buy say viagra
buy online drug viagra pharmacy
generic viagra 20mg pills erections
cheap soft tab viagra
buy cheap viagra uk
cialis 24
buy online price viagra
buy levitra wighout prescription
buy viagra online at cheap price
viagra buy ionline
buy cialis online now
buy cialis no prescription
viagra brand
cheap 25mg levitra
cheap viagra online order viagra now
buy cheap generic viagra online
cheap viagra uk
cheap online generic viagra
30mg cialis
cialis 20mg
buy cialis wighout prescription
buy viagra wighout prescription
viagra buy
cialis 25 mg
discount drugs viagra 100mg
levitra 50mg online
viagra 100mg price
cheap prescription viagra without
50 mg levitra
buy low price viagra
generic levitra 100mg
36 hour cialis
viagra by mail catalog
buy cheap deal viagra viagra viagra
10mg viagra
buy generic online viagra
cialis 2.5
cheap order prescription viagra
viagra buy it
buy cialis online
buy now viagra
buy levitra online
order 50mg cialis
viagra online prescription
cheapest generic viagra and cialis pills
cheap pharmaceutical viagra
cheap discount levitra
buy free viagra viagra
cheapest prices on generic viagra
50 mg viagra retail price
buy cheap online viagra viagra
buy cheap sale viagra
cialis 10mg
250 mg cialis
buy viagra online
levitra 50mg
buy cialis online 50mg
generic levitra wholesale 100mg
buy online uk viagra
buy sildenafil viagra
cialis 30
buy cheap cialis
cialis 20 mg
cheaper viagra
levitra online prescription
viagra 100mg
cialis 20 mg
buy cheap cialis generic levitra viagra
buy pharmacy pill viagra
cheapest viagra in the uk
buy from pharmacy us viagra
levitra 125 mg
buy viagra online 50mg
cheapest generic viagra and canada
50 mg cialis retail price
100 mg cialis us pharmacy
cialis 125 mg
cheapest generic substitute viagra
viagra buying online
buy cialis now
cheap online viagra
order levitra
buy cheap generic online viagra
buy cheapest online place viagra
cialis 10 mg
buy cheap online prescription viagra
cheapest generic viagra and cialis
cheap viagra st
buy viagra 50mg
generic cialis
cialis 20mg
buy generic viagra buy
cialis 5m tablets
cialis 2005
buy cheap viagra
cheapest cialis
viagra buy it online now
buy get online prescription viagra
buy online pharmacy viagra
buy discount levitra
cialis 2005
cheap viagra online uk
buy in spain viagra
buy cheap site viagra
cialis black
buy cialis online viagra
cheapest price for viagra
cheapest place buy viagra online
buy internet viagra
poker table
cheap online order viagra
buy cheap viagra online now
buy levitra online viagra
generic levitra 20mg pills erections
cheaper viagra levitra cialis
viagra by phone
cialis 50mg
viagra by mail
buy discount cialis
order 50mg viagra
cheap pill viagra
buy cialis 50mg
cheap sale viagra
buy kamagra viagra
levitra 100mg price
viagra and cialis
buy generic viagra online pharmacy online
buy later now pay viagra
buy generic viagra online
viagra buy in uk online
250 mg viagra
5mg cialis
buy locally viagra
viagra brazil
buy keyword viagra
rx cialis 100mg
cheaper viagra levitra cyalis
cheap site viagra
5mg cialis generic
cheap prescription viagra
buy prescription viagra
buy real viagra pharmacy online
viagra buy do nu
buy cheap viagra online now uk
buy price viagra
buy cheap discount levitra
cheap 25mg cialis
cheap order site viagra
buy cheap online viagra
cheapest price for generic viagra
viagra and coupon
cialis 5mg
levitra no prescription
50 mg cialis
buy online sale viagra
buy viagra online a href
buy cheap p viagra
cialis 100mg
buy line viagra where
buy sale viagra
buy online online viagra viagra
buy generic viagra pharmacy online
rx levitra 100mg
buy levitra now
cheapest price on viagra
buy free viagra on internet
viagra buy online
viagra buy viagra
cheapest line viagra
cheap viagra uks
buy viagra online and get prescription
viagra by money order
usa cialis
buy generic viagra
cheap cialis canada