A List Apart

Menu
Issue № 60

Meet the DOM

by Published in Browsers, CSS, HTML, JavaScript

These pages summarize information I’ve discovered while experimenting with Netscape® 6 (in the form of Mozilla release 14 on Linux®). The information is intended for people who are already familiar with using JavaScript to manipulate dynamic HTML elements. However, if you’re one of those folks who has been adding JavaScript to pages by copying code and tweaking it, the first topic gives you a very cursory introduction to the Document Object Model.

Review of the Document Object Model

At first glance, people look at web pages as though they are pages in a book, consisting of static text and images. It soon becomes apparent that there are things with which you can interact, such as links and forms. In fact, pages aren’t static “paintings,” but are actually built up out of parts.

Let’s take a “real world” example of a radio, which is made up of parts:

  •   Radio
    •    Volume dial  
    •    Tuner dial  
    •    Power Supply  
    •    Speaker  

Each of these parts has properties which describe it, and methods, or things that it can do. For example:

                 
   Object      Properties      Methods  
   Volume dial      minimum setting   
   maximum setting  
   Set volume to a specified level  
   Power Supply      voltage      Turn on   
   Turn off  

An HTML document you might be made of “spare parts”, as follows:

  • Document
    •    images [0] (French flag)  
    •    images [1] (Spanish flag)  
    •    Forms [0]
         
      •    Elements[0] (input area 1)   
      •  
      •    Elements[1] (input area 2)   
      •  
      •    Elements[2] (button)   
      •  

Where did this image go?

Screenshot of HTML page

—>

Each of these parts also has   properties which describe it, and   methods, or things that it can do. In the case of the parts that make up your page, here’s a brief list:

                       
   Object      Properties      Methods  
   image      src (URL for image)   
   align (left, right, etc.)  
      (see below)  
   form      action   
   target  
   submit()   
   reset()  
   input text element      value   
   size  
   focus()  

You may have noticed that the properties of these objects correspond nicely with the attributes of the <img>, <form>, or <input type=“text”> tags.

Note: the   img tag does have methods, but none that I care to mention in this brief review.

This, then, is the Document Object Model (DOM); just as we could model a real-world object like a radio as a set of objects that we assemble, so we model our document as a set of HTML objects that the browser puts together.

In the case of modeling an HTML document, we have to decide:

  •   which objects can be manipulated in JavaScript?
  •   how are the objects “nested”?

In earlier versions of some browsers, the model said that you could manipulate input areas in a form, but that the images on your page weren’t objects that you could get to from JavaScript. In the latest browsers, not only can you access the images and the input areas in a form, you can change the text between any two tags, or even change the attributes on virtually any tag.

The other design issue is to decide how the objects   nest inside one another, and what the property names and method names ought to be. (Should an element’s background color property be called   bgColor or   backgroundColor? Is it a property of the document as a whole, or just of the   <body> tag?)

At this moment, there are three different Document Object Models:

  1.   The Netscape Navigator model
  2.   The Internet Explorer model
  3.   The World Wide Web Consortium standard model

Netscape 6 (Mozilla), Internet Explorer 5 (Macintosh), and Opera all implement– or purport to implement– the World Wide Web consortium’s Document Object Model. The remainder of these pages investigate how we work with the DOM in Netscape 6 (Mozilla).

Showing Properties

  Showing Properties Examples

The divisions above were produced by these in-line style sheets for the first and third divisions:

...and this style sheet (for the second and third divisions)

<style type="text/css">
#d2 {
   visibility: visible;
   background-color: #ccccff;
   position: absolute;
   top: 10px; left: 110px;
   width: 100px; height:100px;
}#d4 {
   position: absolute;
   top: 10px; left: 210px;
}
</style>

Let’s take a look at some of the properties of these three

s.

Where Properties Reside

