CGI Programming Unleashed
- Blending HTML and Programming
- The ActiveX Scripting Model
- The Languages
- Scripting Hosts and Engines
First, HTML pages were text. And they were good. Then they were text with lots of fun attributes, and they looked better. Then came images, imagemaps, audio, tables, and so on. Every time you looked, some new tag or new functionality was being added to HTML, but everything was still kind of static. The HTML code itself didn't contain the content or the interactivity; the code just pointed to it. That was then, this is now.
ActiveX scripting is Microsoft's answer to putting the programming language inside the HTML code itself. No longer do basic interactions such as verifying input format have to take place on the server side-all the work can be done on an end user's machine, putting a fraction of the power of distributed computing at your disposal.
Embedding the programming language of your choice in an HTML file
can be very useful. Embedding is not quite the way to write your
next generation of applications, because everyone can easily view,
copy, and modify the source code, but it makes more advanced interaction
easy. In this chapter, you look at the ActiveX scripting model
and become familiar with the following:
- Blending HTML and programming
- The ActiveX scripting model
- The languages
You don't have to be a programmer to get basic and useful functionality out of ActiveX scripting; you just have to know a little background and be willing to try it.
For the better part of its reasonably young life, HTML was static. It was originally designed around the idea of text being the information conveyed, and it did its job quite well. Then images popped in, as was inevitable, and soon more and more capabilities were included as people said, "This is great, but it'd be even better if I could present my information in this other way."
Although you could program on the server side, the desire for distributing the work load to client machines and making it more seamless pushed new ideas of what comprised interaction in HTML right to the forefront. The reason is that people are impatient. You, me, your neighbor-when we're looking for information, we want to get it quickly. We don't want to call and get a busy signal; we want an answer. We don't want to fill out a form, wait a minute or two for the server to think about doing something with it, and then get back a message saying "Sorry, you didn't complete the form correctly." Likewise, if we're doing a job in which we just need simple functionality-like creating basic calculations, working with random numbers, or developing better interactions-sending simple tasks to an overloaded computer just isn't the best solution. When the work is done by our machine, without our ever having to go out and connect to another location, we are saved the time, effort, and frustration. And that savings helps us out.
Like the rest of HTML, though, editing and viewing what's going on in the program should be easy, which means that the HTML can't really be precompiled. It has to be a script that gets interpreted at runtime on the client's machine. There has to be some way for the end user's machine to realize that it has to do something. That's where the SCRIPT tag comes in.
But what happens if the browser doesn't support scripts? Normally, it would get a whole lot of garbage between the <SCRIPT> and </SCRIPT> tags, because the browser would just ignore those tags and move on to the text. The answer to this problem is to trick the browser. You place everything that's supposed to be code inside comment tags within the SCRIPT tags. If the browser can't handle the SCRIPT tags, it just sees all that code as nondisplaying comments and doesn't show it to the end user.
Hiding script elements within comment tags is a trick you can use with browsers to seamlessly incorporate the code. In early 3.0 alpha and beta releases, Internet Explorer didn't handle this functionality, but later versions are designed to do so. If you see the code but know the browser is supposed to handle the script, check your HTML and then check what version of the browser you're running.
What goes between the two SCRIPT tags? Almost anything. The most basic element you need to include is an identifier for what scripting language you're using, like the following beginning SCRIPT tag for a VBScript:
You can also include a unique name for the script so that you can run multiple scripts on a page and do specific jobs with different scripts. To include the name for the script, just add it to the first SCRIPT tag, as follows:
<SCRIPT LANGUAGE="VBS" NAME="myscript1">
As time goes on, scripting languages may add more tags to control behavior further, but because you can control the behavior in the script as well, adding new tags is not a real priority.
To make sure that scripts are read in at the right time, you should normally place them in the HEAD section of the HTML file. This way, you ensure that they get loaded properly.
To show how cooperative user interfaces can be with HTML, as well as how dependent they can be, the primary user interfaces for scripts are the same elements that are used by HTML forms: checkboxes, radio buttons, input fields, buttons, and so on. Without them, most scripts are limited to tossing up message boxes and maybe a single box in which the users can type some information. Without the ability to use the HTML forms elements, message boxes and input boxes by themselves would not blend well with HTML.
Because each element on a form can be named, you can use these names to cause events and interpret them. If you have a button named Go, for example, you can include a line in your script to perform a specific action when someone clicks the Go button. If you have an input box named MyText, you can get text from that box as easily as you can send text to it. Using this capability, you can add functionality to your forms and other functions, such as checking for valid e-mail addresses before sending in a form or comparing phone numbers to states to determine what sales office's page they should get directed to for further information.
The components that are available to script functions go beyond just HTML-created components, though; they include aspects of the browser itself. Each part of the browser-the window, any frames, the status bar, the menu bar-is part of the scripting environment and can be controlled. Because each part has its own special way of being named, you can single it out to create an effect on it. If you want to set the status bar to read "Today's specials are " or create a new browser window, you can do so. You just have to know how scripting-ActiveX scripting in particular-enables you do make these changes.
The whole concept of ActiveX scripting is that you're using small, interoperable components that work together to get the job done. A browser or other application works like this as well. Applications have child windows, objects, and sets of components that they pass messages between them to make everything work. When you bring ActiveX scripting into the equation, what really makes the application more powerful is the capability to interact with the parent object, such as Internet Explorer, another browser, or whatever container the script is being run as part of.
The interactions with the container in which the script is running can be on two levels with ActiveX scripting: on the container itself or on any elements within the container's ability to control. In the first case, you need to know the Object Model that the container makes available to the script; that is, what are the individual components that container has, and what is it willing to let you use. In the second case, you need to know what other elements could possibly be controlled, such as ActiveX controls being downloaded, or other pieces of functionality.
When you bring a script into Internet Explorer, you can take hold of a variety of hidden pieces. These individual components are treated as separate objects to the script because each has its own unique functionality. Main windows, child windows, frames, links, other scripts-everything is an object unto its own, and you can isolate each object and do neat tricks with it, if you're inclined to.
Figure 28.1 shows the basic levels of Internet Explorer's Object Model-which object relates to which other object and how they all piece together. Certain objects such as scripts, frames, forms, links, and anchors may exist multiple times, with unique names and data for each, whereas other elements have underlying components that end up being dependent on the parent component. Forms, for instance, start out as part of the window, but they are also part of the HTML document. Any elements in the form itself are thus dependent on the form component, which is dependent on the document component, which is part of the window itself. (If you feel like singing "the knee bone's connected to the thigh bone" at any time, feel free.)
You can make use of this model to aim your commands accurately at a component. If you want to aim a command at a specific checkbox on a specific form, the chain of reference in the traditional Object.Property chain of command would be Window.Document.Form.Checkbox. In some cases, you can bypass a level or two of this direction because Internet Explorer is smart enough to know that if you don't specify a window, it should just go ahead and use the base window identifier. Many times, however, knowing how the flow of this structure proceeds is necessary to ensure that your script works the way you would expect, especially when you start tossing in frames (if you're so inclined) and new windows. I show just what you can do with the whole Object Model later in this chapter, so you get a hands-on view of what it all does.
In the world of open components being obtained from anywhere, your script may end up with more components to play around with than you thought it had. Some basic system controls such as timers, for example, are built in but not really part of the main container itself. Does this mean they're off limits? Not a chance.
All ActiveX components and controls that are registered with the system are fair game for your script, with some security-based exceptions. You have access to timers, media control, database control, and other Visual Basic for Applications-capable servers, if you know how to call them. The trick to calling them is knowing their unique identifiers, called ClassIDs or GUIDs (Globally Unique Identifiers, rhymes with squid). These piles of alphanumeric confusion come from the System Registry. By knowing what control you want to use, you can run REGEDIT and search for the name of that control, hoping you stumble across it. Knowing more about the controls themselves is also important to your design and implementation., and you can get more of those details in Chapter 27, "ActiveX Controls".
VBScript has the option of including its own objects as well as everything else that's built into the browser's object model. In the initial release, the only additional object was the ERR object for getting information about runtime errors in executing the script. Other objects will most likely appear as time goes by, just to extend functionality while preserving the basic Object Model.
You shouldn't be surprised that Microsoft decided to make its own Visual Basic language the most hyped implementation of ActiveX scripting. With hundreds of thousands, if not millions, of Visual Basic authors in one form or another out there, doing otherwise would have been silly. Because what you can do inside another application over the Internet is more limited for a variety of reasons, Microsoft scaled back the Visual Basic for Applications specification into a more reasonable (though not quite as functional) subset, called Visual Basic Scripting Edition (VBScript)
If you're already a Visual Basic programmer, you can probably use VBScript in your sleep, and knowing what's in (and what's not in) VBScript should help you get a good handle on just how portable some of your work will be from another version of VB. If you're not a Visual Basic programmer, the actual delineation of what functions are and aren't in VBScript may not float your boat, and you may want to move ahead to the examples to see the basics of VBScript at work. In either case, you can find more in-depth reference for what any of these commands do (or don't do) in the VBScript documentation from Microsoft, which is available for download at http://www.microsoft.com/activex/
What's in VBScript?
VBScript, which has a lot of features, is straightforward and very functional. Although it does not have the full set of Visual Basic functionality (see the "Resources" section for details), it can certainly hold its own in creating eye-catching applications. You don't need to be a Visual Basic programmer, or really even a programmer at all, to make VBScript work or to get a handle on some sample applications. If you become familiar with the pieces of the whole process, writing VBScript applications won't be any trouble.
The easiest VBScript function to come to terms with is the message
box. You've run into message boxes before; you know that they
just exist to pop up a piece of information, a warning, or an
error in a generic manner. Well, now you can make your own. In
the tradition of the "Hello, world!" application, an
HTML file with a message box in VBScript is shown in Listing 28.1.
Listing 28.1. A "Hello, World" VBScript sample.
MsgBox "Hello, World"
You should have seen a message box by now...
As you can see from Listing 28.1, writing basic functions is no
problem at all. If you want a message box, you use the MsgBox
function. But what if you want to get a little more tricky and
make the message box more interactive? Listing 28.2 shows an example
of letting a script interact with a form on your page, where users
type in their names, and a message box appears and says "Hi"
Listing 28.2. A "Hello, whoever you are" VBScript example.
username="Hello, " & username name
Please type in your name: <input name=namebox> <p>
Now click this button to display a message box:
<input type="button" name="SayHi" value="Say Hi">
If you're a Visual Basic programmer, you probably noticed that the Dim statement doesn't say what the variable's type is in Listing 28.2; it doesn't need to. In VBScript, everything is considered a data variant and is classified by what gets tossed inside it later on.
Two concepts in the script shown in Listing 28.2 serve as the basis for almost all interactions: referencing by name and referencing by action. Referencing by name means that any item you want to use with something else, be it a CGI script or a VBScript function, should be uniquely named so that other things can get access to it later. When text is obtained for the message box, it looks for the form named MyForm, then for the namebox element in that form, and finally for the Value of that element. You can easily have multiple forms on a page and one big VBScript that handles all of them; you just have to name everything carefully so that there's no confusion.
Referencing by action is more general because it uses the name of an element and then an action that would normally be associated with it. The most common is finding out when a particular button is clicked, which is referenced as an OnClick event. Sub SayHi_OnClick uses both name and action to define when this particular subroutine should be run, not just what its name is.
With good referencing, knowledge of the Object Model of the browser or viewer comes into play. To get something done, you have to know what the name of the function is (if it's available) and how to organize your commands so that they get to the right element and do the right thing. Remember that the Object Model can also include reference for what kind of actions (methods) are supported. You can create buttons that do the navigation for you or combo boxes (like at Microsoft's site, though they don't use VBScript for it yet).
What's Not in VBScript?
People who have been developing with Visual Basic for some time may find that a lot of stuff is not in VBScript. Some elements are missing for security reasons, others for keeping the runtime engine small, and others, well, just because.
First and foremost, VBScript limits the functionality available in the development environment. How much of it? Almost the whole thing. Gone are such useful elements as the editor, the debugger, the project manager, and source code controls. Welcome to your new development environment: Notepad or your favorite text editor. Will this change? Quite possibly. With FrontPage as a front end, Microsoft may decide to turn it into an Integrated Development Environment, providing the tools you need to create VBScript as an add-on feature.
Second, VBScript can't create user interfaces-not a one-unless, of course, you believe that a message box is a good user interface, in which case you can rejoice. You can, however, take control of HTML elements such as listboxes, checkboxes, and other elements mentioned previously to get the components you need.
Last, but certainly not least to VB developers, is that the controls and commands in VBScript are a subset of Visual Basic for Applications (VBA), which is itself a subset of Visual Basic. Translated, this means that a lot of elements were left out to make VBScript tiny and efficient. If you're an experienced Visual Basic programmer, you may want to look in the "Resources" section to see just what some of these elements are so that you can determine what you have available in your toolbox. If you're not a Visual Basic programmer with prior experience, you can just stick with the VBScript documentation, which will keep you from fretting about what might have been there and ground you on what's actually there that you can use.
Your ability to run an ActiveX script, regardless of its language, is based on two elements:
- A host browser or viewer that supports ActiveX
- An ActiveX control, or engine, for the script language
Although getting one or the other may be easy, without your hard work and these two elements, your script doesn't do anything once it gets where it's going.
Although most browsers and viewers easily handle HTML, trying to convince them to deal with a new scripting language can be difficult. Fortunately, any host that allows ActiveX controls to hang on to it is a lot more flexible.
Internet Explorer, as I said earlier, is really just a big container with lots of components added on to make it work. The main executable that starts it all is well under 50K (less than half that, in the early stages of beta), and the majority of the work is done by other DLLs and OCXs, such as MSHTML.DLL (which is several hundred kilobytes, and does almost all the HTML work). The rest of the ActiveX strategy uses this same approach-build in little pieces and add on when you need them. Using this approach keeps containers small and updateable, while still being transparently expandable.
Because it is from Microsoft and able to handle all sorts of ActiveX expansions, Internet Explorer is capable of supporting ActiveX scripting implementations both now and in the future.
Microsoft is working on removing the distinction between files on the Internet and files on the desktop. As other shells become available with built-in HTML and URL support, chances are built-in script controls will be implemented as well. More value would be added by supporting the scripting information in more hosts as well, such as server-based scripting and other Internet-related authoring tools (just as Visual Basic for Applications is supported in large applications, adding the lighter VBScript version to small applications would be a possibility). All you really need is an engine to attach to the viewer.
Many developers may be wondering, "But what about Netscape? Don't they support ActiveX scripting?" In the early ActiveX stages, Netscape announced that it had no plans to support ActiveX, and that would mean scripting as well. Some good news appeared for developers, however, when Ncompass labs of Vancouver started developing ActiveX intermediaries for Netscape as plug-ins. The ScriptActive plug-in is the first step toward enabling ActiveX scripting on a Netscape Navigator client. Only time will tell if Netscape changes the decision not to support ActiveX natively, however.
To add support for another scripting language, such as Perl, Tcl/Tk, or Joe Bob's Miracle Script, all you need is another ActiveX control container that the viewer can use. Because you can set up ActiveX controls to download automatically, you don't really need to worry about forcing people to get this container. Make it available where the scripts are, and it can take care of that obnoxious task all by itself. (See "Internet Component Download," in Chapter 27, "ActiveX Controls.")
Creating such a container can be a daunting task. You need intimate knowledge of the language in question and the ability to test every situation that could be encountered, all the functions, and even all the hosts it could be used on. The most likely candidates for their own engines would be popular scripting languages such as Perl and Tcl, because large numbers of programmers who use these languages have the resources to do these kinds of tasks. For a one-person shop or even a two- or three-person shop, creating such an engine would be a Herculean task-but impressive!
In the pursuit of VBScript excellence, you'll make a lot of stops along the way, as you learn in the following sections.
If you're already a Visual Basic programmer, you may want to look for utilities that convert your existing VB applications to VBScript and HTML or ones that can at least use your original VB code to create a starting point. The biggest benefit may not be full conversion, but you may gain an educational tool to let you see how what you do in VB may or may not be transportable. Even if a utility turns out a horrible overall conversion, but has a small portion that works, you can put that component to work and build from there.
Although a number of these tools were in development at the time of writing, none were in a state where they could be reliably tested or recommended. Check the Microsoft Web site and your favorite search engines for the keywords "VBScript converter," and you should get a number of matches which may be of use.
Tables 28.1 through 28.4 show what functions are supported in
the first iteration of VBScript and what's not. For these tables,
I'm assuming that you're either familiar enough with Visual Basic
to make some sense out of what you see listed or that you'll be
willing to track down a comprehensive reference on Visual Basic
and find the meanings there.
|Arrays||Declaration (Dim, Static, and so on), LBound, UBound, ReDim, Erase|
|Assignment||=, Let, Set|
|Comments||REM and '|
|Control flow||Do...Loop, For...Next, For Each...Next, While...Wend, If... Then...Else|
|Error trapping||On Error, Resume, NextErr object|
|Literals||Empty, Nothing, Null, True, False, User-defined literals: 123.456, Foo, and so on|
|Miscellaneous||Line continuation character (_), line separation character (:)|
|Nonconforming identifiers||o.[My long method name]|
|Operators||Arithmetic: +, -, *, /, \, ^,|
|String concatenation (&),|
|Comparison: =, <>, <, >, <=, >=,|
|IsLogical: Not, And, Or, Xor, Eqv, Imp|
|Options: Option Explicit|
|Procedures||Declaring procedures: Function, Sub|
|Calling procedures: Call|
|Exiting procedures: Exit, FunctionExit|
|SubParameters for procedures: ByVal, ByRef.|
|Variables||Procedure-level: Dim, Static|
|Module-level: Private, Dim|
|Type of Function|
|Dates||AbsAsc, ChrCBool, CByteCDate, CDbl, CIntCLng, CSng, Cstr, CVErr, DateSerial, DateValueFix, Int, SgnHex, Oct|
|Math||Date function, Time function, Day, Month, Weekday, YearHour, Minute, Second, Now, TimeSerial, TimeValue|
|Object||Atn, Cos, Sin, TanExp, Log, SqrRandomize, Rnd|
|User Interface||Asc, AscB, AscWChr, ChrB, ChrWInstr, InStrB Len, LenBLCase, UCaseLeft, RightLeftB, MidB, RightB Mid function, Space(number), StrComp, String(number, character), Trim, LTrim, RTrim|
|Variant support||InputBox, MsgBox|
|IsArray, IsDate, IsEmpty, IsError, IsNull, IsNumeric, IsObject, VarType|
|Collection||Add, Count, Item, Remove|
|Constants||(Too many to list)|
|Conversion||Chr$, Hex$, Oct$, CVar, CVDate, Ccur, Format, Format$, Str$, Str, Val|
|Date/Time||Date statement, Time statement, Date$, Time$, Timer|
|DDE||LinkExecute, LinkPoke, LinkRequest, LinkSend|
|Financial||(Too many to list)|
|Graphics||TextHeight, TextWidth, LoadPicture, SavePicture, QBColor, RGB|
|Managing objects||Arrange, ZOrder, SetFocus, InputBox$, Drag, Hide, Show, Load, Unload, Move, PrintForm, Refresh, AddItem, RemoveItem|
|Miscellaneous||Environ, Environ$, SendKeys, Command, Command$, DoEvents, appactivate, ShellBeep|
|Printing||TextHeight, TextWidth, EndDoc, NewPage, PrintForm|
|Strings||LCase$, UCase$, LSet, RSet, Space$, String$, Format, Format$, Left$, Mid$, Right$, Trim$, LTrim$, RTrim$, StrConv|
|Arrays||Option Base, Declaring arrays with Lbound <> 0|
|Collection access||MyCollection! Foo|
|Conditional compilation||#Const #If...Then...#Else...#End If|
|Control flow||DoEvents GoSub...Return GoTo, Line numbers and labels, On Error...GoTo, Select Case|
|Data types||Boolean, Byte, Currency, Date, Double, Integer, Long, Object, Single, String; Type suffixes(%, $, !, and so on); User-defined classes (no Me)|
|Debugging||Debug.Print, End, Stop|
|Error trapping||Erl, Error, Error$On Error...Resume, Resume, Resume Next|
|Graphics||Cls, Circle, Line, Point, PSet, ScalePrint, Spc, Tab|
|Literals||User-defined literals: Based real numbers such as 1.2345E+100; Dates such as #4/7/69#; Trailing type characters such as &hFF&|
|Named arguments||Use of named arguments in calling members such as Call Foo(bar:= 4).|
|Options||DefType, Option Base, Option Compare, Option Private Module|
|Specifying Public/Private; Exiting procedures: Exit Property;|
|Parameters for procedures: ParamArrayOptional|
|Strings||Fixed-length strings; Mid, LSet, RSet statements|
|Structs||Type...End Type, LSet, RSet|
|Using classes||Dim x As New TypeName,|
|Set x = New TypeName,|
|If TypeOf x Is TypeName,|
|Variables and constants||Data types: Currency type; ccur|
|Module level: ConstPrivate, DimPublic, Global|
|Procedure level: Const|
Naturally, a scripting language that is supposed to enhance Web sites has an incredibly large number of sites dedicated to demos and fun examples. You can find one of the best lists at http://www.inquiry.com/thevbpro/vbscentral/gallery.html. Here, you can find an extremely long list that just keeps going and going. It's full of personal pages, so you can see a real variety of ideas for use, and not just the more common ones. Of course, Microsoft maintains a big list of resources at http://www.microsoft.com/vbscript/, where you can always get the latest documentation and improvements. Last, but not least, a general search with the keyword vbscript opens up a growing number of entries.
ActiveX Scripting is a new area, and it's constantly evolving. The basic premise behind its existence is that you can integrate programming elements right into the HTML code that clients download. All the processing work is then done on their machine, reducing the load on your server that would normally have to be done through CGI and speeding up the response on the client end.