In this chapter, you'll continue to revise the FSC Web pages created in Chapter 8 moving on to features found in the latest browsers- specifically, the latest version of Netscape. Features such as frames and cookies enable you to add unique capabilities to a JavaScript-enhanced page.
Although Netscape version 3.0 is the current version at this writing,
most of the features discussed in this chapter were introduced
in version 2.0, which also introduced JavaScript.
Note |
At this writing, Microsoft has released a beta version of version 3.0 of its Internet Explorer (MSIE) Web browser. This release supports frames and cookies, along with much of JavaScript. |
Before you get into the use of the new features with JavaScript, let's take a quick look at how you use them in a simple HTML page. This will enable you to make them work easily with JavaScript later in this chapter.
Netscape introduced frames in version 2.0. Recall that frames, also called framesets, are used to divide a Web page's display into multiple sections, each of which can display a different document or portion of a document. Frames are becoming a popular feature in Web pages and are already supported by some non-Netscape browsers.
An example of a document that uses frames is Netscape's JavaScript Authoring Guide, shown in Figure 9.1. The window is divided into three frames: a frame on the left with the table of contents, one on the right with the actual text, and a small strip on the bottom with two buttons used for JavaScript functions.
Figure 9.1 : Netscape's JavaScript Authoring Guide is an example of a document that uses frames.
Each frame acts as a separate window; it has its own URL. Each frame can also have horizontal and vertical scrollbars. The user can move the dividing lines to resize the different frames. You can enable and disable scrollbars and resizing through HTML attributes.
You use the <FRAMESET> tag to define a framed document. This tag is used instead of the <BODY> tag. The page with the <FRAMESET> declaration defines the layout of the different frames and which documents are loaded into them, but contains no actual data-the contents of each frame are at their own URLs.
The frame definition begins with the <FRAMESET>
tag and ends with the closing
</FRAMESET> tag. Within
these tags you can't use any ordinary HTML; you can use only tags
and attributes that define frames. You can also nest a frameset
within another frameset.
The <FRAMESET> tag has two attributes: ROWS and COLS. These define how the window is divided. You can use either of these attributes or both. Both of these attributes have the same value, which is a list of dimensions for each row or column. You can define the rows or columns in the following ways:
Note |
It is considered bad style to specify an exact number of pixels for a frame except in certain cases. Users may have different window sizes and different fonts, and you will end up annoying some users. One exception is when you are using a frame to display an image, such as a logo or navigation icons. You can then set the frame size to fit the image exactly. |
You can combine the different methods any way you like; in fact, this is almost always the best way to define a frameset. The following examples will give you some ideas of how these can be combined:
Note |
Notice that you are not required to define a value for the number of frames in the frameset. This value is calculated based on the number of values in the ROWS and COLS lists. |
Within the frameset, you use the <FRAME> tag to define each of the frames and the document it will contain. You should include one <FRAME> tag for each of the frames you defined in the ROWS and COLS attributes. The <FRAME> tag includes the following attributes:
As an example of the <FRAMESET> and <FRAME> tags, Listing 9.1 shows a complete definition for a frameset containing three documents, each displayed in a horizontal frame.
Listing 9.1. (FRAME1.htm) A simple frameset definition with three horizontal frames.
<FRAMESET ROWS="10%,*,*"> <FRAME SRC="doc1.htm"> <FRAME SRC="doc2.htm"> <FRAME SRC="doc3.htm" MARGINWIDTH="50"> </FRAMESET>
The first frame takes 10 percent of the available space, and the second and third divide the remaining space equally, giving them 45 percent each. The third frame includes a left and right margin of 50 pixels. Figure 9.2 shows how this set of documents looks in Netscape.
Figure 9.2 : An example of a framed document with three horizontal frames.
Although you can combine ROWS and COLS to divide a page both ways, you might wonder how you create unevenly divided frames. This is done by nesting the <FRAMESET> tags. You can use a <FRAMESET> tag instead of a <FRAME> tag to further subdivide that frame.
To use nested frames, try to start with the largest divisions of the page and end with the smallest. As an example, Listing 9.2 shows a frameset document that defines a set of nested frames.
Listing 9.2. (FRAME2.htm) A document with four frames, using nested framesets.
<FRAMESET ROWS="*,*"> <FRAMESET COLS="*,*"> <FRAME SRC="doc1.htm"> <FRAME SRC="doc2.htm"> </FRAMESET> <FRAMESET COLS="30%,*"> <FRAME SRC="doc3.htm"> <FRAME SRC="doc4.htm"> </FRAMESET> </FRAMESET>
This first divides the window into two rows, each with half of the area. The first row is divided into two columns of equal size; the second row is divided into a narrow column and a wide column. The output of this example is shown in Figure 9.3.
Figure 9.3 : A window with nested framesets showing four documents.
Along with the <FRAME> tag and nested framesets, one other tag can be used within a frameset document: <NOFRAMES>. This is a container that you can use to display information to users with non-frame browsers.
The way it works is this: Netscape and other browsers that support frames ignore everything within the <NOFRAMES> tags. Other browsers don't know what to do with the tag, so they ignore it and display the information between the tags.
This enables you to do things like this:
<FRAMESET ROWS="*,*"> <FRAME SRC="doc1.htm"> <FRAME SRC="doc2.htm"> <NOFRAMES> <h1>Hello</h1> You are using a non-frame browser. Please go away and don't come back until you support frames. </NOFRAMES> </FRAMESET>
This simply displays a rather rude message to users of non-frame browsers, although frame browsers display the framed documents normally. Unfortunately, <NOFRAMES> is often used to display messages like this; there are many users with non-frames browsers, though, and they often don't have the option of upgrading.
A much better approach is to use the <NOFRAMES>
section to enclose a non-frame version of the same document set
or an index of links to the documents. You could also include
a simple link to send the user to the non-frame version.
Note |
One common mistake is to assume that browsers that support frames also support JavaScript. Some Web authors have used <NOFRAMES> to weed out non-JavaScript browsers. There are now several browsers that support frames but not JavaScript, so this is not reliable. The <NOSCRIPT> tag, introduced in Netscape 3.0b4, provides a solution. |
You might wonder why you would want to display several documents on the screen at once with frames. In fact, many users of the Web complain about just that. Nonetheless, there are several valid uses for frames. Here are a few ideas:
You will look at some of these uses later in this chapter; you will also use frames in many of the applications created in the upcoming chapters.
Because you can display multiple documents in a window with frames and multiple windows, you need a way to specify which window or frame to use. The TARGET property enables you to do this.
The TARGET property is used in links, and it indicates the window or frame in which the document will be displayed. This is the name you assigned using the NAME attribute of the <FRAME> tag. For windows you create in JavaScript, this is the window reference you specified when creating the window.
For example, this link will open the order.htm document in the win1 frame or window:
<A HREF="order.htm" TARGET="win1">Order form</A>
If the window doesn't already exist, a new window will be created with the document loaded. For example, this link creates a new window called win2 and loads the support.htm document into it:
<A HREF="support.htm" TARGET="win2">Technical Support</A>
Another tag, <BASE>, enables you to define a default target window for a document. This target will be used for all links in the document except those with a differing TARGET property of their own. This statement sets the default target to win2:
<BASE TARGET="win2">
This is particularly useful for a frame that will be used as a
navigation bar or table of contents, because you will want every
link in the document to load in a different frame.
Note |
As mentioned in Chapter 6 "Using Interactive Forms," the <FORM> tag can also have a TARGET property. In this case, it defines which window or frame will be used to display the results after the form is submitted. |
In CGI programming, one of the most vexing problems is storing state information. When users go from one page to the next, it's hard to keep track of what they were doing, or even if they are the same users.
Netscape created cookies as one solution to this problem. A cookie is a chunk of information sent by the server, which can be stored on the client. Cookies are stored with a date they expire and the name of the host from which they came. When the user communicates with the same host later, the data is sent back.
Here are some examples where cookies can be useful:
Cookies can also be used in JavaScript. You can use them to store information between pages, or even to store information on users' computers to remember their preferences next time they load your page.
Each cookie stores a named piece of information and includes an expiration date. With few exceptions, this date is usually one of the following:
The cookies are stored in a "cookie jar" on the user's computer. Specifically, each cookie is a line in a file called cookies.txt, usually in the same directory as Netscape itself.
One feature added by Netscape surpasses even frames: the plug-in specification. This is an Application Program Interface (API) that enables programmers to create add-ons for Netscape. These are typically used to enable the browser to view non-HTML data.
Plug-ins are available for a wide variety of formats, and more are coming out every day. You can use plug-ins to display new kinds of images, animations, video, and 3D graphics directly in the browser window.
Because plug-ins are all about multimedia and bring many new media
formats to
the Web, you'll explore them in detail in Chapter 13, "Working
with Multimedia and Plug-Ins."
Note |
You can't write plug-ins with JavaScript, but there are features to enable you to control and interact with them using JavaScript. |
By combining JavaScript and frames, you can create multiwindow documents that interact with each other in new ways. Frames and JavaScript are used together frequently, and you'll use them many times in the rest of this book.
This section begins with an introduction to the objects and terminology you'll need to know to work with frames in JavaScript. Next, you'll apply what you've learned to add frames capability to the FSC Web page created in Chapter 8.
When a window contains multiple frames, each frame is represented in JavaScript by a frame object. This object is equivalent to a window object, but it is used for dealing with that frame. The frame object's name is the same as the NAME attribute you gave it in the <FRAME> tag.
Remember the window and self keywords, which refer to the current window? When you are using frames, these keywords refer to the current frame instead. Another keyword, parent, enables you to refer to the main window.
Each frame object in a window is a child of the parent window object. Suppose you define a set of frames using the HTML in Listing 9.3.
Listing 9.3. (FRAME3.htm) A framed document that divides the page into quarters.
<FRAMESET ROWS="*,*" COLS="*,*"> <FRAME NAME="topleft" SRC="topleft.htm"> <FRAME NAME="topright" SRC="topright.htm"> <FRAME NAME="bottomleft" SRC="botleft.htm"> <FRAME NAME="bottomright" SRC="botright.htm"> </FRAMESET>
This simply divides the window into quarters. If you have a JavaScript
program in the topleft.htm
file, it would refer to the other windows as parent.topright,
parent.bottomleft, and so
on. The keywords window and
self would refer to the topleft
frame.
Note |
If you use nested framesets, things are a bit more complicated. Window still represents the current frame, parent represents the frameset containing the current frame, and top represents the main frameset that contains all the others. |
Rather than referring to frames in a document by name, you can use the frames array. This array stores information about each of the frames in the document. The frames are indexed starting with zero and beginning with the first <FRAME> tag in the frameset document.
As an example, you could refer to the frames defined in Listing 9.3 using array references:
You can refer to a frame using either method interchangeably, and depending on your application, you should use the most convenient method. For example, a document with 10 frames would probably be easier to use by number, but a simple two-frame document is easier to use if the frames have meaningful names.
Each frame object (or each member of the frames array) has two properties:
In addition, you can use all the properties of the window object, which you looked at in Chapter 5 in a frame. You can also use the methods setTimeout(), clearTimeout(), blur(), and focus().
You can define the onLoad and onUnload event handlers for the parent window object within the <FRAMESET> tag. The individual frames in a document do not have their own event handlers for loading and unloading; the parent window's onLoad event indicates that all frames have been loaded.
At this point, you should have an idea of how to access the various frames in a window from JavaScript. Now let's apply this knowledge by making improvements to the FSC Software page created in Chapter 8.
You'll use a simple two-frame structure for the revised FSC page. You will move the navigation bar (the selection lists and "go" button) to the top frame, along with the logo. This will enable the logo and table of contents to remain at the top while the user visits the various pages in the bottom frame.
To begin, you'll need a frameset document. This will be the document the user loads first, and it will define the frame layout and the contents of each frame. This is the easiest part; the frame definition document is shown in Listing 9.4.
Listing 9.4. (FRAMEFSC.htm) The frame definition document for the revised FSC page.
<HTML> <FRAMESET ROWS="30%,*"> <FRAME NAME="contents" SRC="index.htm"> <FRAME NAME="main" SRC="fscmain.htm"> </FRAMESET> </HTML>
This simply defines two rows of frames. The first will be used for the navigation bar, which you will store in the file index.htm. The second frame will be used for whichever document the user is looking at; it will start with the introductory page, fscmain.htm.
Next, you need to create the index.htm file. This will include the Navigate() function created in Chapter 8 the navigation form, and the company logo. Listing 9.5 shows the contents document.
Listing 9.5. (index.htm) The contents of the top frame.
<HTML> <HEAD> <TITLE>Fictional Software Company</TITLE> <SCRIPT> function Navigate() { prod = document.navform.program.selectedIndex; cat = document.navform.category.selectedIndex; prodval = document.navform.program.options[prod].value; catval = document.navform.category.options[cat].value; if (prodval == "x" || catval == "x") return; parent.frames[1].location.href = prodval + "_" + catval + ".htm"; } </SCRIPT> </HEAD> <BODY> <IMG SRC="fsclogo.gif" alt="Fictional Software Company"> <FORM name="navform"> <SELECT name="program"> <OPTION VALUE="x" SELECTED>Select a Product <OPTION VALUE="w">Fictional Word Processor <OPTION VALUE="s">Fictional Spreadsheet <OPTION VALUE="d">Fictional Database </SELECT> <SELECT name="category"> <OPTION VALUE="x" SELECTED>Select a Category <OPTION VALUE="tech">Technical Support <OPTION VALUE="sales">Sales and Availability <OPTION VALUE="feat">List of Features <OPTION VALUE="price">Pricing Information <OPTION VALUE="tips">Tips and Techniques </SELECT> <INPUT TYPE="button" NAME="go" VALUE="Go to Page" onClick="Navigate();"> </FORM> </BODY> </HTML>
The form definition is the same one used in Chapter 8. Only one change was needed in the Navigate() function. The last line was changed to this:
parent.frames[1].location.href = prodval + "_" + catval + ".htm";
This sets the location of the second frame to the new URL, rather than the current frame. Thus, the documents the user selects load in the second frame, and the navigation bar stays in the first frame.
To test this multiframe FSC page, you will need the introductory page, fscmain.htm, to display in the second frame. This file is shown in Listing 9.6. This is simply a modified version of the version in Chapter 8after adding onMouseOver status line help.
Listing 9.6. (FSCMAIN.htm) The document for the second frame.
<HTML> <HEAD> <TITLE>Fictional Software Company</TITLE> </HEAD> <BODY> Welcome to our web page! Fictional Software Company specializes in creating innovative, user-friendly software applications with descriptions filled with industry buzzwords. <P> We have a wide range of products (3 of them) to meet the needs of you and your company. Follow the links below for more information. <P> <UL> <LI><A HREF="spread.htm" onMouseOver="window.status='Information about the spreadsheet';return true;"> Fictional Spreadsheet 7.0</A> <LI><A HREF="word.htm" onMouseOver="window.status='Information about the word processor';return true;"> Fictional Word Processor 6.0</A> <LI><A HREF="data.htm" onMouseOver="window.status='Information about the database';return true;"> Fictional Database 7.0</A> </UL> <P> Unlike other software companies, our products have absolutely no bugs, and always work perfectly on all computers. Nevertheless, you may run into problems in rare cases, usually your own fault. If this happens, visit our <A HREF="support.htm" onMouseOver="window.status='Technical Support for our products';return true;"> Technical Support</A> department for helpful information and tips. You can also view more information <A HREF="company.htm" onMouseOver="window.status='Information about FSC Software Co.';return true;"> about our company</A> or order products with our friendly <a href="order.htm" onMouseOver="window.status='Allows you to order products';return true;"> Order Form</A>. <HR> <I>(c)1998 FSC - designed by the FSC staff</I> </BODY> </HTML>
You are now ready to test the multiframe document. All you need to do now is load the frameset document (Listing 9.4) into the browser. The complete document in Netscape is shown in Figure 9.4.
Figure 9.4 : The complete multiframe document.
Notice that you are now using two HTML documents and two JavaScript applications. The application in the top frame is used to manage the navigation. The second frame includes the onMouseOver functions to display useful information in the status line. JavaScript works in both at the same time.
You should now understand how frames can be used and the benefits they offer. You will use frames throughout the rest of this book in many more complicated applications.
As a final example of frames, let's create a document that uses the open() and close() methods to rewrite a frame's contents from a script in another frame. As a simple application of this technique, you will create a clock that displays the time in a frame in a large font.
As usual, the frameset document is the simplest part. The frameset document for this example is shown in Listing 9.7.
Listing 9.7. (FRAMEUP1.htm) The frameset document for the frame update example.
<FRAMESET ROWS="50%,50%" onLoad="window.setTimeout('parent.CodeFrame.Update();',5000);"> <FRAME NAME="TimeFrame" SRC="Doc1.htm"> <FRAME NAME="CodeFrame" SRC="frameup2.htm"> </FRAMESET>
The top frame, called TimeFrame, is initially loaded with a generic file; if you don't specify the SRC property, frames don't always work correctly with JavaScript. This document will be erased by the clock five seconds after the page loads, as defined in the frameset's onLoad event handler.
The real work for the clock is done by the document in the second frame, called CodeFrame. Listing 9.8 shows this document.
Listing 9.8. (FRAMEUP2.htm) The main document for the frame update example.
<HTML> <HEAD> <TITLE>A Silly JavaScript Clock</TITLE> <SCRIPT LANGUAGE="JavaScript"> var now; //function to update time in frame function Update() { // get the time now = new Date(); hh = now.getHours(); mm = now.getMinutes(); ss = now.getSeconds(); // clear and rewrite the "time" frame parent.TimeFrame.document.open(); parent.TimeFrame.document.write("<HTML><BODY><CENTER><FONT SIZE='+35'>"); parent.TimeFrame.document.write(hh + ":" + mm + ":" + ss); parent.TimeFrame.document.writeln("</H1></BODY></FONT>"); parent.TimeFrame.document.close(); // set the next timeout window.setTimeout("Update();",5000); } </SCRIPT> </HEAD> <BODY> The above frame displays the time, which is updated once every 5 seconds after you load this page. The frame is updated with the <b>document.open()</b> and <b>close()</b> methods in JavaScript. </BODY> </HTML>
This document includes the Update() function, which updates the clock by rewriting the TimeFrame frame's contents. The document.open() and document.close() methods used to accomplish this are explained in Chapter 5. Figure 9.5 shows this example in action.
Figure 9.5 : The output of the frame update example.
Let's take a look at using cookies with JavaScript. You can use cookies to store a preference for the user, or to remember the user when they come back to your page. (No, you can't eat them.)
Cookies are stored for the current document, and they are accessed with the document.cookie property. This property is a text value which can contain the following components:
As an example, Listing 9.9 shows a document that remembers the name of each user who accesses it. Each section of the document is explained later.
Listing 9.9. (COOKIE.htm) An example of cookies in JavaScript.
<HTML> <HEAD> <TITLE>The page that remembers your name</TITLE> <SCRIPT> if (document.cookie.substring(0,2) != "n=") { nam = window.prompt("Enter your name"); document.cookie = "n=" + nam + ";"; document.cookie += "expires=Tuesday, 31-Dec-99 23:59:00 GMT" } </SCRIPT> </HEAD> <BODY> <H1>Here is Your name</H1> <HR> <SCRIPT> indx = document.cookie.indexOf(";"); nam = document.cookie.substring(2,indx+1); document.write("Hello there, ", nam); </SCRIPT> <P> next paragraph </BODY> </HTML>
The script in the document header simply checks the name portion of the cookie string for the n= characters. If they are not found, it prompts for the user's name, and stores the value in the "n=" cookie. A faraway expiration date is used to save the information indefinitely.
The script in the body of the document is then able to greet the user by displaying a name, if one has been defined. The output of this page is shown in Figure 9.6. Obviously, there are more uses for cookies than just names. You will explore another use in Chapter 11.
Figure 9.6 : The output of the JavaScript cookie example.
In this chapter, you continued the process of adding interactive features to a company Web page with JavaScript, taking advantage of the latest browser features:
You have now expanded your knowledge of JavaScript to include frames and cookies, and you should have an idea of the possibilities they offer. Move on with one of the following:
How do frames and cookies fit into the HTML standards, if at all? | |
Frames have been proposed as an extension to HTML, but have not been implemented in the latest version (HTML 3.2). You can bet they will become a standard, with both Netscape and Microsoft behind them. Cookies have not yet been discussed as an addition to HTML. | |
Is there any way for a user to access information stored in a cookie by a previous user? | |
No. Cookies are stored on the user's machine, so each user has a separate database. There is no way to send this data to the server with JavaScript. | |
Can I modify the frameset "on the fly"-for example, adding a new frame or eliminating an existing one? | |
Not without loading a different frameset. JavaScript has no capability of changing framesets, at least in the current version. | |
Can I call a function I defined in a different frame's document? | |
Yes. JavaScript functions are properties of the window object, so you can specify the window and document when you call the function, such as parent.frame2.Update(). Listing 9.7 uses this technique. | |
Nobody takes me seriously when I talk about cookies. Who at Netscape can I blame for creating a silly term like that? | |
Netscape is innocent in this case. The terms "cookie" and "cookie jar" have been used for years in the computer industry to represent named bits of information, usually stored in a computer's memory. |