Let’s look at the properties of the three divisions above. The values you see in the table below were extracted using   this script. A   “” means that the browser returned the null string for that particular property.

                                                                                       
          Property      Navigator 4      Explorer 5      Mozilla  
      Div one      visibility      inherit      inherit      inherit  
   background-color      null      #ccffcc      rgb(204,255,204)  
   left, top, width, height      10, 10, undefined, undefined      10px, 10px, 100px, 100px      10px, 10px, 100px, 100px  
      Div two      visibility      show      show      show  
   background-color      null      null      null  
   left, top, width, height      110, 10, undefined, undefined      110, 10, undefined, undefined      110, 10, undefined, undefined  
      Div three      visibility      inherit      inherit      inherit  
   background-color      null      cyan      cyan  
   left, top, width, height      210, 10, undefined, undefined      210, 10, undefined, undefined      210, 10, undefined, undefined  

First, we note that there’s a large difference between Navigator 4 and the other browsers. In Navigator 4, the location of a

is a simple number; in the others, it’s measured in pixels (px).

Explorer and Mozilla give closely matching results, except for background color. Looking at

one, we see that Explorer displays a color originally expressed as hexadecimal in hex; Mozilla displays it in   rgb format using decimal equivalents. Colors entered as names stay as names.

Concentrating on Mozilla, let’s look more closely at the properties detected and the HTML that produced the styles. When we retrieve, say, division one’s style object with this [removed]

{Line wraps are marked thusly: ». – Ed.}

styleObject = »
  document.getElementById( "d1" ).style;

we get the style object that’s attached to the tag. The style information defined in the stylesheet is not “merged” in with the information, as was the case in Navigator 4.

Table 1 shows the relevant properties and associated HTML.

If we needed to use DHTML and JavaScript on only one page, this wouldn’t be a problem. We’d simply put all the style information into the tags and have it at our disposal.

What do we do if we have several pages that use the same styles and JavaScript?

Using Properties on Multiple Pages

When we have several pages using the same styles and JavaScript, we can:

1. Duplicate the styles into the tags on all the pages

This strategy will certainly work, but it defeats the purpose of style sheets - the ability to separate style from content.

2. Use JavaScript to set initial conditions

We could set all the

s to be invisible in the style sheet, and then explicitly set all the initial style attributes from a shared JavaScript .js file. This is a reasonable solution when every page starts out in the same initial state.

3. Access Style Objects in a Stylesheet

If we can find a way to access the styles that are in the stylesheet, we have the greatest flexibility; we can use a style across multiple pages, and, since we can access them from JavaScript, we can read the initial conditions rather than use fixed code to set them.

Accessing Style Sheets

From Mozilla, it’s possible to access all the style sheets. Starting from the document, here’s the hierarchy for accessing a particular style within a stylesheet:

  • styleSheets (list)
    • href (property)
    • cssRules (list)
         
      • type (property)
      •  
      • selectorText (property)
      •  
      • style (property)
      •  

Filling in some details on the properties:

href
The URL of the stylesheet
type
An integer telling which type of rule this is. The only ones we’re interested in are the ones of type CSSRule.STYLE_RULE.
selectorText
style
The selector and the style.  In the following stylesheet rule:
p {color:blue; font-size:24pt;}

the selectorText would be the string p and the style would be an object corresponding to the properties in the braces.

JavaScript Access to Style Sheets

