If the Window object, which represents a window or a frame, is the
central object in client-side JavaScript, then the Document
object, which represents the contents of a window or frame, runs a
close second, and is just as commonly used. This object has
properties that specify information about the document: the URL,
its last-modified date, the URL of the document that linked to it,
the colors that it is displayed in. The Document object also has
a few methods that allow JavaScript programs to dynamically output
text into a document, and to dynamically create new documents from
scratch. Finally, the Document object also contains a number of
array properties that specify information about the contents of
the document. These arrays contain objects that represent the
links, anchors, HTML forms, applets, and embedded data contained
in the document. These arrays and the objects they contain are
very important in JavaScript programming, and will be described in
their own sections later in this chapter.

The Document object has a number of properties that correspond
to attributes of the <BODY> tag, and
which are used to specify the colors that the document is
displayed in. The bgColor property, and the
BGCOLOR attribute specify the background
color of the document. Similarly, the
fgColor and the TEXT
attribute specify the default color for text in the document.
The linkColor property specifies the color of
unvisited links, and vlinkColor and
alinkColor[1]
specify the color of visited links
and of activated links (i.e., links currently being
clicked on). The LINK,
VLINK, and ALINK
attributes correspond to these properties.

[1]
You can set the alinkColor property in
Internet Explorer, but it will be ignored, since IE never
displays a separate color for activated links.

These color properties of the Document object are read/write
properties, but they can only be set before the
<BODY> tag is parsed. You can set them
dynamically with JavaScript code in the
<HEAD> of a document, or you can set
them statically as attributes of the
<BODY> tag, but you cannot set them
elsewhere.

The exception to this rule is the bgColor
property. You can set this property at any time, and doing so
will cause the background color of the browser to change.
Unfortunately, on Unix platforms, changing the background color
can make the contents of the page disappear (usually until the
window is scrolled or otherwise redrawn). Setting the
background color can still produce a useful special effect when
done with small, empty frames, however.

Each of these color properties has a string value. To set a
color, you can use one of the predefined color names listed in
Appendix G, JavaScript and HTML Color Names and Values, or you can specify the
color as red, green, and blue color values, expressed as a
string of six hexadecimal digits in the form
"RRGGBB".

The Document object also has properties that are somewhat more
interesting than these color properties. For the most part, the
values of these other properties are derived from the HTML content
of the document or from HTML headers supplied by the web server.
As we saw in the discussion of the Location object, the Document
object has a location property (and a
URL property which is a preferred synonym in
Navigator 3.0) that specifies the URL of the document. Because
of redirection performed by the web server, this URL may be
different than the requested URL.

The lastModified property is a string that
specifies the date and time of the most recent change to the
document. This is a value supplied by some, but not all, web
servers. The referrer property specifies the
URL of the document that contained the hypertext link that the
user clicked on to get to the current document. If the current
document was loaded by explicitly typing a URL, then this
property will be empty. Note that this property is not
supported in Internet Explorer 3.0. Finally, the
title property contains any text that appears
between the <TITLE> and
</TITLE> tags in the
<HEAD> of the document. You cannot use
this property, of course, in code that appears before the
<TITLE> of a document.

A simple use for the lastModified property is
to automatically include a timestamp in your documents, so that
users know whether the information they are seeing is
up to date. You can do this by including HTML and JavaScript
code like the following at the bottom of all your documents.
Note that this code displays the document title and URL as well
as its modification date:

A possible use for the referrer property is
to save this value in a hidden field of a form on your web
page. When the user submits the form (for whatever reason your
page contains the form in the first place) you can save this
referrer data on the server. This will allow you to analyze
what links exist to your page, and also what percentage of hits
come through which links. Another use of this property is a trick
to prevent unauthorized links to your page from working
correctly. For example, if you only want users to be able to
get to your page through links in pages from one particular
site, you might use code like this at the top of your page:

Without a doubt, the most important feature of the Document
object (and perhaps of client-side JavaScript in general) is the
write() method, which allows us to
dynamically generate web page content from our JavaScript
programs. There are several ways that this method can be used.
The most obvious is to use it within a script to output HTML
into the document that is currently being parsed. This is the
way it was used above to display the Document
lastModified property at the bottom of the
web page. Be aware that you can only output HTML to the current
document while that document is being parsed. That is, you can
only call document.write() from within
<SCRIPT> tags, because these scripts
are executed as part of the document parsing process. In
particular, if you call document.write() from
an event handler, you will end up overwriting the current
document (including its event handlers), instead of appending
text to it.

Although you can't usefully write to the current document from
an event handler, there is no reason you can't write to a
document in another window or frame, and doing so can be a very
useful technique for multiwindow or multiframe web sites. For
example, JavaScript code in one frame of a multiframe site
might display a message in another frame with code like this:

