Special Edition Using Microsoft® Visual Studio for Enterprise Development

Previous chapterNext chapterContents


- 18 -
Dynamic HTML

by Chris H. Striker

The exposed object model, with the comprehensive event model, allows you to control every aspect of your pages.
Not only can you control the elements of your pages, you can control the actual content of your pages.
You now can bind HTML elements to data sources via new data controls, create tables that automatically generate rows for each record of a data source, and exploit on- the-fly HTML regeneration based on sorts and filters, all without additional trips to the server.
Follow the instructions to create a sample page that demonstrates all the key features of Dynamic HTML.

As the number of World Wide Web users has increased, developers of web-based content have struggled to provide content that approximates the functionality, ease-of-use, and flexibility of traditional software applications. This has been no small task; the web's nature challenges the fundamental structure of application development. Over the years, various technologies have been introduced that help developers come closer to their goals: new HTML standards, Java applets, ActiveX controls, scripting, and so on. Nevertheless, because a fully exposed object model didn't exist, these technologies necessarily remained only partial solutions at best.

With Dynamic HTML, the landscape has changed. Web-based development is about to take a significant leap forward. Based on the Document Object Model that Microsoft proposed to the World Wide Web Consortium (W3C), Dynamic HTML offers to developers a comprehensive, fully exposed object model. Via Dynamic HTML, developers can create content that maximizes speed while maximizing interactivity--these are no longer necessarily mutually exclusive. Developers can create content that changes in response to user input without having to access the server. Ultimately, many restrictions to web-based development have been removed.

Overview of Dynamic HTML Features

In this chapter, you have an opportunity to create a single page that demonstrates all the key features of Dynamic HTML: dynamic content, dynamic styles, absolute positioning, multimedia effects, and data binding. To do so, you need to have installed Internet Explorer 4.0 for Windows 95 or Windows NT 4.0. This chapter also assumes that you're familiar with HTML 3.2 and VBScript.


ON THE WEB:Keep in mind that this chapter is a small tip of a relatively large iceberg; to fully take advantage of Dynamic HTML, you need to familiarize yourself with the contents of the Internet Client SDK. For a full treatment of the technologies discussed in this chapter, and especially for complete documentation regarding scripting with Dynamic HTML, refer to the Internet Client SDK from Microsoft at http://www.microsoft.com/workshop/prog/inetsdk/.

Dynamic Content

One chief restriction of web-based development has been that offering content to users is a one-shot deal. Users request a page, the web server processes the request and offers the page to users, users read the page and send further requests. Change to the page's content was severely limited; with the exception of objects embedded in the HTML (such as Java applets), the content was necessarily static. New content had to come as another page sent by the server. With Dynamic HTML, this has changed; developers can author pages that dynamically change their content in response to any of the events exposed by the event model, all without going back to the server. Dynamic HTML elements, as well as the information contained in elements, can be removed, added, or modified on-the-fly.

Dynamic Styles

Styles are specified by using Cascading Style Sheets (CSS) or as element attributes. With Dynamic HTML, developers can alter style information at runtime via scripting. Any attribute or property specified in a style can be altered--such as color, size, position, and visibility--all in response to any events exposed by the event model. Internet Explorer 4.0 supports "intelligent recalculation" so that the rest of the page responds to any changes; if a change to a particular section of the page forces other elements to move, Internet Explorer handles the moving.

Absolute Positioning

Another main difficulty that web developers have had to grapple with is the limit on the layout and design of pages. The positioning of elements on a page was restricted to the options offered by traditional HTML. Given this context, web developers made creative use of tables, frames, and other HTML constructs to present the illusion that their designs broke the boundaries of HTML. In the process, however, these developers spent considerable amounts of time and introduced unnecessary levels of complexity to "outsmart" HTML.

With absolute positioning, a page's layout is free from old limitations. You can now create attractive designs and user interfaces with the degree of flexibility programmers have come to expect from visual tools such as Visual Basic, Delphi, or Visual C++. The first step toward absolute positioning was taken by Microsoft with its HTML Layout Control--within the confines of the HTML Layout objects, developers were free to position objects anywhere on a 2D plane. Absolute positioning in Dynamic HTML represents the effort to move this capability to HTML itself, via an open standard. It allows positioning on x-y coordinates and z-planes, as well as with scripting animation.

Multimedia Effects

As a sort of "extra," Microsoft has offered developers a set of controls with Dynamic HTML that provides multimedia effects to HTML elements and demonstrates some of the eye- catching potential that Dynamic HTML affords. The following is a list of the controls and their descriptions:

Data Binding

Web pages have traditionally been a fairly weak means of accessing databases. Although developers have used CGI scripts and other means to provide some of the functionality users have come to expect from true client/server applications, many key elements have been absent. Every distinct view of data required a new request to a server, and there was no means of binding elements on web pages to a database. Also, users had to wait until a server built and sent an entire page containing data before they could view any of the contents. Finally, generating the HTML to present the data to users was often needlessly time-consuming and sometimes arduous.

Dynamic HTML addresses all the aforementioned limitations via several new data controls. When a page is accessed, Dynamic HTML knows how to regenerate content on-the-fly based on sorting and filtering user input without accessing the server. You can bind HTML elements and form fields to records or fields in records, allowing updates to data sources. You can write pages that begin displaying data as soon as the client receives the first record. Also, by linking HTML elements to a data control via DATASRC, DATAFLD, and DATAFORMATAS attributes, Dynamic HTML allows for automatic generation of table rows from data records. In short, Dynamic HTML provides a new level of database connectivity within the context of the web.

Now, Microsoft has plans for three data controls to be used with Dynamic HTML: the Tabular Data control (which accesses delimited text files), the Advanced Data control (which allows access to ODBC-compliant databases), and the JDBC control (which allows access to JDBC-compliant databases). Microsoft has indicated, as has been the case with ActiveX controls in general, that it expects other parties to develop data controls.


ON THE WEB:For the latest information about the Advanced Data control, visit Microsoft's site at http://www.microsoft.com/adc.

The Dynamic HTML Object Model

What makes all the preceding features possible is the exposed object model. Before Dynamic HTML, only a limited set of elements was available to developers for programmatic control. Only a small number of the attributes of HTML elements were available, as well as a limited number of events. With the introduction of Dynamic HTML, all elements on a web page are exposed to developers, as well as all attributes and a comprehensive set of events.


NOTE: The object model works with whatever scripting language you want to use, be it VBScript, JScript, or any other model-compliant language. Also, pages that use Dynamic HTML still display reasonably well in older browsers that don't support the proposed standard.

Dynamic HTML Object Model Tree

The hierarchy shown in Figure 18.1 in the Dynamic HTML Object Model exposes the highest-level objects in Internet Explorer. The highest-level object is the window object, which is the highest-level parent object to all other objects and elements within Internet Explorer. Via these objects, developers have what might be considered meta-level control of the browser relative to the actual content displayed.

