Bob Jervis
Senior program manager, Microsoft Visual Studio group
September 24, 1994
With the introduction of scripting languages to the Web, the Internet has been transformed into a dynamic environment supporting sophisticated programming. Particularly with the introduction of Dynamic HTML in Microsoft® Internet Explorer version 4.0, the Web is maturing into the user-interface framework of choice, not only for Web programmers but also for developers of any Microsoft Windows® application.
Scripting as supported in Netscape Navigator, for example, fails to provide the mechanisms needed to create true components. This omission severely limits the abilities of programmers to share their work, and even costs them in higher numbers of bugs when they try to create large-scale applications employing script.
Scriptlets, a standard feature of Internet Explorer 4.0, fill the gap and make Internet Explorer 4.0 the target platform of choice for anyone building applications for the Web.
Scriptlets are simply Web pages in which script has been written according to certain conventions. To use them, just insert an <OBJECT> tag into another Web page. The scriptlet is named by any standard Uniform Resource Locator (URL). Internet Explorer 4.0 recognizes a scriptlet by marking the tag as using a MIME type of "text/x-scriptlet". Note that there is no CLSID in the <OBJECT> tag. For example:
<OBJECT width=200 height=123
TYPE="text/x-scriptlet" DATA="Calendar.htm">
</OBJECT>
Internet Explorer 4.0 will support this MIME type on all platforms, whether Microsoft Windows-based, Apple® Macintosh® or UNIX. Because of the open nature of the architecture, competing vendors will be able to implement this support as well. There is nothing in the nature of scriptlets that restricts users to Microsoft platforms.
The functionality of a scriptlet can be written in any scripting language including but not limited to Microsoft JScript™ and Microsoft Visual Basic® Scripting Edition (VBScript).
While the implementation will have to be modified on other platforms, on the Microsoft Win32® platform, the Scriptlet MIME type exploits new Internet Explorer 4.0 features so that scriptlets use a Component Object Model (COM) object to accomplish their work.
Because this COM object encapsulates the Hypertext Markup Language (HTML) rendering engine in Internet Explorer 4.0 and hides most of its functionality, it is different from the Web Control object that exposes the rendering engine to its users. Instead, the scriptlet component exposes the interface of the Web page that is loaded.
This exposure is accomplished by loading the page into the Internet Explorer 4.0 HTML rendering engine and letting it run the page's script normally. Once completely loaded, the scriptlet component is ready to interact with its container. The container in the pure Web case is, of course, Internet Explorer, but any COM container, including a program written in Visual Basic or even Microsoft Word, can insert a scriptlet control just like any other ActiveX™ control.
The Scriptlet Component bridge layer then acts as a broker, passing requests for properties and methods into the scriptlet and passing events out of it. The bridge also performs certain basic housekeeping functions such as negotiating the size of the scriptlet between the container and the rendering engine.
Scriptlets are as secure as Dynamic HTML and script itself. And a scriptlet recognizes when it is placed in a secure container, such as Internet Explorer, and obeys the security policies of its container.
In general, to operate correctly, a scriptlet must be loaded from the same Web server as its container page, similar Java applets.
A scriptlet can be either an HTML page or an Active Server Page (ASP). You can use any HTML authoring environment to create a scriptlet, such as Microsoft FrontPage® or Visual InterDev™. Of course, if your environment does not support scripting, you may have to manually insert the scripting code after first composing the HTML display elements within the environment.
A scriptlet exposes only the global variables, procedures and functions that you want. Just use a public_ prefix on any variable or function you want exposed. Any global variable with this prefix becomes a readable and writable property of the scriptlet. Any global function or subroutine with this prefix becomes a public method of the scriptlet. When you refer to the property or method from outside the scriptlet, you do not include the prefix.
For example, you might declare the following in a scriptlet:
<Script language=jscript>
public_property1 = "Some text";
function public_method1(param1, param2)
{
... some code ...
}
You would then refer to these in your container page script as:
Scriptlet1.property1 = "Some different text";
a = Scriptlet1.method1(2, "Still more text");
Scriptlets can throw two kinds of events: onscriptletevent events and standard window events. The first can be thrown at any time inside the scriptlet. Standard window events, such as mouse clicks, cannot be initiated arbitrarily by a scriptlet, but can be thrown in certain circumstances described below.
Scriptlets are considerably more dynamic in nature than traditional programs running on the Microsoft Windows operating system. So the development tools are not prepared to understand event types known only after the scriptlet has been loaded and parsed. For this reason, scriptlets communicate with their containers through a single type of event: onscriptletevent.
The onscriptletevent event includes two parameters: a string and an arbitrary object. An event handler can select how to respond, based on the string that is passed. The object parameter can then include additional detail about the event itself.
The standard window events supported in a scriptlet are thrown by propagating an event from an HTML component in the scriptlet. If you write an event handler within a scriptlet that catches, say, the mouse-click event for some part of the page, you may propagate it through to the scriptlet container. It then appears as a mouse-click event from the scriptlet with the same event detail information that the scriptlet received.
You can easily create context menus for your scriptlets. These are popup menus that appear over your component whenever a user right-clicks the mouse while the cursor is over the component. You can have one context menu defined for each scriptlet and can replace the menu at any time.
To create a context menu, first create an array of strings. Assign the strings in pairs to successive elements of the array. The first element of each pair is the label string that will appear in the context menu; the second is the script function to call within the scriptlet when that menu item is selected. When you have initialized the array, call the function window.external.setContextMenu with the array as its only parameter. The next time a user right-clicks over your component, the context menu will appear.
An example of creating a context menu:
<script language='vbscript>
sub window_onload
dim a(6)
a(0) = "Add &Hello"
a(1) = "Hello"
a(2) = "Add &Goodbye"
a(3) = "Goodbye"
a(4) = "&About"
a(5) = "About"
window.external.setContextMenu(a)
end sub
</script>
Properties behave in some ways like a memory location, but often this is not enough. If you have a color property on a component, you want the component to change color as soon as you set the property. Most components need to respond immediately to changes in at least some of their properties.
To support this, component architectures allow you to define functions that masquerade as the property. Scriptlets are no different. If you define a function with either the prefix public_get_ or public_put_, the function acts as if it were supporting a property. For example, the following code shows how functions can be used to implement a property:
<script language=jscript>
property1 = "some text";
property1GetCount = 0;
property1PutCount = 0;
function public_get_property1()
{
// Keeping track of how many times this is called.
property1GetCount++;
// This is the real work.
return property1;
}
function public_put_property1(new_value)
{
property1PutCount++;
property1 = new_value;
refresh();
}
In this example, the number of times each function gets called is recorded. After the new value is set in the put function, the component is refreshed in some way. You would still refer to property1 in the container like any other property:
Scriptlet1.property1 = "new text";
a = Scriptlet1.property1;
In the first line above, the public_put_property1 function is called to store the string. In the second line, the public_get_property1 function is called to retrieve it.
If you are writing in JScript, you have a second option to describe your scriptlet interface. If you define an object with the name public_description in your scriptlet, then its members become the set of named properties and methods exposed to the outside world. The public_ prefix is not used; if you have any global variables or functions with the prefix, they are ignored.
At present, VBScript does not allow you to create objects as JScript does, but this capability will be available in a future release.
Which mechanism should be used to define a scriptlet interface? It is largely a matter of style. However, using public_description allows you to describe the scriptlet public interface succinctly in one place, rather than scattering it throughout the scriptlet code.