This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with DHTML, VBScript, and JScript.
Download the code (6KB)

Microsoft Internet Explorer 5.0: The Inside Story
by
the Microsoft Internet Explorer
SDK Documentation Team
Stephen Cote • Jeff Kirkham• Erik Kjerland Lanie Kurata • Jacqueline Sowell • Bradley Yamauchi
     
     
Internet Explorer 5.0 expands the horizons of the Internet. The new version boasts improvements in extensibility and has become a rich platform for application design.
After years of improvement, the technology of the extensible browser comes of age with Microsoft® Internet Explorer 5.0. This browser release has been driven by three strategic objectives: it needed to be fast and stable, it had to be easily extensible, and the browser itself was to become a rich platform for applications. We’ll focus on the latter two goals. We will preview some of the new features in Internet Explorer 5.0 that make it an extensible environment for application developers, including Dynamic HTML (DHTML) behaviors, user data persistence, dynamic properties, data transfer, and mouse capture. (Note that this article is based on the Developer Preview release, and features are subject to change in the final version.)

DHTML Behaviors
      DHTML behaviors (also known simply as behaviors) are one of the most exciting and innovative features in Internet Explorer 5.0. This new architecture brings the benefits of encapsulation and code reuse to the world of DHTML. Behaviors are simple, lightweight components that separate HTML from script by moving the script to a separate file. Doing so results in a cleaner, more manageable page, and allows you to reuse the same code across multiple pages. Let’s look at two common Web authoring scenarios where behaviors can be put to good use.

Figure 1: Mouseover Highlighting
Figure 1: Mouseover Highlighting


      Mouseover highlights and controlling when content is shown or hidden are two popular effects made possible in Internet Explorer 4.0. Figure 1 shows how these two effects have been applied to MSDN table of contents. To illustrate some differences between Internet Explorer 4.0 and 5.0, we implemented the same page two different ways. The code in Figure 2 uses DHTML features of Internet Explorer 4.0. It requires a combination of HTML and lots of script on the page. The code in Figure 3 uses DHTML behaviors with Internet Explorer 5.0. Notice that most of the script is confined to a separate file.
      Behaviors makes the page much more readable, and thus more maintainable. It is also easy to use the same behavior on different elements on a page, and even across multiple pages.
      Two behaviors were created for this example: one (hilite.sct) to implement the mouseover highlighting effect, and the other (showHide.sct) to show or hide text by expanding and collapsing the list when clicked. These behaviors are applied to the <A> and <LI> elements on the page in the same way a style is applied to an element through Cascading Style Sheets (CSS). The proposed CSS behavior attribute specifies the location of the behavior you want to apply to the element.
      This code defines two embedded styles, COLLAPSING and A.


 <HEAD>
 <STYLE>
     A           {behavior:url(hilite.sct)}
     .COLLAPSING {behavior:url(showHide.sct)}
 </STYLE>
 </HEAD>
The first style uses the HTML element <A> as the selector, causing each instance of an <A> tag on the page to change its color to red when the mouse moves over it. This behavior is defined in the file hilite.sct. The second style defines a COLLAPSING class and uses it as a selector. Every element with CLASS="COLLAPSING" behaves as defined in showHide.sct, toggling its display property.

 <UL>
     <LI><DIV CLASS="COLLAPSING" CHILD=Topics1>HTML 
         Authoring</DIV>
     <UL ID=Topics1>
         <LI><A HREF="">Internet Explorer 4.0 authoring
             tips</A>
         <LI><A HREF="">Four special effects with IE 
             4.0</A>
       ...
     </UL>
 </UL>
      If you’ve ever designed a form, chances are you’ve had a need for a masked entry field—an input field that takes a preformatted value like a phone number, a date, or a time. The <INPUT> tag does not have this functionality built in; with Internet Explorer 4.0 you have to use a script that monitors the keypress and focus events, then set the input value to the formatted string accordingly. Consequently, you have to include the same script on every page that uses those masked entry fields.
      With Internet Explorer 5.0, you can simply use a DHTML behavior that encapsulates all the masked entry functionality in a separate file. This lets you enhance the default behavior of the <INPUT> tag. Any time you need a masked entry field, you can simply insert an <INPUT> tag on a page with the class set to mask.

 <HEAD>
 <STYLE>
     .MASK   {behavior:url(mask.sct)}
 </STYLE>
 </HEAD>
 <input type=text class="mask" mask_Value="(###) ###-####">