FIG. 18.1
The top levels of the object model exposed by Internet Explorer for use with Dynamic HTML. The items in the object model are accessed by specifying the hierarchy; for example, to get at the links collection of the current document, you might use code such as window.document. links.

The location property references the address to which the browser points. By manipulating this object, the browser can be set to point to a different address. For instance, the following VBScript code sends the browser to the Microsoft home page:

window.location.href = "http://www.microsoft.com"

The history object represents the list of addresses the browser has recently visited. Via scripting, you can send user browsers backward or forward through the list, or take action based on the list's contents.

The navigator object, representing the browser, allows you to do a host of useful things. For instance, you can grab the name of the browser, the version of the browser, or the state of the Alt key; you also can check whether users have cookies enabled or Java enabled.

The read-only event property returns the event being addressed.

The visual object allows you to gather information about the users' viewing capabilities/preferences. With this object, you can determine the color depth at which users are viewing your page, the horizontal resolution, and the vertical resolution.

The document object addresses the actual contents of whatever page is loaded in the browser. Under the document object are collections for the following items:

links                 embeds
anchors               plugins
images                frames
forms                 scripts
applets

Other items of particular note are

Element Class and Collection

Within a page, every element is available for programmatic manipulation. Dynamic HTML exposes an element model through which all properties, methods, and events are made accessible to scripts. This access is facilitated by the organization of HTML elements. Since the earliest HTML standards, document tags have been arranged in a hierarchical structure. Consider this HTML code:

<HTML>
       <HEAD>
              <TITLE>Sample Page</TITLE
       </HEAD>
       <BODY>
              <H1>Section One</H1>
              <H2>Section Two</H2>
              <P><I>Sample Content</I></P>
       </BODY>
</HTML>

Here, the hierarchy is clear from the structure of the HTML itself. The <HEAD> and <BODY> tags are directly subordinate to the <HTML> tag. The <TITLE> tag is subordinate to the <HEAD> tag, the <H1> and <H2> tags are subordinate to the <BODY> tag, and so on.

The actual elements are made available to you via collections. Earlier, you read that all elements on a page are exposed through an all collection. To use the all collection via scripting, you might use code similar to this:

dim holdItem
holdItem = document.all(1)

This code would set the holdItem variable to the second element on the page.


NOTE: Keep in mind that an index for a collection always begins with zero and ends with (collection.length) - 1. The length property specifies how many members are in the specified collection.

Another way to grab elements via script is to grab an element by using the tag itself to access a subset of the all collection:

holdElement = document.all.tags("P").item(0)

This line grabs the first <P> element on the page.


NOTE: The item method is the default for a collection; you can specify it if you want, but the code works the same way if you omit item.

You can also use the name of the element, as specified in the id attribute for the element. If you wanted to grab this element,

<P id = "firstelement">Here is some sample code</P>

you might use VBScript like this:

holdElement = document.all.item("firstelement")

The all collection may be considered a good general-purpose tool; however, you can access particular sets of HTML elements via the aforementioned collections (links, anchors, images, forms, applets, embeds, plugins, frames, and scripts). Most are self-explanatory. The links collection allows access to the <A> elements that contain href attributes and the <AREA> elements. The anchors collection accesses the <A> elements containing name attributes. The images collection refers to the <IMG> elements; the forms collection accesses all <FORM> elements on a page. The applets, embeds, and plugins collections access their respective HTML elements. The frames collection addresses a page's frame structure, and the scripts collection accesses a page's <SCRIPT> elements.

Table 18.1 shows the properties available for every element. (There might be others for specific elements.)

Table 18.1  Element Properties Accessible to Scripts

Property Access Description
parentElement as Element read-only Returns the containing element in the structural tree.
tagName as read-only Returns the tag name represented by the String element. The tag name is returned uppercased.
ClassName as String read/write Returns the class specified for the element. Class is uppercased to avoid conflict with the reserved class name.
id as String read/write Returns the ID identifier for the element.
style as Style read-only Returns a style object representing the inline style for the element.
document as Document read-only Returns the document object containing the element.
left as Long read-only Returns the calculated position of the element in coordinates relative to the window.
top as Long read-only Returns the calculated position of the element in coordinates relative to the window.

Table 18.2 shows the methods available. (Again, there might be others for specific elements.)

Table 18.2  Element Methods Accessible to Scripts

Method Return Value Description
scrollIntoView(start as Boolean) none Scrolls the element to the first or last line of the display
contains(element as Element) Boolean Returns whether the supplied element is contained within the element's subtree
getMember(attribName as String) String Returns the persisted value for the specified attribute
setMember(attribName as String, value as Variant) none Sets the persisted value for the specified attribute
removeMember(attribName as String) none Causes the attribute to be removed and not persisted into the HTML document

The Event Model

The exposed event model is the last piece of the puzzle. Via the event model, you can create pages that respond to user actions. As was the case with the object model, a limited set of events has been available to developers in the past. With Dynamic HTML, the event model is fully fleshed out.

One of the most significant features of the event model is bubbling. As the event model adheres to the hierarchical nature of the object model, events bubble up through the hierarchy until they reach a handler that addresses them. This means you can write generic code that will handle onmouseover events for every element on the page, for instance. In the past, you would have had to specify the handler explicitly for every element individually.

Regarding bubbling, remember a couple of key points:

Suppose that you have an image (specified with the <IMG> tag) that you've given the ID parameter Image1. You might want a handler for the onclick event for the document as a whole, but a different handler that executes only when users click the Image1 image. In this case, you need to make certain that after the handler specific to the Image1 element fires, the event doesn't bubble up to the main document onclick handler. You can manage this with code such as the following:

<script language = "VBScript" for="document" event="onclick()">
     ElementID = window.event.srcElement.id
     Msgbox("This was processed by the document-wide handler.")
</script>
<script language = "VBScript" for "Image1" event = "onclick()">
     msgbox("This was processed by an element-specific handler.")
     event.cancelBubble = true
</script>

In binding events to scripts, you have three options:

<A onmouseover = "processrollover"language = "VBScript">
<SCRIPT FOR=... EVENT=... IN=... LANGUAGE=...>
<SCRIPT language = "VBScript">
Sub object_onmouseover
...
End Sub
</SCRIPT>

At this point, to take full advantage of scripting for Dynamic HTML, you need to delve deeper into the event object itself. Tables 18.3 through 18.7 contain detailed information on the event object, standard events, and element-specific events.


ON THE WEB:You also can find the information in Tables 18.3 through 18.7 in Microsoft's Internet Client SDK at http://www.microsoft.com/workshop/prog/inetsdk/.

Table 18.3  Event Object Properties

