Hypermedia Production, Fall 1998
Dynamic HTML

1. Overview

The latest development in Hypertext Markup Language is the proposed HTML-4 standard, also known as Dynamic HTML or DHTML. Strictly speaking, DHTML consists of a Document Object Model combined with Cascading Style Sheets and a scripting language. The term "dynamic" refers to a basic shift in the nature of Web pages. Up to now, pages have been static or "stateless" documents: once the page transfers from the server, its contents cannot be altered. Developments such as CGI/forms, JavaScript, Java, and plugins have chipped away at this statelessness, but mainly these innovations are confined to small regions of the page. Most ordinary markup elements remain the electronic equivalent of printed type, fixed and immutable.

This limitation disappears under DHTML. Browsers that support DHTML (at the moment, only Microsoft Internet Explorer 4) understand the page as a set of elements or objects whose properties conform to the Document Object Model. Behavior and appearance of objects may be modified through scripting. For starters this means that the ubiquitous "rollover" effect, which in HTML-3 applies only to <IMG> and <AREA> tags, extends to virtually all HTML elements. Paragraphs, headings, horizontal rules, table cells, and other components can all be assigned script handlers. Changes applied through scripts are reflected instantly, without having to reload the page from the server.

The Document Object Model was proposed by the World Wide Web Consortium as an industry standard, but Netscape Communications initially proposed an alternative solution, based on a special <LAYER> container implemented in its 4th-generation browser. Layers did not catch on, partly because Microsoft's browsers don't recognize them. Netscape has withdrawn support for the concept. This week Netscape announced it will fully support the Document Object Model and other aspects of DHTML in Navigator 5.0, due in beta next month (December, 1998).

At the moment DHTML is still embroiled in "browser war" hostilities. Microsoft provides the best implementation of the Document Object Model but wants us to depend on Visual Basic Script (VBScript) and Windows-only ActiveX controls, assuming that all PCs should run Windows. Netscape meanwhile has wasted time pushing inferior alternatives to the Object Model and Style Sheets. These troubles will fade away eventually (and be replaced by new ones), but for the moment we have to pick and choose. I'll be using the Macintosh version of Internet Explorer 4.01 to demonstrate DHTML, but will follow industry practice in choosing JavaScript over VBScript. Likewise, I will not show any effects dependent on ActiveX controls. Both VBScript and ActiveX are covered in Powers in case you're interested.

2. "Exposing" markup elements

The Document Object Model lets you name any element on the page and refer to it by that name. This is called "exposing" the element to script control. Suppose you want to connect the first paragraph on your page to a certain scripted function:

    <P ID="firstPara" onClick="doSomething()">Paragraph text here</P>

The ID attribute gives this paragraph a name, in much the same way that the NAME attribute works with images and frames or the CLASS attribute in Style Sheets. Note, though, that you cannot substitute CLASS for ID in DHTML.

In the Document Object Model the <P> tag accepts a JavaScript handler called onClick. This handler refers to a JavaScript function defined in the <HEAD> container or some other suitable place. Other familiar handlers, such as onMouseOver and onMouseOut, are also implemented.

3. The STYLE object

Among the most important aspects of the Document Object Model is the STYLE object. This object contains and controls information about all display features of a given markup element that are affected by Cascading Style Sheets (which is how Style Sheets come into DHTML). For example, to change the text color of my paragraph above, I would include the following statement in the JavaScript function doSomething():

    document.all.firstPara.style.color="#FF0000";

As you can see, firstPara is subordinated to two other objects (actually, one object and another thing Microsoft calls a "collection"). The full specification is optional. As long as frames are not involved, we can trim the statement down to:

    firstPara.style.color="#FF0000";

4. The innerText property

You can make even more powerful transformations on most HTML elements using the Document Object Model. If your page element consists of a span of text contained within a pair of markup tags -- for instance, a paragraph, a table cell, a heading, a SPAN or DIV, or even the entire BODY of the document -- you can use the innerText property to operate on this text. Here's an example:

    <P ID="testPara" onClick="nextText()">Note that the text presented here flows in-line with the paragraph tags. Line breaks upset the function of innerText.</P>

Here's the relevant JavaScript function:

    function nextText()
    {
    testPara.innerText="Enough said.";
    }

When the user clicks anywhere in the original paragraph, the text changes to the simple sentence, "Enough said." The rest of the text on the page will adjust to fill in the gap.

Pay attention to what the original text says in the example above: changing innerText replaces all the text between two paired tags. If you insert a line break into this sequence, the function may not behave properly. Note also that you have to use the </P> tag, as always, to complete the paragraph unit.

