Chapter 7

Advanced HTML Objects and Navigation


CONTENTS

Your users will demand quicker response time as you add more interactivity to your pages. Before JavaScript, most interactive features required your Web page to invoke a CGI script on the server. The more interactivity, the more the users have to wait on the server to deliver new documents. The response time improves dramatically as JavaScript handles interactivity on the browser side instead of waiting on CGI scripts.

To meet this increasing demand for better response time, you will increase the size of your Web documents with JavaScript. This is because your pages are more like applications and less like plain reading material. As your document gets larger, you will incorporate more navigational aids. You will create dynamic elements with JavaScript to let users quickly see the

material they want and skip irrelevant information. And you will do this without waiting on the server.

Controlling the flow of user interaction is critical to good design. You can confuse your users with the multiple windows and frames possible in the new browsers. The dynamic capability of JavaScript allows you to create new documents in response to your users' preferences. For example, if the viewer selects a favorite sport, the hyperlink named "Last Year's Champion" could vary based on the viewer's selection.

With JavaScript features, you can transform the browser from static displays to interactive applications. There are a variety of examples in this chapter which let you try out the new dynamics of hyperlinks, anchors, and selection lists. The chapter concludes with a much larger application that shows you the possibilities of the new browser.

Link In with JavaScript

Click and follow the designer's lead. That's how people navigate the Web: they follow the links chosen by the designer. Click the same link a hundred times and it takes you to the same page every time. Every user is different and has different expectations. For example, a link that's appropriate for an adult might be too complex for a young child.

This limitation of HTML drives many people to build a better Web page. You probably looked at a few poorly designed Web pages and were frustrated by the hyperlinks designed into those pages. As a designer, you might have chosen other sites to link to. So people build other Web pages and try to make them perfect for their audiences. They still end up with pages in which the viewer follows the designer.

Your links are now dynamic with JavaScript. Based on options a user can select, clicking the link takes the user to different places without waiting on a CGI script to feed a page from the server. Also, by using the frames and windows, your existing page is not necessarily replaced by the new page. Your browser can be a kaleidoscope on the Web simultaneously viewing multiple sites around the world. Or you can pull in different publications based on the day of the week.

Additions to the LINK Syntax

You are probably familiar with using the link tag in an HTML document. A very simple example is the following:

<A HREF="http://www.yoursite.com">Click here</A>

Your browser would display "Click here" as a hyperlink.

The reference of a LINK is a URL or a location. You know the World Wide Web protocol, which is http:// as you see in the preceding example. You could also have used the MailTo protocol (for example, mailto:info@mailcall.com). There are formats for FTP, Gopher, and File. JavaScript makes two additional protocols available: javascript: and about.

javascript: protocol  A new URL type is now defined in JavaScript for the LINK tag. The protocol is simply javascript:. For example, you could specify javascript: history.go(-1) as the URL. When used as the URL for a LINK, the browser executes the statement following the colon. In the following example it executes: history.go(-1). As a useful example, try adding the following line to any page:

<A HREF="javascript: history.go(-1)">Go back to previous page</A>

This is particularly useful on documents displayed in browser windows where you have disabled the toolbar.

When you click this hyperlink, the browser takes you back to the previous page in your history list. If you want to test this, open your browser and load your default home page. Then load the page in listing 7.1 called history.htm on the CD-ROM. Clicking the hyperlink returns you to your default home page.


Listing 7.1  history.htm  Demo of javascript URL

<HTML><HEAD><TITLE>history.htm by Ray Daly</TITLE>
</HEAD><BODY>
<P>Juno said, "<A HREF="javascript:history.go(-1)">
History will repeat itself.</A>"<P>
</BODY></HTML>

Hyperlinks can also behave like buttons in forms. Instead of placing a function in an onClick event, place the function behind the javascript: protocol. Clicking the hyperlink will have the same effect as clicking a button. In other words, replace the following code for a button in a form:

<INPUT TYPE="botton" VALUE="click here" onClick="myfunction()">

with this code for using a hyperlink:

<A HREF="javascript: myfunction()">click here</A>

Now let's take this a step further and replace the grey, rectangular JavaScript button with your own colorful icons. Again, use the javascript: protocol, but this time use it with the IMG tag. Here's some sample code:

<A HREF="javascript: myfunction()"><IMG SRC="youricon.gif"></A>

This gives you the ability to make your own shape, size, and color buttons! Imagine how bright and colorful a simple calculator can now appear.

The code for creating a button, a text link, and an icon is in listing 7.2. Pressing any one of these items produces the same result.


Listing 7.2  Substituting Text and Icons for Buttons

<HTML><HEAD><TITLE>jsbutton.htm by Ray Daly </TITLE>
<SCRIPT LANGUAGE="JavaScript">
function netalert() {
     alert('Any function could go here')
}
</SCRIPT>
</HEAD><BODY>
<P><B>You can substitute icons for buttons or links for buttons</B><BR>
<FORM><INPUT TYPE="button"  VALUE="same as link or icon"
   onClick="netalert()"></FORM>
<A HREF="javascript: netalert()">same as icon or button</A><BR>
<P>This icon will function the same as a button or link<BR>
<A HREF="javascript: netalert()"> <IMG SRC="helpmark.gif"></A>
</P></BODY></HTML>

You can take this concept one step further by using imagemaps. Imagemaps are graphics with active areas. Click one area and you link to one site, click another part of the image and you link to another. Geographical maps and directories are common uses of imagemaps.

When coding an imagemap you use URLs to instruct the browser. By substituting in the javascript: protocol, you can now create imagemaps that execute various JavaScript functions instead of jumping to another location.

Prior to Netscape Navigator 2.0, all imagemaps were executed on the server. Now you can create client-side imagemaps where the browser does not need to wait on results from the server. Click an image and the browser immediately executes the instruction.

Coding an imagemap requires that URLs be specified for various regions of the image. With client-side imagemaps, you can substitute the javascript: protocol. Clicking the imagemap can now execute JavaScript functions as well as jump to locations specified in URLs.

