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



Cutting Edge
cutting@microsoft.com        Download the code (58KB)
Dino Esposito

The Evolution of Scripting

I
n the software development world, there's probably no other field evolving as rapidly as scripting.
      The world of scripting now encompasses countless technologies that developers must be aware of. HTML as a language is most often compared to XML, since they share a similar syntax. XML appears to be a more complete way to develop or simply glue together various pieces of applications. ASP, on the other hand, is well-integrated with just about any COM-based technology you can name, including Microsoft® Transaction Server. Scripting engines like VBScript and JScript® are continuously updated to satisfy goals like providing two languages with comparable features and standardization. When you discuss scripting, you can't leave out the Windows® Scripting Host (WSH) and Remote Scripting. Even though these are two totally different technologies, they both address needs that people have had in the past.
      In this column, I'll try to provide you with an all-encompassing and annotated overview of what's going on in scripting. I'll discuss the good and the bad of scriptlets, the whys and wherefores of Dynamic HTML (DHTML) scriptlets, and the transition to server scriptlets (now called simply scriptlets). Reusability and componentization will be key themes. These issues encompass HTML-based presentations, WSH modules, and Web applications. I'll start by focusing on the Microsoft Internet Explorer 4.x and Windows 98 environment, and finish by looking at the new features of the upcoming Internet Explorer 5.0, VBScript 5.0, and JScript 5.0. I'll also touch on issues like background layout and the rationale behind some cool but seemingly odd features like behaviors and dynamic properties.

Once You Had DHTML Scriptlets
      In the January 1998 installment of Cutting Edge, I examined DHTML scriptlets. The idea behind them is both simple and clever. A DHTML scriptlet is an HTML page with all of its typical content (tags, text, and script code) embedded inside a host page. In other words, a scriptlet is an HTML-based COM component. By combining scripting code and HTML tags, you can define a certain component with a certain behavior and a certain set of properties, methods, and events. In this scenario, the DHTML object model plays a primary role in bringing the scriptlet's user interface to life. Having a scriptlet inside a page is conceptually like running another instance of Internet Explorer 4.x.
      Although DHTML scriptlets were introduced primarily to componentize pieces of DHTML code, they are not necessarily required to have a user interface. You can easily write hidden scriptlets that simply provide a particular behavior and work like a COM server. DHTML scriptlets are hosted inside a page through the <OBJECT> tag and internally follow the HTML syntax by using a specific public descriptor object to define the programming interface. More information about and examples of scriptlets can be found in my book, Instant DHTML Scriptlets (Wrox Press, 1998).

