N341 Client Programming

Modified

Client Side Pros and Cons

HTML is basically static, the browser displays the text and graphics and waits for the user to click a link or fill in a form to return data to the server. Any dynamic behavior is limited mainly to clicking a link or submitting a form to a server and receiving more static HTML. Client side programming is designed to add dynamic behavior to the client by executing a program on the browser. There are a number of reasons for client side programming, though the most common are for verifying that data has been correctly entered (e.g. all required fields of a form are filled in) or for extending the capability of the browser (e.g. Shockwave for animation). The most common tools and reasons for using them are:

Pros and Cons of Client Side Programming Tools
Type Examples Pros Cons
Scripting
Language
JavaScript
PerlScript
Safe, in theory cannot access client files/hardware.
Common to client and server.
Limited, cannot access client files/hardware.
Little interactivity, cannot generate graphics, sound, etc. 
Scripting
Language
VBScript Can access client files/hardware, extensible using ActiveX.
Common to client and server.
Demands trust, OK perhaps for an intranet.
Requires installation of ActiveX objects on client system.
Plug-in Shockwave Can extend browser capabilities. Demands trust that the plug-in is safe.
Applet Java Safe, cannot access client files/hardware directly.
General programming language with graphics, user interface, etc.
Program delivered to client on demand by server.
Cannot access client files/hardware.
High user interface development time, comparable to C++.

Rantings - Generally, scripting languages are light-weight programming languages, which is not intended to be a compliment. It takes a lot of imagination to implement a script with anything more than trivial user interaction. Though basic user interfaces with buttons, menus, etc. can be easily generated, scripting languages lack the ability to directly generate graphics so something as simple as a line graph is not very feasible.

VBScript qualifies as a curse when coupled with ActiveX technology. To offset weak scripting languages, it attempts to provide to the browser client all the power of Visual Basic or any language that can generate DLLs. The curse is that the DLL must reside on the client, has complete access to the client hardware, be uniquely identified, have an entry in the client system registry, only runs on Microsoft systems, and be completely trustworthy since an ill-mannered DLL can access anything on a client machine. Oh yes, it presently only runs on Internet Explorer. Otherwise, this is a wonderful technology. To be fair, it probably is manageable on an intranet where everyone can trust everyone else, the threat of personal abuse does not exist, the software is always completely tested, and every browser is IE. Don't count on ActiveX gaining ground as a client technology.

Plug-ins are fine from the user point of view, they can decide that they want to listen to RealAudio and download the plug-in. However, for implementing a real Web-site, unless it caters to a select group, remember that most users won't have the plug-in and many are not willing to download a plug-in just to see your wonderful stuff. VBScript and other Microsoft scripting language implementations coupled with ActiveX is sort of like plug-ins for the masses, anyone that can write a Visual Basic program and generate a DLL can do much of what plug-in writers do. A neat technology but one with too great of technical demands and security risks to be worthwhile for the masses.

Java applets represent a compromise between power and security risks. Applets are downloaded by the browser and are run within a virtual machine on the browser. An applet is restricted by the browser security which generally, in theory at least, forbids applet access to local hardware directly or establishing a new Internet connection. Otherwise an applet can do most of what a regular Java program can do; real time graphics, threads, etc. Proponents claim that it is a write once, run anywhere language. Reality is that each browser behaves slightly differently, applets that run reliably on one Windows browser may crash the same browser on Linux. The biggest complaints against it are that it is slow (somewhat over 10 times slower that C++, where C++ takes 0.001 seconds an applet takes 0.01 seconds) which is generally not an issue; that the user interface is clunky which is true since it attempts to work on every computer so is tailored to none; and the applet download time which usually includes the startup time of the Java virtual machine (JVM). While not perfect, it boils down to trusting an ActiveX component programmer to not on purpose or accidentally cause harm versus trusting a language design to be safe. Java currently represents the only serious programming language that can be somewhat trusted not to thrash the client computer.

Key Script Programming Points

Mixed HTML/Script - Scripting languages are typically mixed with HTML in a single file. The HTML provides a user interface and the script program provide the logic. Consider the following JavaScript that displays Hello World 5 times.

The file, JHelloWorld.htm, consists of a mixture of HTML and JavaScript.

JavaScript and HTML 
JHelloWorld.htm JavaScript

<H1>Hello World JavaScript</H1>

<SCRIPT LANGUAGE="JavaScript">
  for( i=1; i<=5; i++)
     document.write ("Hello World<br/>");
</SCRIPT>

 

Exercise 0 - JavaScript

Using the JavaScript program above as a starting point:

  • modify to display your name in bold 1000 times
  • display the line number with each name; concatenate a string and number by: "hi "+5 gives "hi 5"

Hint: Trust the C++/Java force, much of JavaScript is the same syntax. JavaScript data is dynamically typed so numbers and strings are interchangeable. 

<SCRIPT LANGUAGE> Tag

To distinguish script from HTML. Some possible languages are VBScript, JScript, JavaScript, and PerlScript.

document.write - Provides a way for the script to write to the browser with new HTML.

document.write ("Hello World<br/>");

Generating HTML - The document.write statement generates new HTML for the browser. For example, the following displays the table at right:

<SCRIPT LANGUAGE="JavaScript">
    document.writeln("<table border='1' cellspacing='0' cellpadding='0'>");
    document.writeln("<caption><center>4x3 Table</center></caption>");        

    for (row=1;row<=4;row++) {
         document.writeln("<tr>");
         for (col=1; col<=3; col++)
              document.writeln('<td>' + row + ',' + col + '</td>');
         document.writeln('</tr>');
    }
    document.writeln("</table>");
