Time Off for Good Behavior: DHTML Behaviors in Internet Explorer 5
As of December 2011, this topic has been archived. As a result, it is no longer actively maintained. For more information, see Archived Content. For information, recommendations, and guidance regarding the current version of Internet Explorer, see Internet Explorer Developer Center.
Dave Massy
Microsoft Corporation
Updated March 18, 1999
Editor's Note: Behaviors, like many of the new authoring features in Internet Explorer 5, are proposed extensions to already approved World Wide Web Consortium (W3C) standards, such as HTML 4.0 and CSS2.
DHTML behaviors, a new feature in Microsoft® Internet Explorer 5, make Dynamic HTML functionality more accessible and easier to use in a document. A DHTML behavior component can be written in any scripting language, such as Microsoft JScript® or Microsoft Visual Basic® Scripting Edition (VBScript), and supplies dynamic functionality that can be applied to any element in an HTML document through Cascading Style Sheets (CSS).
All well and good, but what does it mean for Web developers and authors? First, let's look into how you would use DHTML behaviors in a document and what benefits they bring to the world of DHTML.
Who's Afraid of Mixing Script and Content?
Although DHTML is generally thought to be a great technology that makes pages interactive and fun, there is a reason that we don't see even more DHTML in use. It basically comes down to having the content of the document and the script of the dynamic functionality mixed together in a single file.
For many people who are authoring HTML documents, to include script in the document is a step down the slippery slope of becoming a programmer (that's not to say that programmers are a bad bunch—I even occasionally program myself!). The script in the document adds enough complexity and fragility that any content change could break the functionality of the script. Even for those authors who are comfortable with programming concepts and with using script to add dynamic functionality to a document, having the script and content in the same file makes the process slow and difficult to manage.
Three job disciplines are involved in creating a dynamic HTML page: content provider, designer, and engineer. The content provider is the author of the content of the document, while the designer decides on the look and feel of the document and adds formatting information, and the engineer adds any dynamic functionality using script. By using CSS and DHTML behaviors, the design and engineering aspects of the document can be separated from the content, allowing the specialists in each discipline to concentrate on their particular area without worrying about conflict.
DHTML behaviors use CSS to separate the script from the content and style of a document. Programmers call the ability to isolate functionality in this way "encapsulation"; it brings the benefits of reuse to the world of DHTML.
Flying, Without Behavior
Let's look at an example of some text flying in from the left of the screen:
<body onload=Bonload()> <span delay=1000 id=Fly1> This is some text <img src=ie.gif> <br> This is some more text </span> <br> <span delay=3000 id=Fly2> This is some text <img src=ie.gif> <br> More text </span> <br> <span delay=5000 id=Fly3> This is some text <img src=ie.gif> <br> This is some more text </span> <br> <span delay=7000 id=Fly4> This is some text <img src=ie.gif> <br> This is some more text </span> <script language="jscript"> var flyCount; var msecs; msecs = 50; flyCount = 20; document.all.Fly1.flying = false; document.all.Fly2.flying = false; document.all.Fly3.flying = false; document.all.Fly4.flying = false; document.all.Fly1.style.position = "relative"; document.all.Fly1.style.visibility = "hidden"; document.all.Fly2.style.position = "relative"; document.all.Fly2.style.visibility = "hidden"; document.all.Fly3.style.position = "relative"; document.all.Fly3.style.visibility = "hidden"; document.all.Fly4.style.position = "relative"; document.all.Fly4.style.visibility = "hidden"; function Bonload() { setTimeout("tick(document.all.Fly1)", document.all.Fly1.delay); setTimeout("tick(document.all.Fly2)", document.all.Fly2.delay); setTimeout("tick(document.all.Fly3)", document.all.Fly3.delay); setTimeout("tick(document.all.Fly4)", document.all.Fly4.delay); } function tick(elem) { if (elem.flying) { doFly(elem); } else { fly(elem); } } function fly(elem) { elem.style.posLeft = -400; elem.style.visibility = "visible"; elem.flying = true; flyTextIn(elem); } function flyTextIn(elem) { elem.oTop = elem.style.posTop; elem.oLeft = elem.style.posLeft; elem.currCount = 0; setTimeout("tick(document.all." + elem.id + ");", msecs); } function doFly(elem) { var dt, dl; elem.currCount++; dt = elem.oTop / flyCount; dl = elem.oLeft / flyCount; elem.style.posTop -= dt; elem.style.posLeft -= dl; if (elem.currCount < flyCount) { setTimeout("tick(document.all." + elem.id + ");", msecs); } else { elem.style.posTop = 0; elem.style.posLeft = 0; elem.flying = false; } }</script>
Here is a mix of both content and script on the page. While this example isn't terribly complex, you can see how a page with more functionality could become increasingly complex and difficult to maintain.
Flying, with Behavior
Now, let's look at the source of the same HTML document, but this time using a DHTML behavior to provide the fly-from-left functionality:
<html> <head> <Style> .fly{behavior:url(fly.htc)} </style> </head> <body> <div class=fly delay=1000> This is some text <img src=ie.gif> <br> This is some more text </div> <br> <div class=fly delay=3000> This is some text <img src=ie.gif> <br> More text </div> <br> <div class=fly delay=5000> This is some text <img src=ie.gif> <br> This is some more text </div> <br> <div class=fly delay=7000> This is some text <img src=ie.gif> <br> This is some more text </div> </body> </html>
Here, the document is mainly composed of the content and uses a behavior component implemented in an HTML Component file (.htc) to provide the functionality for flying text. Now the content of the page can be changed with a much lower risk of breaking any functionality, thus making the page easier to maintain. Also, the behavior component can be used multiple times on the same page or on multiple pages. This particular behavior exposes some additional attributes that set the direction and delay of the flying text, so we have a component that can be used easily in a document without the page author having any knowledge of script or object model.
Using DHTML Behaviors in a Document
So how can you declare and use DHTML behaviors in an HTML document?
If you know how to use CSS, you know how to use DHTML behaviors. It really is that easy. As proposed to the World Wide Web Consortium(W3C), a new CSS property called behavior defines the location of the behavior component.
In the earlier example a fly class was declared that included the behavior component fly.htc:
<style> .FLY{behavior:url{fly.htc}} </style>
This class can then be used on any HTML tag in the same way that any class can be used.
<div class=fly> This text will fly </div>
The contents of the <DIV> will then gain the flying functionality. Anything that can be achieved in a document using HTML and script can be achieved using a DHTML behavior. This allows designers to apply dynamic functionality that has been prepared by the engineer using the familiar syntax of CSS.
But there's more. Once DHTML behaviors are combined with XML-tag support in Internet Explorer 5.0, it is possible for the page author to define new tags that expose default functionality.
What About this XML Stuff?
One of the great things you can do in Internet Explorer 5 is use XML to define custom tags for use in an HTML Document. A custom tag consists of two parts: a namespace that precedes a colon and the tagname that comes after the colon.
To declare an XML namespace, use an xmlns instruction in the HTML tag of the document:
<html xmlns:
This means that the MYTAGS namespace is now declared for use in the document and any custom tags that use that namespace can be used as tags in the HTML document. For example, we can enclose some standard HTML content in a <MYTAGS:TAGA> tag as follows:
<MYTAGS:TAGA> This is some <b>Bold</b> HTML content </MYTAGS:TAGA>
But why would you ever want to do that? Well, it gives the ability to add structure to a document so that certain content can be distinguished. For example, in a document that lists products and prices, the product descriptions could be contained in a <PRODUCT:DESCRIPTION> tag and prices in a <PRODUCT:PRICE> tag. Script could then be written to access all the prices in the document.
And what has all this got to do with DHTML behaviors? The custom tags can have CSS applied to them. So if I wanted to have all the prices in my document rendered in pink, I could declare the following style in the head of the document:
<style> @media all{ PRODUCT\:PRICE{color:pink} } <style>
Now the content of every <PRODUCT:PRICE> tag in the document will be rendered as pink.
Remember that a DHTML behavior is simply a proposed CSS property, so now I can apply a default behavior to any new XML tag. Going back to our fly behavior, I can now declare a fly tag that can be used to wrap any HTML content to get the flying functionality:
<html xmlns: <style> @media all{ MYTAG\:FLY{behavior:url{fly.htc}} } </style> ..... <MYTAG:FLY> This text flies </MYTAG:FLY> </html>
The functionality I've shown here is fairly simple. Take a look at our samples, which show how powerful this technology is in allowing quite complex functionality to be defined with no script in the document (the link takes you to a Fly-In sample, one of several Internet Explorer 5 samples available; from there, you can browse the others by choosing "show samples list"):
How Do I Write a DHTML Behavior?
It's easy. Using HTML and any scripting language, it is very nearly the same as if the script were in the document. The script is in an HTML Component, or .htc file, which is referred to from the document in the behavior declaration.
What can a DHTML behavior do?
- Expose new attributes and methods on the HTML element to which it is attached, so they appear to the document author as standard attributes and methods on the element
- Fire custom events so that they appear to the document author as standard events on the HTML element
- Access the element to which it is attached, and therefore access the whole document through the document's object model
- Catch any event from anywhere in the document
The HTC file can be considered to consist of two parts: First, the declarations for the properties, methods, and events that will appear as properties, methods, and events on the element to which the behavior is attached; second, the script.
Take a simple HTC file:
<PUBLIC:METHOD name=myMethod /> <PUBLIC:PROPERTY name=myProperty /> <PUBLIC:EVENT ID=myEvent name=onmyevent/ > <script> ... </script>
This behavior exposes a method (myMethod), a property (myProperty), and fires a custom event (onmyevent). When used in an HTML document, these properties, methods, and events will add to any standard properties, methods, and events available on the element to which the behavior is applied. Once the methods, properties, and events have been declared, the remainder of the HTC file is script written in much the same way as script in the document.
Timing considerations
It is important to understand that the behavior component may not be connected to the HTML element instantaneously when the document is loaded. This is because the .htc file is separate from the main document and will be downloaded separately, during which time the HTML document may continue to download, parse, and display its content.
As the document and behavior are parsed and loaded, the behavior will receive notifications of progress. There are two notification events, oncontentready and ondocumentready. The oncontentready notification is received once initially; it says that the content of the element to which the behavior is attached has been parsed. The ondocumentready notification is received when the document has been downloaded and parsed.
Any inline script in the .htc file will be executed when the behavior is instantiated. If the values of any attributes set from the document need to be accessed, then the behavior should wait until at least the first oncontentready notification to use them, as they may not have been set when the inline script runs.
Dynamic List Behavior
Let's look at a simple behavior that adds expanding- and collapsing-list functionality whenever it is applied to a list element:
<head> <title>UL with Behavior</title> <style> .LIST{behavior:url(ul.htc);} </style> </head> <body> <p>This is an example of an expanding/collapsing list using DHTML Behaviors <ul class="LIST" style="cursor: hand;" title="Click to toggle the List"> This is an unordered list which has a behavior attached to the ul. <li> Item 1 <li> Item 2 <li> Item 3 <li> Item 4 </ul> </body>
Now, look at the HTML Componet (.htc) file; the script is very simple, and is similar to having the script in the document itself:
<script language="jscript"> attachEvent("onclick", event_onclick); function event_onclick() { var i; var style; if (event.srcElement != element) return; for (i = 0; i < children.length; i++) { style = children[i].style; if (style.display == "none") { style.display = ""; } else { style.display = "none"; } } } </script>
Here, the script captures the onclick event on the element to which it is attached. When a mouse click occurs, the child elements of the list are hidden or shown appropriately. This particular behavior does not expose any properties, methods, and events, but if it did they'd be declared above the script at the start of the .htc file.
Conclusion
To see the full power and flexibility of DHTML behaviors, a visit to the sample gallery is essential. The benefits of removing the script functionality from the document are many, but most important among them are maintainability and reuse. Separating content from script allows the document contents to be maintained without the risk of breaking any dynamic functionality. What's more, the behaviors can be reused throughout multiple documents without having to have an engineer maintain individual documents.
Have fun with DHTML behaviors!