Andrew Clinick
Program Manager
Microsoft Corporation
Updated November 17, 1998
Updated to cover DHTML behaviors. With the release of Internet Explorer 5, Microsoft now recommends DHTML behaviors -- instead of the DHTML scriptlets supported in Internet Explorer 4.0 -- for adding componentized functionality to Web pages. This article was originally published in the Site Builder Network Magazine, which is now MSDN Online Voices.
Microsoft has evangelized componentization for quite a while, and the concept certainly helps the development process of any application. Componentization has moved further with the onset of Web development, both on the client and the server. Unfortunately, in order to create these components, you can't use the script languages that you use in HTML and on the server.
So to take full advantage of the brave new component world you had to learn new languages (Java, Visual Basic or even C++) and then convert your existing script code to them. To address the needs of the script community, we in the Microsoft Script group developed scriptlets, components written in any ActiveX script engine. This means that if you know Visual Basic® Scripting Edition (VBScript), Microsoft® JScript (ECMAScript), or PERL, you can create components for the client or the server. In this article I'll go through what, exactly, a scriptlet is, how to create one, and where to use them.
A scriptlet is a component written in script. Scriptlets were originally launched with Internet Explorer 4.0 in 1997. These scriptlets were aimed at creating user-interface components for HTML pages. The great thing is that to create a scriptlet all you needed to know is HTML and script. If you know Dynamic HTML (DHTML), then with a few simple naming conventions you can create a component for use in your HTML pages. Since these scriptlets were based on DHTML and used within HTML documents, they were called DHTML scriptlets.
Scriptlets provided a great solution for user-interface components, but didn't provide a general-purpose component architecture for use outside of the browser. Why would you want to create a component outside of the browser? Take Active Server Pages (ASP) technology as an example. To create a set of common routines for ASP, at the moment you must rely on includes within your ASP pages. This is fine for some solutions, but doesn't provide many of the benefits provided by components. It was exactly this problem that the next release of scriptlet technology was designed to solve. Initially called server scriptlets (they were aimed at the server), scriptlets are components written in Extensible Markup Language (XML) and script. XML is used to define the object, methods, properties, etc., and script to provide the functionality. Once the initial development began on these new scriptlets, it became clear that they are not just useful on the server but also on the client. As a result, Internet Explorer 5 Developer Preview release covers the needs not only of ASP/server developers, but also of client developers.
So we now have two variants:
When developing this new technology, we went back, took a long, hard look at DHTML scriptlets, and tried to take all that was good and fix the problems users had found when developing them.
XML has an effective mechanism for storing meta information in a standard format. For the uninitiated, XML provides way to create a markup language definition for a specific purpose. A basic scriptlet file contains these elements:
Note The scriptlet run time includes the automation-interface handler, so you can create your scriptlet as a COM Automation component, and the event handler, so you can fire events from inside your scriptlet.
Since it's approaching performance-review time where I work, I thought it would be interesting to create an employee object with the ability to raise an employee's salary that you might want to implement for a human-resources system. To define a simple employee scriptlet that has one read-only property (Salary), one read/write property (EmployeeNumber), and one method (RaiseSalary), the scriptlet would look something like this:
<scriptlet> <Registration ProgID="Employee.Scriptlet"/> <implements id=Automation type=Automation> <property name=Salary> <get/> </property> <property name=EmployeeNumber internalname=EmpID> <get/> <put/> </property> <method name=RaiseSalary> <PARAMETER name=Percentage/> </method> </implements> <script language=VBScript> dim Salary dim EmpID 'Set Salary to nominal amount Salary = 10000 ' We don't get paid that well here in Redmond ! function get_EmpID() get_EmpID = EmpID end function function put_EmpID(newValue) EmpID = newValue ' Query Database to get employees salry level here end function function get_Salary() get_Salary = Salary end function function RaiseSalary(Percentage) ' Do security checks here to ensure the user ' can increase the salary increase = Salary * (Percentage/100) Salary = Salary + increase end function </script> </scriptlet>
The <registration> element in this scriptlet includes only the ProgID attribute, so when registered (by right-clicking on the scriptlet or running regsvr32 with the scriptlet), the scriptlet run time will automatically create a unique identifier (a ClassID, for the COM savvy).
The key to the scriptlet is the <implements> element. This element includes the external definition of the scriptlet. The scriptlet run time will interpret the <property> and <method> elements, and expose these as standard COM properties and methods. In this case, the Salary property is defined as read-only (there's no <put> element within the <property> element), so the only way that the salary of an employee can be changed is by calling the RaiseSalary method which will:
To call the scriptlet from script within Windows Scripting Host , the following code would be required:
Dim x Set x = CreateObject("Employee.Scriptlet") ' Set the employee id x.EmployeeNumber = 99234 ' Display Salary level Msgbox x.Salary ' Raise the salary by 20% (It's worth a try) x.RaiseSalary(20) 'Display new salary msgbox x.SalaryThis is obviously a simple component, but it's an example of the type of component being written for n-tier application environments, where the business logic is encapsulated in components. The user-interface designer doesn't need to know the underlying data structures, just the object model of the business components provided.
It's vital that scriptlets be able to scale and interoperate with existing server programs. The key to this is the ability to utilize Microsoft Transaction Server (MTS) features from within scriptlets. In Internet Explorer 5 Developer Preview release, scriptlets have the ability to take advantage of existing MTS objects.
For the Developer Preview release, you need to use the MTxAS.AppServer.1 object. This is provided by default with MTS and provides a link between any COM component and the MTS transaction in which the component is running. A simple example of using this object is the ability to get access to the intrinsic ASP objects (Request, Response, Session, and so forth). This allows you to create a scriptlet and still have the same access to the response and session objects you would have if you were writing the script within an ASP file.
Consider the following scriptlet written in PERL (the same scriptlet is available in VBScript (zipped, 2K) and JScript (zipped, 2K). It uses the MTS object to get the object context for the scriptlet, and Active Data Objects (ADO) to get access to the Adventure Works database, which is installed with Internet Information Server (IIS). The object context provides a mechanism for getting all objects that are in the MTS transaction context -- in this example the ASP intrinsic objects:
<scriptlet> <Registration ProgID="Orders.PERL.Scriptlet"/> <implements id=Automation type=Automation> <method name=Display/> </implements> <script language=PERLScript> use OLE; # Get the Object Context from MTS $objCurr = CreateObject OLE "MTxAS.AppServer.1"; $objCurrObjCont = $objCurr->GetObjectContext(); # Create an ADO Connection $Conn = CreateObject OLE "ADODB.Connection"; $Conn->Open("advworks"); $RS = $Conn->Execute("SELECT * FROM Orders"); $Count = $RS->Fields->count; for($i = 0; $i < $Count; ++$i) { $GetRequest = $objCurrObjCont("Response")-> Write($RS->Fields($i)->name); } while(! $RS->EOF) { for ( $i = 0; $i < $Count; $i++ ) { $GetRequest = $objCurrObjCont("Response")-> Write($RS->Fields($i)->value); } $GetRequest = $objCurrObjCont("Response")->Write("<br>"); $RS->MoveNext; } $RS->Close; $Conn->Close; </script> </scriptlet>This is a simple scriptlet, but it illustrates how you can take advantage of the scalability and flexibility of MTS transactions with a small amount of coding. We are currently working on an add-on to the scriptlet run time that will allow you to add an <implements> element to your scriptlet. The ASP intrinsic objects will automatically be added to the namespace of the scriptlet. This allows you to literally cut and past existing ASP code into a scriptlet and it will work the same way as it would in the original ASP file.
<scriptlet> <Registration ProgID="Orders.PERL.Scriptlet"/> <implements id=Automation type=Automation> <method name=Display/> </implements> <comment> Implement the ASP handler that will provide the ASP intrinsics by default </comment> <implement id=myASP type=ASP default/> <script language=PERLScript> # Create an ADO Connection $Conn = $Server->CreateObject("ADODB.Connection"); $Conn->Open("advworks"); $RS = $Conn->Execute("SELECT * FROM Orders"); $Count = $RS->Fields->count; for($i = 0; $i < $Count; ++$i) { $Response->Write($RS->Fields($i)->name); } while(! $RS->EOF) { for ( $i = 0; $i < $Count; $i++ ) { $Response->Write($RS->Fields($i)->value); } $GetRequest = $Response->Write("<br>"); $RS->MoveNext; } $RS->Close; $Conn->Close; </script> </scriptlet>
Scriptlets provide an enhanced programming model for component creation. It's vital that these new components can be used from the browser while maintaining all the security requirements of components running in HTML combined with access to the Dynamic HTML Object Model. Internet Explorer 5 provides this ability through the introduction of DHTML behaviors.
DHTML behaviors (see separate feature article) are components that encapsulate specific functionality or behavior on a page. These behaviors can be applied to HTML elements through the familiar CLASS attribute, while specifying the location of the behavior with the new Cascading Style Sheets (CSS) behavior attribute. As components, behaviors can expose properties, methods, and events. When a behavior is applied to an element, the element's properties, methods and events are extended to include those exposed by the behavior.
When a scriptlet is used in conjunction with DHTML behaviors in Internet Explorer 5, the script in the scriptlet inherits the security settings of the HTML page it is being called from. This means that if a scriptlet is called from an HTML page in the Internet zone, the scriptlet will not be able to gain access to any system functionality that is not guaranteed to be safe. Any attempt to access unsafe objects will be denied.
Internet Explorer provides the behavior handler as a means for a behavior scriptlet to communicate back to its containing page and its object model.
With the behavior handler, a scriptlet is able to:
Expose custom events: These events are defined using the <event> element and are fired back to the containing page using fireEvent. Additionally, the createEventObject method is provided to allow the scriptlet to set event context information when firing the event.
More information on exposing events can be found below.
Access the containing page's DHTML Object Model: The element property exposed by the behavior handler returns the element on the page to which the behavior is applied. With this property, the browser makes the containing document and its object model (properties, methods, and events) accessible to a behavior scriptlet.
Receive notifications: By specifying a function with the behavior handler's attachNotification method, the browser notifies the scriptlet of certain occurrences, such as when the document is loaded, or when the content of the element changes.
Scriptlets used to implement DHTML behaviors don't require registering before they can be used, since they are downloaded from the Web when required. Therefore, you don't need to have a <registration> element in scriptlets that implement DHTML behaviors.
A simple example of a DHTML behavior is a scriptlet that highlights the contents of any HTML tag to which the behavior is applied.
<scriptlet id="hilite"> <comment> This is a DHTML behavior scriptlet so we need to implement the Behavior handler </comment> <implements id="Behavior" type="Behavior" default/> <script language="JScript"> var normalColor, normalSpacing; // Attach to the mouseover and mouseout events on the // parent HTML page attachEvent("onmouseover", event_onmouseover); attachEvent("onmouseout", event_onmouseout); function event_onmouseover() { // save original values normalColor = style.color; normalSpacing= style.letterSpacing; // change the color to red and change the spacing style.color = "red"; style.letterSpacing = 2; } function event_onmouseout() { // reset to original values style.color = normalColor; style.letterSpacing = normalSpacing; } </script> </scriptlet>
DHTML behaviors are available in Internet Explorer 5.
Scriptlets and DHTML behaviors provide an entry point into component-based development. We have tried to keep scriptlet development as simple as possible. To provide further assistance the Microsoft Scriptlet Wizard is available from the Microsoft Scripting Web site . We hope that scriptlets provide script authors with an effective mechanism to create components that will fit into an Internet/intranet solution on the client or server no matter what language you use. We are very keen to get feedback on what you think of our new scriptlet architecture so please take the time to go to the scriptlet newsgroup on news://msnews.microsoft.com/public.sc ripting.scriptlets
Andrew Clinick is a program manager for the Microsoft Script Group.
Links to Microsoft Scripting Web sites:
VBScript = Microsoft Visual Basic® Scripting Edition
Jscript = JavaScript or ECMAScript JScript