We previously saw code that dynamically creates an HTML document
like this in Example 12.2 and Example 12.6. Recall that to create a new
document, we first call the open() method of
the Document object, then call write() any
number of times to output the contents of the document, and
finally call the close() method of the
Document object to indicate that we are complete. This last
step is important--if you forget to close the document, the
browser will not stop the "document loading" animation it
displays. Also, the browser may buffer up the HTML you have
written, and is not required to display it until you explicitly
end the document by calling close().

In contrast to the close() call, which is
required, the open() call is optional. If
you call the write() method on a document
that has already been closed, then JavaScript implicitly opens a
new HTML document, as if you called the
open() method. This explains what happens
when you call document.write() from an
event handler within the same document--JavaScript opens a new
document. In the process, however, the current document and its
contents, including scripts and event handlers, is discarded.
In Navigator 3.0, this causes surprising programming difficulties
and unexpected error messages. In Navigator 2.0, it can
actually cause the browser to crash. The best rule of thumb is
that a document should never call write() on
itself from within an event-handler.

A couple of final notes about the write()
method. First, many people do not realize that the
write() method can take more than one
argument. When you pass multiple arguments, they will be output
one after another, just as if they had been concatenated. So
instead of writing:

document.write('Hello, ' + name + " Welcome to my home page!");

you can equivalently write:

document.write('Hello, ', name, " Welcome to my home page!");

The second point to note about the write()
method is that the Document object also supports a
writeln() method, which is identical to the
write() method in every way, except that it
appends a newline after outputting its arguments. Since HTML
ignores linebreaks, this newline character usually doesn't make
a difference, but, as we'll see in a bit, the
writeln() method can be convenient when
working with non-HTML documents.

When you use the write() method to
dynamically generate HTML output, the text you write may not
appear in the browser window right away. The contents of your
individual write() calls may be buffered up
so that they can be written out to the document in larger
chunks. Unfortunately, there is no flush()
method of the Document object that forces all output to appear.
Instead, you must know the necessary tricks to make your output
appear.

Calling the close() method is the simplest
technique for forcing your output to be displayed, of course.
Sometimes, though, you want intermediate output to be displayed,
and are not yet ready to close the document you are generating.
In this case, there are two techniques for flushing output. In
Navigator 3.0, output is flushed whenever a new line is forced
in the browser. Thus, if you output a
<BR> or <P> or
<HR> tag, all the text before that tag
will appear. In Internet Explorer 3.0, it is not so easy,
however--your output does not appear until the current
<SCRIPT> block ends or the current
event handler function returns. Thus, for this browser, you may
need to break your code up into smaller chunks in order to
assure that output is correctly flushed. Note that you can
always use setTimeout() to schedule the next
"chunk" of code to run in 0 milliseconds. This technique allows
control to temporarily return to IE so that it can display any
pending output.

When you open a new document with the open()
method, the browser assumes that you'll be creating an HTML
document. But this is not necessarily the case. Web browsers
can display a number of other data formats besides HTML text.
When you want to dynamically create and display a document using
some other data format, you call the open()
method with a single argument, which is the MIME type you
desire. Note that while this technique is supported in
Navigator 2.0 and 3.0, it does not work in Internet Explorer
3.0--in that browser, any argument passed to
open() is ignored.

The MIME type for HTML is "text/html". The most common
format other than HTML is plain text, with a MIME type of
"text/plain". If you want to use the write()
method to output text that uses newlines, spaces, and tab
characters for formatting, then you should open the document by
passing the string "text/plain" to the open()
method. Example 14.1 shows one
way you might do this. It implements a
debug() function that you can use to output
plain-text debugging messages from your scripts into a separate
window that appears when needed.
Figure 14.1 shows what the
resulting window looks like.

This technique of using non-HTML documents is not limited to
plain-text documents, or to textual documents in general. It
can also be used with images, for instance. If we open a
document and specify the MIME type "image/xbm", for example,
then the browser will expect the contents of that document to be
an image in XBM format. Because XBM images have an ASCII
representation, we can easily write a static XBM image to the
document, or even generate a dynamic image on the fly (perhaps
using a Java applet to do the image processing, for speed).
Example 14.2 shows how you can
create an "image/xbm" document with a static XBM image, and also
shows how this XBM image can be used for image embedded in an
HTML document. Figure 14.2 shows
the windows created by the example. This technique would be
much more efficient and interesting if it used a compact image
format like "image/gif". Unfortunately, this is not possible
because GIF images use a binary format that includes NULL
characters (i.e., the byte 0) and the current versions of
JavaScript cannot output this character.