XML Scriptlets
      If you need Web components with a user interface, then DHTML scriptlets provide your most lightweight choice. However, the browser is just one possible container for script code. More recently, WSH (see Cutting Edge in the June 1998 issue of MIND) has become a new and really useful script-based environment. Furthermore, the release of the Microsoft Script Control (see http://msdn.microsoft.com/scripting) makes it easy for each developer and each application to host a scripting engine. The demand for reusable, self-contained script code components is continually growing.
      DHTML scriptlets are an interesting solution, but they're too closely oriented to the Web for some applications. Server scriptlets (which I covered in the May 1998 issue) provide a more general layout that encompasses DHTML scriptlets as a special case. Server scriptlets are written in XML code—in fact, they've been called XML scriptlets, or simply scriptlets— and they have a few significant differences from DHTML scriptlets. First of all, XML scriptlets have a runtime engine that makes them appear to be full-fledged automation components. Second, they can't have a user interface or fire events. Scriptlets are just servers, though they may run on either the client or server side of the Web.
      On the client side you can use scriptlets through the <OBJECT> tag and the CLASSID attribute as if they were standard ActiveX® controls. On the server side, you can use them as UI-less COM servers whose instances are created in ASP code through the VBScript CreateObject or JScript ActiveXObject functions.
      The great advantage of XML scriptlets is that they can be used without significant modification in conjunction with WSH. Although their interface is COM-based, you don't need a clear perception of the COM stuff that is behind it. You just write a few JScript or VBScript functions, give them a descriptive global name (a ProgID), a 128-bit identification number (a CLSID), and add the component to the system registry using the regsvr32.exe utility.
      OK, much of this is actually COM-related stuff. But if you don't use terms like ProgID, CLSID, or registration, you won't be reminded of COM since interface definitions, the implementation, class factories, IUnknown, and the like are isolated in a virtually invisible runtime module.
      In addition to the references I already mentioned, check out the series of articles written for MSDN by Andrew Clinick (links at the end of this article) for a really clear grasp of the evolution of scriptlets.

Scriptlet Events
      Like most development concepts, scriptlets have both an upside and a downside. They are lightweight, easy-to-write objects, but lack some code protection. Moreover, both DHTML and XML scriptlets have some structural drawbacks. DHTML scriptlets can have a user interface, but rely on the browser—and the browser must be Internet Explorer 4.0 or later. XML scriptlets are hidden objects that work in the background and don't accept even the most innocent MsgBox call.
      Another scriptlet difficulty is event handling, both when firing events and listening for them. XML scriptlets don't support event handling yet because they rely on special modules called interface handlers to implement all the required COM interfaces (I discussed this in the May 1998 issue). At present, only the IDispatch interface has been defined to handle automation. Handling events requires additional interfaces, starting with IConnectionPointer.
      DHTML scriptlets can raise events in two ways. They can bubble standard events like onclick or onmouseover, or they can raise custom events. When bubbling standard events, scriptlets make use of the window.external.bubbleEvent method. Raising a custom event involves using the onscriptletevent event, whose first argument is the actual name of the event.
      The problem is that scriptlets can't easily communicate with each other on the same page. Suppose you want to link two scriptlets so that one performs some action in response to an event fired by the other one. A typical example would be an edit box component that notifies a label when its text changes. If you want a page with an edit control and a label that displays the length of the text, you might want to turn the edit control into a scriptlet that contains the actual UI element, and catch the change event it raises through onscriptletevent. Next, you can explicitly invoke a method on the label scriptlet to make it redraw properly. You have to write glue code on the main page that hosts both components. But can the scriptlets do it all by themselves? In other words, can a given scriptlet listen for the events raised by another scriptlet?
      The onscriptletevent interface is not enough because it assumes you know the name of the object that raises it. You want something different here: a scriptlet that's ready to handle any event raised by any scriptlet in the same page, regardless of the names of the various scriptlets involved. If you're familiar with Java, you'll realize that what I'm thinking about is similar to the Java delegation model for event handling.
      By design, DHTML scriptlets have a simplified event-raising mechanism. They always raise the same event function, leaving specific information about the real event in the function's arguments. But there's a better way to do this. In practice, you define and document the event interface your scriptlet exposes. An event interface is merely a collection of functions, each of which is called as a consequence of a certain event that happens inside the scriptlet. For example, the edit box discussed previously might have the following event interface:

 OnTextChange( newText )
 OnKeyPress( key )
 OnMouseClick( position ) 
The first function will be called each time the edit buffer changes, while the other two will occur when you press a key or click on the component.
      Another scriptlet that knows of this interface and is interested in handling these events can simply expose the same functions listed earlier in its own public_description object. The scriptlet that fires the events doesn't call any internal function, but searches for a scriptlet that exposes functions with those names on the same page. In this way, scriptlets on the same HTML page can communicate with each other by defining event interfaces. A scriptlet that wants to listen for a certain set of events must implement a certain interface. Let's see how it works in practice.
      I have a page with four listener scriptlets and two other scriptlets that work as event generators. In Figure 1, the four gray rectangles represent four different scriptlets with much the same structure. Each exposes only two properties, Background and Description, to render the background color and descriptive text. The bottom of Figure 1 shows two other scriptlets that are directly derived from the HotImage scriptlet presented in the January 1998 installment of Cutting Edge. This component is a button whose bitmap changes when the mouse passes over it.
Figure 1: Scriptlet Interaction
Figure 1: Scriptlet Interaction

      The HotImage scriptlet exposes an interface called Clicked, which represents a single function Clicked that takes no parameters. This event is fired when the button is clicked. The four scriptlets in this system can register themselves as listeners of this event by simply adding a Clicked function to their own interfaces.
 function CreateScriptlet() {
     this.put_BackgroundColor = put_BackgroundColor;
     this.get_BackgroundColor = get_BackgroundColor;
     this.put_Description = put_Description;
     this.get_Description = get_Description;
 
     this.Clicked = DoClicked;
 }
The complete code for a listener scriptlet is shown in Figure 2. The lines you need to change to support event listening are bracketed by lines of slashes.
      The most interesting part of this story is how a scriptlet can retrieve a connection point from all the scriptlets found on the host page. Figure 3 shows the source code for the HotImage control. The core functionality is contained in the following snippet:
 <script language="JScript" for="image" event="onclick">
     if( InScriptlet )    {
         EnumScriptlets();
         window.external.bubbleEvent();
     }
 </script>
The function EnumScriptlets gets called whenever the user clicks on the control, before the standard onclick event is bubbled down. It obtains a reference to the document object of the parent page. Then it walks the entire collection of <OBJECT> tags, checking the TYPE attribute against the MIME string for scriptlets: text/x-scriptlet.
 function EnumScriptlets() {
     parentDoc = window.parent.document;
     sctColl = parentDoc.all.tags("object");
      
     for( i=0; i<sctColl.length; i++ )    {
      obj = sctColl.item(i);
      if( obj.getAttribute("type")=="text/x-scriptlet" ) 
             if( mInterface == "XClicked2" ) {
                 if( typeof(obj.Clicked2) != "undefined" ) 
                            obj.Clicked2();
             }
             else {
                 if( typeof(obj.Clicked) != "undefined" ) 
                            obj.Clicked();
             }
     }
     return;
 }
For each scriptlet found the function checks the validity of the expression given by the object name and the function to call. In EnumScriptlets, it is obj.Clicked.
      The typeof function returns the word "function" if it is defined or "undefined" if it's not. This lets you issue a call only if the method actually exists. The previous fragment also shows another feature: a scriptlet can expose more than one interface. In the previous sample, I've exposed both XClicked and XClicked2. (Since these are not exactly real COM interfaces, I chose to replace the typical I in the name with an X.)
Figure 5: Listening for Xclicked
Figure 5: Listening for Xclicked
Example Online!

      The source code for the host page is shown in Figure 4. Each scriptlet that fires events ends up calling methods exposed by other scriptlets on the same host page. Figure 5 shows the sample page where scriptlets 1 and 4 are listening for XClicked, and scriptlets 2 and 3 are listening for XClicked2. The red rectangles are automatically painted by clicking the first button. You could further refine this approach by introducing a specific function to toggle the scriptlets' listening capability when desired.

Script Components
      DHTML scriptlets are souped-up HTML pages, so they need to run in a second instance of Internet Explorer 4.0. In addition, they take the form of windows opened inside the main page. A typical drawback is that you can't have the scriptlet share a bitmapped background with the page because they're always placed on different layers. This is not an issue if you're using pure DHTML code instead of scriptlets. Despite all this, DHTML scriptlets are an excellent way to create reusable script components. Using pure DHTML code causes plenty of script code to appear in a page, so scriptlets considerably improve maintenance and readability. Let's take a look at a concrete example of this.

Figure 6: Internet Client SDK Page
Figure 6: Internet Client SDK Page

      You should be familiar with the autohide feature of the Windows taskbar and the hierarchical menu look of the Internet Client SDK documentation (see Figure 6). Why not try to put them together? To create such a component, you would first arrange a panel with a little button that hides or displays it. Then the content of the panel should render a tree-based menu with expandable main items and child items that cause some action to occur—typically displaying a new page in another frame.
Figure 7: Show/Hide Panel Navigation
Figure 7: Show/Hide Panel Navigation

Figure 7 shows an example of what I mean. The panel on the left is a scriptlet that contains a header bitmap plus a hierarchical menu. By clicking the button in the top-right corner, you can hide or show the panel (see Figure 8). The code to get this result is shown in Figure 9.
Figure 8: Hidden Panel
Figure 8: Hidden Panel
Example Online!

      The HideOff scriptlet is an HTML page composed of a table with a single row and two columns. The first column contains the menu, while the second shows the button that opens and closes it. The body of the page is contained in two mutually exclusive DIV sections, one for the panel's hidden state and one for its displayed state.
      The panel contains a header and a menu bar. The header can contain literally anything in HTML format. For example, you can use a bitmap like this:

 navBar.Head = "<img src=topbar.jpg>";
The header content corresponds to the settable Head property exposed by the scriptlet. The menu is created dynamically through the following properties and methods:
 function CreateHideOff()    {
     this.put_Head = PutHead;
     this.ToggleShow = DoShow;
     this.addItem = DoAddItem;
     this.addItemList = DoAddItemList;
     this.SetStyle = DoSetStyle;
     this.SetColors = DoSetColors;
 }
With AddItem you can add a new main menu node. The method returns an ID you'll use to add specific items to it. Here's an example:
 navBar.Head = "<img src=topbar.jpg>";
 i = navBar.addItem( "Internet" );
 navBar.addItemList( i, "WinInet API" ); 
 navBar.addItemList( i, "Server-side programming" ); 
 navBar.addItemList( i, "Shell Integration" );
 navBar.addItem( "" );
Calling AddItem with an empty string inserts a separator line. I think that the trickiest part of this code is event handling. In order to handle highlighting and clicking, you should detect any mouse movement over any item (see Figure 10). The scriptlet interface can be customized via SetColors and SetStyle, which let you set the background, normal, and highlighted colors, the font family, and size.
Figure 10: Detecting Mouse Movement
Figure 10: Detecting Mouse Movement

      It's easy to integrate your component with existing pages, even richly featured ones. Refer to Figure 11 for the source code of the sample page shown earlier.

Is Readability a Real Issue?
      The HideOff menu is a complex sample. In principle, you can write it in pure DHTML code, inserting a <SCRIPT> tag where necessary. If you do this, you'll be swamped with lines and lines of script code that'll be difficult to read and maintain. The real power of the DHTML object model comes when it is componentized. Scriptlets lighten the complexity of the code by applying the principle of divide and conquer. Once you code all the logic of the menu in a hideoff.htm component, using it in a page is as simple as writing

 <OBJECT id="navbar" data="hideoff.htm" 
       type="text/x-scriptlet">
 </OBJECT>
and adding a bit of initialization code to set up the various menu items, as shown in Figure 11.
 <script language="JScript" for="window" event="onload">
     navBar.Head = "<img src=topbar.jpg>";
     i = navBar.addItem("Internet");
     :
     i = navBar.addItem("Scripting");
     :
     navBar.SetStyle( "Verdana", 15);
     navBar.SetColors( "darkblue", "white", "yellow" );
 </script>
      Scriptlets are a great step forward. I think that many developers underestimate their potential because they don't like to be tied to Internet Explorer 4.0 as their browser. However, scriptlets are helpful for both developers and users. Making use of scriptlets slices away a lot of the complexity and code volume you need to provide DHTML effects. But you still have to insert a number of <SCRIPT> tags to take care of component initialization and event handling, as you can see in Figure 9.

Behaviors and Dynamic Properties
      To the user, the HotImage control examined earlier works almost as if it were an IMG with some trapped mouse events. However, when it comes to implementation and testing it's quite different. The bitmap it uses appears in the topmost window with a given size, a margin, and its own opaque background. From the code's point of view, you always see a new object.
      Internet Explorer 5.0 will introduce behaviors, a concept that will mean a significant reduction in client-side scripting. A behavior is an XML scriptlet that provides a behavior for a specific HTML tag. In practice, if you want a specialized IMG component, you can simply add a behavior to the tag instead of writing a DHTML scriptlet.

 attachEvent("onmouseover", Hilite);
 attachEvent("onmouseout",  Restore);

       function Hilite() { image.src = "high.gif"; }
       function Restore() { image.src = "normal.gif"; }
This snippet shows how a behavior works. In a nutshell, you attach events and procedures to a given tag. What's important, however, is that the tag is hosted in the main page and not in an overlapped window as with DHTML scriptlets.
 <STYLE> 
     .HotImage {behavior:url{hotimage.sct}}
 </STYLE>
 •••
 <IMG class=HotImage src=•••></IMG>
      Technically speaking, a behavior is a new Cascading Style Sheet style that points to a URL where an XML scriptlet implements the logic. This type of scriptlet implements a bunch of new COM interfaces. You can write behaviors with low-level languages like C++ or with scripting languages like VBScript. In this case, your scriptlet will declare that it implements a specific interface handler called, appropriately, behavior. (Before behaviors, the only interface handler was automation.)
      Behaviors are neither the only new feature of Internet Explorer 5.0 nor the coolest. From a script development standpoint, dynamic properties promise to be useful. They are expressions assigned to a traditional object's attributes. Dynamic properties are linked to dependency lists and get evaluated each time Internet Explorer 5.0 detects a change in some element of the list. A typical use of dynamic properties would be a table recalculation mechanism triggered by some content change. This means an HTML table will be a bit more comparable to a Microsoft Excel spreadsheet.
      If you want to know more about behaviors, dynamic properties, and other features of Internet Explorer 5.0, I recommend you take a look at "Internet Explorer 5.0: The Inside Story" (MIND, September 1998). In the near future, Cutting Edge will also be covering various topics specific to Internet Explorer 5.0.

JScript and VBScript 5.0
      As you know, Microsoft distributes two scripting engines: VBScript and JScript. These allow you to write scriptlets and components and provide behaviors and dynamism to your Web pages. Internet Explorer 4.0, Internet Information Server 4.0, and WSH all ship version 3.0 of these languages. This provides JScript and VBScript with rich features and unique personalities. By design, VBScript will be more familiar to developers who have experience with Visual Basic®, even though Visual Basic and VBScript have a number of key differences.
      On the other hand, JScript sports a syntax and programming approach that will be more familiar to C/C++ or Java programmers. Before version 3.0, both VBScript and JScript had clear-cut strengths and weaknesses. In particular, JScript suffered from the lack of an error-handling mechanism, while VBScript couldn't evaluate runtime expressions. Microsoft is now trying to provide developers with two languages with the same programming power despite their different syntax, so developers can feel free to choose according to their own preferences. To reach this goal, version 5.0 of JScript and VBScript have been improved to fill major gaps. Figure 12 outlines what's new with both of these languages.
      The exception handling in JScript now appears to be superior to the On Error Resume Next mechanism provided by VBScript. It lets you try a block of statements and catch any errors that might occur. An error is rendered through a brand new Error object, which exposes two properties that return the number and description of the error. VBScript 5.0 has caught up to JScript by being endowed with a new runtime processing capability. Two functions, Eval and Execute, are supported. Eval is intended to evaluate any expression and return the result, and Execute actually executes commands. In a language like VBScript, this distinction is reasonable since a syntax like

 a = b
may be interpreted in two ways: as a comparison or as an assignment. Providing two functions lets the developer remove ambiguity in such cases. In other cases, the only difference is that Eval always returns a value, while Execute does not.
      Version 5.0 of both engines is currently planned to ship with Internet Explorer 5.0. Since Internet Explorer 4.0 runs the 3.0 version of each language, version 4.0 of the languages seems to be missing. The documentation available as compiled HTML files on the Microsoft scripting site (http://msdn.microsoft.com/scripting) claims that the 4.0 language engine is part of Visual Studio 6.0. However, I was unable to find any significant difference between this and the 3.0 versions.

Summary
      The evolution of scripting has now reached the point where scripting engines and frameworks can provide many of the same features you find in traditional programming languages. Not only does the syntax work better, but structural aspects such as reusability, maintenance, readability, and extensibility have been improved.
      With the newest revisions of scripting languages, especially version 5.0 of JScript and VBScript, scripting is no longer a second choice of developers, geared towards those who found C++ too difficult. The increasing complexity of browsers and the latest technologies makes scripting more difficult, but also more rewarding, requiring manageability, up-to-date tools, and the right design approach.

From the November 1998 issue of Microsoft Interactive Developer.