When developing websites, it’s good practice to separate behaviour (JavaScript) from structure and presentation using The Document Object Model (DOM). This indepth tutorial is all you’ll need in order to get a good understanding on how to do it.

Clean Up Your Page, Removing Bad Behaviour

By Luke Dingle | May 7th, 2008 |
Print This Article

Let’s work through the showInfo function.

  1. We store a reference to the div that will hold the info. This id is stored in a global variable infoDiv at the top of the script.
  2. workingDiv.innerHTML would probably be the way most would achieve the next part of the code but innerHTML is not part of the DOM specification. To emulate the innerHTML function we have to work a bit differently. Into a new variable, we clone workingDiv using cloneNode. The boolean false that is passed as an argument tells JavaScript that we want to clone the element only and not anything inside of it.
  3. Now that we have a new empty div, we insert this into the document and introduce a couple of new concepts. workingDiv.parentNode refers to the parent of workingDiv or the next level up in the document hierarchy if you wanted to you could use workingDiv.parentNode.parentNode.parentNode.parentNode to refer through all parents to the <html> element. workingDiv.parentNode.insertBefore(emptyDiv, workingDiv) is a function that will insert a the first argument node or element directly before the second node or element passed to the function. Now we have the same div as before (because we cloned it) inserted before the old one.
  4. Now that we have two nodes, we need to remove the old one from the document so again we refer to the parent node of workingDiv and run the removeChild function passing workingDiv as an argument. workingDiv no longer exists in the document and we are left with just the emptyDiv that was inserted in step 3.
  5. Because the DOM works on document hierarchy, it’s not a simple matter of adding text inside emptyDiv we need to give emptyDiv a child. In this case we will create a text node using createTextNode out of the text in the title attribute. We then use appendChild to add the text node as a child of emptyDiv!

hideInfo is exactly the same as showInfo except for step 5 we clear the text out of the document onmouseout.☺

So you’re probably starting to see that there aren’t many limits on what can be done without a single line of code inside the HTML.

Let’s look at another method of isolating a group of elements.

I want users to know when they will be leaving my page. In order to flag this, I give them a confirm message whenever they click a link to an external page. (I wouldn’t do this on a real site unless you wanted to annoy your users ☺ ). This next method will find all the links on the page and add the confirm function to any link that has a class of “external”.

Add the below code just above the last } in the initiatePage function.

// loop through and check if the class name contains externalFlag
	// it will add a confirm message if it does...
	nm = links.length;

	for (i=0; i< nm; i++)
	{
	   if (links[i].className.indexOf(externalFlag) != -1)
	   links[i].onclick = function () { return confirm(message);};
	}

See results at : www.lukedingle.com/scripts/dom.php?getCode

This is as simple as it gets really. Get all the links, check their className for the external link flag and add a confirm message to it if it is found.

As you can see now, our page has a lot of JavaScript going on and we haven’t written a single line into the HTML page yet.

Hierarchy Acrobatics and Elements on the Fly

Now that you can access any element you want inside of a document, let’s have a look at some more DOM properties and methods you can use to swing your way around the HTML family tree.

Some Additional Properties

  • element.firstChild: This holds a reference to the first child of the element. If element is <html> it will return a reference to <head> as it is the first child of <html>. If the element has no first child, it holds the value null. You can use firstChild an arbitrary number of times all the way down to the wee wee grandchildren.
  • element.childNodes: An array of all the child nodes inside an element. If element was <html>, this would hold all the elements in the document.
  • element.parentNode: We had a quick look at this earlier in the examples, this holds a reference to the parent node of the element. If element was <head> then parentNode would hold a reference to <html> as it is the next level up in the hierarchy. As with firstChild, this can be used an arbitrary amount of times up to the top level element <html>. If there is no parent, this will be null.
  • element.previousSibling/element.nextSibling: This holds a reference to the element that is previous/next within the document but has the same direct parent. If element was <body> then previousSibling be a reference to <head> as they are both direct descendants of <html>.

Some Additional Methods

  • document.createElement(tagName): This will create an element of type tagName. If you wanted to create a div you would usevar newDiv = document.createElement(”div”);You can then set some attributes of the new divnewDiv.setAttribute(”id”, “newDiv”);Then you can add it to the element of your choice – in this case the document.document.appendChild(newDiv);
  • element.getAttribute(attName)/element.setAttribute(attName, attVal): This will get and set attributes of an element. Although it is possible to access a lot of attributes directly, the DOM requests that you use get and set attributes in favour of the older methods.
  • element.removeChild(element): Pass a reference to an element to this method to remove it from the document.

Summing Up

I certainly hope that I have conveyed how easy the DOM can make your client-side scripting life. In the example code we have gone through, there are many elements with JavaScript applied to them using events but even without JavaScript the page is completely functional. There isn’t a single line of code amongst the HTML and the JavaScript can be re-used with little or no change in any HTML file you want.

