DOM Design Tricks III: Using Events in the Document Object Model

Dynamic Text in the Document Object Model#section1

In this tutorial, we’ll learn how to enhance content by dynamically changing text on a page. Take a look at the example below and move your mouse over the Spanish text and click the bold words. The example will work in Mozilla and IE5.

Article Continues Below

La primera fuente para conseguir el sistema Linux es la propia red Internet, y es donde estarán siempre las últimas versiones y las aplicaciones más actualizadas en muchos servidores de FTP anónimo. Otra vía muy frecuente, de interés para principiantes y para quienes no deseen o no puedan permitirse copiar tanta cantidad de información a traves de la red, es mediante las versiones comercializadas en CDROM.

Show full translation

Click any bold word or phrase to see its meaning.
spanish
english

The primary source for obtaining the Linux system is the Internet itself, and it is where the latest versions and most current applications will be on many anonymous FTP servers. Another method, very frequently of interest to beginners or for those who don’t want or might not be allowed to copy such a quantity of information over the net, is by means of commercial versions on CDROM.

Click any bold word or phrase at the left to see its meaning.

If you look at the source code for the left side, you’ll see something like this:

  La primera <span id="s0">fuente</span> para 
  <span id="s1">conseguir</span>
  el sistema Linux es <span id="s2">la propia red</span>

  Internet, y es donde 

There are no <b> tags, since we’ve used the knowledge from the first tutorial to set that property from JavaScript. Similarly, there are no onMouseOver, onMouseOut, or onClick attributes anywhere. Instead, a JavaScript function adds event listeners to each <span> as we did in the previous tutorial.

The Dynamic <div>#section3

    <div id="instructionDiv">
    Click any bold word or phrase to see its meaning.
    </div>

    <div id="fullDiv">

    <p>
    The primary source for obtaining the Linux system is
    the Internet itself, and it is where the latest...
    ...versions on CDROM.
    </p>
    </div>

    <div id="glossDiv">
    <dl id="dlist">

    <dt id="dterm">spanish</dt>
    <dd id="ddefn">english</dd>
    </dl>
    </div>

The first two <div>s are no surprise; they’re needed for the initial instructions and the full translation. The real surprise is the <div> with the id="glossDiv". You might have thought that the HTML would need sixteen different <div>s, one for each of the words to be translated. Instead, we have only one <div>, and it is just a placeholder. What we’re going to do is replace the words spanish and english with the appropriate text on the fly. To do this, we first have to review the concept of nodes.

Review of Nodes#section4

As we saw in the previous tutorial, when CSS-compliant browsers read an HTML file, they analyze its structure and create a structure of nodes which you can manipulate. The HTML below produces the structure shown in the diagram.

<body>
<p>
   First Text
   <img src="picture.png">
   <i>More Text</i>
</p>
</body>

tree diagram of HTML

In the previous tutorial, we only read information from our document’s tree in order to find out which <span> had been clicked. Now we’re going to modify the document structure on the fly.

Modifying a Node#section5

In order to modify the definition list in our vocabulary example, we will use these functions:

document.createTextNode("node contents");
document.replaceChild(new_node, old_node);

The createTextNode function will create a new text node with the contents that you specify.

The replaceChild function puts the new node that you specify in place of the old node. There are two important things to know about this function.

  1. The new node comes first, then the old node.
  2. You should always use this function rather than directly assigning the nodes yourself. As you saw on the previous page, there are a lot of links among nodes, and the replaceChild function makes sure that they are all properly maintained. For example, if you have <div id="myDiv">, and you want to replace its lastChild node by some different text, you should do it like this:
    var myDiv = document.getElementById("myDiv");
    var newNode = document.createTextNode("different text");
    document.replaceChild( newNode, myDiv.lastChild );  

    Do not do this:

    var myDiv = document.getElementById("myDiv");
    var newNode = document.createTextNode("different text");
    myDiv.lastChild = newNode; /* NO! NO! NO! */

Armed with this information, we can now write the gloss() function.

The gloss() function#section6

We first create a list of the English translations for each glossary term. A list of Spanish words isn’t necessary; we’ll see why later.

vocabList = new Array("source","obtain",..."by means of",
"through (by means of)");