</SCRIPT>

4x3 Table

1,1   1,2   1,3  
2,1 2,2 2,3
3,1 3,2 3,3
4,1 4,2 4,3

<table border="1">
  <caption><center>
    <p>4x3 Table</p>
    </center></caption>
  <tr>
    <td>1,1</td>
    <td>1,2</td>
    <td>1,3</td>
  </tr>
  <tr>
    <td>2,1</td>
    <td>2,2</td>
    <td>2,3</td>
  </tr>
  <tr>
    <td>3,1</td>
    <td>3,2</td>
    <td>3,3</td>
  </tr>
  <tr>
    <td>4,1</td>
    <td>4,2</td>
    <td>4,3</td>
  </tr>
</table>

 

User-Interface

The user-interface HTML components, such as buttons, can interact with script code.

Consider the following VBScript and JavaScript that displays the current time and the name entered in the text box when the button is clicked. The VBScript example can only be run in IE.

VBScript/JavaScript and HTML 
VBHello.htm VBScript

<SCRIPT LANGUAGE="VBScript">
   Sub Button1_onClick
      Document.Write ("Hello " & Document.NameForm.Text1.Value & "<br>")
   End Sub
</SCRIPT>

<H1>Hello in VBScript</H1>
<FORM NAME="NameForm">
      Enter your name and click button: 
     <INPUT NAME="Text1" TYPE="TEXT" SIZE="10">
    <INPUT NAME="Button1" TYPE="BUTTON" VALUE="Hello">
</FORM>

<SCRIPT LANGUAGE="VBScript">

  Document.Write "Current time: " & time & "<br/>"

</SCRIPT>

IE Browser Output

JHello.htm JavaScript

<SCRIPT LANGUAGE="JavaScript">
  var now = new Date();
  document.write ("Current time: " + now.getHours() + ":" + now.getMinutes())

  function Button1_onClick() {
    document.write ("Hello " + document.NameForm.Text1.value + "<br/>")
  }
</SCRIPT>

<H1>Hello in JavaScript</H1>
<FORM NAME="NameForm">
     Enter your name and click button: 
    <INPUT NAME="Text1" TYPE="TEXT" SIZE="10">
    <INPUT NAME="Button1" TYPE="BUTTON" 
              VALUE="Hello" onClick="Button1_onClick();">
</FORM>

Events

When a user clicks on a button, passes the mouse over a link, etc. an event is generated that can be used to execute a specific function. The examples above illustrate the onClick event handling, when Button1 is clicked a call is made to the Button1_onClick function.

In JavaScript the event handler (function called) can be any name, in VBScript it must be a concatenation of object _ event similar to VB; Button1_onClick is the Button1 object and the onClick event.

The event to event handler name is automatically created in VBScript but in JavaScript the event handler must be explicitly designated (e.g. onClick="Button1_onClick()" ).

Note that JavaScript does not support all the events of VBScript but only IE supports VBScript.

Form Objects

User interaction occurs through buttons, text boxes, hyperlinks, etc. that can generate events to execute a script function, such as the onClick event. Buttons and text boxes are defined in a HTML form but can be referenced in a scripting language.

To define form ButtonInput with Button1 object as:

<FORM name=ButtonInput>
        <INPUT NAME="Button1" TYPE="BUTTON" VALUE="Button 1">
</FORM>

Form Object Access

Accessing a specific form object can be relatively simple. The following JavaScript changes the value of the Button1 object to "OK":

document.ButtonInput.Button1.value = "OK";

document.write

One point of confusion is that:

The example below illustrates that behavior where any JavaScript outside a function is executed when the page is loaded; any function code is executed only when called, in this case only after the page is loaded and the user clicks the Helllo button:

<H1>Hello in JavaScript</H1>
<FORM NAME="NameForm">
     Enter your name and click button: 
    <INPUT NAME="Text1" TYPE="TEXT" SIZE="10">
    <INPUT NAME="Button1" TYPE="BUTTON" 
              VALUE="Hello" onClick="Button1_onClick()">
</FORM>

<SCRIPT LANGUAGE="JavaScript">
  var now = new Date();
  document.write ("Current time: " + now.getHours() + ":" + now.getMinutes());

  function Button1_onClick() {
    document.write ("Hello " + document.NameForm.Text1.value + "<br>");
  }
</SCRIPT>

displays the time on the same page with HTML for the form, heading, etc.

The script executed after the page is loaded when the button is clicked causes the browser to open a new page.

  function Button1_onClick() {
    document.write ("Hello " + document.NameForm.Text1.value + "<br>");
  }

 

Start Execution of Script

All scripting code outside of functions is executed when the form is loaded or refreshed. Function definitions are not executed until called.

Button1_onClick above is never executed until Button1 is clicked. In C++ and Java execution starts with a main function, in JavaScript and VBScript, script execution starts with the first script code encountered outside of a function definition.

Any document.write statements encountered during loading the page are executed and added to the current window; this allows the script to construct the HTML displayed when the page is loaded by the browser.

Any document.write statements encountered after loading the page are executed and overwrite the current window; the effect is to overwrite the loaded HTML with new HTML, erasing the display and rendering the new HTML in the window.

Global variables - Any variable defined or first used outside of a function is globally accessible.

Exercise 1 - JavaScript Forms

