Web DevCenter    
 Published on Web DevCenter (http://www.oreillynet.com/javascript/)
 See this if you're having trouble printing code examples


Dynamic Content with DOM-2 (Part II of II)

by Scott Andrew LePera and Apple Developer Connection
09/07/2001

In Part I we introduced portions of the Document Object Model (DOM), which provides a scriptable interface for a document structure. With the DOM, an HTML document is described as a series of nodes, each node representing an object in the document, including all text, tags, comments, and other data. Altering these nodes through JavaScript, a developer can alter the visual display of the page in a browser. If you read the last article you know how to use DOM methods to create, insert, and remove elements and text nodes from the page.

This article dives a little deeper into the JavaScript node interface and examines the different ways of altering the visible properties of an element or text node. You'll first learn how to alter element attributes with DOM element methods, then you'll see how to change an element's style properties through the DOM Level 2 (DOM2) Style specification interface.

Getting an Element Reference

Before you use the DOM interface to manipulate element nodes, you will need to get a reference to the element with which you want to work. By "reference" I mean a variable that points to the correct object in the page. You may already be familiar with document.images, document.forms, and other collections available in most browsers. These collections are groups of references to objects within the page. If you needed a reference to an image with the NAME attribute of imgHeader, you could use the images collection to grab the correct element by its name:

var img = document.images["imgHeader"];

However, these collections are only available to a subset of a page's elements. For example, there is no document.tables or document.paragraphs collection that allows you to get references to those classes of elements.

Fortunately, the DOM2 interface provides two methods to help get a hold of any element (and hold onto it tightly -- believe me, elements can be slippery). These two methods are:

Thus, to get a reference to a table element with an ID of "tableMain", you could use the following line of JavaScript:

var table = document.getElementById("tableMain");

The variable table should now contain a reference to the appropriate table. getElementById() assumes the element in question has an ID attribute to match against. If no element with a matching ID is found, getElementById returns a null value.

It's important to realize that the NAME attribute of an element is not the same as its ID. For example, if you're in the habit of assigning NAME attributes to your image tags, you cannot access them with getElementById unless you also include an ID attribute. It's perfectly fine to have elements with identical NAME and ID values.

getElementsByTagName() is useful for situations where you need references to all elements of a particular type. This method returns a collection containing a reference to each matching element it finds. For example, if you we wanted to count the number of table cells in the page, you could use something like the following code:

var allTDs = document.getElementsByTagName("td");
alert("# of table cells: " + allTDs.length);

Try it out. Click the button below to use getElementsByTagName() to count the number of table cells in this page.

To get a particular element reference in the collection, use the collection's item() method, which returns a reference to the element at the specified index. If you wanted to get a reference to the first and last table cells in the collection, you could use this:

var allTDs = document.getElementsByTagName("td");
var firstTD = allTDs.item(0).id;
var lastTD = allTDs.item(allTDs.length-1).id;
var str = "# of table cells: " + allTDs.length + "\n";
str += "First TD: " + firstTD + "\n";
str += "Last TD: " + lastTD;
alert(str);

Previously in this series:

Dynamic Content with DOM-2 (Part I of II)

Comment on this articleIs DOM-2 supported by enough browsers for you to begin using its functionality? Or will you continue to rely on other tools for dynamic content?
Post your comments

The advantage of using item() instead of directly referencing the slot in the collection is that item() returns a null value if the index supplied is invalid or the element in question is not within the collection. This is often more desirable than the error message you might get when referencing a nonexistent slot in the collection.

getElementsByTagName() is also a method of every element, which means you can retrieve a collection of references to all elements within a particular element. The following code uses getElementsByTagName() at the element level to retrieve references to all images within a table:

var table = document.getElementById("myTable");
var imgs = table.getElementsByTagName("img");

Once you have an element reference, you can manipulate its properties.

Reading and Setting Element Attributes

Related Reading

JavaScript: The Definitive Guide, 4th EditionJavaScript: The Definitive Guide, 4th Edition
By David Flanagan
Table of Contents
Index
Sample Chapter
Full Description

Element tag attributes are translated by the browser into properties of the object (the reference you've created). The DOM interface provides each element with two methods for reading and setting these attribute values:

I often like to use a utility function to inspect an element and see the properties and methods attached to it. The inspect() function seen below uses getElementById() to retrieve a reference to the element and launch an alert box containing a list of the element properties. The string of properties and values is assembled using getAttribute() to retrieve the value of each named property.

function inspect(elm){
  var str = "";
  for (var i in elm){
    str += i + ": " + elm.getAttribute(i) + "\n";
  }
  alert(str);
}

To use the inspect() function to examine a table element, simply pass the table element to the function:

table = document.getElementById("tableMain");
inspect(table);

Want to see it in action? Click the button to inspect the table below.

one two three
four five six
seven eight nine


Setting new element properties can be done with the setAttribute() method. Just pass the name and the value of the attribute you want to set. Note that both parameters must be strings, so even numeric values must be within quotes. To readjust the width of a table to 400 pixels, you can employ the following code:

var table = document.getElementById("tableMain");
table.setAttribute("width","400");

The following example uses setAttribute() and the changeSize() to assign different values to this table's WIDTH attribute.

function changeSize(px){
   var table = document.getElementById("tableMain2");
   table.setAttribute("width",px);
}
one two three
four five six
seven eight nine


If no attribute of the specified name exists for the element, setAttribute() will create a new one. There's really no inherent advantage to using setAttribute() over directly setting the value via JavaScript. The following two statements essentially accomplish the same thing:

table.setAttribute("border","2");

table.border = 2;

To prevent new attributes from being set where you don't want them, you can use the element method hasAttribute() to test for the existence of the named attribute. hasAttribute() returns either true or false depending upon whether the element possesses the attribute or not.

var table = document.getElementById("tableMain");
if (table.hasAttribute("border")){
  table.setAttribute("border","2");
} else {
  alert("Table has no border");
}

It should be noted that hasAttribute() is supported in Netscape 6/Mozilla, but not IE5 at the time this article was composed.

Manipulating Element Styles

So far, I've only talked about manipulating element attributes. Often, an element will employ CSS to give it a particular style or formatting. Altering the CSS properties of an element requires a similar yet slightly different approach.

The DOM specification provides another interface called DOM Level 2 Style, which is for manipulating the CSS properties of an element. Each CSS rule for an element is represented as a property of the element's style object.

Because style is an object, we can examine its properties with a function similar to inspect(), above. The inspectStyle() function below checks the element in question for a style object before proceeding to inspect its values. As described Modifying Styles, a bug in the current releases of Netscape 6 and Mozilla prevents CSS rules in an inline stylesheet from populating the style object correctly in those browsers. So for the sake of this demonstration, all element CSS has been defined within the tags themselves via the STYLE attribute.

function inspectStyle(elm){
  if (elm.style){
    var str = "";
    for (var i in elm.style){
	  str += i + ": " + elm.style[i] + "\n";
	}
	alert(str);
  }
}

var header = document.getElementById("h2");
inspectStyle(header);

Click the button below to view the style properties of the H2 element below. Note: some users of IE 5.1 Preview for Mac OS X have expirenced problems with this script.

Headline Here

You'll notice that many of the style properties are empty, since we haven't defined them to be otherwise. You can set style properties directly. To read and then set the background color of an HTML page (or specifically, the background color of the BODY element):

var doc = document.getElementsByTagName("body").item(0);
var color = doc.style.backgroundColor;
alert ("Background color is: " + color);

doc.style.backgroundColor = "#0000ff";

Manipulating the CSS properties of elements is key to DHTML functionality. For example, you can use JavaScript to change the table's LEFT and BACKGROUND-COLOR CSS properties, thus changing its color and position on the page. Try it out:

one two three
four five six
seven eight nine


Change Position

Change Color:

Here's the JavaScript that makes it happen. In all cases, the table ID, tableMain3 is passed to getElementById() in order to get a reference to the table element. The new CSS property value is assigned directly to the style object.

<span class="sourcecode">
<script language="JavaScript" type="text/javascript">
  function tableRight(){
    var table = document.getElementById("tableMain3");
    table.style.left = "100px";
  }
  function tableLeft(){
    var table = document.getElementById("tableMain3");
    table.style.left = "0px";
  }
  function changeTColor(col){
    var table = document.getElementById("tableMain3");
    table.style.backgroundColor = col;
  }

To get the name of the scriptable style property, take the original style rule from the CSS declaration and capitalize the first letter following each hyphen, then remove the hyphens altogether. The following table contains a few examples:

CSS property JavaScript equivalent
background-color style.backgroundColor
font-size style.fontSize
left style.left
border-top-width style.borderTopWidth

From Here

This concludes our brief tour of the Document Object Model. We've touched on some of the more exciting features of the DOM, including dynamic element creation and setting element attributes and CSS properties through JavaScript. The DOM interface has many more features we didn't explore in these articles; I encourage you to check out the specification at the W3C site, specifically the ECMAScript bindings pages which describe the DOM Level 2 Core and Style scripting interface in more detail. Be sure to check your browser's documentation to see what DOM features it supports.

Scott Andrew LePera lives in San Francisco, where he ekes out a schizoid existence as both a web applications developer for KnowNow and a frustrated urban folk singer.

Previously in this series:

Dynamic Content with DOM-2 (Part I of II) -- The DOM-2 is supported in both Mac IE5 and NS6, and it provides an interface that enables developers to generate dynamic content without being limited to JavaScript trickery. This article explores some of the basic functionality of DOM-2.


Return to the JavaScript and CSS DevCenter.

Copyright © 2009 O'Reilly Media, Inc.