Property Permissions Description
altKey as Boolean read-only Returns whether the Alt key is pressed at the time of the event.
contains(element as Element) read-only Returns bitmask indicating which mouse buttons are pressed at the time of the event: 0 for none, 1 for left, 2 for right, 3 for both.
cancelBubble read/write Sets or returns whether the event should continue to bubble up through the container-ship hierarchy. True value on return from a handle cancels further event bubbling for only that event.
ctrlKey as Boolean read-only Returns whether the Ctrl key is pressed at the time of the event.
fromElement as Element read-only Returns the element that the mouse is coming from for the onmouseover and onmouseout events.
keyCode as Integer read/write Returns a standard numeric ASCII keycode for key events; if set by onkeypress, changes the character sent to the object.
returnValue as Variant read/write Sets or returns a return value to the event, a language-neutral way to return values to events, as some languages may not support event notifications as functional routines.
shiftKey as Boolean read-only Returns whether the Shift key was pressed at the time of the event.
srcElement as Element read-only Returns an element object representing the element that first received the notification before it started to bubble.
toElement as Element read-only Returns the element that the mouse is going to for the onmouseover and onmouseout events.
x as Long read-only Returns the horizontal position of the mouse with respect to the origin of the document's physical location at the time of the event.
y as Long read-only Returns the vertical position of the mouse with respect to the origin of the document's physical location at the time of the event.

Table 18.4  Keyboard Events

Event Name(Parameters) Return Value Description
onkeydown(keycode as integer, shift as htmlShift) none Fired when a key goes down.
onkeypress(keyCode as integer) Change keyCode to 0 to cancel Fired when a key is pressed. Changing event.keyCode or integer return value changes the character.
onkeyup(keyCode as integer, shift as htmlShift) none Fired when a key goes up. Note that for a shift key, the key is up and so shift state is off accordingly.
onhelp none Occurs when help key (F1) is pressed.

Table 18.5  Mouse Events

Event Name(Parameters) Return Value Description
onmousedown(button as htmlButton, shift as htmlShift, x as long, y as long) none Fired when the left mouse button goes down over the element.
onmousemove(button as htmlButton, shift as htmlShift, x as long, y as long) none Fired when the mouse moves over the element.
onmouseup(button as htmlButton, shift as htmlShift, z as long, y as long) none Fired when the left mouse button goes up over the element.
onmouseover none Fired when the mouse enters the element.
onmouseout none Fired when the mouse exits the element.
onclick false to cancel default action Fired when users left-click the element. A click event can also occur when Enter is pressed on a focusable element. The click event follows the onmouseup event when it occurs as a result of a mouse button. For a mouse with one button, the button is considered the left mouse button.
ondblclick none Fired when users double-click the element. The system determines the timing between what constitutes two click events or a click and a double-click.

Table 18.6  Focusable Element Events

Property Name (Parameters) Return Value Description
onfocus none The element is receiving the focus.
onblur none The element is losing the focus.

Table 18.7  Element-Specific Events

Event Name (Parameters) Supported Object(s) Return Value Description
onabort <IMG> none Occurs if users abort the download of the image. To abort an image, click a link, click the stop button, and so on.
onbounce(side as String) <MARQUEE> none Occurs when marquee with behavior equal to alternative text hits edge, "bottom", "left", "right", or "top".
onchange <INPUT TYPE= CHECKBOX>,
<INPUT TYPE= FILE>
,
<INPUT TYPE = RADIO>,
<INPUTTYPE= TEXT>
,
<SELECT>, <TEXTAREA>
none Occurs when the contents of the object change. This event is fired when the contents are committed, not while the value is changing. For example, for a text box, this event isn't fired while users type, but rather when they commit their changes by pressing Enter or leaving the text box's focus. This code is executed before the code specified by onblur, if the control is also losing the focus.
onerror <IMG> none Occurs when an error happens when loading an image element.
onfinish <MARQUEE> none Occurs when motion is complete.
onload <IMG>, document window none Occurs when the element is completely loaded.
onreadystatechange <APPLET>,<EMBED>, <FRAME>, <IFRAME>,<IMG>, <OBJECT>, <SCRIPT SRC=...>, document none Occurs whenever the state of the element changes. This is a more detailed version of the onload event. Check the readyState property for the element. The different states causing this event to be fired occur when the element is loading, when the element is still loading but is now firing events and can be interacted with, and when the element is completely loaded.
onreset <FORM> none Occurs when users reset a form. The onreset event handler executes code when a reset event occurs.
onscroll(scrollParam as scrollObject) none Fired on elements that have an overflow mechanism specified through the overflow CSS attribute. Occurs when the element is scrolled; event doesn't bubble.
onselect <INPUT TYPE = PASSWORD>, <INPUT TYPE= TEXT>, <TEXTAREA> none Occurs when the text selection on a text element changes.
onsubmit <FORM> none Occurs when a form is about to be submitted (the onsubmit event default action is to submit the form). Event can be overridden by returning false in the event handler. Purpose is to allow client-side validation.
onunload window none Occurs immediately before the page being unloaded.
onselectionchange document none Fires on the document when the user's selection changes.
onzoom(zoomPercent as integer) document Return integer to override the percent of the zoom Fires on the window whenever the window is zoomed.

Accessing Document Content

To Dynamic HTML, the content of a page is a single stream of text that begins and ends with the <BODY> tag. The textRange object representing this stream can be manipulated to alter the content on the page. Very few pages, however, offer a stream of text between <BODY> tags with no other elements in between. This is good news for you if you want to manipulate the actual content of a page. The elements between <BODY> tags provide an easy way to break down that stream into easily manipulated component parts.

Keep in mind that the textRange object doesn't automatically exist--you need to create it explicitly by using the createTextRange method. After you create a textRange, methods exist with which you may change the start and end positions, search, or modify all or part of the range. The most basic way to create a text range containing the entirety of a page (everything between the opening and closing <BODY> tags) is a line of VBScript such as


Set newRange = document.body.createTextRange()

The textRange object itself exposes five properties and a number of methods, as shown in Tables 18.8 through 18.11.

Table 18.8  textRange Object Properties

Property Name Description
end Sets or returns the end-character position in relation to the entire stream. If this is set less than the start value, start is also set equal to this value.
start Sets or returns the start-character position in relation to the entire stream. If start is greater than end, end is also set equal to this value.
htmlSelText Returns the raw HTML for the selected text.
htmlText Returns the valid HTML fragment for the text.
text Sets and returns the text for the range without any of the HTML markup.

Table 18.9  textRange Object Methods