NOTE
To enable client-side imagemaps, Netscape introduced a new attribute to the IMG element called USEMAP (see http://home.netscape.com/assist/net_sites/html_extensions_3.html). It is added to the IMG tag to tell the browser to invoke client-side imagemapping by reading information from a MAP element. The syntax is:

<IMG SRC="yourimage.gif" USEMAP="yourfile.html#mapname">

NOTE
where mapname is the name of a MAP element in the document called yourfile.html.
The MAP element must have a name in order to be referenced by the USEMAP attribute. Contained within the MAP element are AREA tags. A MAP element usually contains more than one AREA tag, one for each different region of the imagemap. The syntax is:

<AREA [SHAPE="shape"] COORDS="x,y,..." [HREF="reference"] [NOHREF]>

NOTE
where shape can be RECT (retangles), POLY (polygons), CIRCLE (circle), and DEFAULT (default). COORDS specifies the points that define the shape. You then have the option to specify an action using the HREF attribute. Or you can specify no action using NOHREF.

In JavaScript, you can specify the reference to use the javascript: protocol. For example, this code defines a rectangular area where the browser loads the previous page from the history list:

<AREA SHAPE="rect" COORDS="0,0,100,50" HREF="javascript:history.go(-

You can have the browser take you to new locations, execute a JavaScript statement, or a JavaScript function. Your Web pages are more alive than ever now. Listing 7.3 shows a script for creating a client-side imagemap with the javascript: protocol.


Listing 7.3  Client-Side Imagemap with javascript: Protocol

<HTML><HEAD><TITLE>imagesid.htm by Ray Daly</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function sayhi () {
     alert ('Alert poped up from an Image Map')
}
</SCRIPT></HEAD><BODY>
<P><B>Demo of Client Side Image Mapping and the <I>javascript</I> 
 protocol.</B><P>
<IMG SRC="imagesid.gif" USEMAP="#mapdemo">
<MAP NAME="mapdemo">
<AREA SHAPE="rect" COORDS="0,0,100,100" HREF="javascript:history.go(- 1)">
<AREA SHAPE="rect" COORDS="100,0,200,100" HREF="javascript:sayhi()">
<AREA SHAPE="rect" COORDS="200,0,300,100" HREF="http://www.yahoo.com">
</MAP>
</BODY></HTML>

CAUTION
A javascript:xxx() call replaces a URL. The browser tries to interpret any return from a function call as if it were a URL. If the browser does not understand the return value, it reloads the current page. When that occurs, any window globals that you set during the xxx() function call will be lost.

The other new protocol is the about: protocol. When used as a location for a link, it provides Navigator information (see listing 7.4, which can also be found in the about.htm file on the CD-ROM). In its basic format without any arguments, it is the same as selecting About Netscape from the Help menu. When used with the plug-ins argument, the page displayed is the same as About Plugs from the Help window. The last usage is with the argument cache which is supposed to display the disk cache statistics.

NOTE
On Windows NT, this features does not work. N


Listing 7.4  about.htm  Demo of about: Protocol

<HTML><HEAD><TITLE>about.htm by Ray Daly</TITLE>
</HEAD><BODY>
<P>Demo of the <I>about:</I> protocol:
<UL><LI><A HREF="about:">about:</A></LI>
<LI><A HREF="about:cache">about:cache</A></LI>
<LI><A HREF="about:plug-ins">about:plug-ins</A></LI>
</UL><P>
</BODY></HTML>

Properties of the LINK Object

Each object has properties. The properties of the LINK object tell you about the URL. There is also a property to tell you the target for the document. I have created a small page that shows all of the LINK properties in action (see fig. 7.1 and listing 7.5). The code for this page can also be found in the linkprop.htm file on the CD-ROM.

Figure 7.1 : All of the properties, except TARGET, extract substrings from the HREF property.


Listing 7.5  linkprop.htm  Demo of LINK Object Properties

<HTML><HEAD><TITLE>linkprop.htm by Ray Daly</TITLE></HEAD><BODY><P>
<B>LINK[0]:  </B>
<A HREF="http://www.yoursite.com:80/mystuff/index.html?search=htmljive" 
TARGET="parent.bottom">
http://www.yoursite.com:80/mystuff/index.html:80?search=htmljive</A>
<BR><B>LINK[1]:  </B>
<A HREF="http://www.yoursite.com:80/mystuff/index.html#anchorhere" 
TARGET="parent.bottom">
http://www.yoursite.com:80/mystuff/index.html:80#anchorhere</A>
<BR><BR>>This demonstrates the properties of the LINK[0] object.
<SCRIPT LANGUAGE="JavaScript">
document.write( "<BR>hash = " + document.links[0].hash)
document.write( "<BR>host = " + document.links[0].host)
document.write( "<BR>hostname = " + document.links[0].hostname)
document.write( "<BR>href = " + document.links[0].href)
document.write( "<BR>pathname = " + document.links[0].pathname)
document.write( "<BR>port = " + document.links[0].port)
document.write( "<BR>protocol = " + document.links[0].protocol)
document.write( "<BR>search = " + document.links[0].search)
document.write( "<BR>target = " + document.links[0].target)
document.write( "<P>>The LINK[0] has no hash.  ")
document.write("Howver the LINK[1] has:<BR>")
document.write( "hash = " + document.links[1].hash)
document.write("<BR><BR>The numbr of links is the length = ")
document.write( document.links.length)
</SCRIPT></BODY></HTML>

The NAME Attribute has New Significance

Prior to putting JavaScript into HTML pages, there was not much point in using the NAME attribute, so my tags remained nameless. NAME was only used for anchors and when sending form information to a CGI script.

As you use JavaScript to make your links dynamic, you need to distinguish between the various links on your page. The properties of the link object are accessible using the following format:

document.links[index].propertyname

In using this format, you need to know the index number. The index number is assigned to each LINK object in sequence as it is loaded by the browser. The first link loaded has the index of 0, the second is 1, and so on. So you need to keep track of the order in which the LINK objects are loaded. This is the default method of accessing properties.

Often, a simpler means is to name the elements that are referenced by your JavaScript code. Therefore, using our first example, add the NAME attribute:

<A NAME="myname" HREF="http://www.yoursite.com">Click here</A>

Now your JavaScript code can access the properties of this object without having to know the index number. Simply use the following format:

document.name.propertyName

Using the NAME attribute is probably familiar to you if you have used anchors in your HTML documents. It is the identical format and is still how you create anchors. So whenever you use the NAME attribute for your JavaScript code, you are also adding a new anchor.

LINK Events: onMouseOver and onClick

JavaScript code executes when the browser recognizes certain events. The link object recognizes two events: onClick and onMouseOver. You will probably use onClick in most of your code and onMouseOver only occasionally. The following will remind you of the format of these events used with the LINK tag.

TIP
When debugging code involving the status bar, make sure you include the statement return true.

The format is the same as for other events. Use our example, as follows:

<A NAME="myname" HREF="http://www.yoursite.com"
onMouseOver="window.status='Please visit my site.'; return true">
Click here</A>

This places the message Please visit my site. in the status bar when the viewer places the mouse pointer over the hyperlink. This overrides most browsers that would display the URL in the status bar in this event.

You can use this feature to change the look and feel of your pages. Instead of showing the URL, which is geek talk to many, change your links to verbally tell people where the links take them. So instead of displaying something like

http://www.cris.com/~raydaly/sponsors.html 

you can display an easier to understand message in the status bar, such as

Hyperlink to "Sponsor of the Day"

The onClick event uses the same format. Also, the example application for this chapter makes frequent use of the onClick event. The following is a short example:

<A NAME="mymessage" HREF="http://www.newsite.com"
onClick="alert('Thanks for visiting.  Enjoy the new site.')">
Visit Newsite</A>

This code displays an alert dialog box prior to jumping to the new site (see
fig. 7.2). Only after the user clicks OK in the dialog box does the browser hyperlink to www.newsite.com.

Figure 7.2 : You can display a dialog box prior to hyperlinking to a new site.

CAUTION
The onMouseOver event is trapped at each boundary of a link. This results in an event occuring twice as the point enters and leaves the link.
If you use the onMouseOver event to write to the status bar, you find that if you move your mouse too quickly you miss the status write. This is because it is rapidly replaced by the browser's own response to the event. When you exit, the status written stays there until you encounter another link. If you want to use the content of your link in a function called from an onMouseOver handler, you can pass the function the keyword this. Links are treated like any other JavaScript object.

CAUTION
You might confuse your users by changing the HREF using onClick. Users often look to the status bar to see the URL that the hyperlink will take them to. When you assign the HREF attribute of the LINK, it is displayed in the status bar. When using the onClick event you can set the HREF to a different URL. By reading the status bar the user may assume he is going to the first URL, but instead your JavaScript code takes him to the URL specified by the onClick statement.
In the following example, the status bar makes it appear that the link is to Yahoo's site, but the code takes you to Infoseek. It goes to show that you cannot even trust links anymore.
<A NAME="searchme" HREF="http://www.yahoo.com"
onClick="this.href='http://www.infoseek.com'">
Search Internet for a Topic</A>
To avoid such a deception in the status bar, just add onMouseOver to change the contents of status bar. For the preceding example, just insert the following as the second line:
onMouseOver="window.status='Will take you to a search engine.';  return true"

Change Link URLs, Not the Displayed Text

Unlike text boxes, JavaScript cannot change the hyperlink text displayed by the browser. In listing 7.6, the hyperlink text is Yahoo!. Regardless of the changes you make to this object, this stays on the screen.

As you design your dynamic links, consider the words and images that reflect the new nature of your hyperlinks. For example, you could write a simple random URL function. When you click the link, it takes you to a random search site. You might use the words, "Spin the wheel to a random search site," or add a graphic image of a roulette wheel.

Listing 7.6 is an example showing how to make a dynamic link to Yahoo! The browser simply displays the hyperlink text Yahoo! When you click this link before 6:00 p.m., you link to the text-only version of Yahoo! But after 6:00 p.m., you link to the regular graphic version of Yahoo! So the HREF changes, but the displayed text stays the same. The following code can also be found in the file atlyahoo.htm on the CD-rom.


Listing 7.6  atlyahoo.htm  Page with Alternative Yahoo! Links

<HTML>
<HEAD><SCRIPT Language="JavaScript">
function timeText () {
   today=new Date()
   hour = today.getHours()   //...get hour of the dat
   if (hour>18 ) {
        //...after 6:00 p.m use graphics
        yahooURL= "http://www.yahoo.com/"
   } else {
      //...all other times use test mode
       yahooURL = "http://www.yahoo.com/text/"
   }
   return yahooURL   //...result of function is a URL
}
</SCRIPT></HEAD>
<BODY>
<A NAME="yahooLink" HREF=""
onClick="this.href=timeText()"   //...get the right URL
onMouseOver="window.status='Hyperlink to Yahoo!'; return true">
Yahoo!</A>
</BODY></HTML>

The URLs are not just for the Web. For example, suppose you have a fairly lengthy form to be completed by a customer, and one of the first entries asks about the customer's location. Based on that entry, you might dynamically change the mailto address. Then any e-mail the customer might send is directed to the proper salesperson. Listing 7.5 asks the user where he is located. (This code is included on the CD-ROM as atlmail2.htm.) Based on his selection, e-mail goes to a different address. Figure 7.3 shows the result of listing 7.7.

Figure 7.3 : Depending on the selection, e-mail goes to a different address. Remember to include a default address or use a dialog box to ask the user to make a choice before trying to send e-mail.


Listing 7.7  atlmail2.htm  Page that Switches Mailto: Addresses

<HTML><HEAD></HEAD>
<BODY>
<FORM>
<B>Where are you located?</B><BR>
<INPUT TYPE="radio" NAME="country" onClick="salespersonMailto=
     'mailto:worldsales@company.com'"> Outside North America<BR>
<INPUT TYPE="radio" NAME="country" onClick="salespersonMailto=
     'mailto:nasales@company.com'"> North America<BR>
</FORM>
<A NAME="salesperson" HREF="mailto:info@yoursite.com"  
onClick="this.href=salespersonMailto">Email your salesperson.</A>
</BODY></HTML>

Display Documents in Frames and Windows

The LINK tag now enables the designer to specify the TARGET for the URL. This is an optional attribute. If it is not used, the new page simply replaces the previous page as before. But JavaScript allows you to display these new pages in frames or new windows.

One target for your link can be a new browser window. The windows will generally look and function as if you opened a second browser. Therefore, the original page is still displayed in your first window, and the new page is displayed in the second. You can reduce the functionality of these windows by changing their features when the windows are open.

A frame is the other possible target for your link. Frames divide your browser window into two or more areas. Inside these frames you can display standard Web pages or create your own documents. The applications constructed in this chapter use frames.

The following code displays the Yahoo! page in the frame labeled "three."

<A HREF=" "onClick="this.href=http://www.yahoo.com" "  TARGET="three">Show picture Tri</A>

Windows and frames are often a vital part of a design with dynamic links. Using JavaScript code behind a link, you can build new types of browsers. You can also build new tools. For example, you might bring a page into a frame, analyze it, and display the results in another frame.

One area of a frame is often like a control panel that can control the display in another. For example, researchers constantly use different search engines on the Web, and these sites are bookmarked. But it would be handier if these sites were always available like the Directory buttons in Netscape Navigator. Listings 7.8, 7.9, and 7.10, (called searchdr.htm, display.htm, and search.htm on the CD-ROM), show how the top frame contains one line with hyperlinks to eight different search engines. This frame is like a control panel with the documents targeted at the lower frame. Figure 7.4 shows the result.

Figure 7.4 : SearchDr puts any of the listed search engines in the frame marked Display. When you create frames, let the default frames provide instructions to the new users.


Listing 7.8  searchdr.htm  Top Page for SearchDr

<HTML><HEAD><TITLE> searchdr.htm </TITLE></HEAD>
<FRAMESET ROWS="60,*">
   <FRAME SRC="search.htm" NAME="buttons">
   <FRAME SRC="display.htm" NAME="display">
</FRAMESET>
</HTML>


Listing 7.9  display.htm  Initial Screen in Display Frame

<HTML><HEAD><TITLE>Part of searchdr.htm: display.htm</TITLE></HEAD>
<BODY><H1>Display Area</H1>
<P>Click on any hyperlink above to display a search engine here.
</BODY></HTML>


Listing 7.10  search.htm  Frame for SearchDr with Hyperlinks

<HTML><HEAD><TITLE>Part of searchdr.htm:  search.htm</TITLE></HEAD>
<BODY>
<A HREF="http://www.altavista.digital.com/" TARGET="display"> Alta  Vista</A>  --  
<A HREF="http://www.excite.com" TARGET="display">Excite</A>  --  
<A HREF="http://www.lycos.com/" TARGET="display">Lycos</A>  --  
<A HREF="http://www.mckinley.com/" TARGET="display">Magellan</A>  --  
<A HREF="http://www.nlightn.com/" TARGET="display">NlightN</A>  --  
<A HREF="http://www.opentext.com:8080/" TARGET="display">Open Text</A>    
<A HREF="http://www.webcrawler.com" TARGET="display">WebCrawler</A>  --  
<A HREF="http://www.yahoo.com" TARGET="display">Yahoo!</A>
</BODY>
</HTML>

For a more substantial example, we will construct an application in this chapter called Internet Tri-Eye. It will truly give you a different view of the world. In listing 7.11 and its corresponding figure 7.5, you see the frames used in creating Internet Tri-Eye. This code can be found in the file trieye.htm on the CD-ROM.

Figure 7.5 : The frames used to create Internet Tri-Eye will contain the control panel at the bottom and display Internet camera pictures from around the world. The contents of frames can be .GIF and .JPEG files as well as HTML documents.

Although this will be displayed using your browser, it is not the same old browser anymore. Frames and dynamic hyperlinks let you reshape the browser.


Listing 7.11  trieye.htm  Frame Document for Internet Tri-Eye

<HTML><HEAD><TITLE>Internet Tri-Eye</TITLE></HEAD>
<FRAMESET ROWS="*,200">
   <FRAMESET COLS="33%,34%, 33%">
      <FRAME SRC="one.htm" NAME="one">
      <FRAME SRC="two.htm" NAME="two">
      <FRAME SRC="three.htm" NAME="three">
   </FRAMESET>
   <FRAME SRC="guide.htm" NAME="guide">

<NOFRAMES>
<H1>Internet Tri-Eye</H1>
<P><B>Internet Tri-Eye</B> is a demonstration of several features of 
Javascript.  To view and use this program you need a Javascript 
compatible browser like Netscape 2.0.
</NOFRAMES>

</FRAMESET></HTML>

Creating and Using Anchors

Anchors are not commonly used on Web pages. If you have an alphabetical listing, an anchor might take you to a particular section. However, most sites have tended to use rather short pages. These pages might be one or two screens in length and do not often need anchors.

As you develop JavaScript applications, your documents will get longer. Also, with frames and multiple windows, less of your document is displayed on-screen. Your users will want you to take them right to the information instead of being required to scroll through your page. Anchors help you deliver your information more directly.

Your HTML Elements

The pages you design with JavaScript are fundamentally different from most other HTML pages. Because they are so interactive, your viewers will spend more time on your pages than the average HTML page. They may also save the page because it is not just a page of text anymore, but an application.

These differences should make you consider making your pages bigger than before. The user may be willing to wait a little longer for a page to load if that means it will be richer.

Since your pages are now applications, users will expect quick responses to their inputs; you cannot deliver that promise if you have to keep requesting documents from the server. Instead, take what you might have normally put on several different pages and build it into one big page. This can also benefit users because when they save the page, they can have the complete application.

For example, with your Great JavaScript Application you might have a page of help and documentation. Given the sophistication of your application, this could be fairly lengthy, and normally you might consider separating it from the application page. However, if you follow that course, when users save the application, they will not have the help when loading it from their hard drives. Instead, consider making a bigger page that includes all of the help information and documentation. Then set up anchors to the help topics so people can easily refer to them (see fig. 7.6).

Figure 7.6 : By combining multiple pages into one, your JavaScript application becomes more responsive. The fewer the requests to the server, the more responsive your application is.

When you have longer documents, anchors become crucial for navigating around the document. Instead of scrolling through screen after screen, click the keyword and you have found your place. Use this technique for documentation, help, or other reference material.

Anchor Any Text or Element

Use anchors in the standard way and in new ways with JavaScript. Anchors enable you to specify a destination for a hyperlink within a document. For example, assume you want to be able to jump to the words, "Part Two." Then you would put this code in your document:

<A NAME="jumphere">Part Two</A>

Note that the name does not have to be the same as the text. In this example the name is jumphere, and the text displayed by the browser is "Part Two." To create the hyperlink to this section, use the following code:

<A HREF="#jumphere"> Go To Part Two</A>

This is useful not only within the current document, but also when pulling up information within frames or in other windows. For example, take the case of a form in which you are verifying the input. You would probably use a dialog box to notify the viewer that the input is out of range; then use an anchor at the description of the text box, and link the browser to it with hypertext. Now the text box is right at the top of the screen awaiting a new input.

NOTE
You can use the anchor to scroll the page to the place you want. The FOCUS and the SELECT methods can do the same with form elements. However, if your form elements have labels, these methods will move the element to the top of the screen cutting off your label. If you want your users to be able to read the labels, anchor the labels and jump to them
For comparison, both techniques are used in the code formname.htm on the CD-ROM (see listing 7.12 and fig. 7.7). n

Anchors can also provide you with a new way to control the flow in completing a form, as shown in listing 7.12 and figure 7.7. Many times in completing paper forms, you see such instruction as "If you answered NO to question 6, skip to question 9." With JavaScript and anchors, you can look at the response to a question, then-depending on the answer-automatically jump to the anchor for the next appropriate question.

Figure 7.7 : You will see a visual difference in comparing the use of anchors to control the flow or the use of the FOCUS and SELECT methods.


Listing 7.12  veriname.htm  Anchors in Form Verification

<HTML><HEAD><TITLE>verfname.htm by Ray Daly</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function skip2 (form) {
    if (form.q1.value>11) {
       alert ('You get FREE Overnite Shipping.  Skip to question 12.')
        form.q2.value="FREE Overnight"
        window.location="#a12"
        //...jump to anchor a12
    }
    if (form.q1.value<0) {
       alert ('You can not return these items')
       form.q1.value=""
       form.q1.focus()
       form.q1.select()
       //...instead of jumping to an anchor, this uses focus and select 
    }
  }
</SCRIPT></HEAD><BODY><FORM>
<P>Try filling in quanties of 16, 8 and -3.  </P>
<B>1.)  How many do you want?</B><BR>
FREE Overnite shipping when ordering 12 or more.<BR>
<INPUT NAME="q1" TYPE="Text" onBlur="skip2(this.form)"><BR>
<a NAME="a2">
<B>2.)  How do you want it shipped?</B><BR>
<INPUT NAME="q2" TYPE="Text" ><BR>
<BR><BR><BR><BR><BR><BR>
<I>(more questions are listed here)
<BR><BR><BR><BR><BR><BR>
<BR><BR><BR><BR><BR><BR>
<B>12.)  What color do you want?</B><BR>
<A NAME="a12"><INPUT NAME="q12" TYPE="Text" ><BR>
<BR><BR><BR><BR><BR><BR>
<I>(more questions are listed here)
<BR><BR><BR><BR><BR><BR>
<BR><BR><BR><BR><BR><BR>
</FORM>
</BODY></HTML>

