JavaScript and XHTML

You may already know that JavaScript doesn't work as well with XHTML as it does with HTML. If you think it does, either you are using Internet Explorer, because it can't handle XHTML correctly (Go get firefox now!), or you don't know that you should serve the document as application/xhtml+xml and not text/html as regular html pages, more on that here. There are two compatibility problems with XHTML and JavaScript that I know about. And I will give you solutions for both right here!

document.write() in XHTML

The first problem is document.write(), it just doesn't work with XHTML because of the way the XML parser behaves. More on that over here.

Instead of document write we do have 4 different JavaScript functions to use: createElementNS(), createElement(), createTextNode() and nodeValue() And here I will show you how to use the last three.

Using createTextNode()

Creating a text node is easy:

var newText = document.createTextNode("Hello world! ");

Now we have a text node, and we just have to insert it into the page using DOM functions in javascript (A good list of those) . Here's the element we will insert the text into:

<div id="addToMe">Hello You!</div>

And here's the javascript:

var theElement = document.getElementById("addToMe");
theElement.insertBefore(newText, theElement.childNodes[0]);

Watch my demo page for this script!

Explanation

In the javascript we create a simple variable, var theElement that refers to the html div with the ID addToMe. On the second line we have theElement.insertBefore which means we will insert a node before a childnode of theElement. Then on the same line we have (newText, theElement.childNodes[0]) which will insert our text node newText, before the first child node of theElement, which here is the text Hello You!.

Using createElement()

Some javascripts use document.write() to write a new javascript to the page with some variables in the url. Often used by free website statistics services etc. Here's an example using createElement() to create an img element:

var newElement=document.createElement("img");
newElement.setAttribute("height", "23px");
newElement.setAttribute("width", "38px");
newElement.setAttribute("src", "http://xonium.net/designo/menuico.gif");
document.getElementById('testDiv').appendChild(newElement);

And here is the div tag we will insert the element to as a last node, (after "Image:") :

<div id="testDiv">Image: </div>

Watch my demo page for this script!

Using nodeValue()

Here is the html in which we will change the textnode. "Here is a boring text!" is the textnode.

<div id="testDiv">Here is a boring text!</div>

And here is the javascript to change it:

document.getElementById('testDiv').childNodes[0].nodeValue = '<div id="test">Hello World!</div>';

Watch my demo page for this script!

Making these scripts load when page has finished loading

In all my demos you have to click a link to run the javascript function. If you want these scripts to run automatically it's a BAD idea just to remove the function declaration and make it run as the page is still loading! Because when the script runs, the xhtml which it is supposed to manipulate, is not yet created! We need to make the script not to run before the page has finished loading. However this is very easy. Here's the script to use (made by Simon Willison):

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function'){ 
		window.onload = func; 
	}
	else { window.onload = function(){ 
			oldonload(); 
			func(); 
		}
	}
}

And here's an example of a function, and a call to load it with the function above:

function test() {
	document.getElementById('testDiv').childNodes[0].nodeValue = '<div id="test">Hello World!</div>';
}
addLoadEvent(test);

Here's the demo to show you that it works, and how. If you have many functions you want to run, simply use an addLoadEvent(functionname); for every function.

The second problem in XHTML

For a long time people have encaptured javascripts like this when occuring in the source code of a page. This was to prevent very very old browsers, that doesn't understand javascript, from writing out the javascript code as text on the page.

<!--
/* Your javascript goes here */
//-->

Now this era is finally over thanks to XHTML, but we've got some new problems instead. In HTML, browsers that understand JavaScript know that what is inside the script tag should not be treated as HTML. In XHTML the XML parser don't know this. So we have to add some code to make the XML parser not parse this as XML:

<![CDATA[
/* Your javascript goes here */
]]>

But, now we've got a new problem, this will cause trouble for the JavaScript interpreter. So we have to comment that out too.

// <![CDATA[
/* Your javascript goes here */
// ]]>

Now our javascript should work very well in pretty much all browsers. You can see me using this in all the demos above. It won't work in those very very old browsers that still doesn't understand javascript at all. Do never try to solve this by also using <!-- and //-->. This will cause the javascript to be completely ignored in XHTML. Check out the proof! IE6 users don't even bother.

Leave a comment

CAPTCHA image (Click the image to get a new one)