Here is the JavaScript code that will retrieve a style by its selector name. Note that it works only on Mozilla; it doesn’t appear to work properly in IE4.

   function getStyleBySelector( selector )
   {
       var sheetList = document.styleSheets;
       var ruleList;
       var i, j;
   
       /* look through stylesheets in 
        reverse order that they 
        appear in the document */
       for (i=sheetList.length-1; i >= 0; i--)
       {
           ruleList = sheetList.cssRules;
           for (j=0; j»
                CSSRule.STYLE_RULE »
                && »
                ruleList[j].selectorText == »
                  selector)
               {
                   return ruleList[j].style;
               }   
           }
       }
       return null;
   }

  This will work with      any     selector, so you can find the style associated with, say, the  

    tag by calling      getStyleBySelector(“h3”), the style associated with a  

    tag by calling      getStyleBySelector(“p.footnote”), or the style associated with      id=“card1”     by calling      getStyleBySelector(”#card1”).

     Note:     Mozilla M14 will not correctly find a style if it is in an imported stylesheet (using      @     notation). It causes a JavaScript error.

  Example of Style Sheet Access in JavaScript

  Here’s an example that uses      getStyleBySelector()     to dynamically change the style of a class. The text below contains warnings and features defined as clsses by the style sheet below; by clicking the buttons you can see those parts of the highlighted.

<style type="text/css">
.warning { color: black; }
.feature { color: black; }
</style>

   Blend-O-Matic   

   Thank you for choosing Blend-O-Matic as your new food processor. The Blend-O-Matic has a large variety of attachments that allow you to stir, whip, blend, and purée your foods.         We’ve even added a gentle rinse cycle for your delicate vegetables!   

   Your Blend-O-Matic requires a 110 volt AC power supply in the United States, and a 220 volt AC power supply in Europe.         A 12-volt DC adapater is included so that you can use the Blend-O-Matic in your car, although         you should not operate this device while driving or intoxicated.   

   All the metal parts are coated with Cruft-B-Gone®, making clean-up a breeze.         Do not immerse the blender in water while it is plugged in.   

   We hope you enjoy using your Blend-O-Matic as much as the grossly underpaid workers in some unnamed third world country enjoyed making it.   

<form acti></p>

   <input type=“button” value=“Toggle Features”  /><br />      <input type=“button” value=“Toggle Warnings”  /><br />

</form><br /> [removed]
     if (!isNav6)
     {
[removed]ln("

These buttons work only with Netscape 6 or " + "Mozilla.

");
}
//—>

[removed]

     JavaScript DOM Utilities   

     I have written a few utilities to work with the DOM in Mozilla. You may            see a text version of that file here.   

     Below is a listing of the function names, preceded with a brief commentary of what each one does. You may see them in action on the next page.   

/*
 * Browser version snooper; determines 
 * your browser (Navigator 4, Navigator 6, 
 * or Internet Explorer 4/5)
 */
function setBrowser()/*
 *
 * Given a selector string, return a style
 * object by searching through 
 * stylesheets. 
 * Return null if none found
 */
function getStyleBySelector( selector )/*
 *
 * Given an id and a property (as strings),
 * return the given property of that id.  
 * Navigator 6 will first look for the property 
 * in a tag; if not found, it will look 
 * through the stylesheet.
 *
 * Note: do not precede the id with a # -- it 
 * will be appended when searching the 
 * stylesheets
 *
 */
function getIdProperty( id, property )/*
 *
 * Given an id and a property (as strings), 
 * set the given property of that id to the 
 * value provided.
 *
 */
function setIdProperty( id, property, value )/*
 *
 * Move a given id to position (xValue, yValue)
 * In Navigator 6 and IE 4/5, 
 * length units are preserved.
 *
 */
function moveTo( id, x, y )/*
 *
 * Move a given id to 
 * (currentX + xValue, currentY + yValue)
 * In Navigator 6 and IE 4/5, 
 * length units are preserved.
 *
 */
function moveBy( id, x, y)/*
 *
 * Retrieve background color for a given id.
 * The value returned will be in hex format 
 * (#rrggbb)
 *
 */ 
function getBackgroundColor( id )/*
 *
 * Return a division’s document
 * 
 */
function getDocument( divName )

     CSS Property Tests   

           CSS Properties Examples (1)   

           CSS Properties Examples (2)   

     Summary   

     As these introductory examples suggest, the DOM is a remarkable tool that can make your web pages far more dynamic. And it does so without resorting to proprietary tags or “innovations” that work only in one browser. At the moment, Netscape 6 is the only browser that fully supports the DOM - and Netscape 6 is still in development. Once it’s released, it’s hard to imagine that other browsers won’t be forced to catch up.   

     As you begin to explore and work with the DOM, take time out to thank the folks at            Mozilla           for doing the heavy lifting and delivering this thing. You will also want to read up on the DOM at the W3C’s            Document Object Model           pages. And if you’d like to see all browser makers offering us this tool, consider lending your support to            The Web Standards Project, a group that wants to see W3C standards like this fully implemented in all web browsers. Meantime, code on, and have fun!   

No Comments

  1. Sorry, commenting is closed on this article.