TIP
When debugging your JavaScript, check your quotes. Although double quotes and single quotes work the same, you cannot start with a double quote and end with a single quote, or vice versa. Your quotes must match or you will end up with errors several lines later.

Selection or Scrolling-Your Option

What kind of test did you prefer in school: multiple choice or essay? You probably found multiple choice easier. Certainly, your teacher found multiple choice easier to grade.

When you design interactive forms, your viewers probably also find your requests easier to understand in a multiple choice format. Understanding this aspect of form design, you have probably used radio buttons and checkboxes. These are excellent devices for presenting a limited number of choices.

When you present the viewer with a large number of choices, use the SELECT element. This enables you to present a large list without cluttering up your page. A good use would be geographical lists, such as states or countries in address forms.

Syntax in Review

Although using the SELECT element makes it easier for your viewer, you have to do more work. Remember, SELECT is an element within a form, so it must be between the <FORM></FORM> tags. The syntax of SELECT is one of the most complicated of all the HTML elements. You should be familiar with most of this specification. To support JavaScript you can optionally include event handlers of onBlur, onChange, and onFocus (see listing 7.13).


Listing 7.13  Using onBlur, onChange, and onFocus with the SELECT Element

<SELECT
   NAME="selectName"
   [SIZE="integer"]
   [MULTIPLE]
   [onBlur="handlerText"]
   [onChange="handlerText"]
   [onFocus="handlerText"]>
   <OPTION VALUE="optionValue" [SELECTED]> textToDisplay
      [ ... <OPTION> textToDisplay]