Thanks for reading and I hope to answer your DOM questions on the Web Squeeze soon!

Here is all the JavaScript code:

Or you can download from http://www.lukedingle.com/scripts/javascript.js

// This function will be added to throughout the tutorial
// This function will be run when the a page loads and will set up
// The various things using the DOM
var backgroundColour = '#EEEEEE'; // This is the colour the background will turn on mouseover
var date = new Date();			  // a nice date object to work with

var infoDiv = 'border';			 // This is the div we will be adding text to later

var externalFlag = 'external';   // The class name given to links to external sites

var message      = 'Oh! Please don\'t leave so soon! By clicking okay, you will go to another site. Are you sure you want to?'; // Message on leaving

function initiatePage ()
{
	// Let's get a reference to the #header div in our document.
	var header = document.getElementById('header');

	// Now, we'll attach the background colour changing function
	// to the header div's onmouseover and onmouseout event handlers

	if (header != null)
	{
		header.onmouseover = changeBackground;
		header.onmouseout  = changeBackground;

		//let's get all of the links found inside the header div
		// we will add the showInfo function to the mouseover eventHandler
		// to hide the details 

		var headerLinks = header.getElementsByTagName('a');

		// count how many there are and add the function to them
		nm = headerLinks.length

		for (i=0; i<nm; i++)
		{
			headerLinks[i].onmouseover = showInfo;
			headerLinks[i].onmouseout  = hideInfo;
		}

	}

	// Get references to all of the images in the document using getElementsByTagName
	// The results are returned in an array
	var imgs = document.getElementsByTagName('img');

	// count how many images there are and loop through adding a simple onclick function
	// to alert the alt text to the user...

	nm = imgs.length;

	for (i=0; i<nm; i++)
	{
		// date.getFullYear() is using the date object declared earlier
		imgs[i].onclick = function () { alert(this.getAttribute('alt') + '\n\n \t\t(c) ' + date.getFullYear());};
	}

	// Let's get all the links and add a confirm message if it leads to an external site

	var links = document.getElementsByTagName('a');

	// loop through and check if the class name contains externalFlag
	// it will add a confirm message if it does...
	nm = links.length;

	for (i=0; i <nm; i++)
	{
	   if (links[i].className.indexOf(externalFlag) != -1)
	   links[i].onclick = function () { return confirm(message);};
	}

}

function changeBackground()
{
	if (this.style.backgroundColor == '')
	{
		this.style.backgroundColor = backgroundColour;
	} else {
		this.style.backgroundColor = '';
	}
}
function showInfo ()
{
	// Store a reference to the div that we will add the content to
	// the id is given in the global variable at the top of this script
	var workingDiv = document.getElementById(infoDiv);

	// We want to clear all the content from the div before we add the new
	// content...
	var emptyDiv = workingDiv.cloneNode(false);

	// This new empty div now goes before the old one

	workingDiv.parentNode.insertBefore(emptyDiv, workingDiv);

	// Now get rid of the old one all together

	workingDiv.parentNode.removeChild(workingDiv);

	// Insert the new text into the new div

	emptyDiv.appendChild(document.createTextNode(this.getAttribute('title')));

}
function hideInfo ()
{
	// Store a reference to the div that we will add the content to
	// the id is given in the global variable at the top of this script
	var workingDiv = document.getElementById(infoDiv);

	// We want to clear all the content from the div before we add the new
	// content...
	var emptyDiv = workingDiv.cloneNode(false);

	// This new empty div now goes before the old one

	workingDiv.parentNode.insertBefore(emptyDiv, workingDiv);

	// Now get rid of the old one all together

	workingDiv.parentNode.removeChild(workingDiv);
}
// Attach the initiatePage function to the onload event handler of the window object
window.onload = initiatePage;

Pages: 1 2 3

About The Author

Article By: Luke Dingle
Luke Dingle

Luke Dingle is a professional web developer working in Tasmania, Australia. Although much of his time revolves around writing, then re-writing PHP and JavaScript code for others, he manages to find time to work on pet projects like http://www.openthource.com and http://www.lukedingle.com. Luke likes to juggle and play piano but usually runs out of time as his attempts to lobby the government for 3 extra hours in each day have so far failed.

You can view other posts by Luke Dingle. Or you can visit Luke's website at: http://www.lukedingle.com

Comments

  1. Alex said :

    I found your site on technorati and read a few of your other posts. Keep up the good work. I just added your RSS feed to my Google News Reader. Looking forward to reading more from you down the road!

  2. Alex said :

    Your blog is interesting!

    Keep up the good work!

  3. Luke Dingle said :

    Hey Alex,

    Glad you like what we’re doing here. Hopefully we’ll keep feeding you the good stuff through RSS.

Trackbacks

  1. y coded
  2. jQuery - Why Wouldn’t You?

Do you have something to say?