Chapter 2
What Can You Do with JavaScript?
CONTENTS
JavaScript offers you much more expressive power than HTML alone. This
chapter touches on a few of the things you can do with JavaScript, such
as create multipart documents, build dynamic documents that take you through
a Web site from one document to another, and generate documents that interact
with the user. It is by no means exhaustive, as you can see by checking
out some of the URLs listed in the Quick Reference at the end of this book.
Multipart
documents with frames
You can create documents that split the browser window into pieces-you
have probably seen such documents while surfing the Web. The pieces are
called frames, and much of JavaScript's power derives from what
it can do with frames.
Frames give you more control over the layout of your document than conventional
HTML allows, and frames let you keep parts of your documents on the screen
while other parts change. For example, in one frame you can place a corporate
logo, copyright information, and so forth; in another frame, you can place
a document describing some particularly interesting information about your
company. As the user pages through your Web site, the frame that holds
your logo and copyright can remain visible while the information in the
other frame changes.
Frames also give you the power to create and present HTML on the fly.
JavaScript code in the document of one frame can clear another frame and
write new HTML or even more JavaScript code into another frame. Before
JavaScript, it was enormously complicated to create, on the fly, a new
page tailored to the user's wishes. Now you can do it yourself.
You define frames within a frame document, or layout document.
A typical Web page is made up of an HTML element that contains a HEAD element
and a BODY element. A frame document is usually made up of an HTML element
that contains a HEAD element and a FRAMESET element.
FRAME elements are contained within FRAMESET elements, and FRAMESET
elements can also contain other FRAMESET elements, allowing you to divide
and subdivide the browser window. Be careful with this capability, however:
You can easily subdivide the browser window to the point that nothing of
value is visible.
Each FRAME element is loaded with its own Web page document. A frame
document requires several separate documents; the one in Figure 2.1 requires
four documents: one for the frame document itself, and one for each of
the three frames.
Figure
2.1 : A typical frame document.
Here are the HTML file listings for the frame document in Figure 2.1.
What follows is the file main.htm.
<HTML>
<HEAD>
<TITLE>Sample Frame Document</TITLE>
</HEAD>
<FRAMESET ROWS="2Ø%,*">
<FRAME SRC="welcome.htm" NAME="Welcome" SCROLLING="auto"
MARGINWIDTH=1 MARGINHEIGHT=1 NORESIZE>
<FRAMESET COLS="2Ø%,8Ø%">
<FRAME SRC="dir.htm" NAME="Directory" SCROLLING="auto"
MARGINWIDTH=1 MARGINHEIGHT=1 NORESIZE>
<FRAME SRC="contents.htm" NAME="Contents" SCROLLING="auto"
MARGINWIDTH=1 MARGINHEIGHT=1 NORESIZE>
</FRAMESET>
</FRAMESET>
</HTML>
The outermost FRAMESET element breaks the window into rows; the top
row is given 20 percent of the screen, and the bottom row is given the
remainder of the screen. The top row will contain the document welcome.htm.
The bottom row contains a FRAMESET element that divides the row in two
columns. The left column gets 20 percent of the row's width and contains
dir.htm. The right column gets the other 80 percent of the row's width
and contains contents.htm.
The next listing is welcome.htm. It displays a single line, "Welcome
to My Frame Document." The line is centered, and the text is
green on a black background.
<HTML>
<HEAD>
<TITLE>Welcome</TITLE>
</HEAD>
<BODY BGCOLOR="ØØØØØØ" TEXT="ØØ8ØØØ" >
<P ALIGN=CENTER>Welcome to My Frame Document</P>
</BODY>
</HTML>
Next is dir.htm. It contains a list of topics, with lists nested inside
lists. Like welcome.htm, it uses green letters on a black background.
<HTML>
<HEAD>
<TITLE>Directory</TITLE>
</HEAD>
<BODY BGCOLOR="ØØØØØØ" TEXT="ØØ8ØØØ" >
<UL>
<LI>Multi-Part Documents
<UL>
<LI>Reload Part of the Window
<LI>Interactive Documents
</UL>
<LI>More Control over User Interaction
<LI>Documents with Memory
<LI>Live Documents
<UL>
<LI>Scrolling Messages
<LI>Clocks
<LI>Countdown Timers
<LI>Self-Updating Documents
</UL>
</UL>
</BODY>
</HTML>
Finally, below is contents.htm. It displays one of the topics for this
page, and does so in green letters on a black background.
<HTML>
<HEAD>
<TITLE>Contents</TITLE>
</HEAD>
<BODY BGCOLOR="ØØØØØØ" TEXT="ØØ8ØØØ" >
<P>
<B>JavaScript</B> offers you <I>much</I> more expressive
power than HTML alone. This chapter will touch on a few of
the things you can do with <B>JavaScript</B>, and is by no
means exhaustive.
</P>
</BODY>
</HTML>
Reloading Part of the Window
So what can you do, once you've subdivided the browser window? Well,
you can update one frame, loading it with a new document while the other
frames remain unchanged. In the document shown in Figure 2.1, the top frame
contains information about the overall purpose of the Web site. The lower-left
frame contains a directory of pages that pertain to the purpose expressed
by the top frame's document. The lower-right frame contains a page that
the user has selected from the directory in the lower-left frame. The top
and lower-left frames never change, but the user can change pages in the
lower-right frame.
Creating Interactive Documents
You can also write JavaScript code that can rewrite the contents of
a frame in response to the user's actions. You can't modify a frame's contents,
but you can rewrite the frame contents from scratch. Here are three frame
documents that demonstrate this capability:
Here is main2.htm; it simply divides the screen into two rows.
<HTML>
<HEAD>
<TITLE>Self-Modifying Document</TITLE>
</HEAD>
<FRAMESET ROWS="6Ø%,*">
<FRAME SRC="input.htm" NAME="input" SCROLLING="auto"
MARGINWIDTH=1 MARGINHEIGHT=1 NORESIZE>
<FRAMESET ROWS="78%">
<FRAME SRC="output.htm" NAME="output" SCROLLING="auto"
MARGINWIDTH=1 MARGINHEIGHT=1 NORESIZE>
</FRAMESET>
</FRAMESET>
</HTML>
This is input.htm:
<HTML>
<HEAD>
<TITLE>Input</TITLE>
<SCRIPT>
<!-- hide script
function sayHello(form)
{
parent.output.document.open();
parent.output.document.open();
var gt = unescape("%3E");
parent.output.document.write("<HTML" + gt);
parent.output.document.write("<BODY BGCOLOR='ØØ4ØØØ' TEXT='FFFFFF'"
+ gt);
parent.output.document.write("Hello " + form.firstName.value + " " +
form.middleName.value + " " + form.lastName.value);
parent.output.document.write("</BODY" + gt);
parent.output.document.write("</HTML" + gt);
parent.output.document.close();
}
// -->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="ØØ4ØØØ" TEXT="FFFFFF" >
<FORM NAME="form">
<INPUT TYPE=TEXT SIZE=2Ø NAME="firstName"> First Name
<BR>
<INPUT TYPE=TEXT SIZE=2Ø NAME="middleName"> Middle Name
<BR>
<INPUT TYPE=TEXT SIZE=2Ø NAME="lastName"> Last Name
<BR>
<INPUT TYPE=BUTTON VALUE="Say Hello"
ONCLICK="sayHello(this.form)">
</FORM>
</BODY>
</HTML>
input.htm creates a form into which you can write your first name, middle
name, and last name. When you're done, you click on the button labeled
"Say Hello." When you click on that button, the JavaScript function
"sayHello" is called, with a reference to the form as a parameter.
The function "sayHello" opens the document in the output frame
and creates and displays a new page in the output frame. It uses the form
to get the names you entered and incorporates them into the new page. To
accomplish this trivial task without JavaScript would require writing a
program that runs on a server-a much more difficult task than putting together
this little piece of JavaScript.
The following is output.htm:
<HTML>
<BODY BGCOLOR="ØØ4ØØØ" TEXT="FFFFFF" >
</BODY>
</HTML>
This code does nothing at all except make the background of its frame
match the background of the other frame. It doesn't have to do anything
else; it's just a placeholder. Figure 2.2 shows the frame document when
it's first loaded. Figure 2.3 shows the frame document after data has been
entered in the form in the lower-left frame.
Figure
2.2 : Frame before data is entered.
Figure
2.3 : Frame after data is entered.
More
control over user interaction
JavaScript recognizes several events that a user can cause within a
document. You can create JavaScript code that reacts to those events, providing
interaction with the user.
Within a FORM element, there are SELECT, INPUT, and TEXTAREA elements,
which act as input fields. The user can typically move the cursor from
one input field to another by using the Tab key or by clicking the pointing
device in an input field. When the user moves the cursor from one field
(the source) to another (the destination), the destination field is said
to have acquired focus; the user can now modify that field's contents.
At the same time, the source field has lost focus. In Netscape terminology,
the destination field has experienced a focus event and the source field
has experienced a blur event.
Another kind of event takes place when the user highlights text in a
field; this is called a select event. A change event occurs when text within
a field is changed and focus is moved to another field. A click event occurs
when certain fields are clicked on with the pointing device.
You can write JavaScript expressions or functions that are executed
when any one of these events occurs on a field. The following code demonstrates
how these events and their event handlers work. Each of the input fields
has event handlers that handle focus, blur, select, change, or click events.
Each event handler calls the announce function, passing it the name of
the input field and the name of the event. The announce function displays
that information in the window's status area.
<HTML>
<HEAD>
<TITLE>Focus, Blur, Select, Change, Click Test</TITLE>
<SCRIPT>
<!--
function announce(widgetName, eventType)
{
status = "The " + widgetName + " field just experienced a " +
eventType + " event";
return true;
}
//-->
</SCRIPT>
</HEAD>
<BODY >
<FORM ONSUBMIT="return false">
<INPUT TYPE=BUTTON NAME="button" VALUE="button"
ONCLICK="announce('button','click')">
<INPUT TYPE=CHECKBOX NAME="checkbox"
ONCLICK="announce('checkbox','click')">A
<INPUT TYPE=CHECKBOX NAME="checkbox"
ONCLICK="announce('checkbox','click')">B
<INPUT TYPE=CHECKBOX NAME="checkbox"
ONCLICK="announce('checkbox','click')">C
<INPUT TYPE=RADIO NAME='radio'
ONCLICK="announce('radio','click')">AM
<INPUT TYPE=RADIO NAME='radio'
ONCLICK="announce('radio','click')">FM
<BR>
<INPUT TYPE=RESET NAME="reset"
ONCLICK="announce('reset','click')">
<BR>
<INPUT TYPE=SUBMIT NAME="submit"
ONCLICK="announce('submit','click')">
<BR>
<INPUT TYPE=TEXT NAME="text" SIZE=1Ø
ONBLUR="announce('text','blur')"
ONCHANGE="announce('text','change')"
ONFOCUS="announce('text','focus')"
ONSELECT="announce('text','select')">
<BR>
<TEXTAREA NAME="textArea" COLS="2Ø" ROWS="2"
ONBLUR="announce('textarea','blur')"
ONCHANGE="announce('textarea','change')"
ONFOCUS="announce('textarea','focus')"
ONSELECT="announce('textarea','select')"
Sample Text
</TEXTAREA>
<BR>
<SELECT NAME="select"
ONBLUR="announce('select','blur')"
ONCHANGE="announce('select','change')"
ONFOCUS="announce('select','focus')">
<OPTION>Option 1
<OPTION>Option 2
<OPTION>Option 3
</SELECT>
</FORM>
</BODY>
</HTML>
A word of caution: You can accidentally force the browser into a loop
that never ends by creating chains of events that repeat themselves. Pop-up
windows, created using the alert, confirm, or prompt methods, can interact
badly when created by a focus event handler. As an example, the following
code pops up an alert window when the text field receives focus:
<HTML>
<HEAD>
<TITLE>Endless Loop</TITLE>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE=TEXT NAME="text" SIZE=1Ø
ONFOCUS="alert('Here we go again...')">
</FORM>
</BODY>
</HTML>
If the alert window happens to be displayed over the text field, we
have a problem. Here's what happens:
- The text field receives focus.
- The onFocus event handler begins executing.
- The alert window pops up, acquiring focus from the text field.
- The user dismisses the alert window.
- The alert window is erased. Focus returns to the text field.
- The onFocus event handler begins executing.
- The alert window pops up�.
And on and on it goes. To avoid this kind of endless loop, place messages
in a text input field, on the status area of the window, or in another
window or frame altogether.
Within the FORM element, another kind of event, the submit event, occurs
when the user clicks on a submit button. Before there was JavaScript, clicking
on the submit button sent the form data to a CGI process on a remote server.
The CGI process would then process the data and send back a new page of
data. With JavaScript, you can write an event handler for the submit event.
Within the submit event handler, you can do whatever you like. Most of
the input field contents are accessible to your JavaScript code (password
fields are the exception); you can modify the data and you can decide not
to send it out at all. You can create a document and display it in another
frame or window. And you can still send it to a CGI process.
In addition to form and field event handlers, you can write event handlers
to be executed when the pointing device moves over certain elements; such
an event is called a mouseover event. You can also define event handlers
that are executed when the document is loaded (a load event) and when the
document is exited (an unload event).
Documents
with memory
Through the use of a feature called a cookie, documents can share information
with each other. Cookies are small data objects that reside on the user's
machine. You can write JavaScript code to create, modify, and delete cookies.
The power of cookies is that they offer persistence. When the document
that created or modified a cookie is no longer loaded, the data in the
cookie is still there. Other documents that know about the cookie can access
and modify its data, so the data can be shared between documents.
One potential use for cookies is in online catalogs. A store with an
extensive inventory would not want to put its entire catalog in a single
document. Instead, they would probably break up the catalog into manageable
pieces, with each separate document focusing on a particular class of merchandise.
The user of such an online catalog could then select items from several
pages. Each page could record the user's selection in a cookie. When the
user was finally ready to send in the order, the cookie would be read back
into a form for the user to verify. The entire list, containing items from
several different documents, would then be submitted to the store.
Using the ability to write frame contents on the fly, you can also use
cookies to remember things about the user and to tailor the contents of
your document's frames to that user. An example might be a personalized
greeting, combined with an indication of how long it has been since the
user last loaded the document.
You might want to display some information at the beginning of the day.
Using a cookie, your document can remember whether it is being loaded for
the first time that day (by a particular user) or a subsequent time. For
example, on the first visit of the day you might load a document containing
the day's weather forecast, which you probably would not want to see later
that same day. You could display a favorite online cartoon; once you've
seen that day's cartoon, there's no reason to look at it again and again.
Live
documents
Live documents are Web pages that change as time passes. You can create
timers in your code. When the timer counts down, a JavaScript expression
is executed. You can do many things with timers, such as scroll messages
on the screen or load a document when the timer counts down.
Scrolling Messages
You've probably seen those cute little messages that scroll along the
status portion of the browser window. They're all done with timers. The
basic concept is simple.
You start the message by appending it to some arbitrary number of spaces.
(The example that follows uses 200.) The message, with its leading spaces,
is then written to the window's status bar. A timer starts that, when timed
out, starts the process over again, but with one less space than the previous
iteration. When the number of spaces before the message becomes zero, the
strategy changes: Instead of appending the message to a string of spaces,
a substring of the message is displayed. With each iteration, the starting
point of the substring moves one character to the right, making the message
appear to move to the left. When the message has disappeared from view,
the entire cycle usually starts over.
Here's an example of how to create a scrolling message:
<HTML>
<HEAD>
<TITLE>Scrolling Message</TITLE>
<SCRIPT>
<!--
var winLength = 2ØØ; // guess at how many spaces wide the status bar is
var speed = 1ØØ; // number of milliseconds between updates
function scroll(count)
{
var msg = "Hi! This is my scrolling message in the status bar.";
var out = " ";
var cmd = "scroll(";
if (count <= winLength && Ø < count)
{
var c = Ø;
for (c = Ø ; c < count ; c++)
{
out += " ";
}
out += msg;
}
else if (count <= Ø)
{
if (-count < msg.length)
{
out += msg.substring(-count,msg.length);
}
else
{
count = winLength + 1;
}
}
window.status = out;
count--;
cmd += count + ")";
window.setTimeout(cmd,speed);
}
//-->
</SCRIPT>
</HEAD>
<BODY ONLOAD="window.setTimeout('scroll(winLength)',speed);">
</BODY>
</HTML>
Scrolling messages don't necessarily have to show up in the status area.
You can create a form and place the message in a text field within that
form.
Clocks
Clocks are really a variation on the scrolling message. They simply
stay put and tell the time, like the clock on your VCR (except that it
doesn't blink "12:00"-it actually displays the time of day).
JavaScript understands dates and times, and creating a simple clock display
is quite easy, as you can see from this code and Figure 2.4:
Figure
2.4 : A simple clock on the status bar.
<HEAD>
<TITLE>Clock</TITLE>
<SCRIPT>
<!--
function updateTime()
{
var now = new Date();
var time = "" + now.getHours() + ":";
var minute = now.getMinutes();
if (minute < 1Ø)
{
time += "Ø";
}
time += minute + ":";
var second = now.getSeconds();
if (second < 1Ø)
{
time += "Ø";
}
time += second;
window.status = time;
window.setTimeout("updateTime()",1ØØØ);
}
//-->
</SCRIPT>
</HEAD>
<BODY ONLOAD="window.setTimeout('updateTime()',1ØØØ);">
</BODY>
</HTML>
This code gets the current time by creating a new Date object. It extracts
the hours, minutes, and seconds and displays them on the status bar. In
the case of the minutes and seconds, it also checks whether either value
is a single digit. If one of them is, it adds the leading zero (a time
of five after twelve would look odd displayed as "12:5:0"). After
the time is displayed, a new timer is created that will time out in exactly
1,000 milliseconds. When the timer times out, it displays the time and
sets up another timer. And on and on it goes, like sand through an hourglass.
Countdown Timers
Another variation on the theme of timers is a countdown timer-a timer
that counts backward. You could use such a timer to let the user know that
something is about to happen, and when. Again, it is easy to create countdown
timers in JavaScript, as shown here:
<HTML>
<HEAD>
<TITLE>Count Down</TITLE>
<SCRIPT>
<!--
function countDown(tick)
{
if (tick == Ø)
{
window.status = "We have liftoff...";
return;
}
var time = "T minus ";
var minute = Math.floor(tick / 6Ø);
if (minute < 1Ø)
{
time += "Ø";
}
time += minute + ":";
var second = tick % 6Ø;
if (second < 1Ø)
{
time += "Ø";
}
time += second;
window.status = time;
--tick;
var command = "countDown(" + tick + ")";
window.setTimeout(command,1ØØØ);
}
//-->
</SCRIPT>
</HEAD>
<BODY ONLOAD="window.setTimeout('countDown(12Ø)',1ØØØ);">
</BODY>
</HTML>
Here an integer holds the time in seconds. The time is divided by 60
to get the minutes (Math.floor() is used to make sure the quotient is an
integer) and the modulus operator is used to get the seconds. The minutes
and seconds are displayed in the status bar. At the end of the timer code,
a new time-out is created that repeats the code with one less second, one
second later. When the seconds get to zero, the status bar is changed and
no further time-outs are created.
Self-Updating Documents
Finally, a document can update itself. For example, every five minutes
a brokerage house might create a GIF image that displays a graph of the
rise and fall of the Dow Jones during a five-minute span. You can create
a document that includes the GIF file as an inline image, and the document
can update itself every five minutes. This document calls history.go(0)
every 300 seconds (five minutes). Recall that history.go(0) acts like a
press of the reload button.
<HTML>
<HEAD>
<TITLE>The Dow Jones</TITLE>
</HEAD>
<BODY>
<IMG SRC="http://www.mythical_brokerage_house.com/DJ.GIF"
ALT="Picture it..." HEIGHT="5ØØ" WIDTH="5ØØ">
</BODY ONLOAD="window.setTimeout('history.go(Ø)',3ØØØØØ)">
</HTML>