</SELECT>

The SELECT tag has one required attribute: NAME. This name and a value associated with the selected OPTION element are sent to the server when a form is submitted. The NAME attribute can also be used as an anchor. An optional attribute is SIZE, which tells the browser how many options to display.

MULTIPLE is an optional attribute of SELECT, which changes the list so that one or multiple items can be selected by the user. This type of list is called a scrolling list.

The SELECT tag always contains two or more OPTION elements. This is where you list the items for the user to select. Each OPTION has a text property that is displayed in the select box. There is also an associated VALUE property that is sent to the server when the form is submitted along with the name of the SELECT tag. The last attribute of OPTION is itself optional. The SELECTED attribute is a means to have one of the items in your selection list be the default when the page is displayed. The only additions to this specification for JavaScript are the events discussed in the next section.

onChange, onBlur, and onFocus Events for SELECT

Like other objects in JavaScript, the SELECT object responds to events. Here you will learn specific uses of onFocus, onChange, and onBlur with the SELECT objects.

onChange  onChange is the most common event that you monitor in SELECT. It looks for change from one selection to another. When the event is triggered, your code executes. An example of using onChange, by selecting a country, is shown in listing 7.14 and figure 7.8. Say you change a country selection from the United States to Mexico. Then onChange triggers a JavaScript function that changes the currency type from U.S. dollars to pesos. However, if you did not change the selection, the event would not trigger.

