Table 4.1 Client and server comparison
There are usually a variety of ways to partition an application between client and server. Some tasks can be performed only on the client or on the server; others can be performed on either. Although there is no definitive way to know what to do where, you can follow these general guidelines:
As a rule of thumb, use client processing (the SCRIPT
tag) for these tasks:
SERVER
tag) for these tasks:
SERVER
tags from the original source code HTML, creating an HTML page based on those bytecodes and any other HTML found in the original. For information on how you can influence that page that is constructed, see "Constructing the HTML Page".
Figure 4.1 Processing a JavaScript page request
<html>
<head> <title> Add New Customer </title> </head><body text="#FFFF00" bgcolor="#C0C0C0" background="blue_marble.gif">
<img src="billlog2.gif">
<br><server>
if ( project.lock() ) {
project.lastID = 1 + project.lastID;
client.customerID = project.lastID;
project.unlock();
}
</server><h1>Add a New Customer </h1>
<p>Note: <b>All</b> fields are required for the new customer
<form method="post" action="add.htm"></p>
<p>ID:
<br><server>write("<STRONG><FONT COLOR=\"#00FF00\">" +
project.lastID + "</FONT></STRONG>");</server><!-- other html statements -->
</body>
When this page is accessed, the runtime engine on the server executes the code associated with the
</html>SERVER
tags. (The code shown in bold.) If the new customer ID is 42, the server sends this HTML page to the client to be displayed:
<html>
<head> <title> Add New Customer </title> </head><body text="#FFFF00" bgcolor="#C0C0C0" background="blue_marble.gif">
<img src="billlog2.gif">
<br><h1>Add a New Customer </h1>
<p>Note: <b>All</b> fields are required for the new customer
<form method="post" action="add.htm"></p>
<p>ID:
<br><STRONG><FONT COLOR="#00FF00">42</STRONG></FONT><!-- other html statements -->
</body>
</html> Server-Side Language Overview
Client-side and server-side JavaScript both implement the JavaScript 1.2 language. In addition, each adds objects and functions specific to working in the client or the server environment. For example, client-side JavaScript includes the form
object to represent a form on an HTML page, whereas server-side JavaScript includes the database
object for connecting to an external relational database.
The JavaScript Guide discusses in detail the core JavaScript language and the additions specific to client-side JavaScript.
ECMA, the European standards organization for standardizing information and communication systems, derived its ECMA-262 standard from the JavaScript language. You can download the standard specification from ECMA's web site at http://www.ecma.ch
.
Core Language
For the most part, server-side JavaScript implements the JavaScript 1.2 language completely, as does client-side JavaScript. By default, however, server-side JavaScript differs from the JavaScript 1.2 specification in its treatment of comparison operators. Also, server-side JavaScript implements prototypes as defined in the specification, but the implications are somewhat different in the server environment than in the client environment. This section discusses these differences.
Comparison Operators
The behavior of comparison operators changed between JavaScript 1.1 and JavaScript 1.2. JavaScript 1.1 provided automatic conversion of operands for comparison operators. In particular:
-a 1.2
option to jsac
, the JavaScript compiler. The compiler is described in "Compiling an Application".
Prototypes
As described in the JavaScript Reference, you can use the prototype
property of many classes to add new properties to a class and to all of its instances. As described in "Classes and Objects", server-side JavaScript adds several classes and predefined objects. For the new classes that have the prototype
property, it works for server-side JavaScript exactly as for client-side JavaScript.
You can use the prototype
property to add new properties to the Blob
, Connection
, Cursor
, DbPool
, File
, Lock
, Resultset
, SendMail
, and Stproc
classes. In addition, you can use the prototype
property of the DbBuiltin
class to add properties to the predefined database
object. Note that you cannot create an instance of the DbBuiltin
class; instead, you use the database
object provided by the JavaScript runtime engine.
You cannot use prototype
with the client
, project
, request
, and server
objects.
Also, as for client-side JavaScript, you can use the prototype
property for any class that you define for your application.
Remember that all JavaScript applications on a server run in the same environment. This is why you can share information between clients and applications. One consequence of this, however, is that if you use the prototype
property to add a new property to any of the server-side classes added by JavaScript, the new property is available to all applications running on the server, not just the application in which the property was added. This provides you with an easy mechanism for adding functionality to all JavaScript applications on your server.
By contrast, if you add a property to a class you define in your application, that property is available only to the application in which it was created.
Usage
You need to be aware of how the JavaScript application compiler recognizes client-side and server-side JavaScript in an HTML file.
Client-side JavaScript statements can occur in several situations:
SCRIPT
tag
SCRIPT
tag
Server-side JavaScript statements can occur in these situations:
SERVER
tag
Environment
The LiveConnect feature of the core JavaScript language works differently on the server than it does on the client. For more information, see Chapter 6, "Working with Java and CORBA Objects Through LiveConnect."
JavaScript provides additional functionality without the use of objects. You access this functionality through functions not associated with any object (global functions). The core JavaScript language provides the global functions described in Table 4.2.
Table 4.2 Core JavaScript global functions
Server-side JavaScript adds the global functions described in Table 4.3.
Table 4.3 JavaScript server-side global functions
Classes and Objects
To support the different tasks you perform on each side, JavaScript has classes and predefined objects that work on the client but not on the server and other classes and predefined objects that work on the server but not on the client.
Important These names of these objects are reserved for JavaScript. Do not create your own objects using any of these names.The core JavaScript language provides the classes described in Table 4.4. For details of all of these objects, see the JavaScript Reference.
Table 4.4 Core JavaScript classes
Server-side JavaScript includes the core classes, but not classes added by client-side JavaScript. Server-side JavaScript has its own set of additional classes to support needed functionality, as described in Table 4.5.
Table 4.5 Server-side JavaScript classes
In addition, server-side JavaScript has the predefined objects described in Table 4.6. These objects are all available for each HTTP request. You cannot create additional instances of any of these objects.
Table 4.6 Server-side JavaScript singleton objects
Embedding JavaScript in HTML
There are two ways to embed server-side JavaScript statements in an HTML page:
<SERVER>
and follow them with </SERVER>
.
You can intermix the SERVER
tag with complete HTML statements. Never put the SERVER
tag between the open bracket (<
) and close bracket (>
) of a single HTML tag. (See "The SERVER tag".) Also, do not use the <SCRIPT>
tag between <SERVER>
and </SERVER>
.
HREF
attribute.
Do not use backquotes to enclose JavaScript expressions outside HTML tags. (See "Backquotes".)write
function in a SERVER
tag or enclose statements in backquotes, the runtime engine dynamically generates new HTML to modify the page it sends to the client.
SERVER
tag is the most common way to embed server-side JavaScript in an HTML page. You can use the SERVER
tag in any situation; typically, however, you use backquotes instead if you're generating attributes names or values for the HTML page.
Most statements between the <SERVER>
and </SERVER>
tags do not appear on the HTML page sent to the client. Instead, the statements are executed on the server. However, the output from any calls to the write
function do appear in the resulting HTML.
The following excerpt from the Hello World sample application illustrates these uses:
<P>This time you areWhen given this code snippet, the runtime engine on the server generates HTML based on the value of
<SERVER>
write(request.newname);
client.oldname = request.newname;
</SERVER>
<h3>Enter your name</h3>
request.newname
in the write
statement. In the second statement, it simply performs a JavaScript operation, assigning the value of request.newname
to client.oldname
. It does not generate any HTML. So, if request.newname
is "Mr. Ed," the runtime engine generates the following HTML for the previous snippet:
<P>This time you are
Mr. Ed
<h3>Enter your name</h3>
`
) to enclose server-side JavaScript expressions as substitutes for HTML attribute names or attribute values. JavaScript embedded in HTML with backquotes automatically generates HTML; you do not need to use write
.
In general, HTML tags are of the form
<TAG ATTRIB="value" [...ATTRIB="value"]>where
ATTRIB
is an attribute and "
value
"
is its value. The bracketed expression indicates that any number of attribute/value pairs is possible.
When you enclose a JavaScript expression in backquotes to be used as an attribute value, the JavaScript runtime engine automatically adds quotation marks for you around the entire value. You do not provide quotation marks yourself for this purpose, although you may need them to delimit string literals in the expression, as in the example that follows. The runtime engine does not do this for attribute names, because attribute names are not supposed to be enclosed in quotation marks.
For example, consider the following line from the Hangman sample application:
<IMG SRC=`"images\hang" + client.num_misses + ".gif"`>This line dynamically generates the name of the image to use based on the value of
client.num_misses
. The backquotes enclose a JavaScript expression that concatenates the string "images\hang"
with the integer value of client.num_misses
and the string ".gif"
, producing a string such as "images\hang0.gif"
. The result is HTML such as
<IMG SRC="images\hang0.gif">The order of the quotation marks is critical. The backquote comes first, indicating that the following value is a JavaScript expression, consisting of a string (
"images\hang"
), concatenated with an integer (client.num_misses
), concatenated with another string (".gif"
). JavaScript converts the entire expression to a string and adds the necessary quotation marks around the attribute value.
You need to be careful about using double quotation marks inside backquotes, because the value they enclose is interpreted as a literal value. For this reason, do not surround JavaScript expressions you want evaluated with quotation marks. For example, if the value of client.val
is NetHead, then this statement:
<A NAME=`client.val`>generates this HTML:
<A NAME="NetHead">But this statement:
<A NAME=`"client.val"`>generates this HTML:
<A NAME="client.val">As another example, two of the
ANCHOR
tag's attributes are HREF
and NAME
. HREF
makes the tag a hyperlink, and NAME
makes it a named anchor. The following statements use the choice
variable to set the attrib
and val
properties of the client
object and then create either a hyperlink or a target, depending on those values:
<SERVER>
if (choice == "link") {
client.attrib = "HREF";
client.val = "http://www.netscape.com";
}
if (choice == "target") {
client.attrib = "NAME";
client.val = "NetHead";
}
</SERVER>
<A `client.attrib`=`client.val`>Netscape Communications</A>If the value of
choice
is "link"
, the result is
<A HREF="http://home.netscape.com">Netscape Communications</A>If the value of
choice
is "target"
, the result is
<A NAME="NetHead">Netscape Communications</A>
SERVER
tag and when to use backquotes. However, sometimes you can achieve the same result either way. In general, it is best to use backquotes to embed JavaScript values inside HTML tags, and to use the SERVER
tag elsewhere.
For example, in Hangman, instead of writing
<IMG SRC=`"images\hang" + client.num_misses + ".gif"`>you could write
<SERVER>Notice the backslash that lets you use a quotation mark inside a literal string. Although the resulting HTML is the same, in this case backquotes are preferable because the source is easier to read and edit.
write("<IMG SRC=\"images\hang");
write(client.num_misses);
write(".gif\">");
</SERVER>
One of the most important things to remember when thinking about JavaScript applications is the asynchronous nature of processing on the Web. JavaScript applications are designed to be used by many people at the same time. The JavaScript runtime engine on the server handles requests from many different users as they come in and processes them in the order received.
Unlike a traditional application that is run by a single user on a single machine, your application must support the interleaving of multiple simultaneous users. In fact, since each frame in an HTML document with multiple frames generates its own request, what might seem to be a single request to the end user can appear as several requests to the runtime engine.
HTTP (Hypertext Transfer Protocol) is the protocol by which an HTML page is sent to a client. This protocol is stateless, that is, information is not preserved between requests. In general, any information needed to process an HTTP request needs to be sent with the request. This poses problems for many applications. How do you share information between different users of an application or even between different requests by the same user? JavaScript's Session Management Service was designed to help with this problem. This service is discussed in detail in Chapter 5, "Session Management Service." For now simply remember that the runtime engine automatically maintains the client
, server
, project
, and request
objects for you.
request
object, such as the request's IP address and any form input elements associated with the request. If the URL for the request specifies other properties, those are initialized for the request
object, as described in "Encoding Information in a URL".
If the client
object already exists, the runtime engine retrieves it based on the specified client-maintenance technique. (See "Techniques for Maintaining the client Object".) If no client
object exists, the runtime engine constructs a new object with no properties.
You cannot count on the order in which these objects are constructed.
Step 2. Find source page and start constructing HTML page
When you compiled your JavaScript application, the source included HTML pages containing server-side JavaScript statements. The main goal of the runtime engine is to construct, from one of those source pages, an HTML page containing only HTML and client-side JavaScript statements. As it creates this HTML page, the runtime engine stores the partially created page in a special area of memory called a buffer until it is time to send the buffered contents to the client.
Step 3. Add to output buffer or execute code
This step is performed for each piece of code on the source page. The details of the effects of various server-side statements are covered in other sections of this manual. For more information, see "Constructing the HTML Page".
flush
function.
redirect
function.
redirect
function in the source file and starts a new request for the page specified in the call to redirect
.
In this situation, the runtime engine finishes this request by performing steps 4 through 6.client
object's properties immediately before the first time it sends part of the HTML page to the client. It only saves these properties once. The runtime engine can repeat steps 3 and 5, but it cannot repeat this step.
The runtime engine saves the properties at this point to support some of the maintenance techniques for the client
object. For example, the client URL encoding scheme sends the client
properties in the header of the HTML file. Because the header is sent as the first part of the file, the client
properties must be sent then.
As a consequence, you should be careful of where in your source file you set client
properties. You should always change client
properties in the file before any call to redirect
or flush
and before generating 64KB of HTML output.
If you change property values for the client
object in the code after HTML has been sent to the client, those changes remain in effect for the rest of that client request, but they are then discarded. Hence, the next client request does not get those values for the properties; it gets the values that were in effect when content was first sent to the client. For example, assume your code contains these statements:
<HTML>
<P>The current customer is
<SERVER>
client.customerName = "Mr. Ed";
write(client.customerName);
client.customerName = "Mr. Bill";
</SERVER>
<P>The current customer really isThis series of statements results in this HTML being sent to the client:
<SERVER>
write(client.customerName);
</SERVER>
</HTML>
<P>The current customer is Mr. EdAnd when the next client request occurs, the value of
<P>The current customer really is Mr. Bill
client.customerName
is "Mr. Bill". This very similar set of statements results in the same HTML:
<HTML>However, when the next client request occurs, the value of
<P>The current customer is
<SERVER>
client.customerName = "Mr. Ed";
write(client.customerName);
flush();
client.customerName = "Mr. Bill";
</SERVER>
<P>The current customer really is
<SERVER>
write(client.customerName);
</SERVER>
</HTML>
client.customerName
is "Mr. Ed"; it is not "Mr. Bill".
For more information, see "Techniques for Maintaining the client Object".
Step 5. Send HTML to client
The server sends the page content to the client. For pages with no server-side JavaScript statements, the server simply transfers HTML to the client. For other pages, the runtime engine performs the application logic to construct HTML and then sends the generated page to the client.
Step 6. Destroy request object and save or destroy client object
The runtime engine destroys the request
object constructed for this client request. It saves the values of the client
object and then destroys the physical JavaScript object. It does not destroy either the project
or the server
object.
Constructing the HTML Page
When you compile your JavaScript application, the source includes HTML pages that contain server-side JavaScript statements and perhaps also HTML pages that do not contain server-side JavaScript statements. When a user accesses a page in an application that does not contain server-side JavaScript statements, the server sends the page back as it would any other HTML page. When a user accesses a page that does contain server-side JavaScript statements, the runtime engine on the server constructs an HTML page to send in response, using one of the source pages of your application.
The runtime engine scans the source page. As it encounters HTML statements or client-side JavaScript statements, it appends them to the page being created. As it encounters server-side JavaScript statements, it executes them. Although most server-side JavaScript statements perform processing on the server, some affect the page being constructed. The following sections discuss three functions--write
, flush
, and redirect
--that affect the HTML page served.
Generating HTML
As discussed earlier in this chapter, the write
function generates HTML based on the value of JavaScript expression given as its argument. For example, consider this statement
write("<P>Customer Name is:" + project.custname + ".");
In response to this statement, JavaScript generates HTML including a paragraph tag and some text, concatenated with the value of the custname
property of the project
object. For example, if this property is "Fred's software company", the client would receive the following HTML:
<P>Customer Name is: Fred's software company.
As far as the client is concerned, this is normal HTML on the page. However, it is actually generated dynamically by the JavaScript runtime engine.
Flushing the Output Buffer
To improve performance, JavaScript buffers the HTML page it constructs. The flush
function immediately sends data from the internal buffer to the client. If you do not explicitly call the flush
function, JavaScript sends data to the client after each 64KB of content in the constructed HTML page.
Don't confuse the flush
function with the flush
method of the File
class. (For information on using the File
class to perform file input and output, see "File System Service".)
NOTE: If you use the client cookie technique to maintain the properties of theThe following code fragment shows howclient
object, you must make all changes to theclient
object before flushing the buffer. For more information, see "Techniques for Maintaining the client Object".
flush
is used. Assume that your application needs to perform some action on every customer in your customer database. If you have a lot of customers, this could result in a lengthy delay. So that the user doesn't have to wait in front of an unchanging screen, your application could send output to the client before starting the processing and then again after processing each row. To do so, you could use code similar to the following:
flush();
conn.beginTransaction();
cursor = conn.cursor ("SELECT * FROM CUSTOMER", true);
while ( cursor.next() ) {
// ... process the row ...
flush();
}
conn.commitTransaction();
cursor.close();
redirect
function terminates the current client request and starts another for the specified URL. For example, assume you have this statement:
redirect("http://www.royalairways.com/apps/page2.html");When the runtime engine executes this statement, it terminates the current request. The runtime engine does not continue to process the original page. Therefore any HTML or JavaScript statements that follow the call to
redirect
on the original page are lost. The client immediately loads the indicated page, discarding any previous content.
The parameter to redirect
can be any server-side JavaScript statement that evaluates to a URL. In this way, you can dynamically generate the URL used in redirect
. For example, if a page defines a variable choice
, you can redirect the client to a page based on the value of choice
, as follows:
redirect ("http://www.royalairways.com/apps/page"If you want to be certain that the current
+ choice + ".html");
client
properties are available in the new request, and you're using one of the URL-based maintenance techniques for the client
object, you should encode the properties in the URL you pass to redirect
. For information on doing so, see "Manually Appending client Properties to URLs".
In general, properties of the request
object and top-level JavaScript variables last only for a single client request. When you redirect to a new page, you may want to maintain some of this information for multiple requests. You can do so by appending the property names and values to the URL, as described in "Encoding Information in a URL".
Accessing CGI Variables
Like most web servers, Netscape servers set values for a particular set of environment variables, called CGI variables, when setting up the context for running a CGI script. Writers of CGI scripts expect to be able to use these variables in their scripts.
By contrast, Netscape web servers do not set up a separate environment for server-side JavaScript applications. Nevertheless, some of the information typically set in CGI variables can also be useful in JavaScript applications. The runtime engine provides several mechanisms for accessing this information:
request
object
httpHeader
method of request
to access properties of the client request header
request
object that correspond to CGI variables. For more information on these properties and on the request
object in general, see "The request Object".
Table 4.7 CGI variables accessible as properties of the request
object
The server-side function ssjs_getCGIVariable
lets you access the environment variables set in the server process, including the CGI variables listed in Table 4.8.
Table 4.8 CGI variables accessible through ssjs_getCGIVariable
The syntax of ssjs_getCGIVariable
is shown here:
value = ssjs_getCGIVariable("name");
This statement sets the variable value
to the value of the name
CGI variable. If you supply an argument that isn't one of the CGI variables listed in Table 4.8, the runtime engine looks for an environment variable by that name in the server environment. If found, the runtime engine returns the value; otherwise, it returns null. For example, the following code assigns the value of the standard CLASSPATH
environment variable to the JavaScript variable classpath
:
classpath = ssjs_getCGIVariable("CLASSPATH");
The httpHeader
method of request
returns the header of the current client request. For a CGI script, Netscape web servers set CGI variables for some of the information in the header. For JavaScript applications, you get that information directly from the header. Table 4.9 shows information available as CGI variables in the CGI environment, but as header properties in server-side JavaScript. In header properties, the underlines in the CGI-variable name (_) are replaced with dashes (-); for example, the CGI variable CONTENT_LENGTH
corresponds to the header property content-length
.
Table 4.9 CGI variables accessible through the client header
For more information on manipulating the client header, see "Request and Response Manipulation".
Table 4.10 shows the CGI variables that are not supported by server-side JavaScript, because they are not applicable when running JavaScript applications.
Table 4.10 CGI variables not supported by server-side JavaScript
Communicating Between Server and Client
Frequently your JavaScript application needs to communicate information either from the server to the client or from the client to the server. For example, when a user first accesses the videoapp
application, the application dynamically generates the list of movie categories from the current database contents. That information, generated on the server, needs to be communicated back to the client. Conversely, when the user picks a category from that list, the user's choice must be communicated back to the server so that it can generate the set of movies.
Sending Values from Client to Server
Here are several ways to send information from the client to the server:
request
object for each value in an HTML form. (See "Accessing Form Values".)
client
object, you can modify the URL sent to the server to include property values for the client
and request
objects. (See "Encoding Information in a URL".)
client
and request
objects. (See "Using Cookies".)
httpHeader
method of the request
object to manipulate the header and possibly the body of the request. (See "Request and Response Manipulation".)
ACTION
attribute of the FORM
tag determines the application to which the values are submitted. To send information to the application on the server, use an application URL as the value of the ACTION
attribute.
If the document containing the form is a compiled part of the same application, you can simply supply the name of the page instead of a complete URL. For example, here is the FORM
tag from the Hangman sample application:
<FORM METHOD="post" ACTION="hangman.html">Forms sent to server-side JavaScript applications can use either
get
or post
as the value of the METHOD
attribute.
NOTE: Server-side JavaScript applications do not automatically support file upload. That is, if the action specified is a page in a JavaScript application and you submit anEach input element in an HTML form corresponds to a property of theINPUT
element ofTYPE="file"
, your application must manually handle the file, as described in "Request and Response Manipulation".
request
object. The property name is specified by the NAME
attribute of the form element. For example, the following HTML creates a request
property called guess
that accepts a single character in a text field. You refer to this property in server-side JavaScript as request.guess
.
<FORM METHOD="post" ACTION="hangman.html">A
<P>
What is your guess?
<INPUT TYPE="text" NAME="guess" SIZE="1">
SELECT
form element that allows multiple selections requires special treatment, because it is a single property that can have multiple values. You can use the getOptionValue
function to retrieve the values of selected options in a multiple select list. For more information, see "Using Select Lists".
For more information on the request
object, see "The request Object".
If you want to process data on the client first, you have to create a client-side JavaScript function to perform processing on the form-element values and then assign the output of the client function to a form element. You can hide the element, so that it is not displayed to the user, if you want to perform client preprocessing.
For example, suppose you have a client-side JavaScript function named calc
that performs calculations based on the user's input. You want to pass the result of this function to your application for further processing. You first need to define a hidden form element for the result, as follows:
<INPUT TYPE="hidden" NAME="result" SIZE=5>
Then you need to create an onClick
event handler for the Submit button that assigns the output of the function to the hidden element:
<INPUT TYPE="submit" VALUE="Submit"
The value of
onClick="this.form.result.value=calc(this.form)">result
is submitted along with any other form-element values. This value can be referenced as request.result
in the application.
Using Select Lists
The HTML SELECT
tag, used with the MULTIPLE
attribute, allows you to associate multiple values with a single form element. If your application requires select lists that allow multiple selected options, you use the getOptionValue
function to get the values in JavaScript. The syntax of getOptionValue
is
itemValue = getOptionValue(name, index)
Here, name
is the string specified as the NAME
attribute of the SELECT
tag, and index
is the zero-based ordinal index of the selected option. The getOptionValue
function returns the value of the selected item, as specified by the associated OPTION
tag.
The function getOptionValueCount
returns the number of options (specified by OPTION
tags) in the select list. It requires only one argument, the string containing the name of the SELECT
tag.
For example, suppose you have the following element in a form:
<SELECT NAME="what-to-wear" MULTIPLE SIZE=8>
You could process the input from this select list as follows:
<OPTION SELECTED>Jeans
<OPTION>Wool Sweater
<OPTION SELECTED>Sweatshirt
<OPTION SELECTED>Socks
<OPTION>Leather Jacket
<OPTION>Boots
<OPTION>Running Shoes
<OPTION>Cape
</SELECT><SERVER>
If the user kept the default selections, this script would return:
Item #0: Jeans
var i = 0;
var howmany = getOptionValueCount("what-to-wear");
while ( i < howmany ) {
var optionValue =
getOptionValue("what-to-wear", i);
write ("<br>Item #" + i + ": " + optionValue + "\n");
i++;
}
</SERVER>
Item #1: Sweatshirt
Item #2: Socks
Encoding Information in a URL
You can manually encode properties of the request
object into a URL that accesses a page of your application. In creating the URL, you use the following syntax:
URL?varName1=value1[&varName2=value2...]
Here, URL
is the base URL, each varName
N
is a property name, and each value
N
is the corresponding property value (with special characters escaped). In this scheme, the base URL is followed by a question mark (?
) which is in turn followed by pairs of property names and their values. Separate each pair with an ampersand (&
). When the runtime engine on the server receives the resultant URL as a client request, it creates a request
property named varName
N
for each listed variable.
For example, the following HTML defines a hyperlink to a page that instantiates the request
properties i
and j
to 1 and 2, respectively. JavaScript statements in refpage.html
can then refer to these variables as request.i
and request.j
.
<A HREF="refpage.html?i=1&j=2">Click Here</A>
Instead of using a static URL string, as in the preceding example, you can use server-side or client-side JavaScript statements to dynamically generate the URL that encodes the property values. For example, your application could include a page such as the following:
<HTML>
<HEAD>
<SCRIPT>
function compute () {
// ...replace with an appropriate computation
// that returns a search string ...
return "?num=25";
}
</SCRIPT>
</HEAD><BODY>
<a HREF="refpage.htm" onClick="this.search=compute()">
Click here to submit a value.</a></p></BODY>
In this case, when the user clicks the link, the runtime engine on the client runs the
</HTML>onClick
event handler. This event handler sets the search portion of the URL in the link to whatever string is returned by the compute
function. When the runtime engine on the server gets this request, it creates a num
property for the request
object and sets the value to 25.
As a second example, you might want to add request
properties to a URL created in a server-side script. This is most likely to be useful if you'll be redirecting the client request to a new page. To add request
properties in a server-side script, you could instead use this statement:
<A HREF=`"refpage.html?i=" + escape(i) + "&j=" + escape(j)`>
If you create a URL in a server-side JavaScript statement, the
Click Here</A>client
object's properties are not automatically added. If you're using a URL-based maintenance technique for the client
object, use the addClient
function to generate the final URL. In this example, the statement would be:
<A HREF=`addClient("refpage.html?i=" + escape(i)
For information on using
+ "&j=" + escape(j))`>Click Here</A>addClient
, see "Manually Appending client Properties to URLs".
The core JavaScript escape
function allows you to encode names or values appended to a URL that may include special characters. In general, if an application needs to generate its own property names and values in a URL request, you should use escape
, to ensure that all values are interpreted properly. For more information, see the JavaScript Reference.
Remember that a URL does not change when a user reloads it, although the page's contents may change. Any properties sent in the original URL are restored to their values in the URL as it was first sent, regardless of any changes that may have been made during processing. For example, if the user clicks the Reload button to reload the URL in the previous example, i
and j
are again set to 1 and 2, respectively.
Sending Values from Server to Client
A JavaScript application communicates with the client through HTML and client-side JavaScript. If you simply want to display information to the user, there is no subtlety: you create the HTML to format the information as you want it displayed.
However, you may want to send values to client scripts directly. You can do this in a variety of ways, including these three:
SCRIPT
statements or event handlers. (See "Direct Substitution".)
client
property values or other values to the client. (See "Using Cookies".)
deleteResponseHeader
and addResponseHeader
functions. (See "Request and Response Manipulation".)
INPUT
tag to create the desired form element, substituting a server-side JavaScript expression for the VALUE
attribute. For example, you can use the following statement to display a text element and set the default value based on the value of client.custname
:
<INPUT TYPE="text" NAME="customerName" SIZE="30"The initial value of this text field is set to the value of the variable
VALUE=`client.custname`>
client.custname
. So, if the value of client.custname
is Victoria, this statement is sent to the client:
<INPUT TYPE="text" NAME="customerName" SIZE="30" VALUE="Victoria">You can use a similar technique with hidden form elements if you do not want to display the value to the user, as in this example:
<INPUT TYPE="hidden" NAME="custID" SIZE=5 VALUE=`client.custID`>In both cases, you can use these values in client-side JavaScript in property values of objects available on the client. If these two elements are in a form named
entryForm
, then these values become the JavaScript properties document.entryForm.customerName
and document.entryForm.custID
, respectively. You can then perform client processing on these values in client-side scripts. For more information, see the JavaScript Guide.
Direct Substitution
You can also use server-side JavaScript to generate client-side scripts. These values can be used in subsequent statements on the client. As a simple example, you could initialize a client-side variable named budget
based on the value of client.amount
as follows:
<p>The budget is:
If the value of
<SCRIPT>
<SERVER>
write("var budget = " + client.amount);
</SERVER>
document.write(budget);
</SCRIPT>client.amount
is 50, this would generate the following JavaScript:
<p>The budget is:
When run on the client, this appears as follows:
<SCRIPT>
var budget = 50
document.write(budget);
</SCRIPT>The budget is: 50
Using Cookies
Cookies are a mechanism you can use on the client to maintain information between requests. This information resides in a file called cookie.txt
(the cookie file) stored on the client machine. The Netscape cookie protocol is described in detail in the JavaScript Guide.
You can use cookies to send information in both directions, from the client to the server and from the server to the client. Cookies you send from the client become properties of either the client
object or of the request
object. Although you can send any string value to the client from the server as a cookie, the simplest method involves sending client
object properties.
Properties of the client Object as Cookies
If an application uses the client cookie technique to maintain the client
object, the runtime engine on the server stores the names and values of properties of the client
object as cookies on the client. For information on using cookies to maintain the client
object, see "Techniques for Maintaining the client Object".
For a client
property called propName
, the runtime engine automatically creates a cookie named NETSCAPE_LIVEWIRE.
propName
, assuming the application uses the client cookie maintenance technique. The runtime engine encodes property values as required by the Netscape cookie protocol.
To access these cookies in a client-side JavaScript script, you can extract the information using the document.cookie
property and a function such as the getSSCookie
function shown here:
function getSSCookie(name) {
The
var search = "NETSCAPE_LIVEWIRE." + name + "=";
var retstr = "";
var offset = 0;
var end = 0;
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search);
if (offset != -1) {
offset += search.length;
end = document.cookie.indexOf(";", offset);
if (end == -1)
end = document.cookie.length;
retstr = unescape(document.cookie.substring(offset, end));
}
}
return(retstr)
}getSSCookie
function is not a predefined JavaScript function. If you need similar functionality, you must define it for your application.
To send information to the server to become a property of the client
object, add a cookie whose name is of the form NETSCAPE_LIVEWIRE.
propName.
Assuming your application uses the client cookie maintenance technique, the runtime engine on the server creates a client
property named propName
for this cookie.
To do so, you can use a function such as the following:
function setSSCookie (name, value, expire) {
Here, too, the
document.cookie =
"NETSCAPE_LIVEWIRE." + name + "="
+ escape(value)
+ ((expire == null) ? "" : ("; expires=" + expire.toGMTString()));
}setSSCookie
function is not a predefined JavaScript function. If you need similar functionality, you must define it for your application.
You can call these functions in client-side JavaScript to get and set property values for the client
object, as in the following example:
var value = getSSCookie ("answer");
This group of statements checks whether there is a
if (value == "") {
var expires = new Date();
expires.setDate(expires.getDate() + 7);
setSSCookie ("answer", "42", Expires);
}
else
document.write ("The answer is ", value);client
property called answer
. If not, the code creates it and sets its value to 42; if so, it displays its value.
Other Cookies
When a request is sent to the server for a page in a JavaScript application, the header of the request includes all cookies currently set for the application. You can use the request.httpHeader
method to access these cookies from server-side JavaScript and assign them to server-side variables. Conversely, you can use the addResponseHeader
function to add new cookies to the response sent back to the client. This functionality is described in "Request and Response Manipulation".
On the client, you can use a function such as the following to access a particular cookie:
function GetCookie (name) {
And you can use a function such as the following to set a cookie on the client:
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) == arg) {
var end = document.cookie.indexOf (";", j);
if (end == -1)
end = document.cookie.length;
return unescape(document.cookie.substring(j, end));
}
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
} function setCookie (name, value, expires, path, domain, secure) {
If the path you specify for a cookie is in your JavaScript application, then that cookie will be sent in any request sent to the application.
You can use this technique for passing cookie information between the client and the server regardless of the
document.cookie =
name + "="
+ escape(value)
+ ((expires) ? "; expires=" + expires.toGMTString() : "")
+ ((path) ? "; path=" + path : "")
+ ((domain) ? "; domain=" + domain : "")
+ ((secure) ? "; secure" : "");
} client
object maintenance technique you use.
Garbage Collection
Server-side JavaScript contains a garbage collector that automatically frees memory allocated to objects no longer in use. Most users do not need to understand the details of the garbage collector. This section gives an overview of the garbage collector and information on when it is invoked.
Important This section provides advanced users with a peek into the internal workings of server-side JavaScript. Netscape does not guarantee that these algorithms will remain the same in future releases.The JavaScript object space consists of arenas. That is, the JavaScript runtime engine allocates a set of arenas from which it allocates objects. When the runtime engine receives a request for a new object, it first looks on the free list. If the free list has available space, the engine allocates that space. Otherwise, the runtime engine allocates space from the arena currently in use. If all arenas are in use, the runtime engine allocates a new arena. When all the objects from an arena are garbage, the garbage collector frees the arena. A JavaScript string is typically allocated as a GC object. The string has a reference to the bytes of the string which are also allocated in the process heap. When a string object is garbage collected, the string's bytes are freed. The JavaScript garbage collector is a based on mark and sweep. It does not relocate objects. The garbage collector maintains a root set of objects at all times. This root set includes the JavaScript stack, the global object for the JavaScript context, and any JavaScript objects which have been explicitly added to the root set. During the mark phase, the garbage collector marks all objects that are reachable from the root set. At the end of this phase, all unmarked objects are garbage. All garbage objects are collected into a free list. A garbage collection is considered necessary if the number of bytes currently in use is 1.5 times the number of bytes that were in use at the end of the last garbage collection. The runtime engine checks for this condition at the following points and starts the garbage collector if it needs to:
Last Updated: 10/30/97 12:18:46