Using the JavaScript Hello program above as a starting point:

  • open the Hello program to observe the effect when the page is loaded and when a new document.write is executed in Button1_onClick(),
  • add another button labeled Factorial;
  • when the Factorial button is clicked, compute the factorial of the value in the text box (if 5 is in the text box, compute 5!);
  • write the factorial as HTML.

Hint: Trust the C++ or Java force, much of JavaScript has the same syntax. JavaScript data is dynamically typed so numbers and strings are interchangeable. 

Yes, you can use recursion in JavaScript.

For example, neither sum or i require definitions of type.

sum = 0;
for (i=0; i<10; i++) sum = sum + i;

 

Passing Values to Script Functions

Values can be passed as function parameters. The following passes the document.TextInput.Text1.value to function Button1_onClick.

Button1_onClick(document.TextInput.Text1.value)

The Button1_onClick function accesses the document.TextInput.Text1.value object passed using the parameter name input.

function Button1_onClick(input)

Note that the parameter input is the value of document.TextInput.Text1.value or text.

Passing Values
<FORM name=TextInput>
   <INPUT type="text" name=Text1 value="1">
</FORM>

<FORM name=ButtonInput>
   <INPUT NAME="Button1" TYPE="BUTTON" VALUE="Text value"
               onClick="Button1_onClick(document.TextInput.Text1.value)" >
</FORM>

<SCRIPT language="JavaScript">
   function Button1_onClick(input) {
     document.write("Value entered: <b>" + input + "</b>");
   }
</SCRIPT>

Value entered: Hello

 

Passing Objects to Script Functions

Objects (references) can be explicitly accessed, as above, or passed as function parameters.

Passing Objects
<FORM name=TextInput>
   <INPUT type="text" name=Text1 value="1">
</FORM>

<FORM name=ButtonInput>
   <INPUT NAME="Button1" TYPE="BUTTON" VALUE="Text object"
               onClick="Button1_onClick(document.TextInput.Text1)" >
</FORM>

<SCRIPT language="JavaScript">
   function Button1_onClick(input) {
     document.write("Value entered: <b>" + input.value + "</b>");
   }
</SCRIPT>

Value entered: Hello

 The following passes the document.TextInput.Text1 object to function Button1_onClick.

Button1_onClick(document.TextInput.Text1)

The Button1_onClick function accesses the document.TextInput.Text1 object passed using the parameter name input.

function Button1_onClick(input)

Note that the parameter input is precisely document.TextInput.Text1 so its attributes are only those of a text object.

The following increments the value of the object passed by first evaluating the text to a number then adding 1 (e.g. eval("5")+1 is 5+1 or 6).

input.value = eval(input.value) + 1;
Form Object Access and Passing
ClientForm.htm
<FORM name=TextInput>
        <INPUT type="text" name=Text1 value="1">
        <INPUT type="text" name=Text2 value="2">
</FORM>

<FORM name=ButtonInput>
        <INPUT NAME="Button1" TYPE="BUTTON" VALUE="Button 1"
               onClick="Button1_onClick(document.TextInput.Text1)" >
</FORM>

<SCRIPT language="JavaScript">

   function Button1_onClick( input ) {
     document.TextInput.Text2.value = input.value;
     input.value = eval(input.value) + 1;
     document.ButtonInput.Button1.value = "Button " + document.TextInput.Text2.value;
   }
</SCRIPT>

 

Exercise 2 - JavaScript Objects and Functions

Copy the JavaScript program above as a starting point, create a simple dice rolling script. 

  • Three buttons, one for each of the dice and one to roll the dice,
  • When the roll button is clicked, call a function two times; pass one of the dice button objects as a parameter each time,
  • The function changes the value of the button object to a random number 1-6.
  • multiple JavaScript statements are separated by ; and can be performed for the onClick event, for example:

    onClick="Button1_onClick(document.TextInput.Text1) ; 
                  Button1_onClick(document.TextInput.Text2)" >

Hint: A random number 1-6 is generated by: Math.round(6*Math.random( ))%6+1;

 

The Document Object Model (DOM)

To access HTML objects in JavaScript, it is necessary to understand the hierarchical DOM structure, the model used to represent HTML (and XML, XSL, etc.) documents.

The above example (ClientForm.htm) creates two objects named document.TextInput.Text1 and document.TextInput.Text2 by the following:

<FORM name=TextInput>
        <INPUT type="text" name=Text1 value="1">
        <INPUT type="text" name=Text2 value="2">
</FORM>

The DOM can be thought of as a tree with document at the root. The browser places all HTML tags (e.g. <b>, <FORM>, etc.) into the tree hierarchy for rendering. The above example can be represented as a tree structure as:

 

Access to the Text1 object is: document.TextInput.Text1

To change the value attribute of Text1 in JavaScript: document.TextInput.Text1.value = "42"

 

Selection Lists

Pull-down lists limit input choice to users. The following gives choices of Red, Green or Blue colors and displays the associated value. The default selected value is Red with the value 1.

Selection Lists
<form name="SelectForm" action>
   <select name="ColorSelect">
      <option selected="selected" value="1">Red</option>
      <option value="2">Green</option>
      <option value="3">Blue</option>
   </select>
   <input name="print" value="Print Color" type="button" onclick="printColor();">
</form>

<script language="JavaScript">
   function printColor() {
      document.write( "Selected value: " + SelectForm.ColorSelect.value );
   }
</script>


Selected value: 2

 

Arrays

JavaScript arrays, while similar to VB, C++ or Java arrays, are dynamically typed and created.

var color = ["Red", "Green", "Blue"];