5. The innerHTML property The innerText property only affects text -- that is, anything not contained within <angle brackets>. However, the Document Object Model lets you change markup as well as text by referring to a more powerful replacement property, innerHTML. This property affects all text and tags that fall between paired tags. Here's an illustration:

    <SPAN ID="outasite" onClick="doSomething()">
    <P>This is an important point</P>
    </SPAN>

Here's the corresponding JavaScript:

    function doSomething()
    {
    outasite.innerHTML="<H1>It's really important!</H1>";
    }

When the user clicks on the phrase, "This is an important point," that phrase changes both in wording and appearance, going from ordinary paragraph type to an H1 heading. Note however that the <SPAN> container remains unaffected, since it's in the "outer" part of the HTML here. It still has the same ID and handler.

As you may have guessed, there is also an outerHTML property. This one replaces everything in the container including its paired tags. Be careful with this property. Since the first tag of the container holds the ID attribute that identifies the container to JavaScript, manipulating outerHTML can make your script a dead end: if you replace the tag containing the ID with a tag that does not contain the ID, the container is no longer exposed to scripting.

6. Visibility, Display, and "Stretchtext"

The style object possesses two other properties quite useful in controlling the appearance of your page: visibility and display. Visibility has two possible values, hidden and visible. In the first case the page element in question does not appear, though space is reserved for it in the layout. Newspapers under totalitarian regimes sometimes run blanks in their columns to protest state censorship, as if to say, "you could be reading something here but the government won't let you." Setting visibility to "hidden" produces a similar effect, though usually without political overtones.

Display is more useful. Its possible values, awkwardly, are none and "" (or null). That's right: if the display of an element has been set to "none", you must reset the display property to "" in order to make it appear. Why didn't the programmers use more sensible values, such as hide/show or false/true? Well, average I.Q. at Microsoft is 128, and genius is as genius does... especially when it's smug, lazy, and overpaid. Anyway, unlike visibility, the display property does not reserve blank space for invisible elements. If you reset an element's display property from "none" to "", the layout of your page will be redrawn to accommodate the new material. That is, the page "stretches" to admit more content.

This technique allows us to create something that Ted Nelson, prophet of hypertext, called "stretchtext:" a kind of writing in which hotspots or link cues indicate places where the text can be amplified and expanded (or alternatively, trimmed and truncated). You'll find a demonstration of stretchtext on the class Web site. The first option for the final project invites you to do something creative or otherwise interesting along these lines.

7. Positioning and animation

Since DHTML essentially combines scripting and style sheets, you won't be surprised to learn that you can use DHTML to control positioning both absolutely and relatively. There's a catch, though. The following example does not work:

    <P style="position: absolute; top: 100px; left: 5px" ID="wrong">
    This code does NOT put my text where I want it.</P>

This is because the Document Object Model does not allow positioning of the <P> tag. DHTML positioning is only available for our two old friends, <SPAN> and <DIV>. So here's an easy fix for the problem above:

    <SPAN style="position: absolute; top: 100px; left: 5px" ID="bingo">
    <P>My text goes exactly where I say it goes.</P>
    </SPAN>

Since you can place anything you want within a <SPAN> container, there's really no constraint on positioning.

But the examples above use only CSS; where does DHTML (including scripting and the Object Model) come into play? Well, let's say you want to move that span of yours...

    var sinister=5;
    function drifter()
    {
    sinister = sinister+10;
    bingo.style.posLeft=sinister;
    if(sinister<400) setTimeout("drifter()", 1);
    }

The script shown here assumes an onClick handler inserted into the <SPAN> container above, calling the drifter() function which is defined within a <SCRIPT> container in the <HEAD> of the page. The variable sinister is initialized to 5 because it represents the left position of the span, and that position has been set to 5 in the in-line style sheet. The logic of the script is simple: the counter variable is increased by 10 (in order to speed up the motion; smaller increments produce slower but smoother action). This value is plugged into the posLeft property of the style object of bingo. Finally, the value of the counter variable is tested against a limit; if it is below the limit, the function recusively calls itself. The one-millisecond delay is pro forma: remember that JavaScript functions can't safely call themselves without a delay.

This example shows just how "dynamic" DHTML can get; but even so, it's probably not a good idea to use DHTML for animations. As you'll see on this week's demo page, DHTML animations are crude and jerky. Flash, Director, Quicktime, and even animated GIF provide far superior support for motion.