We use this array in the gloss() function, which is shown below. The line numbers are just for reference in the explanation.

1 function gloss(evt)
2  {
3   var defnList = document.getElementById( "dlist" );
4   var defnTerm = document.getElementById( "dterm" );
5   var defnData = document.getElementById( "ddefn" );
6   var glossDiv = document.getElementById( "glossDiv" );
7   var instrDiv = document.getElementById( "instructionDiv" );
8   var fullDiv = document.getElementById( "fullDiv" );
9   var owner = findOwner( evt );
10  var spanId = owner.attributes.getNamedItem("id").nodeValue;
11  spanId = parseInt( spanId.substr(1));
12
13  instrDiv.style.display = "none";
14  fullDiv.style.display = "none";
15  
16  defnTerm.replaceChild(
17         document.createTextNode( evt.target.data ),
18         defnTerm.firstChild );
19
20  defnData.replaceChild(
21         document.createTextNode( vocabList[spanId] ),
22         defnData.firstChild );
23
24  glossDiv.style.display = "block";
25 }  
Lines 3-8
Get references to all the <div>s that we’ll need
Lines 9-11
Determine which <span> was clicked, and extract its number from the id.
Lines 13-14
Make sure that the instructions and the full translation are hidden.
Lines 16-18
Replace the text in the <dt> tag’s first child by a new text node, whose contents are the same as the data in the <span> that we clicked. We do this for two reasons: first, it means we don’t have to make an array to hold the Spanish terms — we just take them straight from the HTML. Second, creating a text node with the “ampersand-notation” (like &ntilde;) doesn’t work properly in Mozilla.
Lines 20-22
Replace the text in the <dd> tag’s first child by a new text node whose contents are the appropriate English term from the vocabList array.
Line 24
Make the <div> that contains the definition list visible.

A Philosophical Interlude#section7

Before proceeding to the last example of dynamic text, there’s an issue that we need to address. Those of you who have been using MicrosoftTM®© Internet ExplorerTM®© to do dynamic HTML are probably asking:

“Why do I need to go to all this trouble with nodes and children? All I need to do in Internet Explorer is modify the innerText or innerHTML property to get the same effect.”

Two reasons, and these are personal opinions, by the way, so take them for what they’re worth:

  1. The innerText and innerHTML properties are Microsoft only and non-standard. I prefer to stick with standards that are agreed upon by the World Wide Web Consortium, because I know they’ll work in any browser, on any platform, that conforms to those standards. This will become important in the future, when PDAs (Personal Digital Assistants) and “web tablets” start to become popular. The smaller ones may not have the memory capacity or speed to handle all the varieties of non-standard extensions that have been made to HTML; the trend appears to be that these devices will be standards-compliant.
  2. The very name innerHTML implies that it is tied to HTML. The Document Object Model, however, is generic. It applies not only to HTML documents, but also to XML documents. The knowledge acquired in manipulating the DOM with HTML will be immediately transferable to this new, up-and-coming technology.

End of sermon. Now, on to an example that shows the power of being able to use the DOM to dynamically modify a document.

Summary: A Complex Example#section8

The previous pages show a simple, yet useful effect that you can achieve by manipulating a document’s nodes dynamically. It takes some investment of time to learn the techniques, but, as you can see, they’re well worth it. We’ll leave you with this fairly complex example that shows what you can do when you do some fairly heavy-duty manipulation of the node tree.

Note that we aren’t just replacing the text when the list gets sorted – we’re creating bold text elements for the sorted column. This makes the code non-trivial, so we won’t do a full analysis of it here. However, if you want to see how it was done, view this source code page if you’re using Mozilla, or this one if you’re using IE. (Why two different versions of the same source? Because IE occasionally displays text files as HTML.)

Click the blue arrows to select a column to sort, and the order in which to sort it. Up arrows put the highest item at the top; down arrows put the lowest item at the top.

International Weather Reports#section9

sort descending
City
sort ascending
sort descending
High
sort ascending
sort descending
Low
sort ascending
Bangkok 91 75
Cairo 97 72
Helsinki 59 48
Mexico City 72 57
Sydney 57 46
Temperatures are shown in Fahrenheit.

No Comments

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career