defines an array color with the values:

color[0] = "Red";
color[1] = "Green";
color[2] = "Blue";

The following example uses an array to translate the selection value into the entry selected. Note that the selection values are 1-3 but the array indices are 0-2, hence the need to subtract 1 from SelectForm.ColorSelect.value as an index.

Arrays and Selection Lists
<form name="SelectForm" action>
   <select name="ColorSelect">
      <option selected="selected" value="1">Red</option>
      <option value="2">Green</option>
      <option value="3">Blue</option>
   </select>
   <input name="print" value="Print Color" type="button" onclick="printColor();">
</form>

<script language="JavaScript">
   var color = ["Red", "Green", "Blue"];

   function printColor() {
      document.write( "Selected color: " + color[ SelectForm.ColorSelect.value - 1] );
   }
</script>


Selected color: Green

 

Link Events

An example often used to simulate button presses using a graphic image is the mouseOver and mouseOut events.

The following switches between an image used as a link reference to another page. The name of the HREF (SYLLABUS.HTM in this case) is referenced, that could also be a parameter to the change function. The empty HREF="" and return=false are needed for some browsers, return false prevents processing of the HREF="".
 

 mouseOver.htm

<SCRIPT LANGUAGE="JavaScript">
    function change(newImage,name) {
        name.src=newImage;
    }
</SCRIPT>

<H1>JavaScript Events</H1>
Moving the mouse over the image will switch from one image to another, and back when the mouse is out of the image. Clicking the image will load the page  referenced.

<A  HREF="Syllabus.htm"
   onMouseOver ="change('html_1.jpg', document.ONE)"
   onMouseOut   ="change('html_2.jpg', document.ONE)"
   onClick            ="change('html_3.jpg', document.ONE)">
   <IMG SRC="html_2.jpg" NAME=ONE WIDTH=15 HEIGHT=15 BORDER=0 ALT="SYLLABUS">
</A>


<A  HREF=""
  onMouseOver ="change('html_3.jpg', document.TWO)"
  onMouseOut   ="change('html_4.jpg', document.TWO)"
  onClick            ="change('html_3.jpg', document.TWO); return false;">
  <IMG SRC="html_4.jpg" NAME=TWO WIDTH=15 HEIGHT=15 BORDER=0 ALT="Nothing">
</A>

JavaScript Events

Moving the mouse over the image will switch from one image to another, and back when the mouse is out of the image. Clicking the image will load the page referenced.

 SYLLABUS Nothing

 

Explanation

<SCRIPT LANGUAGE="JavaScript">
   function change(newImage,name) {
      name.src=newImage;
   }
</SCRIPT>

Defines the function change but does not execute. When change is called by:

change('html_3.jpg', document.TWO)

the execution is:

document.TWO.src = 'html_3.jpg'

which makes the IMAGE SRC = 'html_3.jpg' for the HREF NAME=TWO.

 
Explanation

<A  HREF="Syllabus.htm">
<IMG SRC="html_2.jpg" NAME=ONE WIDTH=15 HEIGHT=15 BORDER=0 ALT="SYLLABUS"></A>

just defines a normal HREF link to "Syllabus.htm" that is has an image of  "html_2.jpg" and NAME=ONE.

The document.ONE can refer to this particular HREF.

 onMouseOver="change('html_1.jpg', document.ONE)"

executes the change function when the mouse is over the "html_2.jpg" image.

 

 

Program State

Maintaining state is critical for user interaction such as games, shopping carts, etc. but somewhat challenging given that the HTTP protocol of the Web is a stateless protocol. Generally, the server does not automatically maintain user state; with many potential users, keeping track of what each has done would make the server much more complex. A simpler approach is to maintain state by the client and pass current state to the server when needed. We'll examine several ways to maintain state: appending to the URL, client scripts such as JavaScript, and applets. The state of a computation broadly means the values of program variables.

  • Global variables - In scripting languages, variables defined outside of a function can be accessed globally throughout the program, importantly keeping the value.
  • Local variables - Parameters and variables defined inside a function are local to the function and do not keep value between calls to that function.

In the following example, the button value is incremented each time clicked. The state of the button value is maintained in the variable count and of course the document.ButtonInput.Button1.value itself since it is a global object.
 

Maintaining State
Count.htm

<SCRIPT LANGUAGE="JavaScript">
var count = 0;                    // Global

function increment() {
 count++;
 document.ButtonInput.Button1.value = count;
}
</SCRIPT>

<FORM name=ButtonInput>
 <INPUT NAME="Button1" TYPE="BUTTON" VALUE="0" 
        onClick="increment()" >
</FORM> 

Not Maintaining State
NoCount.htm

<SCRIPT LANGUAGE="JavaScript">

var count = 0;                    // Global

function increment() {
 var count = 0;
 count++;

 document.ButtonInput.Button1.value = count;
}
</SCRIPT>

<FORM name=ButtonInput>
 <INPUT NAME="Button1" TYPE="BUTTON" VALUE="0" 
        onClick="increment()" >
</FORM> 

 

Exercise 3 - Internal State