Method Description
CommonParentElement Returns the common parent element for the range.
executeCommand(cmdID as long, value as Variant) Executes a command on the range--for example, changing the text formatting. The following methods provide information when executing command IDs: queryCommandState, queryCommandEnabled, and queryCommandText.
duplicate Returns a copy of the current range.
isEmbed ([cp as Integer]) as Boolean Returns a Boolean that represents whether the specified character is an embedded object. If true, the parentElement method can be used to access the embedding.
parentElement([cp as Integer]) as Element Returns the parent node for the specified character. The character position is scoped to the current range.
inRange (compareRange as Range) as Boolean Returns whether the specified range is within or equal to the current range.
isEqual (compareRange as Range) as Boolean Returns whether the specified range is equal to the current range.
scrollIntoView(start as Boolean) Scrolls the range into view.

Table 18.10  textRange Object Range Movement Methods

Method Name Description
collapse (start as Boolean) as long Allows you to create an empty range at the beginning or end of the current range.
expand (unit as htmlUnit) as long Expands the range so that partial units are completely contatined.
move (unit as htmlUnit, [count as Variant]) as long Changes the text the range spans over. Doesn't move any text, but instead is used to change what text the range is over.
moveEnd (unit as htmlUnit, [count as Variant]) as long Causes the range to grow or shrink from the end of the range.
moveStart (unit as htmlUnit, [count as Variant]) as long Causes the range to grow or shrink from the beginning of the range.
setRange (begin as long, end as long) Sets the range to the ordinal offsets specified by the method. The offsets are within the scope of the current range.

Table 18.11  textRange Object: Inserting Text

Method Name Description
pasteHtml (string) Pastes HTML into the current range. The HTML is forced to fit the current context of the document.
Two more methods are particularly useful when working with textRanges: rangeFromText and rangeFromElement.

rangeFromText

The rangeFromText method is used in this fashion:

document.rangeFromText(text as String, Optional count as Long, Optional flags,range as Object) as TextRange

This method is useful for creating text ranges based on a search through the content of a page for a specific known string of text. Table 18.12 lists the parameters.

Table 18.12  rangeFromText Parameters

Parameter Name Default If Not Supplied Description
count Search forward The string to search for
Flags No flags >0 to search forward, <0 to search backward, =0 to search only within the supplied range or selection if no range is supplied
Range Start from current insertion point The range to search in

rangeFromElement

The rangeFromElement method creates a text range from the contents of a known element. The method takes only one parameter--the element to be searched for. If you had an element with a specified ID such as

<strong id=firstelement>Sample Text</strong>

and wanted to create a textRange object that contained Sample Text, you could use the rangeFromElement method like this:

Set holdRange = document.body.rangeFromElement(document.firstelement)

Data Binding in Dynamic HTML

As mentioned earlier in the overview of Dynamic HTML features, data binding is accomplished via the use of new data controls and three new attributes: DATASRC, DATAFLD, and DATAFORMATAS.

The New Attributes

The DATASRC attribute specifies the data control to which HTML elements are being bound by referencing the ID of the data control. It applies to only the TABLE, SPAN, DIV, OBJECT, PARAM, INPUT, SELECT, TEXTAREA, IMG, and MARQUEE elements. If you have a data control with an ID attribute of dcOne on your page, you can bind a table to it with HTML like this:

<TABLE DATASRC="#dcOne">


NOTE: Remember that in using the DATASRC attribute for tables, you need to put a number sign in front of the ID.

The DATAFLD attribute specifies the field in a record to which an HTML element is being bound. It applies only to the SPAN, DIV, OBJECT, PARAM, INPUT, SELECT, TEXTAREA, IMG, and MARQUEE elements. If you want to specify a cell in a table to which to bind a field in a record from a data source, you could specify it as follows:

<TD><SPAN DATAFLD="CompanyName">

where "CompanyName" is the name of the field.

The DATAFORMATAS attribute specifies what kind of data is being bound. You can specify "html" for data to be considered a string of HTML, "text" for data to be considered text, and "none" if the data is to be taken in raw format. It applies only to the SPAN, DIV, and MARQUEE attributes.

The Data Consumers

Data consumers are the HTML elements that support current record binding (referred to as the elements to which the preceding attributes apply). The following list provides descriptions of the data consumers, with indications as to whether they support editing:


NOTE: Now, only the Advanced Data Connector supports editing; the Tabular Data Control used in the Sample Page later in the chapter doesn't.

The Data Events

To allow for modifications and updates to data, you need a way to perform client-side validation before the data control sends information to the data source. To cancel an event (for events that can be canceled), you need only to return FALSE by the handler. What follows is a description of the various events:

Building a Sample Page

In this section, you'll build a page that demonstrates most key features of Dynamic HTML: the absolute positioning of various elements on the page, the application of a transition to a graphic element, the dynamic change of a page's content and styles, the display and hiding of content sections, the response to user events on HTML elements, the control of HTML with scripting via the object model, and the access to a data source via the Tabular Data control.

While building this page, keep in mind that before Dynamic HTML, you typically would have to build several pages to provide the same degree of functionality and content. What's more, users would have to request these pages one at a time from a web server, slowing the process considerably.

Step 1: Starting the Project

Before you begin creating your Dynamic HTML page, you need to be set up to work within a web project in Visual InterDev. You must have access to a computer running Personal Web Server (on computers running Windows 95), Peer Web Services (on computers running Windows NT Workstation) or IIS 3.x (on machines running Windows NT Server). The computer must have the FrontPage Server Extension installed. As you develop your web further, you may find that you need Active Server Pages installed as well. You can install the various web servers from your operating system installation discs and the FrontPage extensions and Active Server Pages from the Visual InterDev setup.

You also will need to have Internet Explorer 4.0 installed. There are several installation options, but everything in the sample page you'll build will work with any of the installations.

If you've already created a web with Visual InterDev, you can use that web to develop, test, and implement your Dynamic HTML page. If this is the case, start Visual InterDev and open your web project. Otherwise, follow these steps to create a new web project on your web server:

1. Start Visual InterDev.

2. Choose File, New from the menu.

3. Select the Projects tab in the New dialog box.

4. Select the Web Project Wizard to create a new web project.

5. Enter the name for your new web project in the Project Name text box.

6. Click OK.

7. Enter the name of your web server in the Server Name combo box.

8. Select the option to Create a New Web.

9. Select the option to Enable Full Text Searching for pages in the web.

10. Ensure that the name for your web has been entered in the Name text box.

After you open a web project in Visual InterDev, you need to create a new HTML file:

1. Choose File, New from the Visual InterDev menu.

2. Select the Files table in the New dialog box.

3. Select HTML Page.

4. Select Add to Project.

5. Ensure that the path to your web is entered in the drop-down box.

6. Enter the name for your new HTML file in the File Name box.

7. Click OK.

At this point, you have a new HTML file defined in your web. Your screen should look similar to the one in Figure 18.2.

FIG. 18.2
The Visual InterDev environment with a new HTML file open for editing. Notice that Visual InterDev has created a global.asa file, a search.htm file, and an images directory for your new web.