Figure 7.8 : You will probably find that onChange does not work as you expect with SELECT. You have to click somewhere outside the SELECT box for the change to take effect.

TIP
When using SELECT, you have a built-in associate array. Each OPTION value relates to a selection


Listing 7.14  money.htm  Currency by Country using onChange

<HTML><HEAD><TITLE>money.htm by Ray Daly</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function changeCurrency(form) {
      form.currency.value=form.country.options[form.country.selectedIndex].value
}
</SCRIPT></HEAD>
<BODY><FORM>
<P>Demonstrates <I>onChange</I> event.  After you make a country selec
the currency does not change until you click somewhere else.</P>
<B>Select your country</B><BR>
<SELECT NAME="country" onChange="changeCurrency(this.form)">
<OPTION VALUE="US Dollars">USA
<OPTION VALUE="Canadian Dollars">Canada
<OPTION VALUE="Peso">Mexico
</SELECT>
<P><B>Prices are displayed in:</B><BR>
<INPUT TYPE="text" NAME="currency">
</FORM></BODY>
</HTML>

onBlur  onBlur is a good way to verify proper selections. This event looks for when the focus is no longer on the SELECT object. In other words, it looks for when you click somewhere other than the current element. When the event is triggered, you could execute a verification function. Although you can use the onChange event to verify selections, using onBlur might ensure the viewer's choice. This is because the onBlur event triggers JavaScript code even if a change has not occurred.

Verification is not always simply an either/or choice. For example, you might have a selection with some uncommon, but acceptable answers. This might be an unusual color for a piece of merchandise. For this circumstance, you might verify that this is indeed the correct selection, even if the user made no change in his selection. In listing 7.15, the user is simply notified with an alert dialog box if he wants to buy less than a dozen eggs (see fig. 7.9).

Figure 7.9 : The event onBlur works almost exactly like onChange, except the JavaScript code is executed even if the selection does not change.


Listing 7.15  eggs.htm  Eggs Come by the Dozen Using onBlur

<HTML><HEAD><TITLE>eggs.htm by Ray Daly</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function checkEggs(form) {
    form.eggs.value=form.quantity.options[form.quantity.selectedIndex].value 
    if (form.quantity.selectedIndex==0) {
        alert ('People usually order eggs by the dozen.')
     }
}
</SCRIPT></HEAD>
<BODY><FORM>
<P>Demonstrates <I>onBlur</I> event.  After you select a quanity,
the number on-hold is not updated until you click somewhere else.</P>
<B>How many eggs do you want:</B><BR>
<SELECT NAME="quantity" onBlur="checkEggs(this.form)">
   <OPTION VALUE="6">Half dozen
   <OPTION VALUE="12">Dozen
   <OPTION VALUE="24">Two dozen
</SELECT>
<P><B>We are holding this many eggs for you:</B><BR>
<INPUT TYPE="text" NAME="eggs">
</FORM></BODY>
</HTML>

onFocus  onFocus is an excellent way to assist the viewer in completing your form. It looks for the viewer moving the cursor to the SELECT element and then triggers code prior to any entry by the viewer.

For example, each question in your form can include particular instructions that assist the viewer in making a proper selection. When onFocus is triggered, your code could display in a separate window or frame the instructions related to that question. Or if you require a numeric answer to be calculated, why not pop up a calculator in a new window? That's what happens in the math word problem presented in listing 7.16 (see fig. 7.10).

Figure 7.10: When you design your JavaScript applications, remember that you can call up other people's applications like calculators.

TIP
It is possible to create an endless loop using the onBlur event. To avoid this trap, create a flag variable. Initially set it to zero. Every time you call the routine, check the value of the flag. If the flag is zero, then execute the rest of the routine and set the flag to one. If the flag is not zero, then the routine has already been executed once so you don't need to execute it again.


Listing 7.16  wordprob.htm  Tricky Math Word Problem Using onFocus

