Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
![]() |
|
Element Behaviors in Internet Explorer 5.5 | |
Dino Esposito | |
Download the code for this article:Cutting1200.exe (62KB) Browse the code for this article at Code Center:Element Behaviors |
|
ehaviors were introduced with Microsoft® Internet Explorer 5.0 to provide easy separation of script from content. Before the advent of behaviors, DHTML scriptlets were the only way to encapsulate scripting code into manageable elements if you wanted to make your code more object oriented. For a primer on DHTML scriptlets, refer to the Cutting Edge column in the January 1998 issue of Microsoft Internet Developer. I also covered behaviors in the April 1999 issue. How to Write Behaviors Before going any further, let's review a few basics about writing behaviors. A behavior can be written in two ways, each requiring different skills. One way is to do everything with script code, which results in HTML Component (HTC) files. Alternatively, you can create a binary DHTML behavior that is nothing more than a plain COM object.
Behaviors are programmable components that expose a set of properties and methods and fire custom events as well. Thus, the first thing to do is publish the behavior's programming interface. The following line shows how to declare a property called height.
The name of the property can be used to assign a value from within the calling HTML page. From an HTML page, you use a behavior's property just like a tag attribute. Likewise, a behavior exposes methods that you can call from HTML script code.
The <PUBLIC:ATTACH> tag informs Internet Explorer that you want to sink the specified eventâ€"in this case, the onclick event. When the event gets fired (the item is clicked), the browser runs the function you indicated through the HANDLER attribute. This function must be reachable from the page, so you must either import it from an external file or get it from an embedded <SCRIPT> tag.
In most cases, you write behaviors because you need to handle certain events in a particular way or because you need to inject a special subdocument in the body of the host document. In the former case, your goal is to hook up to the desired events and handle them properly. In other words, the code you write is invoked only when a certain event occurs. A typical example is when you want to automate a hyperlink, highlighting it when the mouse passes over it. Your behavior just needs to hook the onmouseover and onmouseout events and toggle a few Cascading Style Sheet (CSS) styles.
When you need to inject your code into the DOM, not handling the ondocumentready event is a programming error. However, this can be a subtle problem; it doesn't always result in obvious errors. For example, during the course of several months I had a few behaviors that worked just fine in a production environment, despite the fact that they were hooking the onload event and then inserting a subtree into the regular DOM. But it was merely luck that prevented problems. I happened to be using behaviors that had no properties, and a behavior without properties doesn't need to initialize anything. It just builds up an HTML string and inserts it at a certain point, so the readiness of the DOM was not important.
To be certain that both label and height are correctly set before you inject the behavior's information into the document, make sure you read them after the ondocumentready event has been raised, not before.
The rest is done by Internet Explorer, which displays the page after all the involved behaviors have finished responding to the ondocumentready event. Attaching Behaviors to HTML Tags A behavior is just a standalone software component and, as of Internet Explorer 5.0, there was nothing to establish an implicit and automatic association between it and a specific HTML tag. At this point you're probably wondering, "How do I link a behavior to an HTML tag?" Normally you use a new Internet Explorer-specific CSS style called (you guessed it) behavior.
With this kind of declaration, the display content of a tag like <dino:tabstrip> is entirely determined by the tabstrip.htc behavior, allowing for HTML code like this:
Figure 1 shows the dialog produced by the previous code. You can obtain the source code for this behavior from the link at the top of this article. The page shows a tab stripâ€"a logical construct that can't be easily expressed with any existing HTML tag. The previous syntax, however, makes it particularly clear and easily manageable. I discussed this code and how to create a personal library of HTML tags in my May 2000 Cutting Edge column. (I find it particularly exciting that due to these features, an XML namespace can be considered a dynamic library of HTML functions.) The Drawbacks of Behaviors At this point, behaviors might look like the perfect tool for creating custom HTML tags in Internet Explorer 5.0. But there's a subtle problem. Behaviors as you know them are not tied to specific tags; they can be used to provide new functionality to a number of different tags. Elements, in turn, can display more behaviors at the same time. In other words, attached behaviors are function-oriented components that aim to provide a certain behavior without regard for the underlying element, independently from other current settings.
The colorpick class transforms a plain old textbox into a cool color picker component. What's the magic of the colorpick class? It's simply an attached behavior:
Among other things, what's great about this approach is that you can use the same element to show different behaviors at different times. The source code in Figure 4 comes from a Platform SDK sample; Figure 5 shows the page in action. By clicking on different links you can attach or detach a certain behavior using the addBehavior and removeBehavior methods.
To create custom HTML tags, you need a pattern that closely imitates the handling of a standard HTML tag. You can never break the link between, say, a <TABLE> tag and the code that manages it. Furthermore, this association is set before the page is published to the browser. In other words, each standard HTML tag is associated with exactly one precise behavior in a synchronous manner. Such an association is irrevocable and lasts until the page is unloaded. You cannot obtain these features with behaviors in Internet Explorer 5.0. Element versus Attached Behaviors Internet Explorer 5.5 introduces another type of DHTML behavior and renames the former class to attached behaviors. This new type of behavior is called element behaviors to emphasize the connection between the behavior (a software module) and a specific element (a custom HTML tag). An element behavior is irrevocably associated with a specific tag upon page loading. The name of this tag is hardcoded in the behavior's source. An element behavior cannot be handled programmatically, or detached or disabled programmatically. An element behavior is functionally equivalent to the browser's internal code that handles default HTML tags such as <IMG>. You can't replace the handler for <IMG> and you can't replace the handler for any custom tag with an element behavior either.
Simply specify the tagName attribute to specify the name of the custom HTML element to which the behavior should be connected. No other changes are required.
If, like me, you are still relying very heavily on Win32®, you'll soon realize that the <?IMPORT> directive works in much the same way as one of the handiest Visual C++® features, shown here:
This #pragma in the previous code programmatically forces the linker to get the specified DLL import library in the final executable. Likewise, the <?IMPORT> directive forces the browser to import the element behavior to which the implementation attribute points. The HTC must be written according to the rules of element behaviors and must hardcode the name of the custom tag it refers to. While importing a new element into the context of the current HTML page, you associate it with a namespace. The namespace must be specified twice: once in the <HTML> root tag and once in the <?IMPORT> directive.
Assuming that textframe.htc looks like the code in Figure 6, from now on you can use the <dino:textframe> to surround a text with a border. Figure 7 shows the result of the following code:
Of course, the name of the namespace can vary; the sole constraint is that it must be unique within the page. If the HTC file is not an element behavior, you might receive an error message or the tag might display incorrectly or even be invisible. Behaviors Tips One question you may have at this point is: "How can I import more behaviors?" You can do that by repeating the <?IMPORT> directive as many times as you need. You can use either the same namespace or define new ones. The following snippet imports two behaviors through the same namespace.
If you need to keep them separate (with both behaviors mapping to the same tag name), then you should use different namespaces.
When using a custom tag, always remember to close the tag, either using the closing tag or through the short XML syntax.
If you forget to properly close the tag, you won't get a syntax error, but you'll get unpredictable results. So whenever your output is not what you expected, check that all custom tags are closed.
The FOR clause defaults to element, so you rarely need it. Instead, pay attention to ONEVENT clause. It specifies the name of the procedure that will handle the event. Some old Internet Explorer 5.0 documentation recommended the use of the HANDLER clause for the same purpose. With Internet Explorer 5.5 you can use both, although this is not explicitly mentioned. Playing around with behaviors, I noticed only a subtle difference in the way you specify the procedure name. With ONEVENT you can terminate the procedure name with or without the final parentheses and VBScript code is searched first. With HANDLER (which is an obsolete clause), you cannot have trailing parentheses in the handler's name and JScript code is always required.
If you have a DoInit VBScript function, the behavior won't work. If you have both JScript® and VBScript code blocks, again, VBScript blocks are searched first. Why use the onevent clause? You would use it if you have Internet Explorer 5.0 behaviors and you don't want to modify that code. Literal Content One of the reasons you might want to write element behaviors is to create your own data island tags. A data island tag inserts raw text into the page. This text, regardless of its content, won't be parsed by the browser. A well-known data island is the Internet Explorer 5.0 <xml> tag that allows you to store invisible XML code in any HTML page.
Behaviors with literal content also receive the oncontentsave event when someone attempts to read or save their content. The ViewLink Technology When you import an element behavior component in an HTML page, you end up importing all DHTML trees that it creates. For example, in Figure 1 you saw a tabstrip component embedded in an HTML page through a simple and intuitive group of custom tags, such as <tabstrip> and <tabitem>. By importing them, all of the subtrees that form the body of the new element are slipstreamed in the page. Depending on what you really need to do, this may or may not be a problem. In general, it violates the component's encapsulation. In fact, you don't insert a standalone component in the page, but a piece of code that fully integrates with the rest of the page. It inherits and affects CSS stylesheets and the flow of events. Be aware of this when you write your behavior.
and you'll see all the information about the various tables that form the tabstrip and all the implementation details of the component. Enabling ViewLink You can enable the ViewLink feature in your element behaviors in two ways: declaratively or programmatically. To enable it declaratively, just add the following line within the body of the <PUBLIC:COMPONENT> tag:
After this line, all the output of the behavior will combine to form an independent subtree that's linkedâ€"not embeddedâ€"to the primary HTML document. To enable ViewLink programmatically, add the following line instead:
Defaults is an Internet Explorer 5.5 scriptable object that programmatically sets default properties on an element behavior. Its viewLink property contains the document object that the master element connects to. The master element is the custom HTML tag to which you attached this view-linked element behavior.
use
This ensures that the HTML text slips into a new DOM that's hidden from view. Element, in fact, refers to an injection point located in the primary documentâ€"exactly what you want to avoid. ViewLink Considerations All the styles you apply to the custom tag affect the view-linked behavior. However, styles can be overriden within the context of the view-linked subtree. A style property set inside the HTC file takes precedence over any other style attribute set outside it.
This is the result of
where element represents <dino:tabstrip>. The table is therefore part of the main document. It turns out that to detect mouse events you need to hook for the events at the page level, thereby justifying the various <PUBLIC:ATTACH> tags for onclick and onmouseover.
The previous code replaces the following code in a ViewLink behavior:
Incidentally, you could also leave this code in, but it is dead code, hopelessly waiting for events that occur at an inner level and that will never get bubbled up. A Call to Action In this month's source archive you'll find three flavors of the tabstrip behavior: attached, element, and ViewLink. Starting from the old-style version, it took me a few lines of code to adapt it to work as an element behavior and then as a view-linked component. |
|
Dino Esposito is a trainer and consultant based in Rome. Author of several books by Wrox Press, he now spends most of his time teaching classes on ASP(+) and ADO(+). Get in touch with Dino at desposito@vb2themax.com. |
From the December 2000 issue of MSDN Magazine