Click to return to the DHTML, HTML     
Using DHTML Behaviors     Default Behaviors Referen...     DHTML, HTML & CSS    
Web Workshop  |  DHTML, HTML & CSS

Implementing DHTML Behaviors in Script Using HTML Components


Dynamic HTML (DHTML) behaviors are components that can be implemented in a number of ways. For several years, the task of writing components has been limited to developers using C++, Microsoft® Visual Basic®, and Java.

As of Microsoft® Internet Explorer 5, script developers can use HTML Components (HTC) or Windows Scripting Components (WSC) to implement their own DHTML behaviors in script, using Microsoft® Visual Basic® Scripting Edition (VBScript), Microsoft® JScript® (compatible with ECMA 262 language specification), or any third-party scripting language that supports the Microsoft ActiveX® Scripting interfaces.

This article outlines the steps for using HTCs to create behaviors in script. For more information about how to create behaviors using WSCs, see Microsoft Scripting Non-MSDN link.

This article assumes that the reader has a good understanding of script programming and is familiar with HTCs and DHTML behaviors. Implementing behaviors in C++ is beyond the scope of this article. For more information about DHTML behaviors, HTCs, WSCs, and the C++ interfaces involved in implementing behaviors, see Related Topics.

After reading this article, you should be able to implement behaviors in your scripting language of choice, isolate script from your content, and reap the benefits of encapsulation and code reusability in your Web site.

This article is divided into the following sections:

HTC Overview

Introduced in Internet Explorer 5, HTCs provide a simple mechanism to implement DHTML behaviors in script. An HTC file is nothing but an HTML file, saved with a .htc extension, that contains scripts and a set of HTC-specific custom elements that expose properties, methods, and events that define the component.

As an HTML file, an HTC provides the same access as DHTML to all elements on the page. This means that within an HTC, all HTC elements are accessible from script as objects using their ID attributes. This allows all attributes and methods of HTC elements to be dynamically manipulated through script as properties and methods of these objects.

A Web author can use HTCs to implement behaviors that:

For more information about each of the HTC elements, properties, methods, and events described in this section, see HTC Reference.

Creating an HTC

The steps for creating an HTC are demonstrated in the following example, which implements a mouseover highlight effect.

  1. Create a skeleton HTC file.
  2. A typical HTC file consists of a SCRIPT block and an optional enclosing COMPONENT block. It is saved with an .htc extension.

    <PUBLIC:COMPONENT>
        <SCRIPT>
        </SCRIPT>
    </PUBLIC:COMPONENT>
    
  3. Fill in the SCRIPT block with the code to implement the behavior.
  4. In the following code, the ATTACH element is used to set up the HTC to receive notifications as to when the onmouseover and onmouseout events are fired on the element. This allows the HTC to toggle the color of the element to achieve the desired highlighting effect as the mouse hovers over the element.

    Sample Code

    <PUBLIC:COMPONENT>
    <PUBLIC:ATTACH EVENT="onmouseover" ONEVENT="Hilite()" />
    <PUBLIC:ATTACH EVENT="onmouseout"  ONEVENT="Restore()" />
    <SCRIPT LANGUAGE="JScript">
       var normalColor, normalSpacing;
     
       function Hilite()
       {
         // save original values
         normalColor  = runtimeStyle.color;  
         normalSpacing= runtimeStyle.letterSpacing;
     
         runtimeStyle.color  = "red";
         runtimeStyle.letterSpacing = 2;
       }
    
       function Restore()
       {
         // restore original values
         runtimeStyle.color  = normalColor;
         runtimeStyle.letterSpacing = normalSpacing;
       }
    </SCRIPT>
    </PUBLIC:COMPONENT>
    

    Note As mentioned in the preceding HTC overview, the element object returns the element to which the behavior is attached, therefore providing a means to access the element's object model. Alternatively, you can access the properties, methods, and events of the element by using the property, method, or event name directly, without prefixing it with the element keyword. In the preceding example, note how the color was toggled by referring directly to the runtimeStyle property, instead of using element.runtimeStyle, which is also acceptable.

  5. Once implemented, this HTC can be used on a page to achieve the desired mouseover highlighting effect.
  6. <HEAD>
    <STYLE>
       LI {behavior:url(hilite.htc)}
    </STYLE>
    </HEAD>
    
    <P>Mouse over the two list items below to see this effect.
    <UL>
      <LI>HTML Authoring</LI>
      <LI>Dynamic HTML</LI>
    </UL>
       
    This feature requires Internet Explorer 5 or later. Click the icon below to install the latest version. Then reload this page to view the sample.
    Microsoft Internet Explorer