Create a modulus 4 counter by modifying the example program above to display the count as images of the digits also, similar the that at right.

   Count

  1. Start with the Count.htm example above.
     
  2. Create an HTML file named Internal.htm.
     
  3. Collect the four different image files  (right click on the image to save). Name them "digit0.gif", "digit1.gif", etc. for example.
     
  4. Define a single IMG with an image source of "digit0.gif" by:
    <img name="digit" SRC="digit0.gif">
  5. The SRC attribute of the img element above can be accessed in JavaScript. The following changes the image to "digit1.gif":
    • document.digit.SRC = "digit1.gif";
       
  6. The + performs concatenation of strings in JavaScript. "the"+"re" produces "there".
     
  7. When the onClick event occurs, increment the counter and the image displayed to the next image; digit0.gif, digit1.gif, etc. and back to digit0.gif. The modulus operator in JavaScript is %, in VBScript is Mod.

Exercise 4 - Internal State and Link Events

Modify the modulus 4 counter to an adder that adds each digit to the counter when clicked, similar to that at right.

 

Sum

  1. Modify the HTML file named Internal.htm.
     
  2. Remove the button.
     
  3. Make the digits    as clickable images similar to below:
    <A  HREF="" name="two" onClick ="add(2); return false;">
    <IMG SRC="digit2.gif"></A>
  4. Create the add method. When the onClick event occurs, add the digit value of the image clicked to the counter and display the digit image; digit0.gif, digit1.gif, etc. for a modulus four adder.

URL State

A JavaScript script is executed independent of other JavaScript, that means that variables from one page of the browser are not accessible on other pages. However, state of one script can be passed through the URL by appending the state as a parameter to the URL. For example, a script that is invoked by:

Count.htm?15

passes the value 15 to the Count.htm script as part of the URL. A JavaScript in Count.htm can access the URL parameters. The location.search attribute returns the string "?15" which must be parsed from a string to an integer by:

query = location.search; 
n = parseInt(query.substring(1, query.length))+ 1;    // Begin parse after "?"

One advantage of this method is that no server overhead is required, in fact, no server is needed if the page of the URL is already loaded by the browser. A recursive example to increment a counter each time the link is clicked:

Count.htm

<h1>Counting Example using URL parameters</h1><br>
<Script Language = "JavaScript" > 
var n, query;
   query = location.search; 
   if (query.length == 0) {                                        // Initialize when executed by: Count.htm
       document.write ('<A HREF="Count.htm?0">Count 0</A>'); 
   } else {                                                                // Increment counter 
       n = parseInt(query.substring(1, query.length)); // Skip '?' and convert to integer
       document.write ('<A HREF="Count.htm?' + (n+1) + '">Count ' + (n+1) + '</A>'); 
}
</Script>

Points of note:

  • The URL loading the page is initially: Count.htm
  • location.search - A predefined JavaScript parameter that holds the string passed to the page. If the page were loaded by:
  • Count.htm?1234

    location.search = "1234"

The script tests whether any URL parameters exist by location.search.length == 0, generating a link of <A HREF="Count.htm?0">Count 0</A> if not, or increments the URL parameter and generates a link of <A HREF="Count.htm?5">Count 5</A> after 5 clicks. Note that each link click causes the page to be reloaded by the browser with the URL parameters.

 

Exercise 5 - Factorial using URL State

Modify the above Counter.htm to compute the factorial. Start with an initial value of 1, display as:      Factorial 4 = 24

Exercise 6 - URL State

Modify Exercise - Link Events and Internal State to use URL state.

 

Reset

  1. Create an HTML file named URL.htm.
  2. Define a link to reset the count to 0 by loading URL.htm with no parameters.
  3. Define HREF for each digit. HREF linking should occur, that is generate:

  4. <A HREF="URL.htm?0"><img SRC="digit0.gif" height=22 width=18 border=0></A> )

    when the digit image is clicked. The value of the digit clicked should be added to the modulus 4 counter and displayed.

VBScript/JavaScript Differences

At the basic level of functionality the two scripting languages are very similar. The main problem with VBScript is that only IE supports it. This problem will disappear after Microsoft achieves world domination but for now it makes it unwise to use VBScript for client-side programming except where the browser is known to be IE. Try the VBHello.htm in Netscape.
 

Some VBScript and JavaScript Differences
JavaScript VBScript
Browser Any IE
Safe Yes Maybe
Extensible Yes using Java Yes using ActiveX
Case Sensitive Yes No
Concatentation + &
Events handlers Any function name Must be concatentation of object _ event

Conclusions? - VBScript can be both a client and server side scripting language, is powerful and, through ActiveX, extensible by the average programmer. As a client scripting language, one grave concern is security since VBScript provides full access to the file system and other resources of the host computer via ActiveX. A simple example illustrates this in a script that deletes a file (c:\delete.me) on the host computer, given below. To be fair, VBScript does generally warn that bad things might happen but this sort of message is unlikely to inspire faith in your clients. As a server-side scripting language on Microsoft server operating systems it seems to have better access to the Microsoft technologies than other scripting languages.
 

VBScript to Delete a File on Host
Delete.htm

<SCRIPT LANGUAGE="VBScript">
  Dim fso
  Set fso = CreateObject("Scripting.FileSystemObject")
  fso.DeleteFile("c:\delete.me") 
</SCRIPT>

Examples

Three similar TicTacToe examples are given in Java and JavaScript for comparison. Java will be examined more closely later in the course if time permits. In the game, the user always plays X and the computer O. Whenever an empty board position is clicked, an X is placed there. For simplicity, the computer then randomly places an O in any empty position, checking for ties and wins. The board positions are numbered as:

0|1|2
3|4|5
6|7|8

Key similarities beyond that in the code are that both can be safely run without installing any software components on the client machine. Try both the JavaScript and Java applet (no apology for the poor computer play).

Example 1 - Client Side JavaScript TicTacToe with Events and Internal State