Step 2: Adding the Template

To facilitate building your Dynamic HTML page, replace the comment Insert HTML here with the placeholder comments in Listing 18.1.

Listing 18.1  Dynamic HTML template


<!-- HTML for logo -->
<!-- Transition Object -->
<!-- HTML for menu -->
<!-- HTML for sections -->
<!-- HTML for popup window -->
<script language = "VBScript">
`page-level section array variable
`routines to call transition filter upon window load
`routines to process mouseover and mouseout events
`routine to display/hide sub-menu items upon click event
`routine to display content layers upon click event
`routines to handle popup window upon mouseover and mouseout events
`routine to sort table contents via tabular data control

</script>

At this point, the HTML for your page should resemble Figure 18.3.

FIG. 18.3
HTML with placeholder comments. As you build the sample page, you may want to leave the comments in so that you have placeholders marking the various sections of HTML and VBScript.

After adding the template, add the following attributes to the <BODY> tag:

Step 3: Adding the Graphic

As you build your page, you'll replace the placeholder comments with HTML code and VBScript code. The first task is to place the HTML for the image at the top of the page. Replace the comment HTML for logo with the HTML in Listing 18.2.

Listing 18.2  HTML for the Logo Graphic

<img id = "logo" src = "logo.gif" alt="Arcadia Bay"
style="visibility: hidden;" border=0>

Replace the logo.gif filename with a file of your own choosing. If the file you want to use doesn't reside in the same physical directory as your HTML page, you'll need to specify the path to your file (for instance, images/mylogo.gif).

At this point, you can view the page as you develop it by opening the file in Internet Explorer or by previewing it in Visual InterDev. To preview the page in Visual InterDev, right-click anywhere in the file editing window and then choose Preview <filename> from the context-sensitive menu.

This will open the InfoViewer Topic window, which acts as Internet Explorer in this case. This window lets you view and use your page from within Visual InterDev just as you would in a separate instance of Internet Explorer.

Notice that nothing appears on the page, because the style attribute in the <img> tag for the graphic specifies visibility: hidden. If you aren't already familiar with styles, you may want to review the specification for Cascading Style Sheets and their use with Internet Explorer. To view the graphic, remove the style attribute altogether (remember to replace it if you do so).

Step 4: Adding the Transition to the Graphic

The method you used to include a graphic on your page is fairly standard. It's also boring. Traditionally, web designers have used techniques such as animated GIFs, Java applets, and Shockwave objects to spice up their pages; Dynamic HTML dramatically expands the available options. With the new multimedia ActiveX controls (included with Internet Explorer and installed automatically during setup), you have a wide range of effects to choose from.

Here, you'll apply a transition filter to the graphic so that it dissolves into view when the page is accessed. Replace the comment Transition Object with the HTML in Listing 18.3.

Listing 18.3  HTML for the Transition Object

<OBJECT ID="dissolvein"
CLASSID="CLSID:F0F70103-6A8F-11d0-BD28-00A0C908DB96">
<PARAM NAME="Transition" value="12">
<PARAM NAME="RESTOREBITS" VALUE="0">
</OBJECT>

You've specified the Visual Transition ActiveX control for inclusion on the page. However, if you view your page now, you'll notice that nothing has changed; your graphic doesn't dissolve into view because nothing on the page links the graphic to the control. To create the link that tells the control to direct the display of the graphic, you need to use scripting.


NOTE: The choice of VBScript, JavaScript or another scripting engine is up to you if your target platform includes only the Microsoft browser. Because the object models for Internet Explorer and Dynamic HTML are open, you can choose any engine you like that can address the models. The examples here are presented in VBScript; feel free to translate into another language if you feel more comfortable doing so.

To link the Visual Transition ActiveX control to the graphic, replace the comment routines to call transition filter upon window load with the VBScript in Listing 18.4.

Listing 18.4  VBScript Routines to Handle Transition

Sub Window_onLoad()
     logo.style.visibility = "hidden"
     call dissolveLogo()
end sub
sub dissolveLogo
     logo.stopPainting(dissolvein)
     logo.style.visibility = ""
     logo.startPainting(1500)
end Sub

If you preview the page now, you should see the graphic dissolve into view. You can control the rate at which the dissolve occurs by changing the parameter for the startPainting method in the dissolveLogo routine.

In Internet Explorer 3.x, a degree of control over the presentation of HTML was available to programmers via scripting. Because the object models weren't fully exposed, this control was necessarily limited. This is no longer the case. Here, VBScript code is accessing the graphic via the ID specified in the <img> tag (logo). Later, you'll see how to use the object model hierarchy to access HTML elements on the page without specifying their ID attributes explicitly. For now, notice that the VBScript routines you just added reference the element with the ID logo, clear the visibility: hidden style setting, and run the graphic through the startPainting method of the Visual Transition ActiveX control. This wouldn't be possible without the object model that Dynamic HTML exposes.

Step 5: Adding the Menu

The next step is to add a menu with items that highlight when the mouse rolls over them to your page. To add the menu structure, replace the comment HTML for menu with the HTML code in Listing 18.5.

Listing 18.5  HTML for the Menu Layer

<div id = "menu" style = "position:absolute;left:20;top:75">
<font face = verdana size = 2 color = midnightblue>
<!-- onclick events will go within the a tags below shortly -->
<a id = "one" onmouseover = "processover" onmouseout = "processout"
language = "VBScript">Company History</a><br>
<a id = "two" onmouseover = "processover" onmouseout = "processout"
language = "VBScript">Consultants</a><br>
<!-- insert the html for the submenu here -->
<a id = "three" onmouseover = "processover" onmouseout = "processout"
language = "VBScript">Partners</a><br>
</font>
</div>

Notice that the entire structure begins and ends with <div> tags, which mark the contained HTML as a separate chunk of elements that can be positioned independent of the rest of the items on the page. As you build this page, notice that the remaining HTML falls within <div> tags as well. This way, you can control which chunks of HTML are displayed at any given time.

The opening <div> tag contains the information Internet Explorer 4.0 needs to position the menu on the page. The style attribute specifies absolute positioning with pixel locations for the left and top edges. By changing these settings, you can force the menu to appear anywhere on the page.

If you previewed your page at this point, the menu would appear but simply sit there. This is another point at which developers traditionally had to turn to a Java applet or similar technique to provide feedback to users. Again, by exposing the HTML object model, developers can achieve the same result with much less work. Notice that the <a> tags enclosing the menu items contain id parameters and references to routines that handle the onmouseover and onmouseout events. You'll now add these routines. Replace the comment routines to process mouseover and mouseout events with the VBScript routines in Listing 18.6.

Listing 18.6  VBScript Routines to Handle Highlights

Sub processover
     heldID = window.event.srcElement.id
     set heldObj = document.all(heldID)
     heldObj.style.color = "limegreen"
End Sub
Sub processout
     heldID = window.event.srcElement.id
     set heldObj = document.all(heldID)
     heldObj.style.color = "midnightblue"
End Sub

Preview your page again. This time, roll the mouse pointer over the menu items. Notice that they provide feedback by highlighting when the mouse is over them. This is precisely the sort of feedback that was far more difficult to achieve before Dynamic HTML. Make sure that your page looks similar to Figure 18.4.

Look at the routines that provide this functionality--processover and processout. Recall that the routine that handled the link between the graphic and the Visual Transition ActiveX control referenced the <img> tag explicitly by its id attribute; notice that these routines don't, although they work for each of the three menu items. This is possible because of the event model and the all collection.

When an event fires, it's sent up through the event model hierarchy until it reaches a handler or reaches the top level without having found a handler, at which point it disappears. In this case, the onmouseover and onmouseout events have handlers specified in the <a> tags. Within the handlers, the first line of code grabs the ID for the element on the page that fired the event. The construct window.event.srcElement.id references the ID for the element that fired the event that's traveling up the event hierarchy in the current window. The next line sets an object variable (holdObj) to the element that has that ID by looking through the all collection for the document (the all collection can be considered a list of all the elements on the page). When the routine sets the object, it sets the color property through the style collection.

FIG. 18.4
Page with logo and menu in Internet Explorer, with a menu item highlighted. Feel free to play with various fonts, colors, and graphics as you build the sample.

Step 6: Adding the Submenu

Designing navigation structures for web sites has always been tricky--especially for larger sites. Developers have made innovative use of frames, tables, Java applets, ActiveX controls, and other objects in their quest for flexible, intuitive navigation. Dynamic HTML makes the process of developing such structures far easier. In this step, you'll add code for a submenu to your existing menu.

To begin, add the HTML for the submenu itself to your page. Replace the comment insert the html for the submenu here with the HTML in Listing 18.7.

Listing 18.7  HTML for the Submenu

<div id = "twochild" style = "display:none">
<font size = 1>
<a id = "four" onmouseover = "processover" onmouseout = "processout"
language = "VBScript">&nbsp;&nbsp;capabilities</a><br>
<a id = "five" onmouseover = "processover" onmouseout = "processout"
language = "VBScript">&nbsp;&nbsp;directory</a><br>
<font size = 2>
</div>

Notice that this chunk of HTML is contained within a <div> tag that has an id of "twochild". The "twochild" ID is arbitrary--you can name it anything you want. In this case, the name makes it easy to address this element when the element with the ID "two" is clicked. The <a> tags contain references to the same onmouseover and onmouseout events that you used before; the items on the submenu will highlight the same as the elements on the main menu. Last, notice that the display style attribute is set to none. When you first view the page, the submenu won't show up.

Now add the code that makes the submenu work. First, replace the comment routine to display/hide sub-menu items upon click event with the VBScript routine in Listing 18.8.

Listing 18.8  VBScript Routine to Display/Hide the Submenu

Sub expandit
     heldID = window.event.srcElement.id & "child"
     set heldObj = document.all(heldID)
     if heldObj.style.display = "none" then
          heldObj.style.display = ""
     else
          heldObj.style.display = "none"
     end if
End Sub

Next, add a reference to the expandit routine that you just added to the page. You want the routine to be called when users click the second top-level menu item. Change the <a> tag with the ID "two" so that it reads as in Listing 18.9.

Listing 18.9  Addition of onclick Event Reference to HTML <a> Tag

<a id = "two" onclick = "expandit" onmouseover = "processover"
onmouseout = "processout" language = "VBScript">

Preview your page. Try clicking the second menu item. You should see the submenu appear and the items highlight when you pass the mouse pointer over them (check your screen against Figure 18.5). Note the method by which the expandit routine gets the ID for the submenu--it gathers the ID of the element on which users clicked and appends child to the ID. It then looks through the all collection for that new ID. This way, you can handle submenu items for each item on the top-level menu, submenu items for each item on the submenus, and so on, all with the same script. Because the submenu is contained within <div> tags nested inside the <div> tags for the top-level menu, when the submenu displays, the rest of the menu moves down automatically (Dynamic HTML handles this for you).

FIG. 18.5
The submenu visible on the page, with an item highlighted. As you build the sample, think of ways to further cust-omize your page. For instance, you might want to make it so that the top-level items stay highlighted when expanded.

Step 7: Adding the Content Layers

Now that your navigation structure is complete, you need to add the content layers that will display when you click their respective menu items, as well as the functionality that controls their display. To begin, replace the comment HTML for sections with the HTML in Listing 18.10.

Listing 18.10  HTML for Main Content Layers

<div id = "partone"
style = "position:absolute;left:180;top:75;visibility:hidden;width:440">
<font face = verdana size = 4 color = midnightblue>
<p align = right>Company History<br>
<font size = 2>
<p align = left>
Placeholder for information about the company<p>
</font>
</div>
<div id = "partthree"
style = "position:absolute;left:180;top:75;visibility:hidden;width:440">
<font face = verdana size = 4 color = midnightblue>
<p align = right>Partners<br>
<font size = 2>
<p align = left>
Placeholder for general information about partnerships.
Sample partner program:<br>
<ul>
<li>
<!-- surround the following line with <a> tag to trigger popup -->
<font color = indianred>Microsoft<font color = midnightblue>
Solutions Provider Channel
</ul>
</font>
</div>
<div id = "partfour"
style = "position:absolute;left:180;top:75;visibility:hidden;width:440">
<font face = verdana size = 4 color = midnightblue>
<p align = right>Consultants - Capabilities<br>
<font size = 2>
<p align = left>
Sample information about consultant capabilities<p>
</font>
</div>
<div id = "partfive"
style = "position:absolute;left:180;top:75;visibility:hidden;width:440">
<font face = verdana size = 4 color = midnightblue>
<p align = right>Consultants - Directory<br>
<font size = 2>
<p align = left>
<!-- Tabular Data Control -->
<!-- HTML for sort controls -->
<!-- HTML for table bound to data source -->
</font>
</div>

Observe that the IDs for the sections you just added correspond to the items in your menu structure. They appear when their respective items are clicked and are hidden when other items are clicked. Also notice that the HTML you just added contains new comments, which will be replaced as you add more functionality to your page. Now add the rest of the code that displays the content layers.

First, you need to change the <a> tags referenced in Listing 18.11 to include the processclick() onclick event.

Listing 18.11  Changing the Menu Item <a> Tags to Add a processclick() Event Reference

<a id = "one" onclick = "processclick(1)" onmouseover = "processover"
onmouseout = "processout" language = "VBScript">
<a id = "three" onclick = "processclick(3)" onmouseover = "processover"
onmouseout = "processout" language = "VBScript">
<a id = "four" onclick = "processclick(4)" onmouseover = "processover"
onmouseout = "processout" language = "VBScript">
<a id = "five" onclick = "processclick(5)" onmouseover = "processover"
onmouseout = "processout" language = "VBScript">

Notice that the calls to the processclick() routine include an index into an array. You need to add VBScript code to your page that provides the values for this array. What's more, this array and its contents need to be accessible to the entire page, as opposed to being accessible to just the routine you're calling (the array needs to have page-level scope). Replace the comment page-level section array variable with the VBScript code in Listing 18.12.

Listing 18.12  VBScript Code for a Page-Level Section Array Variable

Dim section(5)
section(1) = "one"
section(2) = "two"
section(3) = "three"
section(4) = "four"
section(5) = "five"

Finally, you need to add the actual processclick() routine itself. Replace the comment routine to display content layers upon click event with the VBScript routine in Listing 18.13.

Listing 18.13  VBScript Routine to Handle Menu Item Click Events

Sub processclick(num)
     for x = 1 to 5
          if x <> num and x <> 2 then
               set holdObj = document.all("part" & section(x))
               holdObj.style.visibility = "hidden"
          end if
     next
     set holdObj = document.all("part" & section(num))
     holdObj.style.visibility = "visible"
End Sub

The processclick() routine loops through the index values into the section array. It grabs the ID for each element that wasn't clicked, appends part to the beginning, and sets the visibility to hidden. If the index number is 2 or the index clicked, the routine skips it (there's no "parttwo" content section, and you don't want to hide the one users clicked). The routine then grabs the ID for the one users did select, adds part to the beginning of the ID, and sets the visibility to visible for the section referenced by that ID alone. Try viewing the page to confirm that the content sections are displaying appropriately (check your page against Figure 18.6).

FIG. 18.6
A content layer exposed on the page. Again, this might be a good place for customization. You might want to make Company History remain highlighted so that you wouldn't need the title in the actual content layer.

Step 8: Adding the Pop-Up Window

Another challenge that web developers have had to face is the display of what can be a great deal of information. Users generally don't like to have to scroll through unwieldy amounts of information to get to what they want to see. Users also don't like to have to jump from page to page repeatedly to avoid scrolling. Dynamic HTML offers developers an easy way to design pages that get around both problems. In this step, you'll add a pop-up window that will appear when users pass the mouse pointer over a particular page section. To get started, replace the comment HTML for popup window with the HTML in Listing 18.14.

Listing 18.14  HTML for the Pop-Up Window Layer

<div id = "popup"
style = "position:absolute; left:50; top:305; visibility:hidden;width:550">
<center>
<table width = 550 border = 4 rules = none
bordercolor = midnightblue cellspacing = 0
cellpadding = 10 bgcolor = cornsilk>
<tr><td>
<font face = verdana size = 1 color = midnightblue>
<p id = "popuptext">sample text</p>
</font></td></tr>
</table></center>
</div>

Again, the code begins and ends with <div> tags. The opening <div> tag contains the same sort of absolute positioning information that you've used with other sections. Remember, you can change all these items programmatically; in this example, however, you'll be leaving the positioning attributes alone.

Next, you need to add the VBScript routine that displays and hides the pop-up window. Replace the comment routines to handle popup window upon mouseover and mouseout events with the VBScript code in Listing 18.15.

Listing 18.15  VBScript Routines to Display/Hide Pop-Up Layer

Sub processpopup(whichone)
     Set popupElement = document.rangeFromElement(popuptext)
     If whichone = "microsoft" Then
          holdText = "Some info about Microsoft Solution Provider Partners."
     End If
     popupElement.pasteHTML(holdText)
     popup.style.visibility = "visible"
End Sub
Sub wipepopup
     popup.style.visibility = "hidden"
End Sub

Finally, locate this HTML that follows the comment surround the following line with <a> tag to trigger popup:

<font color = indianred>Microsoft&nbsp;
<font color = midnightblue>Solutions Provider Channel

Add the <a> tag so that it reads as in Listing 18.16.

Listing 18.16  HTML After Modification to Include Calls to Event Handlers to Handle the Pop-Up Window

<a onmouseover = "processpopup(`microsoft')" onmouseout = "wipepopup"
language = "VBScript"><font color = indianred>Microsoft
<font color = midnightblue> Solutions Provider Channel</a>