Exposing Properties

An HTC can expose its own set of properties using the PROPERTY element.

For example, the preceding mouseover highlight example can be extended to expose a hiliteColor property that allows the Web author to set the color of the text to be highlighted. You can do this by using the PROPERTY element to define the property, as shown in the following code:

<PUBLIC:PROPERTY NAME="hiliteColor" />

Once the property is defined, it can be referred to in the HTC's code, as shown in the following code. Note how this code sets the value of the property to red if the containing page does not specifically set its value.

<PUBLIC:PROPERTY NAME="hiliteColor" />
<PUBLIC:ATTACH EVENT="onload" FOR="window" ONEVENT="initColors()"  />

<SCRIPT LANGUAGE="JScript">
function initColors()
{
  // initialize the property
  hiliteColor = (hiliteColor == null) ? "red" : hiliteColor;
}
</SCRIPT>  

The following example applies the mouseover highlight effect to a table of contents, changing the color of the anchors as the mouse hovers over the text. Note how the first list changes the color of the anchors to green when hovered over, whereas the second list simply changes the anchor colors to the default color, red. As explained in the preceding paragraph, if the containing page does not specifically set the hiliteColor property, the color defaults to red.

<style>
   .CollapsingAndHiliting {behavior:url(ul.htc) url(hilite2.htc)} 
   A           {behavior:url(hilite2.htc)}
</style>

<UL>
  <LI CLASS="CollapsingAndHiliting" CHILD="Topics1">HTML Authoring</LI>
  <UL ID="Topics1">
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Beginner's Guide</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">IE4.0 Authoring Tips</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">HTML Coding Tips</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Table Cell Backgrounds</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Drop Caps</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Quote Server</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">HTML Wizard</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Dr. HTML</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">HTML Coding FAQ for Internet Explorer</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">SGML DTD for Internet Explorer 3.0 Markup</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Authoring Basics</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Authoring Effective Pages</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Designing Efficient Pages</A></LI>
      <LI><A HILITECOLOR="green" HREF="/workshop/author/default.asp">Using Frames</A></LI>
  </UL>
   <LI><A HREF="/workshop/author/default.asp">HTML Help Authoring</A></LI>
   <LI CLASS="CollapsingAndHiliting" CHILD="Topics2">HTML References</LI>
   <UL ID="Topics2">
      <LI><A HREF="/workshop/author/default.htm">Elements</A></LI>
      <LI><A HREF="/workshop/author/default.htm">Character Sets</A></LI>
   </UL>
   <LI CLASS="CollapsingAndHiliting" CHILD="Topics3">HTML Applications (HTA)</LI>
   <UL ID="Topics3">
      <LI><A HREF="/workshop/author/default.htm">Overview</A></LI>
      <LI><A HREF="/workshop/author/default.htm">Reference</A></LI>
   </UL>   
</UL>
This feature requires Internet Explorer 5 or later. Click the icon below to install the latest version. Then reload this page to view the sample.
Microsoft Internet Explorer

Note A behavior can override an element's default behavior by exposing a property of the same name as that which is already defined for the element. For example, a behavior that exposes an href property can effectively override the A element's default href property, if that behavior is applied to an A element on a page.

Using the INTERNALNAME Attribute

When exposing a property in an HTC, it is possible to specify both a NAME attribute and an INTERNALNAME attribute in the PROPERTY element. If both names are specified, the NAME is used to refer to the property from the containing document, while the INTERNALNAME is used to refer to the same property within the HTC.

When specifying an INTERNALNAME attribute on the property, the variable name needs to be declared globally and initialized before it can be referenced anywhere in the component. Failure to do so results in either a scripting error indicating that the variable name is undefined, or an incorrect property value retrieved by the containing document.