The example is of interest primarily due to the use of events to signal when and what board position should be changed on the screen. The state of the game is held in a string variable board initialized to "012345678" to indicate that no moves have been taken. If an X is placed in position 2 then board = "01x345678", and an X is placed in the two position. When a position is clicked, a move function is called with the position number and the image object, if the move is valid a graphic for the X is assigned to the image object. The following initially places a blank image named "gameb.gif"  for the HREF named ZERO, since it is the first image it is placed in the first position. The empty HREF="" and return=false are needed for Netscape, return false prevents processing of the HREF="".

<A HREF="" onClick ="move(document.ZERO, 0); return false;">
<IMG NAME=ZERO BORDER=0 HEIGHT=32 WIDTH=32 SRC="gameb.gif"></A>
Client Side JavaScript TicTacToe with Events and Internal State
ETTT.htm

<HTML> 
<HEAD>  <TITLE>Client-Side TicTacToe JavaScript using Events</TITLE> </HEAD>
<BODY BGCOLOR="White">
<H1>Client-Side<br>TicTacToe<br>JavaScript</H1>

<Script Language = "JavaScript" > 
 var board = "012345678";            // Initial board

 function move(imageName, position) { 
  newBoard = process(position, board );
  if (newBoard != board) {           // newBoard different? then valid X move
   imageName.src="gamex.gif";
   board = newBoard;
  }
 }

 function win(player, board) {
  var wins = "012345678036147258048246";
  for (awin=0; awin<8; awin++) {
   i0 = parseInt(wins.charAt(awin*3));
   i1 = parseInt(wins.charAt(awin*3+1));
   i2 = parseInt(wins.charAt(awin*3+2)); 
   if (board.charAt(i0) == board.charAt(i1) && 
       board.charAt(i1) == board.charAt(i2) ) {

    document.TicTacToe.Text1.value = player+' wins!';
    return true;
   }
  }
  return false;
 }

 function tie(board) {
  for (i=0; i<=8; i++) 
   if (board.charAt(i) != 'x' && board.charAt(i) != 'o')
   return false;
  document.TicTacToe.elements[1].value = 'Tie!';
  return true;
 }

 function place(symbol, move, board) {
  i = parseInt(move);
  if (i >= 0 && i <= 8) 
   if (board.substr(i,1) == move) 
    board = board.substr(0,i) + symbol + board.substr(i+1,9-i);
  return board;
 }

 function process(move, oldBoard) {       // Check if X move OK, generate O move
  var oMove; 
  newBoard = place('x', move, oldBoard);  // Place x move 

  if (win("X", newBoard) || tie(newBoard) || newBoard==oldBoard) return newBoard;

  do {          // Random O move
   oBoard = place('o', (oMove=(Math.round(Math.random()*10)%9)), newBoard);
  } while (!win("O", oBoard) && !tie(oBoard) && oBoard == newBoard);

  switch (oMove) {                         // Put an O image at the move
   case 0 : document.ZERO.src="gameo.gif";  break;
   case 1 : document.ONE.src="gameo.gif";   break;
   case 2 : document.TWO.src="gameo.gif";   break;
   case 3 : document.THREE.src="gameo.gif"; break;
   case 4 : document.FOUR.src="gameo.gif";  break;
   case 5 : document.FIVE.src="gameo.gif";  break;
   case 6 : document.SIX.src="gameo.gif";   break;
   case 7 : document.SEVEN.src="gameo.gif"; break;
   case 8 : document.EIGHT.src="gameo.gif"; break;
  }
  return oBoard;
}
</Script>

// Draw the board
<A HREF="" onClick ="move(document.ZERO, 0); return false;">
  <IMG NAME=ZERO BORDER=0 HEIGHT=32 WIDTH=32 SRC="gameb.gif"></A>

<IMG HEIGHT=32 WIDTH=4 SRC="gamedv.gif">
<A HREF="" onClick ="move(document.ONE, 1); return false;">
  <IMG NAME=ONE BORDER=0 HEIGHT=32 WIDTH=32 SRC="gameb.gif"></A>

<IMG HEIGHT=32 WIDTH=4 SRC="gamedv.gif">
<A HREF="" onClick ="move(document.TWO, 2); return false;">
  <IMG NAME=TWO BORDER=0 HEIGHT=32 WIDTH=32 SRC="gameb.gif"></A>

<br><IMG HEIGHT=4 WIDTH=104 SRC="gamedh.gif"><br>
<A HREF="" onClick ="move(document.THREE, 3); return false;">
  <IMG NAME=THREE BORDER=0 SRC="gameb.gif"></A>

<IMG HEIGHT=32 WIDTH=4 SRC="gamedv.gif">
<A HREF="" onClick ="move(document.FOUR, 4); return false;">
  <IMG NAME=FOUR BORDER=0 SRC="gameb.gif"></A>

<IMG HEIGHT=32 WIDTH=4 SRC="gamedv.gif">
<A HREF="" onClick ="move(document.FIVE, 5); return false;">
  <IMG NAME=FIVE BORDER=0 SRC="gameb.gif"></A>

<br><IMG HEIGHT=4 WIDTH=104 SRC="gamedh.gif"><br>
<A HREF="" onClick ="move(document.SIX, 6); return false;">
  <IMG NAME=SIX BORDER=0 SRC="gameb.gif"></A>

<IMG HEIGHT=32 WIDTH=4 SRC="gamedv.gif">
<A HREF="" onClick ="move(document.SEVEN, 7); return false;">
  <IMG NAME=SEVEN BORDER=0 SRC="gameb.gif"></A>