The processpopup() routine first creates a text range from the <p> tag within the HTML for the pop-up window itself. The routine then takes the parameter that's passed when the routine is called and assigns the correct message to a variable. The routine then uses the pasteHTML method to change the text within the text range to the new text. Keep in mind you can paste HTML as well as plain text into the element. Finally, the routine displays the pop-up window. The wipepopup routine simply hides the window when the mouse exits the area that called the processpopup routine. Preview your page and check it against Figure 18.7.

FIG. 18.7
The pop-up window. Another idea for customization is to make the pop-up window remain onscreen after the mouse moves off Microsoft, but allow users to drag it any place in the browser and click it to make it disappear.

Step 9: Adding the Data Connection and Bound Data Fields

Web pages become truly useful when they can access data on a server. For quite a while, developers used CGI scripts to access data. More recently, various technologies have been introduced to allow for database connectivity, such as Microsoft's Internet Database Connector and ActiveX Data Objects (ADO). These technologies required round trips to the server to get new data based on the application of filters, sorts, and queries.

With Dynamic HTML, Microsoft has introduced two new controls with which to access data via completely different means. With the Tabular Data control and the Advanced Data Connector, developers can bring down entire sets of data in one request from the server. Furthermore, page elements can now be bound to the data. By using these controls, developers can create pages that grab data once, present controls to users with which to select and sort subsets of the data, and redraw the page to reflect changes, all without returning to the server. Developers can also allow updates and additions to data sources via the bindings. These capabilities represent a fundamental change in the context of the web; in the near future, the line between web sites and applications that had previously been so distinct will fade away altogether.


