The Simple 'Typing' Scriptlet

Our first example is a Scriptlet with a user interface. All it does is appear to 'type' a message onto the screen. The main page contains a text box and buttons that can be used to control the Scriptlet:

You can run or download this page, typetext.htm, from our Web site at http://rapid.wrox.co.uk/books/0707.

The Scriptlet itself is a Dynamic HTML page, which produces white mono-spaced text on a black background:

<html>
<head>
<script language=jscript>
...
... script goes here
...
</script>
<style>
  BODY {background-color:black; color:white; font-family:"Courier New",Monospace;
        font-size:12pt; font-weight:bold}
</style>
</head>
<body>
  <div id=objDiv style="position:absolute; top:5; left:5; width:100; height:100">
    <p id=objPara></p>
  </div>
</body>
</html>

The main page, typecomp.htm, that uses this Scriptlet contains all the descriptive text, instructions, text box, and buttons. It also contains a <OBJECT> tag that inserts the Scriptlet page typetext.htm:

<html>
<head>
  <title>Using Visible Scriptlet Components</title>
</head>
<body onload="startCode()">
<h3>Using Visible Scriptlet Components</h3>
<object id=myTypist width=400 height=100 type="text/x-scriptlet"
        data="typetext.htm" style="position:relative;">
</object>
...
... rest of page goes here
...
</body>
</html>

As you can see, the Scriptlet simply contains standard HTML that the IE4 parsing engine can display within the window defined by the <OBJECT> tag in the main (original) page.

Defining The Scriptlet's Interface

Of course, to be able to manipulate the Scriptlet, the original page has to have a way of accessing it. Scriptlets define an interface, which the page that contains them can use to reference the public properties, methods and events supported by the Scriptlet – in the same way as it would with any other ActiveX control.

Defining Properties

A property is simply a variable within the control. Any variable that has public_ prefixing the variable name will be exposed as a property that can be accessed by the scriptlet's container. This is the easiest way to declare a property and set the default value of it:

<script language=jscript> 
//public property variables
public_property1 = "Hello"

If you have any experience programming controls for Windows, then you know that COM also allows us to define a function that behaves like a property. This is especially useful if we need to perform input validation or other calculations before we set the value inside the control. The Scriptlet architecture allows us to declare a function for the put and get operations of a property. When the code in the container tries to place a value into a property, it calls the function that has public_put_ prefixing the property name – for example, here is the definition for a property named roomSize:

//private internal 'member' variable
var m_roomSize = 0

function public_put_roomSize(newvalue)
  {
   if ((newvalue > 0) & (newvalue < 99)) m_roomSize = newvalue 
  }

The variable m_roomSize is a private internal variable that will be used inside the Scriptlet's code sections. It cannot be accessed from outside the Scriptlet, and so can only be set using the public_put_roomSize function (i.e. the roomSize property). This allows us to validate the new value proposed by the user and reject any unsuitable ones, as we've done in the code above.

Likewise, when the code in the container tries to get the value of a property, it calls the function that has public_get_ prefixing the property name. In this case, we can just return the value of the internal variable m_roomSize:

function public_get_roomSize()
  {
   return m_roomSize
  }

By providing both the put and get functions, we produce a property that is read/write to the outside world. If we want our property to be read-only or write-only, we define just the put or the get function, as appropriate.

Keep in mind also that we can only define a property using one of the two outline methods we've discussed here. If we use the put and get functions method then we cannot have a variable in our Scriptlet which has public_ prefixing a property name that we are also using for the put and get functions.

Defining Methods

A method is declared simply by adding the prefix public_ to the name of the function or subroutine that carries out the method:

 

function public_rollsOfWallpaper(intLengthEach)
  { 
    ... some code to calculate the result ...
    intNumberOfRolls = ...
    return intNumberOfRolls
  }

Any functions or variables within our Scriptlet not named with the public_ prefix will only be accessible to code within the Scriptlet, and not from the containing page. Like all routines, we can pass values into the routine as parameters (such as intLenghtEach above), and we return the value, if there is one, just like we would from any other function. Of course, the function does not have to return a value if it's only required to carry out some direct action within the Scriptlet.