<IMG HEIGHT=32 WIDTH=4 SRC="gamedv.gif">
<A HREF="" onClick ="move(document.EIGHT, 8); return false;">
  <IMG NAME=EIGHT BORDER=0 SRC="gameb.gif"></A>

// When New Game submit button clicked, execute the ETTT.htm page again to restart the game.
 <form name=TicTacToe action="ETTT.htm">
  <input type='submit' value='New Game?'> <br>
  <input type='TEXT' NAME=Text1 SIZE=20>
 </form>
</HTML>
</BODY>

 

Example 2 - Client Side JavaScript TicTacToe with State Data Passed through URL

The example illustrates how an HTML file can reload itself and pass the current state through the URL. The original HTML file is loaded for each X move but with a new starting state appended. The state of the game board is updated with each move and passed back as part of the URL. The first time the file is loaded by:

JTTT.htm

Assuming that an X move is made to position 2, the JTT.htm file would be loaded with the URL:

JTTT.htm?2012345678

Assuming an O move to 5 and X to 7, the JTT.htm file would be loaded with:

JTTT.htm?701x34o678

This method actually parallels that used by Web servers operating without state or memory of any previous operation. As we've already seen with the Yahoo! search, parameters can be passed as part of the URL. That is precisely what is being done in this example, it just happens that the HTML file contains a reference to itself; recursion!

The data that is passed in is used to generate HTML as the file is being loaded. For example, the URL JTTT.htm?701x34o678 corresponds to a move to position 7 where position 2 is "x" and 5 is an "o". It would generate the partial HTML of:

<A HREF="JTTT.htm?001x34o6x8"><IMG ALIGN=bottom BORDER=0 SRC="gameb.gif"></A>
<IMG ALIGN=bottom SRC="gamedv.gif">
<A HREF="JTTT.htm?101x34o6x8"><IMG ALIGN=bottom BORDER=0 SRC="gameb.gif"></A>
<IMG ALIGN=bottom SRC="gamedv.gif">
<A HREF="JTTT.htm?201x34o6x8"><IMG ALIGN=bottom BORDER=0 SRC="gamex.gif"></A>
<BR><IMG ALIGN=bottom SRC="gamedh.gif"><BR>
<A HREF="JTTT.htm?301x34o6x8"><IMG ALIGN=bottom BORDER=0 SRC="gameb.gif"></A>

which contains the move and current board and, for position 3, uses the X image instead of a blank.
 

Client Side JavaScript TicTacToe with State Data Passed

JTTT.htm

<HTML> 
<HEAD> <TITLE>Client-Side TicTacToe JavaScript</TITLE></HEAD>
<BODY BGCOLOR="White">
<H1>Client-Side<br>TicTacToe<br>JavaScript</H1>

<Script Language = "JavaScript" > 
// With graphic ideas borrowed from Stephen Wassell
 var board = "??012345678";        // Initial board

 if (location.search.length == 11) // ? + Move + board
  move (location.search);
 else 
  display(board); 

 function display(board) {
  for (i=0; i<=8; i++) {
   if (board.charAt(i+2) != 'x' && board.charAt(i+2) != 'o') {
    document.write ('<A HREF="JTTT.htm?'
                     +i+board.substr(2,10)+'">'); 
    document.write('<IMG ALIGN=bottom BORDER=0 ' +
                   'SRC="gameb.gif"></A>');
   }
   else
    document.write('<IMG ALIGN=bottom ' + 
                   'SRC="game'+board.charAt(i+2)+'.gif">');
   if (i == 2 || i == 5) 
    document.write('<BR><IMG ALIGN=bottom ' + 
                   'SRC="gamedh.gif"><BR>')
   else 
    if (i != 8)
     document.write('<IMG ALIGN=bottom SRC="gamedv.gif">')
  }
 }

 function move(input) {  // Display board with move input
  display("??"+process(input.charAt(1), input.substr(2, 10)) );
 }

 function win(player, board) {
  var wins = "012345678036147258048246";
  for (awin=0; awin<8; awin++) {
   i0 = parseInt(wins.charAt(awin*3));
   i1 = parseInt(wins.charAt(awin*3+1));
   i2 = parseInt(wins.charAt(awin*3+2)); 
   if (board.charAt(i0) == board.charAt(i1) &&
       board.charAt(i1) == board.charAt(i2) ) {
    document.write('<b>'+player+' wins!</b><br><br>');
    return true;
   }
  }
  return false;
 }

 function tie(board) {
  for (i=0; i<=8; i++) 
   if (board.charAt(i) != 'x' && board.charAt(i) != 'o')
   return false;
  document.write('<b>Tie!</b><br><br>');
  return true;
 }function place(symbol, move, board) {
  i = parseInt(move);
  if (i >= 0 && i <= 8) 
   if (board.substr(i,1) == move)
    board = board.substr(0,i) + 
            symbol + board.substr(i+1,9-i);
  return board;
 }

 function process(move, oldBoard) { 
  newBoard = place('x', move, oldBoard);  // Place x

  if (win("X", newBoard) || tie(newBoard)) 
    return newBoard;

  do {          // Random O move
   oBoard = place('o', 
                  (Math.round(Math.random()*10)%9),
                  newBoard);
  } while (!win("O", oBoard) && 
           !tie(oBoard) && oBoard == newBoard);

  return oBoard;
}

</Script>
 <form name=TicTacToe action="JTTT.htm">
  <input type='submit' value='New Game?'>
 </form>