In the style definition, mask.sct is the name of the file that contains the behavior implementation. The <INPUT> parameter mask_Value defines the formatting required for the input field—in this case, a phone number. You should find this simple to use, even if you barely know how to write a script! Figure 4 shows this sample in action.

Figure 4: Masked Entry Field
Figure 4: Masked Entry Field


Implementing Behaviors
      By now you may be wondering how behaviors are implemented. Because they are components, you might expect them to be written in C++. Although you can go this route, you’ll probably find it easier to implement them with VBScript or JScript®, through the magic of scriptlets.
      All three behaviors we’ve described so far were implemented as scriptlets (see Figures 5, 6, and 7). They were all simple to implement, involving only a few lines of code. This code consists mainly of script, with a number of XML tags used to define the behavior and, in some cases, to expose a property. The new attachEvent method allows a behavior scriptlet to listen in on events fired on the element and to handle the events appropriately. This method provides the means to encapsulate event handling code that would otherwise be embedded in the page.
      A few enhancements were made to the DHTML object model for Internet Explorer 5.0 to support behaviors. As mentioned above, the proposed CSS behavior attribute specifies the location of the behavior. The attachEvent and detachEvent methods let a scriptlet-based behavior receive event notifications from the containing page by specifying a function that’s called whenever the event fires on the object. The uniqueID property lets a behavior scriptlet assign an ID to the element. This can be useful when a scriptlet injects code into the containing page and needs to specify the ID of the element to which the behavior is being applied.
      Behaviors are not subject to Internet Explorer’s cross-frame security rules. In other words, a Web page may refer to a behavior located on another server or in another domain. However, this should be done with caution as the behavior might change or move without prior notice, leading to undesirable behavior on the page. It is considered good practice to use behaviors from within a trusted domain so that the page always works as expected.
      Developing behaviors is certainly not limited to authors writing scriptlets. For the hardcore C++ developer, a set of interfaces—denoted with the IElementBehavior prefix—has been exposed by Internet Explorer 5.0 to enable the implementation of behaviors in C++. Binary implementations of behaviors are inserted on a page as ActiveX® controls with the <OBJECT> tag. They are designated by behavior: url(#myObject), where myObject points to the ID of the object specified in the <OBJECT> tag, as shown in the following example:

 <STYLE>
     .COLLAPSING { behavior:url(#myObject) }
 </STYLE>

 <OBJECT ID=myObject ... ></OBJECT>
 <UL>
     <LI CLASS="COLLAPSING">HTML Authoring
     <UL>
         <LI>IE 4.0 authoring tips
         :
     </UL>
 </UL>
      Creating behaviors in C++ is beyond the scope of this article. The C++ interfaces involved are documented for the Developer Preview release of Internet Explorer 5.0. See http://msdn.microsoft.com/workshop/c-frame.htm#/workshop/browser/default.asp for more information.
      Note that the scriptlets discussed so far should not be confused with the DHTML Scriptlets that were introduced with Internet Explorer 4.0. More information on scriptlets and how they differ from DHTML Scriptlets can be found at the Microsoft Scripting Technologies home page, http://www.microsoft.com/scripting.

Behaviors and Data Persistence
      Several of the DHTML behaviors included with Internet Explorer 5.0 allow you to instruct the browser to preserve Web page information. Form data, styles, state, and script variables can be persisted in the current session’s memory stream, in the favorites list, in HTML, or in XML. These four DHTML persistence behaviors are saveFavorite, saveHistory, saveSnapshot, and userData.


      The ability to persist information also lets you retain style and state beyond a single Web page. Preserving style and state helps make it easy to produce Web applications that use DHTML, such as an expense report that automatically configures itself based on a user’s personalized settings. A few lines of client-side script can now accomplish what once required server-side programming and complicated scripts.
      The userData persistence behavior makes it easy to save information entered into a text field. Rather than query a server-side CGI script, the persisted information is saved to the client using two JScript-based functions and the persistent object—the data need never go to the server.
      Internet Explorer 5.0 identifies a Web page with a persistence behavior through a CSS class. This class name is then assigned to the object that will contain persistent information. We developed two JScript-based functions, fnSaveInput and fnLoadInput, to perform the save and load processes. The fnSaveInput function, shown below, sets an attribute containing the text field value on the persistent object, which is then saved to an XML store. In this sample, the XML store is called oXMLBranch.

 function fnSaveInput()
 {
     var oPersist = oPersistForm.oPersistText;
     oPersist.setAttribute("sPersistText",oPersist.value);
     oPersist.save("oXMLBranch");
     oPersist.value = "";
 }
After the fnSaveInput function calls the save method, the form input value is cleared.
      The fnLoadInput function recovers the persistent attribute by loading the XML store, oXMLBranch. Next, the persistent object’s value is set to the value of the persistent attribute.

 function fnLoadInput()
 {
     var oPersist = oPersistForm.oPersistText;
     oPersist.load("oXMLBranch");
     oPersist.value = oPersist.getAttribute("sPersistText");
     oPersist.removeAttribute("sPersistText");
     oPersist.save("oXMLBranch");
 }
The persistent input field and the two buttons that call the save and load functions are mostly plain HTML (see Figure 8). A class attribute identifies the input field as participating in userData persistence, and an onclick event handler on each button fires the save and load functions.
      There are myriad possibilities for persistently storing bits of information beyond the current browser session and across pages on the same domain. For example, the style and state of page content can be preserved for later use. Persisting information on the client reduces the number of server queries and cuts down on processor time used by server-side scripts.
      Since the size and structure of client cookies are restricted, they’re an impractical solution for a lot of client-side persistence needs. However, the userData behavior exposes an XMLDocument property that provides access to the XML object model for persistent objects. The hierarchical structure of XML is ideal for storing large quantities of information. Using this property on an object participating in userData persistence allows you to benefit from this structure by storing your persistent data with XML.
      The fnSaveInput function can be used to persist information in XML. The difference between the following fnSaveInput implementation and the one from the previous sample is that the persistent XML attribute used to store the input value is not directly located on the persistent object, but on an XML node (see Figure 9).

 function fnSaveInput()
 {
     var oPersist = oPersistForm.oPersistText;
     var oXMLDoc = oPersist.XMLDocument;
     var oNode = oXMLDoc.createNode(0,"Trunk");
     oNode.nodeValue = "The XML tree trunk.";
     oNode.setAttribute("sPersist",oPersist.value);
     oXMLDoc.documentNode.insertNode(oNode);
     oPersist.value = "";
     oPersist.save("oXMLBranch");
 }
To add information in an attribute on an XML node, the oXMLDoc variable is assigned to the persistent object’s XMLDocument property. The oNode object is then created from the oXMLDoc variable using createNode, an XML method. An arbitrary name (Trunk) and value ("The XML tree trunk") is given to the oNode object. The information from the input value is stored in an attribute on the oNode object, and the node is inserted into the XML documentNode. When the persistent information is saved to the XML store, the data resides in an XML structure.
      Retrieving the data is similar to the first sample’s fnLoadInput function. The difference is that the persistent information is stored in an attribute on an XML node, and the XML structure needs to be accessed through the XMLDocument property. Therefore, the oXMLDoc variable is created for the persistent object XMLDocument property.

 function fnLoadInput()
 {
     var oPersist = oPersistForm.oPersistText;
     var oXMLDoc = oPersist.XMLDocument;
     oPersist.load("oXMLBranch");
     oPersist.value = 
         oXMLDoc.documentNode.childNodes.item(0).getAttribute("sPersist");
 }
Beyond the adjustments to the two JScript-based functions, the HTML from Figure 8 remains the same after XML-osity is added.

Dynamic Properties
      Dynamic properties let you improve the appearance and rendering of Web pages. Using dynamic properties, it is possible to declare HTML property values as an expression or formula. The expressions used in a dynamic property can reference property values from other elements, allowing greater interactivity between objects on a page.
      Here are a few of the effects you can create with dynamic properties:


      Once you understand how dynamic properties work, you’ll come up with many other possible uses.
      Dynamic properties can be implemented with both script and inline HTML. For example, setting a DIV’s position relative to another DIV’s width can be done with script:

 div1.style.setExpression("posLeft","div2.style.posLeft + 
                          div2.clientwidth","jscript");
The setExpression method sets a dynamic property in script. The first parameter is the name of the property to be recalculated. The second is the scripting equation to be applied to the property. The third is the scripting language to use for the equation. Note how the setExpression method is called directly on the object that has the property. In the above code, the target property posLeft is a property of that style object (not div1 itself), so setExpression is called on the style object.
      The equivalent functionality can be accomplished inline using the proposed CSS function notation within the STYLE property:

 <DIV ID=div1 STYLE="left:function(div2.style.posLeft + div2.clientWidth)">
One of the benefits of using the function notation versus the setExpression method is that it degrades to other browsers much more gracefully—they simply ignore it. With setExpression, you must write conditional code, sniffing the browser string to make sure that you don’t call a method that will return an error. By using inline dynamic properties, script usage can be minimized. This lets page designers create advanced effects without having to learn script programming.
      For example, the code shown in Figure 9 includes dynamic properties. Whenever the browser is resized, the width of the Blue DIV is recalculated, as are the positions of the Red and Green DIVs. Figures 10 and 11 show what happens when this code is implemented and the browser window is resized. Figure 10 depicts the DIV before the browser is resized, while Figure 11 shows results of the resizing. Note that the Blue DIV is less wide, and the positions of the Red and Green DIVs move relative to the new size of the Blue DIV.

Figure 10: DIV Before Browser is Resized
Figure 10: DIV Before Browser is Resized
Figure 11: Resized Browser
Figure 11: Resized Browser


      For the Internet Explorer 5.0 Developer Preview release, implicit dependencies, internal property changes, and related properties may result in some expressions not being recalculated even though the properties they reference may have changed. To guard against these issues, refer to the same property name or manually call recalc(true) to force recalculations of all expressions. The code shown in Figure 9, for example, calls the recalc method on the onload and onresize events, which forces a recalculation of the dynamic properties in the document.

Data Transfer
      If you want to incorporate custom drag and drop or editing functionality in your Web apps, Internet Explorer 5.0 makes doing so straightforward with an extensive data transfer implementation. An important part of the data transfer object model is the new dataTransfer object and its supporting cast of properties and methods. The dataTransfer object is available as a property of the window event object, so it can be called like this:


 event.dataTransfer.setData("Image")
It acts as the conduit for transferring information between the data source and the data target. The data source can provide both data and a data format in the same way that the target object can request data of a specified format. The setData and getData methods of the dataTransfer object are central to these exchanges of information.
      This data transfer functionality lets you enable drag and drop operations on just about any object. For example, you can write online shopping cart applications using compact and secure DHTML. Such applications display a catalogue and an order form, allowing the user to drag the image of the item they want to purchase and drop it onto the order form. Figure 12 shows the core code needed for such an application.
      Two properties are unique to drag and drop coding in Internet Explorer 5.0: effectAllowed and dropEffect. effectAllowed stipulates whether the selection will be copied, moved, or linked when it’s dropped. dropEffect matches the system pointer to the action set in effectAllowed. In the Developer Preview release, the dropEffect property has access to the system cursors, but not custom cursors.
      The following code snippet illustrates both the setData method and the effectAllowed property in action:

 function fnSetInfo()
 {
   event.dataTransfer.setData("Text", "Microsoft Golf");
   event.dataTransfer.effectAllowed = "copy";
 }
The setData method associates text with the source object, an image of the Microsoft Golf package. When the image is dropped on a valid drop target, such as an order form, then the text describing the merchandise is displayed.
      You can also enable cut, copy, and paste through the browser’s edit and context menus. This makes it possible to create an HTML-based text editor. In fact, with just a few lines of code, a container can transfer its contents to another location. Figure 13 employs a <SPAN> tag as the text source and a text input field as the target for a copy operation.
      Enabling editing is simple: call the setData method from the oncopy event and the copy item is enabled in the context menu. Alternatively, you could call the setData method from the oncut event to enable the cut option in the context menu. Just remember to cancel the default behavior of each data transfer event you use. The following function call during the onbeforecopy event shows that it’s essential to cancel the browser default behavior in each data transfer event.

 function fnBeforeCopy()
 {
     event.returnValue = false;
 }
      As the examples illustrate, all of the data transfer communication takes place during events. Internet Explorer 5.0 delivers a rich set of notification events, all of which bubble. This level of programmatic control is a big help to Web developers. You can modularize your code by trapping these events once they bubble up to the container level.
      The Internet Explorer 5.0 implementation may be a subset of the COM and Java data transfer implementations. However, Web developers gain ease of use and some freebies in the bargain. For instance, when you drag something to an off-screen drop target, Internet Explorer will scroll the page for you with no additional code. We challenge you to implement this in a traditional Win32®-based application without adding code!

Mice and Scrollbars
      Want to include dropdown menus in your Web apps without resorting to ActiveX controls? Internet Explorer 5.0 delivers new functionality that makes monitoring mouse activity easy. The releaseCapture and setCapture methods and the onlosecapture event allow you to designate one object to trap all mouse events for the document.
      Web page navigation now goes beyond the onscroll event of Internet Explorer 4.0. You can query which component the mouse is hovering over using the componentFromPoint method. This method detects any element the mouse is over—not just scroll bars. The following code writes the pointer position to the browser status bar each time the onmouseover event fires.


 function fnTrackScroll() 
 {
     var sElem = "";
     sElem = document.body.componentFromPoint(event.clientX, event.clientY);
     window.status = "mousemove " + event.clientX + ", " +
                     event.clientY +
                     " The mouse pointer is hovering over:
                     " + sElem;
 }
      You can also move scroll bar components using the doScroll method. This method scrolls the element by the same increments available on the scroll bar, whether vertically or horizontally. The following code causes the scroll bar to scroll horizontally one full page to the right.

 function fnScrollBehavior()
 {
     document.body.doScroll("scrollbarPageRight");
 }
This functionality lets accessibility related hardware, such as screen readers, relay much more navigational information to users with special needs.
      In this release, the CSS overflow attribute works on all elements that render on a page. Setting style=overflow:scroll forces scroll bars to appear on an object. This enhanced scroll bar programmability means that you can code the page to respond to in-page navigation, adjusting it to remain within set parameters.

Client Capabilities
      Internet Explorer 4.0 introduced a number of enhancements to the DHTML object model that provide information about the client, such as the screen resolution, color depth, platform, whether cookies or Java applets are enabled, and so on. This information, collectively known as client capabilities, lets you query which features of the browser are currently enabled. This way you can serve up the right content and have the pages appear exactly as nature intended.
      For example, using the colorDepth property as in the following code, you can dynamically specify the images to be used on the page based on the number of colors supported by the client screen.


 <IMG ID="myImage" WIDTH=200 HEIGHT=200>
 <SCRIPT>
 {
     if (window.screen.colorDepth >= 8)
         myImage.src = "256color.bmp";
   else
         myImage.src = "16color.bmp";
 }
 </SCRIPT>
If fewer than 256 colors (or 8 bits per pixel) are detected, a 16-color image is displayed; otherwise, a higher resolution image is displayed. As a result, the colors are more suited to the client screen, and the overall user experience is improved.
      Internet Explorer 5.0 has enhanced its support for client capabilities by adding a connectionType property, so code can detect whether the user is connected via a network or modem, or is working offline. It also provides three methods related to the detection of Internet Explorer components installed in the system. Figure 14 outlines all the client capabilities currently available in Internet Explorer 5.0, highlighting the four new additions.
      Instead of adding these new methods and properties to the DHTML object model for Internet Explorer 5.0, all of the client capabilities are exposed as one of Internet Explorer’s default behaviors, so the syntax is slightly different. For backward compatibility, all properties available in Internet Explorer 4.0 will continue to be supported as part of the DHTML object model.

Table Enhancements
      The CSS table-layout attribute has been added to Internet Explorer 5.0, resulting in a significant performance boost for table rendering. In a simple test, a 1000-row table without a fixed layout took 50 seconds to load on a Pentium 90 system. With a fixed layout, the same table took under one second to load.
      You can create a fixed-layout table by using a new CSS attribute, table-layout. The default, table-layout:auto, forces Internet Explorer 5.0 to determine the size of the table. To calculate the table size, Internet Explorer must examine the contents of each table cell. However, if you set table-layout:fixed and specify a table width, Internet Explorer 5.0 does not have to check the contents of each cell as it is loaded.
      A fixed table layout will work only if Internet Explorer 5.0 can determine the table width. There are three ways to do this: specify table width manually, set the cell width for each cell, or stipulate the width of the columns. If you specify the table width by adding the width attribute to the table tag, Internet Explorer 5.0 will give each column an equal width. The following HTML will render a table with two 50-pixel-wide columns:


 <TABLE WIDTH=100 style="table-layout:fixed">
 <TR><TD>This is cell 1</TD><TD>This is cell 2</TD>
 </TR>
 </TABLE>
      You can also specify the width of each column using the COL tag or by specifying a width attribute in each cell of the first table row. The following code will render a table with one 50-pixel-wide column and one 100-pixel-wide column:

 <TABLE WIDTH=150 style="table-layout:fixed">
 <COL WIDTH=50><COL WIDTH=100>
 <TR><TD>This is cell 1</TD><TD>This is cell 2</TD>
 </TR>
 </TABLE>
      The fixed value of the table-layout attribute is only effective when loading large tables predefined in the HTML page. It has less impact when used in conjunction with data binding or the innerHTML property of a table container.

Figure 15: Border-collapse
Figure 15: Border-collapse


      A new CSS attribute, border-collapse, allows a table to look more like a spreadsheet. This attribute allows cell borders to be shared, giving a cleaner appearance to the page. Figure 15 shows the difference between a traditional HTML table and a table utilizing the border-collapse attribute. Internet Explorer 5.0 also lets you use the display attribute to selectively show or hide table data.

Unicode and URL Cache Group Support
      For C++ programmers, Internet Explorer 5.0 is scheduled to include Unicode and URL cache group support for the Win32-based Internet functions (more commonly known as WinInet). Many of the Win32-based Internet functions and structures now provide a Unicode wrapper for the ANSI implementation. This allows developers who work in a Unicode environment to use WinInet without converting strings being passed into these functions and structures `from Unicode to ANSI. For backward compatibility, ANSI versions of the WinInet functions and structures will continue to be supported.
      URL cache groups let you create non-removable groups of resources in the Internet cache. Resources added to these groups will not be purged by the normal clean-up mechanism used by the Internet cache, so users can access this content offline with Internet Explorer and other WinInet-based applications that were designed to access the cache.

Conclusion
      Though Internet Explorer looks similar to its predecessor, don’t be fooled. Internet Explorer 5.0 is designed to deliver increased performance and stability through fixed-layout tables, an enhanced rendering engine, and improved CSS support. In addition, with the introduction of DHTML behaviors, it brings the benefits of encapsulation and extensibility to Web development. Finally, it provides a rich platform for applications through dynamic properties, client capabilities, persistence, mouse capture, and many other improved features.
 

From the September 1998 issue of Microsoft Interactive Developer.