The interface of a Scriptlet can also be defined in another way, using the JavaScript public_declaration object. We'll see how this is done later in the chapter. We'll also see how events are declared and implemented.

Setting Properties and Calling Methods

In the main (container) page, we can use the properties and methods of the Scriptlet just like we would with any other ActiveX control or integral HTML object:

MyScriptlet.roomSize = 42;                  'set the roomSize property
alert(MyScriptlet.roomSize);                'retrieve the roomSize property
alert(MyScriptlet.rollsOfWallpaper(33));    'call the rollsOfWallpaper method

The 'Typing' Scriptlet Code

Our Typing Scriptlet, typetext.htm, provides four properties and one method:

You can see how these properties and methods are defined by the interface in the code section below. This is the entire script section of the typetext.htm Scriptlet:

<script language=jscript> 
//private internal 'member' variables
var m_messageText = " ";
var m_typeStatus = "Idle";

//other internal variables
var timer = null;
var nPosition = 0;
var nLength = 0;

//--------------------------------------------
//put routine for text (write only)

function public_put_messageText(newString)
{ 
  nPosition = 0;
  if (newString.length > 0) 
  {
    m_messageText = newString;
    nLength = m_messageText.length;
    timer = setInterval("typeText()", 200);
    m_typeStatus = "Typing";
  }
  else
  {
    nLength = 0;
    m_messageText = "";
    clearInterval(timer);
    document.all("objPara").innerHTML = "";
    m_typeStatus = "Idle";
  }
}

//-------------------------------------------
//get routine for typeStatus (read only)

function public_get_typeStatus()
{ return m_typeStatus }

//--------------------------------------------
//put routine for height (write only)

function public_put_messageHeight(newValue)
{ 
  if ((newValue > 9) & (newValue < 1000))
    document.all("objDiv").style.pixelHeight = newValue
  else
    alert("messageHeight must be between 10 and 999");
}

//--------------------------------------------
//put routine for width (write only)

function public_put_messageWidth(newValue)
{ 
  if ((newValue > 9) & (newValue < 1000))
    document.all("objDiv").style.pixelWidth = newValue
  else
    alert("messageWidth must be between 10 and 999");
}

//-------------------------------------------
// public method for the component

function public_stopTyping()
{ 
  clearInterval(timer);
  m_typeStatus = "Stopped";  
}

//-------------------------------------------
//private internal routines

function typeText()
{
  if (nPosition < nLength)
  {
    nPosition++;
    document.all("objPara").innerHTML = m_messageText.substr(0, nPosition);
  }
  else
  {
    clearInterval(timer);
    m_typeStatus = "Complete";
  }
}

</script>

As you will be able to see from the code, the Scriptlet works by using the setInterval method of its own window object, and simply changing the text that is displayed in the <DIV> tag objDiv each time the interval occurs. At the same time, it sets appropriate values for the internal m_typeStatus variable, which provides the read-only typeStatus property. This simple example should prove that the architecture of scriptlets is relatively simple, and indicate how they allow us to create custom client-side controls quickly and easily.

It's As Easy As That!

So, using scriptlets is as simple as using an ActiveX control. All we have to do is place an <OBJECT> tag within our HTML page that will contain the Scriptlet, and then we can use the scriptlet just as we would use any other ActiveX control:

<object id=myTypist width=400 height=100 type="text/x-scriptlet"
        data="typetext.htm" style="position:relative;">
</object>

The only differences between a scriptlet <OBJECT> tag, and an <OBJECT> tag that defines an ActiveX control, are the values of the type and data attributes, and the lack of a ClassID (or GUID). The type attribute defines the MIME type that Internet Explorer should use when parsing the Scriptlet code; the MIME type for scriptlets is "text/x-scriptlet". The data attribute defines the location of the scriptlet code, as a standard URL. This is similar to the codebase attribute used for ActiveX controls.

Notice that there are no parameters declared using <PARAM> tags. This is because scriptlets do not currently support parameters, however Microsoft is working on adding support for parameter tags for a future release of Internet Explorer.