Specifying either a PUT or GET attribute in the PROPERTY declaration causes the INTERNALNAME attribute to be ignored, if the INTERNALNAME is specified. Setting and/or retrieving the value of the property through the function(s) specified in the PUT and GET attributes takes precedence over setting and/or retrieving the value of the property through the INTERNALNAME.

Exposing Methods

Using the METHOD element, it is possible for an HTC to expose its own set of methods, as shown in the following code:

<PUBLIC:METHOD NAME="startFlying" />

Once the method is defined, the method can be used directly in the HTC's code, as shown in the following example, which implements a flying effect on groups of text on a page.

<PUBLIC:METHOD NAME="tick" />
<PUBLIC:METHOD NAME="startFlying" />
:
<SCRIPT LANGUAGE="JScript">
var currCount;
var flyCount;
var flying;
var msecs;
var oTop, oLeft;

msecs = 50;
flyCount = 20;
flying = false;

runtimeStyle.position = "relative";
runtimeStyle.visibility = "hidden";

window.attachEvent("onload", onload);

function onload()
{
  // delay commences from the window.onLoad event
  if (delay != "none")
  {
     window.setTimeout(uniqueID+".tick()", delay);
  }
}


function tick()
{
   if (flying == false)
   {
      startFlying();
   }
   else
   {
      doFly();
   }
}

function startFlying()
{
  if (fromX==null && fromY==null)
  {
     if (from=="top")
     {
       runtimeStyle.posTop = -offsetTop-offsetHeight;
     }
     else if (from=="bottom")
     {
       runtimeStyle.posTop = element.document.body.clientHeight;
     }
     else if (from=="right" )
     {
       runtimeStyle.posLeft = element.document.body.clientWidth;
     }
     else 
     { 
       runtimeStyle.posLeft = -offsetLeft-offsetWidth;
     }    
  }
  else
  {
     runtimeStyle.posTop = fromY;
     runtimeStyle.posLeft = fromX;
  }

  runtimeStyle.visibility = "visible";
//  runtimeStyle.display = "";
  flying = true;

  oTop = runtimeStyle.posTop;
  oLeft = runtimeStyle.posLeft;

  currCount = 0;
  doFly();
}

function doFly()
{
  var dt, dl;

  currCount++;
  dt = oTop / flyCount;
  dl = oLeft / flyCount;

  runtimeStyle.posTop -= dt;
  runtimeStyle.posLeft -= dl;

  if (currCount < flyCount)
  {
      window.setTimeout(uniqueID+".tick();", msecs);
  }
  else
  {
      runtimeStyle.posTop = 0;
      runtimeStyle.posLeft = 0;
      flying = false;
      evObj = createEventObject();
      evObj.setAttribute("resulty", uniqueID);
      finished.fire(evObj);
  }
}
</SCRIPT>
This feature requires Internet Explorer 5 or later. Click the icon below to install the latest version. Then reload this page to view the sample.
Microsoft Internet Explorer

Note Similar to the PROPERTY element, it is possibly to specify an INTERNALNAME in the METHOD declaration, so that the name by which the method is referred to in the containing page is different from the name it is referred to within the HTC. Additionally, a behavior can override an element's default behavior by exposing a method of the same name as that which is already defined for the element. For example, a behavior that exposes a click method can effectively override the A element's default click method, if that behavior is applied to an A element on a page.

Exposing Custom Events

Using the EVENT element, an HTC can define custom events and expose them to the containing page.

The following code demonstrates how a calculator, implemented as an HTC, defines a custom event—onResultChange—using the EVENT element. When the event is fired to the containing page, the resulting value is passed back to the page, setting an expando property—result—of the event object.

<PUBLIC:EVENT NAME=onResultChange ID=rcID />
 
<SCRIPT LANGUAGE="JScript">
   :
   oEvent = createEventObject();
   oEvent.result = sResult;
   rcID.fire (oEvent);
   :
</SCRIPT>

The following example shows what the containing page should look like:

<HTML XMLNS:InetSDK>
<HEAD>
<TITLE>Calculator Sample</TITLE>

<STYLE>
   INPUT    {font-family: Courier New}
   @media all {
      InetSDK\:CALC {behavior:url(Engine.htc)} 
   }
</STYLE>

