You are here: irt.org | Articles | Dynamic HTML (DHTML) | What is So Dynamic About Dynamic HTML? [ previous next ]
Published on: Monday 27th July 1998 By: Martin Webb
Attention Mac Users:
Since DHTML and the DOM are still in the infancy of development, some of the examples in this article may crash your system if you are using MSIE4.0+.
We did our best to ensure the code was as user-friendly as possible, but there are still some incompatibility problems between what the browsers should do, and what they actually do.
Dynamic HTML, or DHTML, is not something that can easily be pointed out, or separated from other technologies. It is a group of technologies, when brought together, enable a Web developer to bring a Web page to life.
The three main technologies that make up DHTML are HTML, JavaScript and Cascading Style Sheets (CSS). HTML is used for the basic structure of the document, JavaScript to manipulate the Document Object Model (DOM), and CSS to define the presentation and style of the document.
Before version 4 browsers, it could be argued that we already had some form of DHTML with image swapping in NN3. MSIE3 supported the first version of JavaScript (i.e., JavaScript first appeared in NN2), so neither of these two browsers had support for the JavaScript Image object.
This isn't to say that these two browsers couldn't display images -- they could, but those images couldn't be manipulated. To enable images to be manipulated required two basic changes to the browsers -- a change to the DOM to add an Image object to the document structure, and the inclusion of this object within the JavaScript language.
However, the last part is not entirely true. Once an object is available in the document or window, no extra JavaScript code is required to support it. As long as the object has its own methods and properties, it can be used, manipulated, and examined using the existing JavaScript functionality.
MSIE4 is currently ahead of NN4 in its richness in the DOM. By using the the document.all object array with MSIE4, it is possible to address almost any object in a document, including images and text. Sadly, this is not the case with NN4; let's hope this is addressed in later releases of Navigator.
So what is so good about the DOM and objects? Both Microsoft and Netscape are responding to the call from Web developers for the need to be able to control more of the contents in a Web page. Until now, we've only really been able to manipulate images using the Image object, and forms using the Form object. In MSIE4, Microsoft created a whole new means of accessing all the items within a document, oddly enough by introducing an all encompassing object called all. Using the all object, it is possible to access any discrete item within a document -- right down to a single HTML tag. It is possible to access items using the identifier ID that can be optionally given to any HTML tag, for example:
<P ID="myText">This is my text<\/P>
It is then possible to access the properties of the text using the notation:
document.all('myText').propertyName
For example its possible to find out the actual text using:
var text = document.all('myText').innerText
It is also possible to access items using the index position, the following example highlights the first paragraph of a particular document:
for (var i=0; i<document.all.length; i++) { if (document.all(i).tagName == 'P') { alert(document.all(i).innerText); break; } }
One basic addition to the version 4 browsers was the ability to layer information. In DHTML-ese, layering is more commonly referred to as positioning. Layers are used to hold different documents, which can then be positioned either relative to other content or positioned absolutely on the page. The layers can also be positioned above one another using z-order, as opposed to the x and y coordinates. This means layers can overlap each other (e.g., to place text over a graphic).
The only problem with positioning is that Microsoft and Netscape have different implementations. NN4 uses the <LAYER><\/LAYER> and <ILAYER><\/ILAYER> tags, while MSIE4 uses <DIV><\/DIV> and <SPAN><\/SPAN> tags.
The downside of using LAYER and ILAYER is that they do not appear in the HTML 4.0 specification, while DIV and SPAN do. This doesn't mean you should stop using LAYER and ILAYER -- there are some things that can't be done with DIV and SPAN in NN4. This just means the DOM is more flexible in MSIE4 because DIV and SPAN have been accepted as a standard.
This article will attempt to discuss how to change the content of a document once the document has been displayed on the browser -- something that couldn't be done previously without reloading the document.
We'll show how to replace text, replace images, and replace HTML.
The DIV and SPAN tags are grouping elements that are "generic language/style container[s]." You can combine DIV or SPAN elements along with a CLASS or ID attribute to structure and style text in a document differently than the surrounding text. For example:
<STYLE TYPE="text/css"> <!-- #myDiv {font-family: sans-serif; color: red;} --> <\/STYLE> <P>This is normal paragraph text, <DIV ID="myDiv">this isn't<\/DIV> but this is. <\/P>
Click here to see how the above code is rendered in a CSS-enabled browser....
This is one important use of CSS combined with ID attributes of DIV elements. As you can see there is usually a line break before and after the DIV elements. The SPAN elements avoid this:
<STYLE TYPE="text/css"> <!-- #mySpan {font-family: sans-serif; color: red;} --> <\/STYLE> <P>This is normal paragraph text, <SPAN ID="mySpan">this isn't<\/SPAN> but this is. <\/P>
The LAYER and ILAYER elements (supported only in NN4), are used to position content in the browser, either in the horizontal, vertical, or by z-order (i.e., the stacking order). Layers can be positioned relative to the surrounding text or absolute to the top of the container of the layer. Note that layers can also contain sublayers. The document contains the top-most layers, therefore the document is the container in these instances.
They can also be used similarly to DIV and SPAN elements to structure and style the document text.
By default LAYER elements are rendered relative to the surrounding text, but they don't reserve any space in the container. For example:
<STYLE TYPE="text/css"> <!-- #myLayer {font-family: sans-serif; color: red;} --> <\/STYLE> <P>This is normal paragraph text, <LAYER ID="myLayer">this isn't<\/LAYER> but this is. <\/P>
The text "this isn't" is overlaid with the text "but this is," because the layer, myLayer, is another document. The text "this isn't" does not appear in the container document (i.e., the document the paragraph resides in). (Note if you are not using NN4 you'll not see the effect described here.) This is a different approach than that taken by the DIV and SPAN elements.
This is where the ILAYER elements come into use (ILAYER stands for "Inline Layer"). ILAYER elements reserve room in the container document for the initial contents of the layer:
<STYLE TYPE="text/css"> <!-- #myIlayer {font-family: sans-serif; color: red;} --> <\/STYLE> <P>This is normal paragraph text, <ILAYER ID="myIlayer">this isn't,<\/ILAYER> but this is. <\/P>
The three elements -- DIV, SPAN, and LAYER -- can all break out from the current relative position and float free from the container document. To do this we use the STYLE attribute to position the layer absolutely:
<... STYLE="position: absolute;" ...>
For example:
<STYLE TYPE="text/css"> <!-- #myDivAbs {font-family: sans-serif; color: red;} --> <\/STYLE> <P> This is normal paragraph text, <DIV ID="myDivAbs" STYLE="position: absolute;">this isn't<\/DIV> but this is. <\/P>
Note that the contents of the DIV elements no longer reserve the space within the container document. The text is still positioned relative to the preceeding text, as we have not yet specified the absolute location of the layer. This again can be done using the STYLE attribute, but it is outside the scope of this article. (Positioning and DHTML will be covered in a future article.)
The notation within the STYLE attribute uses the slightly different CSS notation, which require a colon (:) instead of an equal sign (=), and a semi-colon (;) instead of a comma (,) separator.
In an attempt to make the examples as generic as possible, we'll use the DIV and SPAN elements wherever possible. Where necessary, we will show how to use the LAYER elements to support on NN4 what cannot be done using just DIV or SPAN elements.
Identifying whether the current browser has support for DHTML is extremely important. We wouldn't want visitors on our sites to be put off with a lot of error messages simply because they are using an older browser. This was a common problem with image swapping scripts.
A badly written script wouldn't test to see if the browser would support image swapping, a poorly written script would check to see if the browser being used was NN3 and if so, it allowed the images to be swapped. If the script didn't detect NN3 as the browser, it wouldn't allow the images to be swapped. The problem with this approach is if the browser being used is NN4 or NN5, or another browser with Image object support. A well-written script actually detects support for the Image object directly. The following test is all that's required:
<SCRIPT LANGUAGE="JavaScript"> <!-- if (document.images) { // supports the image object } else { // does not support the image object } //--> </SCRIPT>
This technique can be carried over to version 4 browsers to detect for two new objects: document.all and document.layers. MSIE4 supports the document.all object and NN4 supports the document.layers object. Therefore, the following script will detect version 4 browsers:
<SCRIPT LANGUAGE="JavaScript"> <!-- if (document.all || document.layers) { // version 4 or greater browser } else { // not a version 4 or greater browser } //--> </SCRIPT>
It will be necessary to detect MSIE4 from NN4 as well. Therefore, the following script is sometimes more suitable:
<SCRIPT LANGUAGE="JavaScript"> <!-- if (document.all) { // MSIE4+ } else if (document.layers) { // NN4+ } else { // not a version 4 or greater browser } //--> </SCRIPT>
The following JavaScript events can be triggered by DIV (D), SPAN (S), or LAYER (L) elements:
STYLE="..." | ||||||
---|---|---|---|---|---|---|
position:relative; | position:absolute; | |||||
Event: | MSIE4 | NN4 | MSIE4 | NN4 | MSIE4 | NN4 |
onMouseOver | D S | L | D S | L | D S | L |
onMouseOut | D S | L | D S | L | D S | L |
onLoad | L | L | L | |||
onFocus | L | L | ||||
onBlur | L | L | ||||
onClick | D S | D S | D S | |||
onDblClick | D S | D S | D S | |||
onMouseDown | D S | D S | D S | |||
onMouseUp | D S | D S | D S | |||
onKeyPress | D S | |||||
onKeyDown | D S | |||||
onKeyUp | D S |
Note: The events triggered are dependent on whether the elements have a STYLE attribute set to position:absolute; or position:relative;. The only two events that are compatible with both browsers are onMouseOver and onMouseOut. However, this shouldn't stop you from using event handlers from other objects (such as forms and links) on the page from affecting the contents of a layer.
Also notice that the ILAYER elements do not trigger any events.
Due to the richness of the DOM in MSIE4 it is sometimes far easier to alter the content of a document than it is in NN4. For example, to change the color of a layer is simplicity itself in MSIE4:
<P> <DIV onMouseOver="this.style.color='red'" onMouseOut="this.style.color='black'"> Move the mouse pointer over this text</DIV> </P>
Which in MSIE4 has the following effect....
Whereas in NN4 using a LAYER tag:
<P> <LAYER onMouseOver="this.style.color='red'" onMouseOut="this.style.color='black'"> Move the mouse pointer over this text</LAYER> </P>
Which if included in this document would cause the following error in NN4:
this.style has no properties.
This is because there are no style properties for layers in NN4. Once the text has been rendered in the document it's not easy to amend it.
For example, in MSIE4 to change the text in a layer:
<P> <DIV onMouseOver="this.innerText='Ha! You moved the mouse over the text'" onMouseOut="this.innerText='Move the mouse pointer over this text'"> Move the mouse pointer over this text</DIV> </P>
Which in MSIE4 has the following effect....
Again in MSIE4 its easy to change the HTML contained in a layer:
<P> <DIV onMouseOver="this.innerHTML='Lets be <FONT SIZE=+2>big</FONT> and <B>bold</B>'" onMouseOut="this.innerText='Move the mouse pointer over this text'"> Move the mouse pointer over this text</DIV> </P>
Which in MSIE4 has the following effect....
Note how the rest of the document shifts downwards to accommodate the extra space required for the larger text.
Because NN4 does not support the innerText, outerText, innerHTML, and outerHTML properties, it is slightly harder to alter the value of text or HTML. It is possible to alter the content LAYER elements in NN4 by using the documents' write() method.
You may be aware that by using the document.open(), document.write(), and document.close() methods, it is possible to alter the content of another frame or window. Well, since a layer is another document within the current document it is possible to use these three methods to alter the content of the layer:
<SCRIPT LANGUAGE="JavaScript"> <!-- function over2() { var text = '<FONT COLOR="red">Ha! You moved the mouse over the text<\/FONT>'; document.layers['myLayer2'].document.open(); document.layers['myLayer2'].document.write(text); document.layers['myLayer2'].document.close(); } function out2() { var text = 'Move the mouse pointer over this text'; document.layers['myLayer2'].document.open(); document.layers['myLayer2'].document.write(text); document.layers['myLayer2'].document.close(); } //--> </SCRIPT> <LAYER ID="myLayer2" onMouseOver="over2()" onMouseOut="out2()"> Move the mouse pointer over this text </LAYER>
Which in NN4 has the following effect....
Using all the techniques discussed so far, let's combine the solutions for MSIE4 and NN4 to create a solution that will work for both MSIE4 and NN4, and at the same time fail safely in older browsers:
<P> <SCRIPT LANGUAGE="JavaScript"> <!-- function changeContent(what,text) { if (document.all) what.innerHTML = text; else if (document.layers) { what.document.open(); what.document.write(text); what.document.close(); } } //--> </SCRIPT> <P> <DIV onMouseOver="changeContent(this,'<FONT COLOR=red>Ha! You moved the mouse over the text</FONT>')" onMouseOut="changeContent(this,'Move the mouse pointer over this text')"> <LAYER onMouseOver="changeContent(this,'<FONT COLOR=red>Ha! You moved the mouse over the text</FONT>')" onMouseOut="changeContent(this,'Move the mouse pointer over this text')"> Move the mouse pointer over this text </LAYER> </DIV> </P>
Which in MSIE4 or NN4 has the following effect....
This works because in MSIE4 the onMouseOver and onMouseOut event handlers within the DIV elements pass a reference to the changeContent() function to the DIV elements. The innnerHTML property of the DIV elements are then changed using the text value passed to the changeContent() function.
In NN4, the onMouseOver and onMouseOut event handlers in the layer elements pass a reference to the changeContent() function to the layer elements. The contents of the layer elements are changed by opening and writing to the layer directly.
Well, you don't have to restrict yourself to plain text or HTML; you can include and manipulate images within layers as well. You can also include links within the layers and then make use of other event handlers. For example, the onMouseOver, onMouseOut, and onClick event handlers can be used for the links themselves.
To illustrate this, the following example demonstrates text link rollovers as opposed to image link rollovers -- the result is a lot quicker than images:
<SCRIPT LANGUAGE="JavaScript"> <!-- function nnRoll(what,href,linktext,color) { if (document.layers) { var text = '<A HREF="' + href + '">' + '<FONT COLOR="' + color + '">' + linktext + '<\/FONT><\/A>' what.document.open(); what.document.write(text); what.document.close(); } } function msieRoll(what,color) { if (document.all) what.style.color=color; } //--> </SCRIPT> <P> <LAYER onMouseOver="nnRoll(this,'http://www.yahoo.com/','Yahoo!','green')" onMouseOut="nnRoll(this,'http://www.yahoo.com/','Yahoo!','blue')"> <A onMouseOver="msieRoll(this,'green')" onMouseOut="msieRoll(this,'blue')" HREF='http://www.yahoo.com/'>Yahoo!</A> </LAYER> <BR> <LAYER onMouseOver="nnRoll(this,'http://www.netscape.com/','Netscape','green')" onMouseOut="nnRoll(this,'http://www.netscape.com/','Netscape','blue')"> <A onMouseOver="msieRoll(this,'green')" onMouseOut="msieRoll(this,'blue')" HREF='http://www.netscape.com/'>Netscape</A> </LAYER> <BR> <LAYER onMouseOver="nnRoll(this,'http://www.microsoft.com/','Microsoft','green')" onMouseOut="nnRoll(this,'http://www.microsoft.com/','Microsoft','blue')"> <A onMouseOver="msieRoll(this,'green')" onMouseOut="msieRoll(this,'blue')" HREF='http://www.microsoft.com/'>Microsoft</A> </LAYER>
Which in MSIE4 or NN4 has the following effect....
This works perfectly in MSIE4 and NN4 and fails safely on older browsers. Note: The LAYER elements do not reserve any space on the page. Break tags (<BR>) are used to keep the links from overlapping each other in NN4. I have yet to work out a generic solution that enables the layers to be positioned side by side across the page. It's possible to insert extra ILAYER tags with a copy of the link text with a style that hides the ILAYER, but on MSIE4 this shows up as extra text between the links.
We have covered changing text and HTML, and altering the style properties of text in a document dynamically. It is also possible to add movement to a document (i.e., moving text and images around the screen using Positioning). But again, this will be covered in a future article.
DHTML is not yet stable enough to use in mission critical Web pages -- if you have a site that must work on all browsers then try to avoid using DHTML. However, if you have the freedom to experiment, then do so. But first, make sure you test your creations on as many platforms as possible -- in particular NN4 and MSIE4 for Win95 and Mac. You may be surprised to find that your carefully handcrafted DHTML may work perfectly on one browser, then fail abysmally on another. But don't despair. Keep at it, and keep your fingers crossed that future versions of the DOM will be more universal.
A Gift of "Life" : The Document Object Model
Multimedia in Microsoft Internet Explorer
Building a Dynamic Thank You Page