ON THE WEB:The Advanced Data Connector and its use is beyond the scope of this chapter. See Microsoft's web site at http://www.microsoft.com/adc for information on the ADC.

In this example, you'll use the Tabular Data control; it's far easier to use quickly and is sufficient to demonstrate the principles of binding and refreshing without returning to the server. You'll build a table bound to a data source that will display when users click the directory submenu item. First, you need to ensure that your data source is in place. Make a file called data.txt from the comma-delimited text in Listing 18.17.

Listing 18.17  Data File for the Data Source

FirstName,LastName,Address,City,State,Zip,Phone,Fax,EMail
Chris,Stevens,102 NE Bernard Street,St.Louis,Missouri,63102,555-9348,555-9283,cstevens
Lud,Mises,1 Chicago Avenue,St. Louis,Missouri,63182,555-3849,555-2893,lmises
Maxwell,Roach,383 Waltz Street,Cincinnati,Ohio,83728,555-2938,555-8827,mroach
Ray,Snyder,83 First Street,Kansas City,Kansas,77363,555-8837,555-8837,rsnyder

Ensure that the data file is in the same directory as your page. Next, you need to place the Tabular Data control object. Replace the comment Tabular Data Control with the HTML in Listing 18.18.

Listing 18.18  HTML for the Tabular Data Control Object