<HTML><HEAD><TITLE>wordprob.htm by Dr. Ray Daly III </TITLE>
<SCRIPT LANGUAGE="JavaScript">
function giveAnswer(form) {
    if (form.answer.selectedIndex==2) {
        alert ('People usually forget trains run on two tracks.')
     }
}
already=0
function callCalculator(form) {
if (already==0) {
   already = 1  //...only need to open this window once
newWindow=window.open("http://www.netscape.com/comprod/products/
 navigator/version_2.0/script/calc.html")
}
}
</SCRIPT></HEAD>
<BODY><FORM>
<P>Demonstrates <I>onFocus</I> event.  As soon as you put click on the
SELECT element, then a calculator pops up.</P>
<P><B>Railroad track is ordered for three sections of track.  The first is 15
miles long.  The second is 23 miles long and the third is 6 miles long. How many miles of
track needs to be ordered to complete construction?
</B></P>
<P><B>What is your answer:</B><BR>
<SELECT NAME="answer" onFocus="callCalculator(this.form)" 
    onBlur="giveAnswer(this.form)">
   <OPTION VALUE="21">21
   <OPTION VALUE="29">29
   <OPTION VALUE="88">88
</SELECT>
</FORM></BODY>
</HTML>

Dynamically Change the Selection, Not the Text

Unlike its textbox cousins, TEXT and TEXTAREA, your code cannot change the text displayed in the SELECT list. Although your viewer may have chosen Canada as the country, your code cannot substitute the name of the provinces for the names of the states as the text displayed by the options.

However, your code can dynamically change the selection made. The selected property reflects the selection status of an option. You can set selected which immediately changes the selection displayed on the browser display. You can see how this works by using radio buttons to change a SELECT list dynamically (see listing 7.17 and fig. 7.11).

Figure 7.11: You can really confuse your users by having one form element change another. Be sure to think through your design.


Listing 7.17  dinner.htm  Pizza for Dinner Using SELECTED Property

<HTML><HEAD><TITLE>dinner.htm by Red Daly</TITLE></HEAD>
<BODY><FORM>
<P>Demonstrates <I>selected</I> property.  See what you can afford for
dinner.  Click on the radio button for a dollar amount and show your dinner in the select
box..</P>
<P><B>How much money do you have for dinner?</B><BR>
<INPUT TYPE="radio" NAME="a"
onClick="this.form.meal.options[0].selected=1">$10<BR>
<INPUT TYPE="radio"
NAME="a"onClick="this.form.meal.options[1].selected=1">$15<BR>
<INPUT TYPE="radio"
NAME="a"onClick="this.form.meal.options[2].selected=1">$20<BR></P>
<B>Your dinner tonite is:</B><BR>
<SELECT NAME="meal" >
<OPTION VALUE="$10">Pizza
<OPTION VALUE="$15">Extra Cheese Pizza
<OPTION VALUE="$20">Extra Veggies Pizza
</SELECT>
</FORM></BODY>
</HTML>

CAUTION
With text boxes, the information displayed in the box is the value property. With select, the value property is not displayed. This is like radio buttons and checkboxes. So don't change the value property of select and expect the display to change.

Example: An Application Using Advanced Navigation

This example is designed to explain the concepts discussed in this chapter. There are several suggestions on how you can make them more robust, but the key is
the explanation. You will see how links, as well as anchors, can be dynamic. The select is also used.

Internet Tri-Eye is truly a kaleidoscope on the Web. With a few clicks, you can see New York, Hollywood, and Pike's Peak; Hong Kong, the Antarctic, and the Netherlands; or fish, a cat, and some ants. It is a great way to demonstrate not only JavaScript, but also the Web.

The purpose of Internet Tri-Eye is to simultaneously display pictures from multiple cameras connected to the Internet. You select a set, say the U.S., International, or Animals. Then you click Show Picture to display one view of the world. Further information about each camera is also available.

Expand the View with Frames

Listing 7.18 shows the basic layout for the browser window. This layout is de-fined by the HTML page. The file is named trieye.htm and can be found on the CD-ROM. The window is divided into two frames with the top frame divided into three additional frames (see fig. 7.12).

Figure 7.12: The basic frames for Internet Tri-Eye are resizable so the user can change their shape to match their screen size.

NOTE
Internet Tri-Eye is a JavaScript application that uses frames. As a result, the entire application consists of five files: trieye.htm, one.htm, two.htm, three.htm, and guide.htm. The code for the first four files is in listings 7.18, 7.19, 7.20, and 7.21. The last file, guide.htm, is developed as you work through this section. The completed application is available on the CD-ROM. You start the application by loading the file trieye.htm. 


Listing 7.18  trieye.htm  Frameset for Internet Tri-Eye Application

<HTML><HEAD><TITLE>Internet Tri-Eye</TITLE></HEAD>
<FRAMESET ROWS="*,200">
   <FRAMESET COLS="33%,34%, 33%">
      <FRAME SRC="one.htm" NAME="one">
      <FRAME SRC="two.htm" NAME="two">
      <FRAME SRC="three.htm" NAME="three">
   </FRAMESET>
   <FRAME SRC="guide.htm" NAME="guide">
<NOFRAMES>
<H1>Internet Tri-Eye</H1>
<P><B>Internet Tri-Eye</B> is a demonstration of several features of 
JavaScript.  To view and use this program you need a Javascript 
compatible browser like Netscape 2.0.
</NOFRAMES>
</FRAMESET>
</HTML>

The content of the top three frames, the eyes, are files one.htm, two.htm, and three.htm (see listings 7.19, 7.20, and 7.21). These are extremely small files that are only used when the application is first loaded.


Listing 7.19  one.htm  Initial Contents of Frame One for Tri-Eye

<HTML><HEAD></HEAD><BODY>
<H1>Eye One</H2>
</BODY></HTML>


Listing 7.20  two.htm  Initial Contents of Frame Two for Tri-Eye

<HTML><HEAD></HEAD><BODY>
<H1>Eye Two</H2>
</BODY></HTML>


Listing 7.21  three.htm  Initial Contents of Frame Three for Tri-Eye

<HTML><HEAD></HEAD><BODY>
<H1>Eye Tri</H2>
</BODY></HTML>

Files two.htm and three.htm are identical to the file one.htm except that the headline is changed to "Eye Two" and "Eye Three," respectively. The guts of Tri-Eye and all of the JavaScript code is found in the file guide.htm. This file contains the contents of the lower frame. As we progress in building the application, all of the changes are made to this file. So far, the four files, trieye.htm, one.htm, two.htm and three.htm, are complete.

TIP
Most people find it easier to write JavaScript after doing the layout. Do your frames, your tables, your controls, and even some windows; then write the code to pull it all together.

Objects for Tri-Eye

Now that we have the framework, the next step is to set up objects for each "eye" or camera. We start by defining an object called cam. The object has three properties: the description of the camera, the name for the anchor (more later), and the URL for the image. The code in guide.htm starts with the standard header, the SCRIPT tag, and then defines the cam object (see listing 7.22).


Listing 7.22  guide.htm  Start of the Coding for Tri-Eye

<HTML><HEAD><TITLE>Internet Tri-Eye by Ray Daly</TITLE></HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--
function cam (name, anchor, url) {
     this.name = name
     this. anchor = anchor
     this.url = url
}

Next, for each camera a new object is established. In this example, there are nine different cameras, so create nine different objects labeled cam1 to cam9 (see listing 7.23). You can add more if you like.


Listing 7.23  guide.htm  Setting Properties for Cam Objects for Tri-Eye

cam1 = new cam ("Hollywood, CA", "#Hollywood", "
http://
 hollywood.bhi.hollywood.ca.us:8000/pictures/image01.gif")
cam2 = new cam ("Pikes Pike, CO",  "#Pikes",
 "http://www.softronics.com/peak_cam/cam.jpg")
cam3 = new cam ("New York City, NY", "#New York City", 
 "http://www.metaverse.com/gate/images/empire.jpg")
cam4 = new cam ("Zandvoort, NE", "#Zandvoort", 
 "http://www.dataplace.nl//images/zandv-gr.jpg")
cam5 = new cam ("Hong Kong",  "#Hong Kong", 
 "http://www.hkstar.com/images/capture1.jpg")
cam6 = new cam (" Australian Antarctic",  "#Antartic", 
 "http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.gif")
cam7 = new cam ("Fishcam", "#Fishcam", 
 "http://www.netscape.com/fishcam/fishcam.gif")
cam8 = new cam ("Mojo - Cat",  "#Mojo", 
 "http://www.lowcomdom.com/mojo.gif")
cam9 = new cam ("Steve's Ant Farm", "#Ant Farm", 
 "http://sec.dgsys.com/images/zANTPIX/Untitled.jpeg")

We now have nine different objects. In order to make it easier to reference these objects, create another object called camset (see listing 7.24). From this object, an object called camindex is created. The first property in camindex is cam1, the second is cam2, etc. Thus, to get the contents of cam5, you reference the fifth element in camindex.


Listing 7.24  guide.htm  Putting Nine Objects into One for Tri-Eye

function camset (eye1, eye2, eye3, eye4, eye5, eye6, eye7, eye8, eye9 ) {
   this.eye1 = eye1
   this.eye2 = eye2
   this.eye3 = eye3
   this.eye4 = eye4
   this.eye5 = eye5
   this.eye6 = eye6
   this.eye7 = eye7
   this.eye8 = eye8
   this.eye9 = eye9
}
camindex = new camset (cam1, cam2, cam3, cam4, cam5, cam6, cam7, cam8, 

We do not need to create so many different objects, but this method seems more straightforward than the other options. If you are good with objects, have fun
minimizing.

The final two lines of the JavaScript for this section initialize two variables to one, as follows:

     var setnumber=1
     var camnumber=1
//-->
</SCRIPT>
</HEAD>

Controls  To make anything happen with Internet Tri-Eye, controls need to be added. So far, all we have in guide.htm is the JavaScript defining the objects. Now the HTML code is added for the controls (see listing 7.25).

To hold the controls, there is a table of three rows and three columns. Across the entire first row is a button and a select element. The button is very simple and labeled About. When you click it, an alert dialog box tells you about Internet Tri-Eye.

The next element in the top row is a SELECT box. Here you select which set of cameras you want to look at. The first three cameras are locations in the United States, the next three are international, and the last three are pets. When you make a selection, it sets the variable setnumber to 1 or 2 or 3.


Listing 7.25  guide.htm  Laying Out the Control Table for Tri-Eye

<BODY><FORM>
<TABLE BORDER="1" WIDTH="100%">
<TR>
   <TD ALIGN=CENTER COLSPAN=3>
      <A NAME="top">   
      <INPUT TYPE="button" NAME="aboutTE"  VALUE="About Tri-Eye"
 onClick="alert('Tri-Eye is a demo from the book:  JavaScript Special
  Edition')">
      <SELECT
         NAME="setselect"
          onBlur="setnumber=setselect.selectedIndex+1">
         <OPTION VALUE="US" SELECTED> U.S.
         <OPTION VALUE="World">World
         <OPTION VALUE="Pets">Pets
      </SELECT>
   </TD>
</TR><TR>
   <TD ALIGN=CENTER VALIGN=TOP WIDTH="33%">
<A HREF=" "onClick="this.href=findHREF(1)" " TARGET="one">Show picture  One </A>
        </TD>
          <TD ALIGN=CENTER VALIGN=TOP WIDTH="34%">
<A HREF=" "onClick="this.href=findHREF(2)" " TARGET="two">Show picture  Two</A>
   </TD>
   <TD ALIGN=CENTER VALIGN=TOP WIDTH="33%">
<A HREF=" "onClick="this.href=findHREF(3)" " TARGET="three">Show picture Tri</A>
   </TD>
</TR><TR>
    <TD ALIGN=CENTER>
      <A HREF=" "onClick="this.href=findHASH(1)" " NAME="Info1">-- Info 
     </TD>
     <TD ALIGN=CENTER>
      <A HREF=" "onClick="this.href=findHASH(2)" " NAME="Info1">-- Info 
     </TD>
     <TD ALIGN=CENTER>
      <A HREF=" "onClick="this.href=findHASH(2)" " NAME="Info1">-- Info 
     </TD></TR>
</TABLE>

The final two rows of controls are for demonstrating dynamic links and anchors.

Dynamic Links

The middle row of controls is for the dynamic links. When you press on these links, one picture from one camera is displayed. There is one control for each of the "eyes." The code we need pulls in the proper URL, given "eye" 1, 2, or 3, and is based on the set chosen with the SELECT box (see listing 7.26). These variables are camnumber and setnumber.


Listing 7.26  guide.htm  findHREF Function for Tri-Eye

function findHREF (eye) {
     // ...eye is 1, 2 or 3  -- the target frame
     indexnumber = (eye-1) +( 3 * (setnumber -1)
     //the value of indexnumber is between 0 and 8
     return camindex[indexnumber].url
}     //returns the url of the camera

This code is added between the SCRIPT tags in the header section. In most cases you will want to place functions in the header so they are loaded prior to the page be displayed. Once you have the URL, the code is fairly simple. When the hyperlink is clicked, the findHREF function is called. It returns the URL, and the href property is changed. The target for the URL is the appropriate "eye" frame. Change the href property to the URL. For "eye" 3, the code is:

<A HREF=" "onClick="this.href=findHREF(3)" " TARGET="three">Show  picture Tri</A>

For simplicity, the hyperlink text is "Show picture one" or "two" or "tri." To polish up the application, an icon could be used here.

Anchors to Complete the Story

So far, Internet Tri-Eye is already spectacular. It is a true kaleidoscope on the world. However, it does not tell us anything about these pictures. Anchors are used in two different ways to complete the story.

Anchors to the Reference Information  The final row of the controls is for information links. Press the text "-Info-" and the frame scrolls down to a description of the site. For this example, there is a short, three-line description with a link to the host site if you would like more information.

When the objects were created for this page, anchors were included. So the same technique that was used earlier for links is now used for anchors. The function has only a minor difference: it returns the anchor property.

function findHASH (eye) {
       // ...eye is 1, 2 or 3 - the target frame
       indexnumber = (eye-1) + ( 3 * (setnumber -1))
       return camindex[indexnumber].anchor
}

The control itself is also similar:

 <A HREF=" "onClick="this.href=findHASH(3)" " NAME="Info1">-- Info --

Anchors to Take You Back  Once you read the information on the picture, you probably want to go back to the controls. Notice that the title of each description is followed by a hyperlink labeled (top). What you may not have noticed is that there is no anchor with the name (top). Instead, (top) is the name of the About button. So press on (top), and the About button is at the top of the page.

<A HREF="#top">(top)</A> 

NOTE
This code completes the guide.htm file (see listing 7.27). All five files that make up this application are found on the CD-ROM. You start the application by loading trieye.htm. n


Listing 7.27  guide.htm  Anchor Section for Tri-Eye

<CENTER><H1>Tri-Eye Guide</H1></CENTER><DL><DT>
<A NAME="Hollywood">Hollywood, CA</A> <I>
<A HREF="#top">(top)</A></I></DT><DD>
Not your typical American street corner, this is
<A HREF="http://www.geocities.com/cgi-bin/main/BHI/look.html">Hollywood
and Vine from GeoCities</A>.  Just remember that &quot;nobody walks in
L.A.&quot;</DD><DT><A NAME="Pikes">Pikes Pike, CO</A><I>
<A HREF="#top">(top)</A> </I></DT><DD>
One of America's most famous mountains. 
<A HREF="http://www.softronics.com/peak_cam.html">Pikes Peak Cam from
Softronics</A> gives you the view from Colorado Springs.</DD>
<DT><A NAME="NYC">New York City, NY</A><I><A HREF="#top">(top)</A> </I></DT>
<DD>New York City's most famous building. 
<A HREF="http://www.metaverse.com/empire.html">Empire Cam from Metaverse</A>
has a view across part of the skyline.  Check the weather.</DD>
<DT><A NAME="Zandvoort">Zandvoort, the Netherlands</A>   
 <I><A HREF="#top">(top)</A></I></DT>
<DD>No close ups of the people on the beach.  This
<A HREF="http://www.dataplace.nl/dp/pages/foto.htm">Livecam from Dataplace</A>
points northwest across a traffic circle and up the beach.</DD>
<DT><A NAME="Hong">Hong Kong</A><I><A HREF="#top">(top)</A></I></DT>
<DD>Street scene that is colorful almost anytime.  The
<A HREF="http://www.hkstar.com/starcam.html">STARcam from HK Star  Internet Ltd.</A>
shows more cars than people.</DD>
<DT><A NAME="Antartic">Australian Antarctic</A>   |
 <I><A HREF="#top">(top)</A></I></DT>
<DD>While often black, some previous pictures are available. The
<A HREF="http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html">
camera at Mawson Station</A> 
captures the pictures and though a variety of technology gets it to your desk.</DD>
<DT><A NAME="Fishcam">Fishcam</A> 
<I><A HREF="#top">(top)</A></I></DT>
<DD>Perhaps the most famous fish in the world. 
<A HREF="http://www.netscape.com/fishcam/fishcam.html">
Fishcam from  Netscape</A>now has multiple cameras and formats.
Who ever imagined an aquarium as a revenue source?</DD>
<DT><A NAME="Mojo">Mojo</A><I>
<A HREF="#top">(top)</A></I></DT>
<DD>You won't believe the technology used to bring you these images.  
<A HREF="http://www.lowcomdom.com/mojo_cam.html">Mojo-Cam</A>
isn't from a fixed view so it worth following.</DD>
<DT><A NAME="Ant">Ant Farm</A><I>
<A HREF="#top">(top)</A></I></DT>
<DD>Some people won't even think that this is a safe distance away. 
<A HREF="http://sec.dgsys.com/AntFarm.html">Steve's Ant Farm</A>
also has a movie available.</DD></DL></FORM></BODY></HTML>

Now Internet Tri-Eye is complete.

Other Possible Improvements to and Uses of Internet Tri-Eye

Internet Tri-Eye was written to keep the code simple to explain, not dazzle you with graphics. The following are several suggestions for improving Tri-Eye or expanding its use:

Example: Tri-Eye FTP Auto Dialer

Trying to FTP a popular new piece of Internet software can be frustrating. You press on a link, and it seems like minutes before you're asked to try again later because the site is busy.

NOTE
Tri-Eye FTP Auto Dialer (see fig. 7.13) uses the same files as Internet Tri-Eye. The only change is to the guide.htm file. To start the application, load trieye.htm.

Figure 7.13: Tri-Eye FTP Auto Dialer looks rather bland when you start it up. The action comes from the user interacting.

You can create the Tri-Eye FTP Auto Dialer with a simple modification to one file of the Internet Tri-Eye application (see fig. 7.14). Simply change the values of the properties for each cam object in the guide.htm file. These properties are the URLs for the information displayed in each of the upper frames. For example, for Netscape's FTP site, use the Windows NT/95 version of Navigator 2.0:

Figure 7.14: Tri-Eye FTP Auto Dialer will make multiple attempts to make an FTP connection. This should increase your chances of success.

ftp://ftp2.netscape.com/2.0/windows/n32e20.exe

Do the same for each FTP location by just changing the host from ftp2 to ftp3, and so on; the last one is ftp10. The function looks nearly the same; only the contents of the properties have changed (see listing 7.28).


Listing 7.28  guide.htm  Redefined cam Object for Tri-Eye FTP Auto Dialer

function cam (name, anchor, url) {
   this.name = name
   this.anchor = anchor
   this.url = url
}
cam1 = new cam ("FTP2", "#Netscape FTP", "ftp://ftp2.netscape.com/2.0/ windows/n32e20.exe")
cam2 = new cam ("FTP3", "#Netscape FTP", "ftp://ftp3.netscape.com/2.0/ windows/n32e20.exe")
cam3 = new cam ("FTP4", "#Netscape FTP", "ftp://ftp4.netscape.com/2.0/ windows/n32e20.exe")
cam4 = new cam ("FTP5", "#Netscape FTP", "ftp://ftp5.netscape.com/2.0/ windows/n32e20.exe")
cam5 = new cam ("FTP6", "#Netscape FTP"," ftp://ftp6.netscape.com/2.0/ windows/n32e20.exe")
cam6 = new cam ("FTP7", "#Netscape FTP", "ftp://ftp7.netscape.com/2.0/ windows/n32e20.exe")
cam7 = new cam ("FTP8", "#Netscape FTP", "ftp://ftp8.netscape.com/2.0/ windows/n32e20.exe")
cam8 = new cam ("FTP9", "#Netscape FTP", "ftp://ftp9.netscape.com/2.0/ windows/n32e20.exe")
cam9 = new cam ("FTP10", "#Netscape FTP","ftp://ftp10.netscape.com/2.0/ windows/n32e20.exe")