</BODY>
</HTML>


Browser client output

Further Information - See Microsoft Development Environment Help index item JScript Tutorial.

 

Example 3 - Java Applet

The key differences between programming the TicTacToe game in JavaScript and Java applet are:

Client Side Java Applet TicTacToe
ATTT.java

import java.awt.*;
import java.applet.*;

public class ATTT extends Applet {

   String board, message;

   Image OImage, XImage, HImage, VImage, BImage;

   public void init() {
       OImage = getImage(getCodeBase(), "gameo.gif");
       XImage = getImage(getCodeBase(), "gamex.gif");
       HImage = getImage(getCodeBase(),"gamedh.gif");
       VImage = getImage(getCodeBase(),"gamedv.gif");
       BImage = getImage(getCodeBase(),"gameb.gif");
   } 
                   // Called whenever applet starts (window open, etc.)
   public void start() {
       board="012345678";
       message="          ";
       repaint();
   }
                     // Called when mouse button released at (x, y) of screen
   public boolean mouseUp(Event evt, int x, int y) {
       int width = (OImage.getWidth(null)+VImage.getWidth(null));
       int height = (OImage.getHeight(null)+HImage.getHeight(null));
       int r = (y/height)-1, c = (x/width)-1;
                                                               // Is move over the board?
      if (r < 0 || r > 2 || c < 0 || c > 2) return true;
      int move = c+r*3;

      String newBoard = process(move, board);
      if (board == newBoard) return true;    // Position occupied, ignore.
      board = newBoard;                            // Otherwise redraw board.
      repaint();
      return true;
   }
                                                                 // Display board
   void display(String board, Graphics g) {
         g.setColor(Color.black);
         int xoff = (OImage.getWidth(null)+VImage.getWidth(null)); ;
         int yoff = (OImage.getHeight(null)+HImage.getHeight(null)); 
         int r, c;

         for (int i=0; i<=8; i++) {
              c = i%3+1;
              r = i/3+1;
              if (board.charAt(i) != 'x' && board.charAt(i) != 'o') 
                   g.drawImage(BImage, c*xoff, r*yoff, this);
              else
                   if (board.charAt(i) == 'x')
                        g.drawImage(XImage, c*xoff, r*yoff, this);
                   else
                        g.drawImage(OImage, c*xoff, r*yoff, this);
              if (i == 2 || i == 5) 
                   g.drawImage(HImage, xoff, r*yoff+VImage.getHeight(null), this); 
              else 
                   if (i != 8)
                        g.drawImage(VImage, (c+1)*xoff-VImage.getWidth(null), 
                                              r*yoff, this);
       }
       g.drawString(message,xoff,yoff*5);  // Display Tie! or Win! message
    }
                                                // Called on window events (open, repaint, etc.)
   public void paint(Graphics g) { 
         display(board, g);
   }

   int parseInt(char n) {
         return (int)(n-'0');
   }

   boolean tie(String board) {
         for (int i=0; i<=8; i++) 
              if (board.charAt(i) != 'x' && board.charAt(i) != 'o')
                   return false;
         message = "Tie!";
         return true;
   }

   boolean win(char player, String board) {
         String wins = "012345678036147258048246";
         int i0, i1, i2;

         for (int awin=0; awin<8; awin++) {
              i0 = parseInt(wins.charAt(awin*3));
              i1 = parseInt(wins.charAt(awin*3+1));
              i2 = parseInt(wins.charAt(awin*3+2)); 
              if (board.charAt(i0) == board.charAt(i1) && 
                  board.charAt(i1) == board.charAt(i2) ) {
                   message = player + " wins!";
                   return true;
              }
        }
        return false;
   }

  String place(char symbol, int move, String board) {
         int i = move;
         if (i >= 0 && i <= 8) 
             if (board.charAt(i) == (char)(move+'0'))
                   board = board.substring(0,i) + symbol + board.substring(i+1,9);
        return board;
  }

  String process(int move, String oldBoard) { 
     String oBoard; 
     String newBoard = place('x', move, oldBoard);  // Place x move

     if (win('X', newBoard) || tie(newBoard)) return newBoard;

     do {                                                                  // Random O move
          oBoard = place('o', (int)(Math.round(Math.random()*10)%9), newBoard);
     } while (!win('O', oBoard) && !tie(oBoard) && oBoard == newBoard);

     return oBoard;
   }
}

ATTT.htm

<HTML> 
 <HEAD> 
<TITLE>Client-Side TicTacToe Java Applet</TITLE>
</HEAD>
 <BODY BGCOLOR="White">
 <H1>Client-Side<br>
TicTacToe<br>
Java Applet
</H1>
 <applet code="ATTT.class"
                         name="Applet TicTacToe" 
                        WIDTH="150" HEIGHT="180">
 </applet>
  <form name=TicTacToe action="ATTT.htm">
      <input type='submit' value='New Game?'>
  </form>
</HTML>


Browser client output


 

Further Information - Java Programming by Joe Wigglesworth, Course Technologies, ISBN 1-85032-922-2

A final note about JavaScript and Java applets. It is possible for JavaScript to invoke a Java applet method. In theory, this provides the ability to extend the functionality of JavaScript, limited only by what a Java applet can do. I personally have not done much with this so cannot comment about important issues such as Java object creation and referencing by JavaScript, thread control, etc. Maybe its the thought of trying to get an application to work reliably that uses three languages: HTML, JavaScript, and Java, on different browser platforms that dampens my enthusiasm.