<OBJECT ID=TDC1 CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83" WIDTH=0 HEIGHT=0>
<PARAM NAME=DataURL Value="Data.txt">
<PARAM NAME=TextQualifier Value=",">
<PARAM NAME=UseHeader Value=True>
</OBJECT>

The DataURL parameter specifies your data source, the TextQualifier parameter specifies what character is being used to delimit your data, and the UseHeader parameter specifies whether the first line of your data source contains field names. Next, you need to add the HTML for the table itself. Replace the comment

HTML for table bound to data source

with the HTML in Listing 18.19.

Listing 18.19  HTML for a Table with Cells Bound to the Tabular Data Control

<center>
<TABLE ID=Table1 DATASRC=#TDC1 border = 0 width = 440>
<TBODY>
<TR><TD width = 440 colspan = 2 bgcolor = midnightblue>
<font face = verdana size = 2 color = white>
<strong><SPAN DATAFLD=FirstName></SPAN>
&nbsp;<SPAN DATAFLD=LastName></SPAN></strong>
</TD></tr>
<tr><TD width = 220>
<font face = verdana size = 2 color = midnightblue>
<SPAN DATAFLD=Address></SPAN></TD>
<TD width = 220>
<font face = verdana size = 2 color = midnightblue>
Phone:&nbsp;<SPAN DATAFLD=Phone></SPAN>
</TD> </TR>
<tr><TD>
<font face = verdana size = 2 color = midnightblue>
<SPAN DATAFLD=City></SPAN>,&nbsp;
<SPAN DATAFLD = State></SPAN>&nbsp;
<SPAN DATAFLD=ZIP></SPAN></TD>
<TD><font face = verdana size = 2 color = midnightblue>
Fax:&nbsp;<SPAN DATAFLD=Fax></SPAN>
</TD></TR>
<tr><TD>
<font face = verdana size = 2 color = midnightblue>
&nbsp;
</TD><TD>
<font face = verdana size = 2 color = midnightblue>
EMail:&nbsp;<SPAN DATAFLD=EMail></SPAN>
</TD></TR>
</TBODY>
</TABLE>
</center>

Preview the page and select the directory submenu item. Check your file against Figure 18.8.

Now look back at the HTML for the table. Notice that the HTML specifies only table cells for a single record from the data source. When a table is bound to a data source with the DATASRC attribute (in the <TABLE> tag), Dynamic HTML knows to repeat the contents of the table enough times to display all the data in the data source. The actual fields in the data source are referenced with the DATAFLD attributes in the <SPAN> tags. The <SPAN> tag tells Internet Explorer that it contains a distinct unit; the DATAFLD attribute within the tag indicates that this field will be acquired from the data source specified by the DATASRC attribute in the <TABLE> tag. Aside from these additions, the rest of the code for the table is standard HTML. Note that the HTML that defines the table is contained within the <DIV> tags for the section with the ID partfive.

Step 10: Adding Sort Capability to the Data Presentation

At this point, the display of data is static; it allows no user interactivity. The last step is to add controls that allow users to sort the data. Typically, this is when you would have to assume a trip back to the server; with Dynamic HTML, this trip is no longer necessary. First, add the table that contains the sort controls. Replace the comment HTML for sort controls with the HTML in Listing 18.20.

FIG. 18.8
A table containing bound data. Here, you might make the email field a link that users could click to send email automatically.

Listing 18.20  HTML for a Table Containing Sort Controls

<table width = 440 border = 4
bordercolor = midnightblue rules = none
cellspacing = 0>
<tr><td valign = top bgcolor = midnightblue
colspan = 4>
<font face = verdana size = 1 color = white>
<strong>Sort:</strong>
</font></td></tr>
<tr><td valign = top bgcolor = cornsilk width = 110>
<font face = verdana size = 1 color = midnightblue>
<span id = "lastname" onclick = "applysort"
onmouseover = "processover"
onmouseout = "processout" language = vbscript>
Last Name</span></td>
<td valign = top bgcolor = cornsilk width = 110>
<font face = verdana size = 1 color = midnightblue>
<span id = "first" onclick = "applysort"
onmouseover = "processover"
onmouseout = "processout" language = vbscript>
First Name</span></td>
<td valign = top bgcolor = cornsilk width = 110>
<font face = verdana size = 1 color = midnightblue>
<span id = "city" onclick = "applysort"
onmouseover = "processover"
onmouseout = "processout" language = vbscript>
City</span></td>
<td valign = top bgcolor = cornsilk width = 110>
<font face = verdana size = 1 color = midnightblue>
<span id = "email" onclick = "applysort"
onmouseover = "processover"
onmouseout = "processout" language = vbscript>
EMail</span></td></font></tr>
</table>

Notice that the <SPAN> tags contain references to the same handlers for the onmouseover and onmouseout events, as well as a new applysort handler for the onclick event. Next, add the applysort handler by replacing the comment routine to sort table contents via tabular data control with the VBScript code in Listing 18.21.

Listing 18.21  Handling Data Sorting in the Tabular Data Control

Sub applysort
     heldID = window.event.srcElement.id
     set heldObj = document.all(heldID)
     if heldID = "lastname" then
         TDC1.SortAscending=true
        TDC1.SortColumn="LastName"
        TDC1.Reset
     elseif heldID = "first" then
          TDC1.SortAscending = true
          TDC1.SortColumn = "FirstName"
          TDC1.Reset
     elseif heldID = "city" then
          TDC1.SortAscending = true
          TDC1.SortColumn = "city"
          TDC1.Reset
     elseif heldID = "email" then
          TDC1.SortAscending = true
          TDC1.SortColumn = "EMail"
          TDC1.Reset
     End If
End Sub

Preview the page and go to the section that contains the table; check your page against Figure 18.9. Click the fields in the new sort control table at the top of the page. You'll see the data in the table sort in accordance with the field you clicked. This happens without a trip back to the data source.

FIG. 18.9
The table containing bound data after the city sort is applied. A good idea for this type of page is to provide filtering as well as sorting capability.

From Here...

As you've probably surmised, web development has taken a dramatic step forward with the advent of Dynamic HTML. The range of possibilities available to web developers dwarfs the limited set of options that came before; combined with Active Server Pages, server-side objects and scripting, and so forth, the day is fast approaching when the line between traditional development and web development dissolves altogether.


Previous chapterNext chapterContents


© Copyright, Macmillan Computer Publishing. All rights reserved.