<LINK REL="stylesheet" HREF="/workshop/basicSDKIE4.css" TYPE="text/css">
</HEAD>

<BODY BGCOLOR="#FFFFFF">
<BLOCKQUOTE CLASS="body">

<P>
<InetSDK:CALC id="myCalc" onResultChange="resultWindow.innerText =window.event.result">
<TABLE>
<TR>
<TD COLSPAN=5>
<DIV ID="resultWindow" STYLE="padding:5; background-color:buttonface" ALIGN="RIGHT">0.</DIV>
</TD>
</TR>

<TR><TD><INPUT TYPE=BUTTON VALUE=" 7 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 8 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 9 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" / "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" C "></TD>
</TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 4 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 5 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 6 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" * "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" % " DISABLED></TD>
</TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 1 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 2 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 3 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" - "></TD>
    <TD><INPUT TYPE=BUTTON VALUE="1/x" DISABLED></TD>
</TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 0 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE="+/-"></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" . "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" + "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" = "></TD>
</TR>

</TABLE>
</InetSDK:CALC>

</BLOCKQUOTE>
</BODY>
</HTML>
This feature requires Internet Explorer 5 or later. Click the icon below to install the latest version. Then reload this page to view the sample.
Microsoft Internet Explorer

Note A behavior can override an element's default behavior by exposing an event of the same name as one that is already defined for the element. For example, a behavior that exposes an onclick event can effectively override the A element's default onclick event, if that behavior is applied to an A element on a page.

Receiving Notifications

An HTC can attach to events being fired on the containing page through the ATTACH element. Using this element, the HTC can attach to standard DHTML events, as well as to HTC-specific events listed in the HTC Reference.

Note The HTC can also use the attachEvent method to receive notifications from the containing page. However, there are disadvantages:

Scope Rules

When working with HTCs, three namespaces are involved: the behavior's, the element's, and the containing page's. A set of scope rules have been defined for HTCs to help establish the order in which name conflicts are resolved. The order of precedence used in conflict resolution, from highest to lowest, is as follows:

  1. The behavior
  2. The element to which the behavior is attached
  3. The window object of the containing document

This means that if an HTC defines a global variable called event, any reference to event in the HTC will resolve to that global variable. The correct way to refer to the window object's event property within that HTC is to use window.event.

In the following example, note how the names have been resolved using the preceding scope rules.

<SCRIPT LANGUAGE="JScript">
var normalColor, normalSpacing;

attachEvent("onmouseover", event_onmouseover);
attachEvent("onmouseout",  event_onmouseout);

function event_onmouseover()
{
  // save original values
  normalColor  = style.color;  
  normalSpacing= style.letterSpacing;
 
  runtimeStyle.color  = "red";
  runtimeStyle.letterSpacing = 2;
}
function event_onmouseout()
{
  // restore original values
   runtimeStyle.color  = normalColor;
   runtimeStyle.letterSpacing = normalSpacing;
}

</SCRIPT>

Timing Considerations

When authoring behaviors, it is important to know when the behavior is applied to the element. Until the behavior is applied, access to the values of behavior-defined properties, which might be set from the document, might not be available to scripts.

To ensure that the behavior is completely downloaded and applied to the element, it is important to wait for the onreadystatechange event to fire, and then verify that the readyState property of the element is set to complete. Until this event fires, attempting to use any of the behavior-defined members before the behavior is attached to the element can result in a scripting error indicating that the object does not support that particular property or method.

Note As the behavior and its containing document are parsed and loaded, the behavior receives notifications of progress through the oncontentready and ondocumentready notifications. The oncontentready notification is received when the content of the element has been completely parsed. At this point, a behavior can count on the innerHTML property of the element to return the correct value. The ondocumentready notification is received when the document has been completely downloaded, including all scripts, images, ActiveX controls, and all other files on the page that need to be downloaded separately.

Behavior-Related Enhancements to the DHTML Object Model

As of Internet Explorer 5, the following enhancements were made to the DHTML Object Model to add support for behaviors.

Related Topics

The following links provide additional information about DHTML Behaviors.



Back to topBack to top

Did you find this topic useful? Suggestions for other topics? Write us!

© 1999 Microsoft Corporation. All rights reserved. Terms of use.