Previous Section:
Introduction
Programming the Body and Frameset Elements
An HTML document can contain either of two types of contents: body
contents or a frameset definition. The first Body or Frameset element
appearing in the document defines the document's type. A similar object model is
exposed for the document in both cases.
The body Property
The document object exposes a
body property that represents the root of
the document's contents. The name of this property is ambiguous because the
body property can represent either a Frameset or a Body element, depending on
the document type. As explained in Chapter 7, "Document Element
Collections," every document has a Body or Frameset element, regardless of whether it
is explicitly declared. If a document's frameset nests other Frameset elements,
the body property represents the outermost Frameset element in the document.
The Body or Frameset element is also contained in the document's
all collection. Thus, the body property can be accessed directly from the
document as follows:
// Returns BODY or FRAMESET depending on the type of document.
document.body.tagName;
Or it can be accessed through the all collection:
// For documents with a Body element
document.all.tags("Body").item(0).tagName; // Returns "BODY"
/* Displays "true"; demonstrates that the two elements are the
same */
alert(document.all.tags("Body").item(0) == document.body);
// For documents with a Frameset element
document.all.tags("Frameset").item(0).tagName; // Returns "FRAMESET"
/* Displays "true"; demonstrates that the two elements are the
same */
alert(document.all.tags("Frameset").item(0) == document.body);
In the preceding code, the tags method returns a collection consisting
of the Body or the Frameset elements. If the document has a Body element,
the HTML DTD (document type definition) limits it to a single Body element,
and the parser ignores any extra ones. If the document has a Frameset element,
it can have multiple Frameset elements; the
tags method returns all of them, beginning with the outermost one. In either case, the first element in
the collection returned by the tags method is the element contained in the
body property. The code uses item to access this element.
Availability of the body Property
The object model is constructed and exposed simultaneously during the
parsing of the document. Before the parser encounters the body or frameset of
the document, the body property is not available, and therefore the
body property returns null. The following code illustrates the availability of the
body property:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
alert(document.body == null); // true--precedes <BODY> tag
</SCRIPT>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
alert(document.body == null); // false--follows <BODY> tag
</SCRIPT>
</BODY>
</HTML>
For documents with body contents, the <BODY> tag does not have
to appear explicitly in the document to be accessible. Instead, the Body
element is implicitly created once the document contains an element--or simply
some text--that must be a part of the body. The elements that make up body
contents are defined by the HTML DTD. Chapter 1, "Overview of HTML and
CSS," explains how to read a DTD, and more information about how the
document is parsed is provided in Chapter 7, "Document Element Collections."
Distinguishing Between Body and Frameset Contents
You can use the tagName property to determine whether a document
contains a body or a frameset. The following code displays an alert box reporting
its document type--in this case, a frameset:
<HTML>
<HEAD>
<TITLE>Frameset Exposed as the Body</TITLE>
</HEAD>
<FRAMESET ROWS="100%" ONLOAD="alert(document.body.tagName);">
<FRAME SRC="foo.htm">
</FRAMESET>
</HTML>
Checking the length of the frames collection on the window is not an
accurate way to determine whether a document is a frameset. A document
with a Body element may contain IFrame elements, which would be included in
the frames collection.
Client Window and Document Size
The width and height of the client window are exposed as properties of
the Body and Frame elements. The physical
size of the document is the size of the client area-- that is, the amount of space the document occupies on the
screen. The logical size of the document is the size of the contents. For document
contents that are larger than the window, scrollbars are usually displayed.
Figure 9-1 illustrates the properties that represent the physical and logical size
of the document, and the subsequent sections describe them. Other elements in the document can expose the same properties for determining their size.
The special relationship these properties share with other elements in the
document is discussed in Chapter 12, "Dynamic Positioning."
Physical Size
The physical width and height of the document (frameset or body type)
are exposed through the offsetWidth and
offsetHeight properties of the Frameset or Body element. The physical width and height measure the area of the
currently visible window including the scrollbars. The
clientWidth and clientHeight properties are exposed to determine the size of the client area--the
physical size as defined by the offsetWidth and
offsetHeight properties less the size of
the scrollbars and surrounding borders. These properties are read-only and
cannot be used to change the size of the window.
In Figure 9-1, no horizontal scrollbar is displayed, so the
offsetHeight and clientHeight properties would be the same if the border was set to
0. However, a vertical scrollbar is displayed, so the
offsetWidth and clientWidth properties represent distinct values.
Figure 9-1. Properties for determining the window and document size.
Logical Size
The Body element exposes four properties for determining the logical size
of the document and the position of the user's view into the document:
scrollWidth, scrollHeight,
scrollTop, and scrollLeft. The logical size of the document
represents the total height and width of the document, not the size of the browser
window that provides a view into the document. These properties are not
available or necessary on frameset documents because the logical size of the
frameset is equivalent to its physical size.
The scrollWidth and scrollHeight properties represent the logical size of the document in pixels. These properties are read-only and are calculated
by the browser based on the document contents. You can change the
scrollWidth and scrollHeight properties by dynamically adding or removing elements
or by resizing the window. Resizing the window usually affects both properties
because the contents rewrap to the new width.
The scrollTop and scrollLeft properties represent the scroll offsets of
the logical document. They represent the point in the document that is
displayed in the upper-left corner of the window. When the horizontal and
vertical scrollbars are scrolled all the way to the left and top edges of the
document, scrollLeft and scrollTop both equal
0. These properties are read/write and can be modified to immediately scroll the document to a particular pixel
position. If you need to set scrollLeft and
scrollTop at the same time, the
scroll method on the window is a more convenient mechanism because it takes both new
coordinates, horizontal and vertical, as arguments.
As a group, these properties provide information for determining
the visible portion of the screen. The currently viewable area of the document
can be easily calculated using the size properties, as shown here:
upperLeftX = document.body.scrollLeft;
upperLeftY = document.body.scrollTop;
lowerRightX = upperLeftX + document.body.clientWidth;
lowerRightY = upperLeftY + document.body.clientHeight;
The scrolling-related properties are also exposed on any other
scrolling element. For example, you can give a Div element scrollbars using the
CSS (Cascading Style Sheets) overflow3 property, and the TextArea element
displays scrollbars by default. When these elements have scrollbars, they expose
the scrolling-related properties for determining the scrolled regions of their
contents. The TextArea element is discussed in detail in Chapter 10, "Forms
and Intrinsic Controls," and the CSS
overflow property is discussed in Chapter 12, "Dynamic Positioning."
Window Events
The Body and Frameset elements expose attributes corresponding to all window-level events. For example, the following code in a document with
a Body element specifies an ONLOAD event handler for the window:
<BODY ONLOAD="doThis();">
The code for a frameset document is similar:
<FRAMESET ONLOAD="doThis();" ROWS="*">
Even when you use the <BODY> or
<FRAMESET> tag to specify the handler for a window event, the event is scoped to the
window object, not to the body object. This distinction is important when you use the
this pointer in the event handler. In a body-level event handler,
this points to the body object; in a window event handler,
this points to the window object, even if you
specify the handler in the <BODY> tag. The following code illustrates how
this pointers work for a window event
(onload) and a body event (onclick):
<BODY ONLOAD="alert(this == document.body); // false"
ONCLICK="alert(this == document.body); // true">
</BODY>
Furthermore, for window events, the
srcElement property of the event
object contains null.
While a document can have multiple framesets, it can have only
one handler for each window event. If several Frameset elements in the
document define handlers for an event, only the last handler's code is executed. In
the following example, only the second
onload event handler executes, displaying the alert
b. The event does not fire until the entire document is loaded.
<HTML>
<HEAD>
<TITLE>Frameset onload Event</TITLE>
</HEAD>
<FRAMESET ONLOAD="alert(`a');" ROWS="100, *">
<FRAMESET ONLOAD="alert(`b');" COLS="*.*">
<FRAME SRC="a.htm">
<FRAME SRC="b.htm">
</FRAMESET>
<FRAME SRC="c.htm">
</FRAMESET>
</HTML>
Because you can define only one handler per window event, you
cannot specify a handler on a Frame or nested Frameset element that works only
for that particular element. To protect against this behavior possibly changing
in the future, window event handlers should be specified only on the first
Frameset element.
The onresize Event
The onresize event is fired whenever the size of the physical window
changes, not the size of the contents within the body or frameset document.
Therefore, this event is actually a window event when defined on the Body element.
The onresize event is also exposed on elements within the document that have
a defined size. In those cases, the event fires only when the physical size of
the element changes.
When a document is first loaded into a new window, the
onresize event does not fire. Therefore, if code is being used to lay out the document based on
the initial window size, the code should be called from the
onload event.
Programming Body Contents
Documents that contain a Body element have a few additional features
not available to frameset documents, including access to the HTML and
textual contents contained within the body and an
onscroll event that fires when the window is scrolled.
You can write scripts to manipulate the text in the Body element or
any element in the body. The techniques are discussed in Chapter 13,
"Dynamic Contents."
The onscroll Event
The window object exposes an
onscroll event that fires whenever the window is scrolled either explicitly by the user or through code. This event
occurs only in documents with Body elements and not in frameset documents
because they do not display scrollbars.
Programming Frameset Contents
Because the frameset document is another type of HTML document, it
supports the document object model. The frameset document exposes an
all collection that provides direct access to all the elements in the document.
Through the all collection, the individual attributes of each Frameset and Frame
element can be accessed and in many cases dynamically modified.
While the number of frames in the frameset is static and cannot
be modified without creating a new document, a number of the attributes of
the Frameset element can be changed. For example, the ROWS and COLS attributes are read/write attributes, which allows you to change the layout
of the frameset dynamically. This flexibility can be used to add custom
behavior to a traditional frameset.
The following code creates a custom layout that allows the user to
select from a set of pages. This example turns off the resizing capability of each
frame and instead automatically expands the frame the user clicks on. This
layout model requires a small amount of code behind the frameset and each document.
<HTML>
<HEAD>
<TITLE>Sliding Frames</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var defSize = 25;
function display(f) {
var newRows = "";
// Get all the Frame elements.
var elFrame = document.all.tags("FRAME");
for (var intFrames = 0; intFrames < frames.length;
intFrames++) {
var curF = frames[intFrames].document;
if (curF.body == f.document.body) {
// Give selected frame all the space.
newRows += "*, ";
/* Make the header much bigger. */
curF.all.header.style.fontSize = "200%";
/* Turn on scrollbars for the active frame
by accessing the Frame element
in the frameset document. */
elFrame[intFrames].scrolling = "yes";
}
else {
// Set to default size.
newRows += defSize.toString() + ", ";
// Reset header font size.
curF.all.header.style.fontSize = "";
// Turn off scrolling.
elFrame[intFrames].scrolling = "no";
}
}
document.body.rows = newRows;
}
</SCRIPT>
</HEAD>
<FRAMESET ROWS="*, 25, 25">
<FRAME SRC="home.htm" NORESIZE>
<FRAME SRC="news.htm" NORESIZE SCROLLING="No">
<FRAME SRC="info.htm" NORESIZE SCROLLING="No">
</FRAMESET>
</HTML>
Figure 9-2 demonstrates this code in action. When the user clicks on
the News or Information heading, the other frames automatically shrink and
the selected frame expands to take up the remaining view.
Figure 9-2. An example of automatically sliding frames.
Run Sample (Windows IE4 Only)
In each document in the frameset, the
onfocus event handler must call the
display routine. The parent property on the document must be referenced
to call the function:
<!-- The onfocus event must be defined for each document in the
frameset. -->
<BODY ONFOCUS="parent.display(this);">
Also in each document in the frameset, the ID of the first paragraph must
have the value header. The text in this paragraph will be enlarged when the
document has the focus.
This example demonstrates modifying the attributes of individual
frames. The Frame element in the all collection of the document is different from the contents of the window's frames collection. The
frames collection on the window returns the window instance created based on the document's
source. The Frame element in the all collection represents the frame as defined by
the HTML source and is used to create the window. Modifying the Frame
element can modify the window and its contents--for example, scrollbars can be
manually turned on and off. Scrollbars have been turned off in our example so
that they do not clutter the collapsed heading view of the document.
Next Section:
Programming the Anchor Element