This chapter describes the creation of dynamic documents and windows, as well as the interaction between windows and their components. This chapter presumes that you now have a working knowledge of JScript syntax; the material covered is somewhat more complex than in earlier chapters (see Chapter 4 "JScript Objects").
The first theme of the chapter is the creation of pop-up windows. The entire content of those windows is defined by a creation function, rather than an URL. We will examine various examples, including pop-ups with text, pop-ups with buttons, and editable pop-ups.
We will next examine the history, status, and location objects. You will see how to hurl the user to a specific URL on the history list, how to examine the various parts of the location object, and how to store and retrieve information using the search property of the location object. Finally, you will learn how to create dynamic documents. In fact, you will create a page entirely from JScript. You will also learn how to rewrite pages on-the-fly.
You have already learned a lot about objects in JScript. In fact, the previous four chapters have been devoted to exploring the various JScript objects and their uses. You have already been exposed to the various built-in objects and HTML objects that JScript provides. To go further and explore dynamic HTML creation, we must first take a closer look at the hierarchy of objects in JScript.
If you are familiar with any object-oriented languages, you expect an object hierarchy to begin with a generic object from which all other objects are descendants or children. Unfortunately, the JScript object hierarchy does not really follow this model. It might be best described as a system of ownership, and, even then, the analogy is not really exact. For example, a window that creates another window could be thought of as the parent of the new window. However, if you try to refer to the original window from the child by saying parent.someobject, it may not work.
On the other hand, frames within a frameset have a parent-child relationship with the original window, and asking for parent.someobject will likely yield the object. Other ownership relationships are not characterized by a parent-child relationship at all. For example, form elements belong to a form, but to obtain the form, you use this.form-not this.parent. With these disconcerting thoughts in mind, let's attempt to sort out the dependencies among browser objects.
The browser is, in a way, the parent of all other JScript objects. It is the executable that runs the browser. The browser is responsible for the creation of all browser windows. It is also responsible for responding to general window events. The browser is not a visual object. You cannot see it. You interact with it only through its visual constructs: its windows.
Most browser window components can be manipulated only in a yes/no fashion at the time of window creation. These include the menu, the button bar, the location display, the status display, history list display, and scroll bars. At the time of window creation, you can also determine whether the window can be resized, as well as finding its dimensions.
This might seem like a significant restriction. By
rewriting the document, however, you can change the contents of
a window. This technique enables you to change the values of form
elements, the content of the status bar, the position of the pointer
in the history list, and the location (the URL that the window
contains) at any time. Table 8.1 lists these various elements,
when they can be modified, and how they can be modified. Note
that the last two items in this table are not really window elements:
They control what is displayed, but are not explicitly displayed
themselves.
Object | When | ||
Button bar | Window creation | ||
Menu | Window creation | ||
Location display | Window creation | ||
Status Bar | Window creation | ||
History | Window creation | ||
Document | During rewrite | ||
Many form element properties | Anytime | ||
Status bar content | Anytime | ||
Location | Anytime | ||
History list | Anytime |
One of the more advanced projects later in this book
is the creation of a sticky notes application (in the "Dynamic
Documents" section). To do that, you need to have a small
note window in which to present the note. Let's create a primordial
note window now. To do that, you must already have a window open
with an element that enables you to call a JScript function (such
as a button with an onClick
handler). This base window is the parent of the child note window.
The child can always find its parent with self.parent,
but the parent can refer to the child only by its name. There
is no self.child[]
reference, nor is there a windows
array available to JScript because of security concerns.
Caution |
Internet Explorer is a mimic. If you create a window under a JScript control, the next window that is created by IE will have the same dimensions as the last window created by JScript. |
The element that we will use is an image that behaves as a button, which is triggered by an HREF=javascript: :myfunc included in the LINK tag. This works very well if you need to call only one function and you need no return value. When you try to use this mechanism in a window constructed on-the-fly, however, the image refuses to display. In fact, any image that uses relative addressing refuses to display in a dynamic window.
The solution is either to use a completely static reference for the image or to set the base directory of your page with <BASE>path</BASE> in the header. This latter approach helps JScript find the image. If you need an object that will be accessed later, you might want to use a form input element, rather than one of these button images. JScript will have less trouble finding it.
The following three steps are necessary to use an image as a button for executing a JScript function:
These three steps are shown in Listing 8.1.
Listing 8.1 Creating a Button Image
<IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE= 2 ALIGN=LEFT SRC="Images/gobtn.gif" BORDER=0> <A HREF='xxxxxx'><IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE=2 ALIGN=LEFT SRC="Images/gobtn.gif" BORDER=0><A> <A HREF='javascript: openNote'><IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE= 2 ALIGN=LEFT SRC="Images/gobtn.gif" BORDER=0><A>
The function used in this example is the openNote() function, the source for which is given in Listing 8.2. Before we plunge into this code, it is worthwhile to notice that the border has explicitly been set to zero. This is the only way you can keep the browser from drawing a border around your image if it is within a reference statement. Listing 8.2 contains the HTML for the base window with the button that creates a note. It includes the openNotes() function in a header script. Once you open a note window, make sure you close it before it gets lost. Internet Explorer will not open a second window by the same name; it just updates the first one. When this code is executed by pressing the Make Note button, you will see something like Figure 8.1.
Listing 8.2 Creating a New Window in Jscript
<HTML> <HEAD> <TITLE>Opening a Window with JScript</TITLE> <SCRIPT> //window globals var aNoteWin function openNote(topic) { aPopUp= window.open('','Note','toobar=no,location=no, directories=no,status=no,scrollbars=yes,resizable=yes, copyhistory=no,width=300,height=200') ndoc= aPopUp.document astr ='<HTML><HEAD><BR><TITLE>' + topic + '</TITLE>' astr +='</HEAD>' astr +='<BODY>' astr +=topic + '<BR>' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() self.aNoteWin = aPopUp } function closeNote(which) { self.aNoteWin.close() } </SCRIPT> </HEAD> <BODY> <H3><BR><HR><BR></H3> <CENTER> <FONT SIZE=5 COLOR='darkred'><B>Example 1</B></FONT>: <FONT SIZE=5 COLOR='darkblue'><B>Opening a New Window</B></FONT> <FORM NAME='noteForm'> <INPUT TYPE='button' NAME='makeBtn' VALUE='Make Note' onclick='openNote("JoAnn Murphy at 7:00; bring salad")'> <INPUT TYPE='button' NAME='closeBtn' VALUE='Close note' onclick='closeNote()'> </FORM> </CENTER> <H3><BR><HR><BR></H3> </BODY> </HTML>
Caution |
In a windows.open statement, there are three things to bear in mind.
|
Figure 8.1 : Dynamically created windows may be tied to button events in JScript.
This small script illustrates several points. First, you can set a window global by defining it outside of any function and preceding it with var. Here, we set the window global aNoteWin with var aNoteWin. This variable is global, so you could use it to refer to aNoteWin in other functions. Although we did not do so here, you might want to save a number of notes in an array. Second, when you create a window de novo via a script, and no URL is specified, the window document is still open, and you can write to it. Here we wrote the note topic and then closed the document.
A window that you create can be as simple as the
note window. However, you can also make this window quite complex.
In order to do so, you must write everything to the document,
including form elements, images, and JScript functions, before
you close it. Listing 8.3 shows a second version of the openNote()
function. This more elaborate version furnishes the note window
with two buttons, including onClick
handlers, the topic text, a warning message, and two JScript functions.
It may be found in the file C8-1.htm on the CD-ROM. Note that
the save
function is stubbed. The topic of data storage is discussed in
Chapter 17, "Using Frames and Cookies." All the display
elements are neatly wrapped in a table.
Data can be stored transiently in the location.search property and persisently in cookies; both topics are discussed in the "Persistent Data Storage" section of Chapter 17, "Using Frames and Cookies." |
Listing 8.3 C8-1.htm-A More Sophisticated Notes Window
function openNote(topic) { aPopUp= window.open('','Note','toobar=no,location=no, directories=no,status=no,scrollbars=yes,resizable=yes, copyhistory=no,width=300,height=200') ndoc= aPopUp.document astr ='<HTML><HEAD><TITLE>' + topic + '</TITLE>' astr +='<SCRIPT>' astr +='function closeNote(aName){' astr +='self.close()' astr +='}' astr +='function saveNote(aName){' astr +='}' astr +='<\/SCRIPT>' astr +='</HEAD>' astr +='<BODY>' astr +='<FORM>' astr +='<TABLE ALIGN=LEFT BORDER><TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE=button NAME=saveBtn VALUE="Save" ONCLICK="saveNote()">' astr +='</TD>' astr +='<TD ROWSPAN=4>' + topic astr +='</TD>' astr +='</TR><TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE=button NAME=closeBtn VALUE="Close" ONCLICK="closeNote()">' astr +='</TD></TR>' astr +='<TR><TD><BR></TD></TR>' astr +='<TR><TD><BR></TD></TR>' astr +='</TABLE>' astr +='</FORM>' astr +='<BR CLEAR=ALL><H3><BR></H3>' astr +='Note: Save button is not active yet' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() self.aNoteWin = aPopUp }
Internet Explorer keeps you apprised of which link or button your mouse pointer is over via its status bar. Occasionally, it sends you other messages via that method, too. Perhaps you have seen it busily scrolling text to catch your attention. The status (not the status bar itself) is a property of a window and is accessible to you as self.status = 'Some message'. When you change the status, the browser immediately displays it in the status bar. You can also set a property called defaultStatus, which is the default message displayed in the status bar. Listing 8.4 illustrates the use of the status property in Internet Explorer. This code will be found in the file c8-2.htm on the CD-ROM.
Listing 8.4 c8-2.htm-Manipulating the Status Bar
<HTML> <HEAD> <TITLE>Manipulating the Status Bar</TITLE> <SCRIPT> // set up a window global so that the new window can be accessed // from all functions. var aStatWin = null function openStatus(defmsg,msg) { aStatWin=window.open('','statWin','toobar=no,location=no, directories=no,status=yes,scrollbars=no,resizable=yes, copyhistory=no,width=550,height=2') if (aStatWin != null) { aStatWin.document.write('<FORM NAME="dform"> <INPUT TYPE=TEXT NAME="dummy"></FORM>') aStatWin.document.close() aStatWin.defaultStatus = defmsg aStatWin.status = msg setFocus() } } function setStatus() { if ( self.aStatWin == null ) alert('Status window is closed!') else { self.aStatWin.status = document.statForm.statMsg.value setFocus() } } function setFocus() { self.aStatWin.document.dform.dummy.focus() } function myclose() { self.aStatWin.close() aStatWin = null } //This function is a work-around to make sure that the table // overlay is drawn correctly. function fixup() { blankWin=window.open('','blankWin','toobar=no,location=no, ¬ directories=no,status=yes,scrollbars=no,resizable=no, ¬ copyhistory=no,width=600,height=450') blankWin.close() } </SCRIPT> </HEAD> <!-- fixup forces redraw of window after everything, including images, has loaded. The redraw is necessary to enforce correct drawing of table overlays. --> <BODY onLoad='fixup()'> <H3><BR><HR><BR></H3> <CENTER> <FONT SIZE=5 COLOR='darkred'><B>Example: </B></FONT> <FONT SIZE=5 COLOR='darkblue'><B>Setting the Contents of the Status Bar</B></FONT> <H3><BR><HR><BR></H3> <H3><BR></H3> </CENTER> <CENTER> <FORM NAME='statForm'> <TABLE WIDTH=520 ALIGN=CENTER BORDER><TR ALIGN=CENTER><TD> <TABLE WIDTH=500 ALIGN=CENTER> <TR ALIGN=CENTER> <TD WIDTH=35 ALIGN=CENTER> <IMG WIDTH=48 HEIGHT=50 VSPACE=2 HSPACE= 2 ALIGN=CENTER SRC="Images/gotray2.gif"> </TD> <TD> <!-- <INPUT TYPE=button VALUE='Make Status Window' onClick='openStatus("Status is GO!", document.statForm.statMsg.value)'> --> <A HREF='javascript: openStatus("Status is GO!", document.statForm.statMsg.value)'> <IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE=2 ALIGN=absMiddle SRC="Images/gobtn1.gif" BORDER=0> Open Status Window</A> </TD> <TD ALIGN=LEFT > <A HREF='javascript: setStatus()'> <IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE=2 ALIGN=absMiddle SRC="Images/gobtn2.gif" BORDER=0> Set Status</A> </TD> <TD ALIGN=CENTER > <A HREF= 'javascript: myclose()'> <IMG WIDTH=31 HEIGHT=30 VSPACE=2 HSPACE= 2 ALIGN=absMiddle BORDER=0 SRC="Images/okbtn.gif"> Close Status </A> </TD> </TR> <TR ALIGN=CENTER> <TD ALIGN=CENTER COLSPAN=4> Msg <INPUT TYPE=text NAME='statMsg' VALUE='Howdy!' SIZE= 50 MAXLENGTH=80> </TD> </TR> </TABLE> </TD></TR></TABLE> </FORM> </CENTER> <H3><BR></H3> </BODY> </HTML>
This example builds a window with a status bar included. Just to make things interesting, we'll set the content of the status bar from the parent window. In addition, this script provides an example of the advanced HTML concept of table overlays, and an onLoad() handler, which provides a workaround for the browser's unpredictable order of drawing images. We will say a little more about table overlays below, when we discuss the fixup() function.
The status window is created with a 'javascript: openStatus(defMsg,msg)' link attached to an image. This function, openStatus(defMsg, msg), performs the following tasks:
We will set the status of the status window with a call to setStatus(). This call is made from a 'javascript: setStatus(document.statForm.statMsg.value)' link attached to an image.
The setStatus() function also checks to see whether aStatWin exists before it tries to address one of its objects. If aStatWin does exist, setStatus changes the content of its status bar. setStatus() then sets the focus on the dummy button in aStatWin to bring the window to the front. This is done by a call to the setFocus() method. The resulting window is shown in Figure 8.2. When you are done with the window, you can close it using an image button linked with a call to close function myclose(). The myclose() function simply closes aStatWin and makes sure that its value is reset to null. Note that it would have been unpleasant if we had named the close function simply close(). This is because there is a built-in window function called close. If we had named our function close(), JScript would not have complained, but when we clicked the Close button, the built-in close() function would have been called, not ours.
Figure 8.2: A status bar window may be created dynamically by the parent window.
The function fixup() is worth looking at in more detail. The order in which the browser draws images depends upon where the images are coming from, whether they are in the cache, and whether their height and width are given explicitly. It can also depend on the size of the images. Extremely attractive presentations can be made by overlaying text and graphics on other graphics via the overlay feature of HTML tables.
However, Internet Explorer will often draw your bottom
image last when the page first loads. Scrolling the screen causes
the correct redraw, but you cannot expect or require your users
to do that. One way to force the redraw is to open and quickly
close another window over your page. You need to do this after
all of the page elements have been loaded. When this occurs,
the browser sends an onLoad
event, which you can capture in the <BODY>
tag. The fixup()
function ensures that all of the image
buttons are visible. Although this is far from an ideal solution,
it is effective.
Tip |
Always check that a newly created window exists before you try to address its properties or methods. Do this by checking to see whether the window is null. If it is null, use an alert to inform the user. |
The location object essentially holds information about the URL to which the browser points. The browser reads this marked-up text from the server's disk and interprets it just as Microsoft Word reads and interprets a file on your disk. In addition to the URL, the location object also contains any post parameters of an HTML form submitted via a Submit button or your call to submit(). Because of this, you can use the location object for temporary storage. In Internet Explorer, the location consists of the following parts:
protocol//hostname: (port) pathname search hash
Protocol is the type of protocol used for this file. Examples are http, ftp, gopher, telnet, and file (for files on the local disk). Hostname and port are valid only when the document is on a remote server. They contain the domain name/IP address of the server and the server port, respectively. The Web port is a number denoting the type of service, and is usually 80 for http. The pathname is the path to the file that the browser displays. search includes any post parameters that are compiled when a form is submitted. hash is usually a link to a local anchor.
The location object also has a host property, which consists of the combination of hostname and port. The location object also has an extremely important property, known as href, which contains the entire URL.
Finding Out Where You Are. This next example is a page that has no body. It is written entirely by the header script. As the page is written, it dissects the location object and lists all of its properties in a table. The host, port, and hostname properties will be nonempty only if you have loaded some page from a server. Listing 8.5 shows the code for the Location Display script. This code is in the file c8-3.htm on the CD-ROM.
Listing 8.5 c8-3.htm-Displaying the Properties of the Location Object
<HTML> <HEAD> <!- Created 08 Feb 1996 a2:41 PM 02:41 PM --> <TITLE>Parts of the Location Object</TITLE> <SCRIPT> var aline = '<H3><BR></H3><HR><H3><BR></H3>' var skip='<H3><BR></H3>' document.write('<CENTER>') document.write('<FONT SIZE=5 COLOR="darkred"><B>Example: </B></FONT> <FONT SIZE=5 COLOR="darkblue"> ¬ <B>What\'s in the Location Object?</B></FONT>') document.write('<BR>') document.write('<BLOCKQUOTE><BLOCKQUOTE>If you are viewing this document from your hard disk, host, hostname, and port will be empty.</BLOCKQUOTE></BLOCKQUOTE>') document.write('<BR>') document.write('<CENTER><TABLE ALIGN= CENTER BORDER CELLPADDING=3>') document.write('<TR><TD><B>Property</B></TD><TD ALIGN=CENTER> <B>Value</B></TD></TR>') document.write('<TR><TD>href</TD><TD>' + location.href + '</TD></TR>') document.write('<TR><TD>protocol</TD><TD>' + location.protocol + '</TD></TR>') document.write('<TR><TD>hostname</TD><TD>' + location.hostname + '</TD></TR>') document.write('<TR><TD>host</TD><TD>' + location.host + '</TD></TR>') document.write('<TR><TD>port</TD><TD>' + location.port + '</TD></TR>') document.write('<TR><TD>pathname</TD><TD>' + location.pathname + '</TD></TR>') document.write('<TR><TD>search</TD><TD>' + location.search + '</TD></TR>') document.write('<TR><TD>hash</TD><TD>' + location.hash + '</TD></TR>') document.write('</TABLE></CENTER>') document.write(aline) document.write('<CENTER>') document.write(aline) </SCRIPT> </HEAD> </HTML>
Sending the User Elsewhere. Not only can you obtain useful information by examining the location object, you can also modify it and send the user elsewhere. This is useful if you should want to dynamically generate an URL or a reference to an anchor. The example shown in Listing 8.6 builds an URL dynamically and sends the current browser to that URL. This code implements a "Message Center," which retrieves messages from URLs created via button clicks. Four users have been created to demonstrate this aspect of the location object. The CD-ROM file c8-4.htm contains this message center code.
Listing 8.6 c8-4.htm-Modifying the Current URL Dynamically
<HEAD> <!- Created 08 Feb 1996 a4:08 PM 04:08 PM --> <TITLE>Message Center</TITLE> <SCRIPT> function getMessage(who) { loc = self.location nloc = "" + lock = nloc.lastIndexOf('\\') nnloc = nloc.substring(0,k+1) + who.value + '.htm' self.location = nnloc } </SCRIPT> </HEAD> <BODY> <CENTER><HR> <FONT SIZE=5 COLOR='darkred'><B>Example 4</B></FONT>: <FONT SIZE=5 COLOR='darkblue'><B>Moving Around Dynamically</B></FONT><BR> <HR><FONT SIZE=6 COLOR='darkslateblue'><B>Message Center</B></FONT><BR> </CENTER> <CENTER> <FORM> <TABLE BORDER ALIGN=CENTER><TR><TD> <INPUT TYPE=radio NAME='getMsgR' VALUE='John' onClick='getMessage(this)'>John <INPUT TYPE=radio NAME='getMsgR' VALUE='George' onClick='getMessage(this)'>George <INPUT TYPE=radio NAME='getMsgR' VALUE='Ken' onClick='getMessage(this)'>Ken <INPUT TYPE=radio NAME='getMsgR' VALUE='Julie' onClick='getMessage(this)'>Julie <INPUT TYPE=hidden NAME='translate' VALUE=''> </TD></TR></TABLE> </FORM> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>
The script works by first obtaining the current location. It then
strips off the file name and replaces it with the value of the
option button clicked. It also makes sure to tack on the suffix
.HTM. This presumes
that the message HTML files are in the same directory as the current
page. However, it would be easy enough to build in a subdirectory
name just for the messages, or even have a separate subdirectory
for each person. The location
object is then set to the newly constructed URL. Setting the location
object retrieves the file at that location. In our example, this
file represents the set of messages for the particular user whose
button was pressed.
Tip |
You can force a page to be reloaded by setting the location object to the URL corresponding to that page. |
Using the Search Property. When you submit a form, all the values of the various form elements are retrieved, parsed, and concatenated with the location object; they are placed after the path and preceded by question marks (?). The value of location.search is precisely that string, including the question mark (?).
This string is not just a simple list of element contents, however.
Each element value is placed in the string in the form 'elementName=elementValue'
and followed by an ampersand (&). Any nonalphanumeric characters
are coded or escaped. The ASCII value of any such character is
changed into a two-digit hex number preceded by a percent sign
(%). If text field or textarea
elements have multiple words, these words are separated by a plus
sign (+). Consequently, when you get the location.search
string, you have to decode it to get the various form elements
that it contains.
The section on "Global and Local Variables" in Chapter 9 "Creating Your Own JScript Objects," discusses character encoding in more detail. |
You can place your own form element values, or anything else,
in the location's search
property. As long as you precede it with a question mark (?),
location.search
will retrieve it. However, not all nonalphanumeric characters
can be placed in the string or retrieved intact. If you are going
to concoct a homegrown search string, you may need either to encode
the parameters yourself or not allow nonalphanumeric characters.
Listing 8.7 is a simple page that shows you how to manipulate
location.search.
Note |
The current release of Internet Explorer severely limits the uses of the location.search property. In most cases, it will be empty on document reload. |
Listing 8.7 Using the Search Property of the Location Object
<HTML> <HEAD> <!- Created 08 Feb 1996 a6:10 PM 06:10 PM --> <TITLE>Forcing a Reload with Location</TITLE> <SCRIPT> function reloadMe() { astr = document.nameForm.myName.value nastr= self.location.pathname + '?' + astr self.location = nastr } function clearUp() { self.location = self.location.pathname } if (self.location.search != null && self.location.search !='') { document.write('<CENTER><FONT SIZE=4 COLOR="darkslategray"><B> Form Entry Data: </B></FONT></CENTER>') document.write('<CENTER><FONT SIZE=4 COLOR="red"><B>' + self.location.search + '</B></FONT></CENTER>') } </SCRIPT> </HEAD> <H3><HR></H3> <CENTER><FONT SIZE=6 COLOR="blue"><B>Forcing a Reload with ¬ Location</B></FONT></CENTER> <H3><BR><HR><BR></H3> <CENTER> <FORM NAME=nameForm> <INPUT TYPE=text NAME=myName VALUE='abracadabra&#^$()'> <INPUT TYPE=button NAME=reloadBtn VALUE='Reload Page' onClick='reloadMe()'> <INPUT TYPE=button NAME=submitBtn VALUE= 'Submit Form' onClick='this.form.submit()'> <INPUT TYPE=button NAME=clearBtn VALUE= 'Clear' onClick='clearUp()'> <INPUT TYPE=hidden NAME=hideFld> </FORM> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>
A script in the <HEAD> part of an HTML document can pick up the command-line parameters with location.search and write something to the document being loaded based on what it finds. This example just reads the parameter string and writes it for you at the head of the page. Note that this write is guarded by a test to see whether location.search is null or empty. If location.search is not a valid string, and you attempt to parse it into variables that are used later, you will encounter error after error. Always test for a null string or an empty string.
The code in Listing 8.7 has two useful functions. ClearUp() simply strips the search string from the location by setting the location object to location.path. The reloadMe() function takes the value from the text box and adds it to location.path. It then sets the location to that result.
The history object is a list that contains the locations of all the URLs that you have visited. You can move backward and forward through the history list with history.back and history.forward. You can also move around in the list in a relative fashion with history.go(). This function takes a positive or negative integer argument and moves you that many URLs forward or backward in the history list. The only property of a history list you can access is its length, which is the number of items in the list. You can neither set nor retrieve history list items.
To show how to manipulate the history list, we'll build another pop-up window that boasts only a Close button and four directional buttons. The buttons enable you to manipulate the history list of the parent window. You can move backward and forward by one step or five. This code is shown in Listing 8.8, and will be found in the file c8-5.htm on the CD-ROM.
Listing 8.8 c8-5.htm-Using the History Object in a Pop-Up Window
<HTML> <HEAD> <!- Created 08 Feb 1996 a9:21 PM 09:21 PM --> <TITLE>Running through the History List</TITLE> <SCRIPT> var aNoteWin var creat function openPopup() { aPopUp= window.open('','Note','toobar=no,location=no, directories=no,status=no,scrollbars=no,resizable=no, copyhistory=no,width=110,height=150') ndoc= aPopUp.document astr ='<HTML><HEAD><TITLE>Window Scroller</TITLE>' astr +='<SCRIPT>' astr +='var creat\n' astr +='function closeNote(aName){' astr +='self.close()' astr +='}\n' astr +='function saveNote(aName){' astr +='}\n' astr +='function goNext(){' astr +='creat.window.history.forward()\n' astr +='}\n' astr +='function goBack(){' astr +='creat.window.history.back()\n' astr +='}\n' astr +='function goBackFive(){' astr += 'creat.window.history.go(-5)\n' astr +='}\n' astr +='function goNextFive(){' astr +='creat.window.history.go(5)\n' astr +='}\n' astr +='<\/SCRIPT>' astr +='</HEAD>' astr ='<BODY>' astr +='<FORM NAME="popForm">' astr +='<TABLE ALIGN=LEFT BORDER>' astr +='</TR><TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE=button NAME="closeBtn" VALUE="Close" ONCLICK="closePopUp()">' astr +='</TD>' astr +='</TR>' astr +='<TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE="button" NAME="startBtn" VALUE="<<" onclick="goBackFive()">' astr +='<INPUT TYPE="button" NAME="backBtn" VALUE="<" onclick="goBack()">' astr +='<INPUT TYPE="button" NAME="nextBtn" VALUE=">" onclick="goNext()">' astr +='<INPUT TYPE="button" NAME="endBtn" VALUE=">>" onclick="goNextFive()">' astr +='</TD></TR>' astr +='<TR><TD>' astr +='<INPUT TYPE="hidden" NAME="IAm" VALUE="0">' astr +='</TD></TR>' astr +='</TABLE>' astr +='</FORM>' astr +='<BR CLEAR=ALL><H3><BR></H3>' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() self.aNoteWin = aPopUp aPopUp.creat = self } function closePopUp() { if ( self.aNoteWin != null ) self.aNoteWin.close() } </SCRIPT> </HEAD> <BODY > <CENTER> <FONT SIZE=5 COLOR='darkred'><B>Example 5</B></FONT>: <FONT SIZE=5 COLOR='darkblue'><B>Running through the History List </B></FONT> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR><BR></H3> <CENTER> <FORM NAME='noteForm'> <INPUT TYPE='button' NAME='makeBtn' VALUE='Make Popup' onClick='openPopUp()'> <INPUT TYPE='button' NAME='closeBtn' VALUE='Close Popup' onclick='closePopUp()'> </FORM> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>
This pop-up is a variation on our old friend, aNoteWin. It can access its parent's variables through an artificial property of aNoteWin, the creat property, which we carefully write into the child's window as a var, using with the astr += 'var creat\n' statement. At the end of the openNote() function, which creates and draws the window, aNoteWin.creat is set to self. This enables you to have ready access to the parent window's variables, functions, and objects.
Although it would be useful to retrieve history list items, this functionality has been removed from JScript. Unfortunately, each history list entry contains the entire location, including the search string. If this information could be retrieved, the possibility exists that credit card or other personal information might be gleaned by malicious individ-uals.
You may have wondered why there is no windows array. This also does not exist in JScript for security reasons. If it did, a script from one window might reach into another unrelated window and scavenge information from its form elements or its location object. Again, what might be perceived as a limitation in JScript has been imposed to protect you.
The document object encapsulates all JScript objects that correspond to the HTML elements. It is the parent of forms, links, and anchors. These objects occur as arrays and are accessed as document.forms[xx], document.links[xx], and document.anchors[xx], where xx is an array index. The document object also has several other useful properties. It has a property, for example, for all of the standard object colors, such as the background color, text color, and link colors. You cannot change the property of a static closed document, however, so these properties are useful only when building a document.
Four properties that are useful in keeping your documents up to date are the location, title, lastModified, and referrer properties. These are used to dynamically write a header or a footer for your documents. Listing 8.9 shows a typical example of how you could use the document object in this way. Note that the properties of the document object are read-only. The attempt to set document.title in this listing will fail. If you want to load this example, you must comment out that line.
Listing 8.9 Writing the Document Header
<HTML> <HEAD> <!- Created 08 Feb 1996 a11:32 PM 11:32 PM --> <TITLE>Writing a Document Header</TITLE> <SCRIPT> document.bgcolor = 'linen' document.text = 'darkslateblue' document.link = 'coral' document.vlink='peach' document.alink='red' document.title='Dynamic Headers' // comment me out document.write('<TABLE ALIGN=RIGHT WIDTH=300 BORDER=1>') document.write('<TR><TD>') document.write('<FONT SIZE=7 COLOR= "navy">') document.write('<CENTER>' +document.title + '</CENTER>') document.write('</TD></TR></TABLE>') document.write('<CENTER><B>') document.write('<HR>') document.write('This document was last modified on<BR> <FONT COLOR="red">' + document.lastmodified + '</FONT><BR>') document.write('Save this URL: <BR><FONT COLOR="red">' + document.location + '</FONT><BR>') document.write('You arrived here from <BR><FONT COLOR="red">' + document.referrer + '</FONT><BR>') document.write('<BR><HR><BR>') document.write('</B></CENTER>') document.write('') </SCRIPT> </HEAD> <BODY> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>
Forms. You can get input from your users via HTML
form elements (sometimes known as widgets). You can have many
forms on a page. If they are named (by an HTML NAME directive),
you can refer to them by name. You can also refer to a form by
its index into the zero-based forms array. Each form can have
any one of the standard HTML form elements. These include single-line
text, radio, checkbox, hidden, password, reset, and submit. There
is also a select widget, which can be either a drop-down list
or a plain list, and a textarea widget, which can be used to collect
large amounts of text spanning multiple lines.
The section on "Using JScript Event Handlers" in Chapter 3 "Events and JScript," talks about the correspondence between HTML form elements, the events that they generate, and their JScript counterparts. |
Tip |
A script can access only elements that have already been created. They cannot be accessed in a document <HEAD> because the forms and their elements do not yet exist. |
Links. Links are the bread and butter of any hypertext system, especially HTML. In JScript, the links array can be canvassed in order to provide a list of links in a document. Links have only one property-the target. The target is not the URL pointed to by the link; rather, it is the window into which that URL will be loaded. Any link is also a location object, so that you can dissect the link in the same way you dissect a location object.
Links can have an onClick
handler just as buttons do. However, when the onClick
handler finishes, the URL specified by the link will be loaded.
If you do not want the link to go anywhere, just specify the current
URL as its destination. If you want to use a link to execute a
function, use HREF= 'javascript:
myfunc()'. Myfunc()
can call a function or contain JScript code. For example, HREF='javascript:
self.close()', immediately closes the
current window.
Caution |
A javascript:xxx() call replaces an URL. The browser will try to interpret any return from a function call as if it were an 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. |
Both text and images can be links. You can include both in the same link, if you want, so that clicking either the text or the image will activate the link's events. Because images can be links, you can use them as buttons to call functions if you use javascript:xxx() as the HREF instead of an URL. Unfortunately, because you cannot replace images dynamically, you cannot modify the appearance of the image to simulate a button-down effect.
Links can also trap the onMouseOver event. However, it traps this event at the boundaries of the link. What that means is that if you run your mouse pointer over a link, the event will be fired twice: once when you enter the bounding box of the link and once when you leave it.
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 will stay 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 JScript object. Figure 8.3 shows an onMouseOver event being triggered just as the mouse moves over the link.
Figure 8.3 was generated by the code in Listing 8.10, which includes examples of trapping onClick and onMouseOver events from links. It also includes a script that uses the document.links array to write the number of links on the page. Examples of using a javascript:xxx replacement for an URL in a link can be found in Listing 8.4, which uses linked images as buttons.
Listing 8.10 Event Processing for the Link Object
<HTML> <HEAD> <!- Created 09 Feb 1996 a2:45 AM 02:45 AM --> <TITLE>What's Your Link</TITLE> <SCRIPT> function checkOut() { a = (confirm("This file is 10 megs in size. It will take 2 hours to download it. Are your sure you want to do that at this time?")) if (a == true) { alert ('loading file ') } else { alert('NOT loading file!') } } function enhance(what) { astr = what.href self.status = 'Example 4 from this chapter: ' + astr} </SCRIPT> </HEAD> <BODY> <TABLE ALIGN=RIGHT WIDTH=250 BORDER=1> <TR><TD> <FONT SIZE=7 COLOR="darkcorel"> <CENTER>What's Your Link</CENTER> </TD></TR></TABLE> <FONT SIZE=5 >Link Example</FONT><BR> This page demonstrates onClick and mouseOver events for links <HR> <H3><BR><HR><BR></H3> <TABLE ALIGN=LEFT BORDER WIDTH=250> <TR><TD> <A HREF='C8-4.HTM' onMouseOver='enhance(this)'> <IMG WIDTH=100 HEIGHT=100 VSPACE=2 HSPACE= 2 ALIGN=Left SRC="Images/grkaleid.jpg"> <CENTER><FONT SIZE=5>Enhanced Status</FONT></CENTER></A> </TD></TR></TABLE> This Linked image has an onMouseOver event in its Link tag. This event appears to be fired twice, once when the mouse passes into the boundary of the image and once when it passes out. Move the mouse SLOWLY to see the effect of the event handler. <BR CLEAR ALL> <H3><BR></H3> <TABLE ALIGN=LEFT BORDER WIDTH=250> <TR><TD> <A HREF='C8-3.HTM' onClick='checkOut()'> <IMG WIDTH=32 HEIGHT= 50 VSPACE=2 HSPACE=2 BORDER=2 ALIGN=Left SRC="Images/answer_u.gif"> <CENTER><FONT SIZE=5>File Information</FONT></CENTER></A> </TD></TR></TABLE> This onClick routine asks you if you want to load a very large file. <FONT SIZE=4 COLOR='red'> </FONT> <BR CLEAR ALL> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> <SCRIPT> k = document.links.length document.write('This page has ' + k + ' links. They are: <BR>') </SCRIPT> </HTML>
Figure 8.3 : MouseOver is fired only when the mouse pointer enters or leaves the linked object.
Anchors. Anchors consist of text or images in your document that are marked, usually named, and can be referenced by a link within the same document (known as a local link). The document object has an anchors array, but at this time its use is quite limited. You can find out how many anchors are on the page using the length property.
Dynamic documents created using JScript provide all the functionality of static documents written in HTML. If you can write it in HTML, you can write it on-the-fly in a document script. In fact, you can write your whole document in a script. You have already seen several examples of this, such as Listing 8.8, which creates a small window that can be used to manipulate the history list of the top-level window. You can also have a script after the </BODY> tag that writes a document footer in a similar fashion.
Unfortunately, you cannot change anything on your current page once the document is finished. If you want to write to the current document, you have to open it and write to it via scripts placed at the beginning and end of the document. You can also choose to rewrite the entire document.
Using the document.write method is like printing on a dot matrix printer: It is top-down only. This makes it particularly hard to do graphing or other innovative work that requires accurate positioning of objects on the page, because you cannot know in advance where they will end up.
You must also be careful when enclosing an HTML statement within a document.write clause. This innocent statement will give you at least one error:
Document.write('<FONT SIZE=5 COLOR='red'>JScript is GREAT!</FONT>')
Many HTML parameters need to be quoted, and it is much easier to use single quotes than double quotes. Unfortunately, the write statement above will terminate with the leading quote of 'red'. The closing parenthesis of the write statement will not be found, and an error will occur. The problem is easily fixed in this case: Just use double quotes around the word "red".
But what do you do if there is a need for a third level of nested quotes? Take this HTML statement for example:
<INPUT TYPE='radio' NAME='mycolor' VALUE='red' onClick='Alert("You chose red!")'>
This statement already has nested quotes. If you want to enclose this within a document.write() clause, you have two choices:
If you have more than three levels of quotes, then
you must use the second option.
The "Variables and Values" section of Chapter 2, "JScript: The Language," gives the basic rules for string quoting. |
To provide a canvas for you to write on, use the
document.open()
command. It is often a good idea to precede this with a document.close()
command as a safety precaution, in case there is already a document
open. You can open or reopen a document in the current window
or any window for which you have a reference. Opening a document
in that window clears anything that is already there. Once the
document is open, you can write to it.
Caution |
If you issue a document.open() command from within a script in the current page and it is not preceded by a window reference, the current page will be opened. Whatever is on the page is gone! This can be quite a surprise. Don't worry. You can recover the page with a reload, but your users might not know that. Check all document.open() references carefully. |
A document is open until you specifically close it or until the browser runs out of things to write on it. When you first open a window, the document associated with that window is also opened. You can then write to it with a header script. Then, the browser writes all of the body, if there is one, and anything it finds in the footer script, if there is one. When it reaches the end of the HTML text, it automatically closes the document. Note that if you open a new window with myNewWin = self.open('', 'NewWin'), you do not have to issue a document.open(). Just start writing on the blank page.
We have already noted some items to be careful of
in using document.write
statements. If you try to write to a document that is not open,
nothing will happen. No error will occur-the command will simply
fail. You can write anything to a nascent document, including
scripts. If you are creating a window from scratch, then you have
to write everything. Listings 8.4 and 8.8 earlier in this chapter
illustrate this approach.
Troubleshooting |
I opened a fresh document using document.open(), wrote to it for quite a long time using document.write(), and nothing happened. Where did I go wrong?
Document.write() places all of its output into an ASCII stream. Think of it as one big string that exists somewhere in memory. The browser does not get to interpret the stream until you specifically say, "That's all, folks!" with a document.close(). Once you close the document, everything that you have written (hopefully) is rendered in the browser window. This also means that any script errors will not be noticed until the document is actually closed. |
If you examine Listing 8.9, you see that this document is written totally within the header. Let's revisit this document and add a little to it. Suppose that you have a number of images that have the same prefix and differ only in a final numerical suffix. Let us also suppose that these numbers are sequential. With very little JScript, you can dynamically generate the image citations and write them to the page.
Listing 8.11 (file C8-6.HTM on the CD-ROM) takes this approach. The for loop is particularly worthy of close examination. It keeps adding citation information to a continuously growing string. When it is finished, it uses one document.write() statement to put the string on the document stream. There are several reasons to use this type of an iterative construct:
Listing 8.11 c8-6.htm-Generating an Entire Document in Jscript
<HTML> <HEAD> <!- Created 08 Feb 1996 a11:32 PM 11:32 PM --> <TITLE>Writing a Document with JScript</TITLE> <SCRIPT> document.bgcolor = 'linen' document.text = 'darkslateblue' document.link = 'coral' document.vlink='peach' document.alink='red' document.write("<TABLE ALIGN=RIGHT WIDTH=350 BORDER=1>") document.write("<TR><TD>") document.write("<FONT SIZE=7 COLOR=indianred>") document.write("<CENTER>" + document.title + "</CENTER>") document.write("</TD></TR></TABLE>") document.write("<BR>") document.write("<LEFT>") document.write("This page is an example of a document written completely within a script. The reference for each image is generated dynamically") document.write("</LEFT>") document.write("<BR CLEAR ALL>") document.write("<HR>") bstr = 'DBLACE' kstr = '' for (i = 1 ; i <= 6 ; i++) { var xstr = bstr + i + '.jpg' kstr += '<IMG SRC=\"Images\/' + xstr + '" ' kstr += 'HEIGHT=100 WIDTH=100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=LEFT>' kstr += '<H3><BR><H3>' kstr += '<CENTER><FONT SIZE=4 COLOR="coral">' + xstr + '</FONT></CENTER>' kstr += '<HR><BR CLEAR ALL>' } document.write(kstr) document.write("<BR><HR><BR>") document.write("This document was last modified on<BR> <FONT COLOR=red><B>" document.write(document.lastModified) document.write("</FONT><BR>") document.write("<BR><HR><BR>") document.write("</B></CENTER>") document.write("") </SCRIPT> </HEAD> <BODY> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>
There are many reasons why you might want to rewrite your page dynamically. You may want to try out various background images and colors, for example. There are two steps to this process: obtaining (or generating) the current information that you will modify, and applying that information to the current page. Because Internet Explorer's current release insists upon sending document.write() calls to a new page, the best one can do is to generate as much information as possible when constructing that new page. Listing 8.12 shows an example of this. It can be easily extended to include a number of different items. In fact, you can build a simple page with it. This code will be found in the CD-ROM file c8-7.htm.
Listing 8.12 c8-7.htm-Using JScript to Dynamically Rewrite a Document
<HTML> <HEAD> <!- Created 08 Feb 1996 a6:10 PM 06:10 PM --> <TITLE>Dynamic Modification of Documents</TITLE> <SCRIPT> function createArray(n) { this.length = n return this } var parms = new createArray(6) function reloadMe() { parms[1] = document.forms[0].aname.value parms[2] = document.forms[0].mytext.value parms[3] = document.forms[0].mylink.value parms[4] += document.forms[0].myvlink.value parms[5] += document.forms[0].myimage.value var astr astr = '<BODY BACKGROUND = "Images/' + parms[5] + '" ' astr += 'TEXT="'+ parms[2] + '" ' astr += 'LINK="'+ parms[3] + '" ' astr += 'VLINK="'+ parms[4] + '" ' astr += 'ALINK="red" ' astr += '>\n' document.write(astr) document.write('<TABLE ALIGN=RIGHT WIDTH=350 BORDER=1>') document.write('<TR><TD>') document.write('<FONT SIZE=7 COLOR= "indianred">') document.write('<CENTER>' + document.title + '</CENTER>') document.write('</TD></TR></TABLE>') document.write('<LEFT><B>') document.write('This page is an example of dynamically revised by a header script which acts on user\' choices.') document.write('</B></LEFT>') document.write('<BR CLEAR ALL>') document.write('<HR>') astr ='<CENTER><FONT SIZE=7 COLOR="' + parms[3] + '"><B> ' astr += parms[1] + '</B></FONT></CENTER>' document.write(astr) document.write('<HR><BR>') document.close(); } function clearUp() { self.location = self.location.pathname } function doTC(what) { what.form.mytext.value = what.value } function doLC(what) { what.form.mylink.value = what.value } function doVC(what) { what.form.myvlink.value = what.value } function doImage(what) { document.forms[0].myimage.value = 'DBLACE' + what + '.jpg' } function doname(what) { what.form.aname.value = what.value } </SCRIPT> </HEAD> <BODY> <CENTER> <FORM NAME=nameForm> Enter your first name here:<BR> <INPUT TYPE=text NAME=myname SIZE= 20 onChange='doname(this)'><H3><BR></H3> <CENTER> <TABLE ALIGN=LEFT WIDTH=100 BORDER CELLPADDING=5> <TR ALIGN=LEFT><TD> <CENTER><B>Text</B></CENTER> <INPUT TYPE="RADIO" NAME="tc" VALUE='white' ONCLICK='doTC(this)'>white<BR> <INPUT TYPE="RADIO" NAME="tc" VALUE='yellow' ONCLICK='doTC(this)'>yellow<BR> <INPUT TYPE="RADIO" NAME="tc" VALUE='navy' ONCLICK='doTC(this)'>navy<BR> <INPUT TYPE="RADIO" NAME="tc" VALUE='blue' ONCLICK='doTC(this)'>blue<BR> <INPUT TYPE="RADIO" NAME="tc" VALUE='orange' ONCLICK='doTC(this)'>orange<BR> <INPUT TYPE="RADIO" NAME="tc" VALUE='red' ONCLICK='doTC(this)'>red<BR> <INPUT TYPE="RADIO" NAME="tc" VALUE='black' ONCLICK='doTC(this)'>black<BR> </TD></TR></TABLE> <TABLE ALIGN=LEFT WIDTH=100 BORDER CELLPADDING=5> <TR ALIGN=LEFT><TD> <CENTER><B>Link</B></CENTER> <INPUT TYPE="RADIO" NAME="lc" VALUE='white' ONCLICK='doLC(this)'>white<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='yellow' ONCLICK='doLC(this)'>yellow<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='navy' ONCLICK='doLC(this)'>navy<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='blue' ONCLICK='doLC(this)'>blue<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='orange' ONCLICK='doLC(this)'>orange<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='red' ONCLICK='doLC(this)'>red<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='black' ONCLICK='doLC(this)'>black<BR> </TD></TR></TABLE> <TABLE ALIGN=LEFT WIDTH=100 BORDER CELLPADDING=5> <TR ALIGN=LEFT><TD> <CENTER><B>VLink</B></CENTER> <INPUT TYPE="RADIO" NAME="vc" VALUE='white' ONCLICK='doVC(this)'>white<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='yellow' ONCLICK='doVC(this)'>yellow<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='navy' ONCLICK='doVC(this)'>navy<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='blue' ONCLICK='doVC(this)'>blue<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='orange' ONCLICK='doVC(this)'>orange<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='red' ONCLICK='doVC(this)'>red<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='black' ONCLICK='doVC(this)'>black<BR> </TD></TR></TABLE> </CENTER> <BR CLEAR ALL> <HR> <CENTER><FONT SIZE=4>Click on the image that you want for a background.</FONT></CENTER> <H3><BR></H3> <A HREF='javascript:doImage(1)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE1.jpg"></A> <A HREF='javascript:doImage(2)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE2.jpg"></A> <A HREF='javascript:doImage(3)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE3.jpg"></A> <A HREF='javascript:doImage(4)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE4.jpg"></A> <A HREF='javascript:doImage(5)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE5.jpg"></A> <BR CLEAR ALL> <HR> </CENTER> <TABLE ALIGN= RIGHT WIDTH=300><TR ALIGN=RIGHT><TD> Name: <INPUT TYPE=text NAME=aname><BR> My Image: <INPUT TYPE=text NAME=myimage><BR> My Text: <INPUT TYPE=text NAME=mytext><BR> My Link: <INPUT TYPE=text NAME=mylink><BR> My VLink: <INPUT TYPE=text NAME=myvlink><BR> </TD></TR></TABLE> <INPUT TYPE=button NAME=reloadBtn VALUE='Rewrite Page' onClick='reloadMe()'> <INPUT TYPE=button NAME=clearBtn VALUE= 'Clear' onClick='clearUp()'> <INPUT TYPE=hidden NAME=hideFld> </FORM> <HR> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>
Figure 8.4 shows the result of loading this page. The page starts out in the default IE colors. It gives the user the opportunity to select text and link colors, and a background tile. The user is in the process of selecting a tile.
Figure 8.4: A dynamically rewritten page stores information for use in the next rewrite operation.
This script does several things that are worth noting, as follows:
Figure 8.5 shows all the choices being placed in the summary form as the user clicks and enters text. Figure 8.6 shows the browser window after it has been rewritten dynamically to use the colors and tiles chosen by the user.
Figure 8.5: Dynamic documents can modify their own appearance under user control.
You can write to any page that appears in your window hierarchy. You cannot write to a page that is not a part of that hierarchy. Consequently, a parent can write to a child window and a child can write to its parent. If you want a parent window to write to a newly created child window, then you need to keep a handle to that window. The window.open() method returns such a handle; you should store this value as a global variable. It can then be used subsequently to access the child. If you do not use a global variable, you will not be able to access the child window from any function other than the one that created it.
Figure 8.6: Dynamic documents can rewrite their own background.
Let's examine the very first complete example in this chapter (Listing 8.3) again now that you have more knowledge and experience. The parent window has two buttons, one to open the window and one to close it. These buttons call the parent window's functions, openNote() and closeNote(), respectively. The parent stores the handle to the openNote window in the global variable, aNoteWin. The responsibilities of the open routine are as follows:
The open routine also exemplifies a common and useful time-saving practice, known as aliasing. The full hierarchical representation of aNoteWin's document (self.aNoteWin.document) is collected in the short and easy-to-write variable known as ndoc.
Finally, it is worth pointing out the utility of having the child window's Close button in the parent window, especially if the child window is small. The open() method will not create a second window of the same name, although it can do some updating if you make a second open() call with different parameters. If you click the Make Note button and nothing happens, it is possible that you did not get rid of the last window you made.
Murphy's Law dictates that the forgotten child will be at the very bottom of the eight other large windows on your screen. Being able to close the window from the parent is a great time-saver and an excellent debugging tool.