11.3. Client-Side JavaScript
Client-side JavaScript is the name
given to JavaScript code that is embedded within an HTML file and
executed by a web browser. In addition to the core objects described
in the previous section, client-side JavaScript code has access to a
number of other objects that represent the web browser, the document
displayed in the browser, and the contents of that document.
Client-side JavaScript programs are usually event-based, which means
that JavaScript event handlers are executed in
response to user interactions with the browser and the document. The
client-side JavaScript scripting framework is powerful enough to open
substantial security holes in web browsers. For this reason, web
browsers typically restrict the actions of client-side scripts. This
section starts by explaining how JavaScript code is embedded in HTML
files, then goes on to introduce the client-side JavaScript objects,
JavaScript events and event handling, and JavaScript security
restrictions.
11.3.2. The Window Object
The Window object represents a web
browser window. In client-side JavaScript, the Window object is the
global object that defines all top-level properties and methods. The
properties and methods of the Window object are therefore global
properties and global functions and you can refer to them by their
property names without any object prefix. One of the properties of
the Window object is named window and refers back
to the Window object itself:
window // The global Window object
window.status // The status property of the window
status // Or omit the object prefix
See Window in the reference section for a full list of its
properties and methods. The following sections summarize the most
important of these properties and methods and demonstrate key
client-side programming techniques using the Window object. Note that
the most important property of the Window object is
document, which refers to the Document object that
describes the document displayed by the browser window. The Document
object is described in a section (Section 11.3.3) of its own following these
window-related subsections.
11.3.2.6. Window control
The Window object defines methods to
move, resize, and scroll windows, and methods to give keyboard focus
to and take focus away from windows. For example:
// Automatically scroll 10 pixels a second
setInterval("scrollBy(0,1)", 100);
See moveTo( ), moveBy( ),
resizeTo( ), resizeBy( ),
scrollTo( ) scrollBy( ),
focus( ) and blur( ) in the
Window entry of the reference section for more information.
More important than these methods that manipulate an existing window
are the open( ) method that creates a new browser
window and the close( ) method that closes a
script-created window. The open( ) method takes
three arguments. The first is the URL to be displayed in the new
window. The second is an optional name for the window. If a window by
that name already exists, it is reused and no new window is created.
The third argument is an optional string that specifies the size of
the new window and the features, or chrome, that it should display.
For example:
// Open a new window
w = open("new.html", "newwin", // URL and name
"width=400,height=300," + // size
"location,menubar," + // chrome
"resizable,scrollbars,status,toolbar");
// And close that new window
w.close();
Note that most browsers only allow scripts to close windows that they
have opened themselves. Also, because of the recent proliferation of
nuisance pop-up advertisements on the Web, some browsers do not allow
scripts to open new windows at all.
11.3.2.7. Multiple windows and frames
As discussed previously, the
open( ) method of the Window object allows you to
create new browser windows that are represented by new Window
objects. The window that a script is running in is the global object
for that script, and you can use all the properties and methods of
that Window object as if they were globally defined. When a script
running in one window needs to control or interact with a different
window, however, you must explicitly specify the Window object:
// Create a new window and manipulate it.
var w = open("newdoc.html");
w.alert("Hello new window");
w.setInterval("scrollBy(0,1)",50);
HTML allows a single window to have multiple frames. Many web
designers choose to avoid frames, but they are still in fairly common
use. JavaScript treats each frame as a separate Window object, and
scripts in different frames run independently of each other. The
frames property of the Window object is an array
of Window objects, representing the subframes of a window:
// Scripts in framesets refer to frames like this:
frames[0].location = "frame1.html";
frames[1].location = "frame2.html";
// With deeply nested frames, you can use:
frames[1].frames[2].location = "frame2.3.html";
// Code in a frame refers to the top-level window:
top.status = "Hello from the frame";
The parent property
of a Window object refers to the containing frame or window. The
top property refers to the top-level browser
window that is at the root of the frame hierarchy. (If the Window
object represents a top-level window rather than a frame, the
parent and top properties
simply refer to the Window object itself.)
Each browser window and frame has a separate JavaScript execution
context, and in each context, the Window object is the global object.
This means that any variables declared or functions defined by
scripts in the window or frame become properties of the corresponding
Window object. This allows a script in one window or frame to use
variables and functions defined in another window or frame. It is
common, for example, to define functions in the
<head> of a top-level window, and then have
scripts and event handlers in nested frames call those functions
using the top property:
// Code in a frame calls code in the window.
top.stop_scrolling();
11.3.3. The Document Object
Every Window object has a
document property that refers to a Document
object. The Document object is arguably more important than the
Window object itself: while the Window represents the browser window,
the Document object represents the HTML document that is displayed in
that window. The Document object has various properties that refer to
other objects which allow access to and modification of document
content. The way that document content is accessed and modified is
called the document object model, or DOM, and there are several DOMs
in existence:
- Legacy DOM
-
The original legacy document object
model evolved along with early versions of the JavaScript language.
It is well supported by all browsers, but allows access only to
certain key portions of documents, such as forms, form elements, and
images.
- W3C DOM
-
This document object model allows access and modification of all
document content and is standardized by the World Wide Web Consortium
(W3C). It is at least partially supported by Netscape 6 and later,
Internet Explorer 5 and later, and other modern browsers. The W3C DOM
is not closely compatible with the IE 4 DOM, but it does standardize
many of the legacy features of the original DOM. This chapter covers
the core features of the standard, and presents a simplified subset
of the DOM relevant for JavaScript programmers working with HTML
documents. You can find complete coverage in JavaScript:
The Definitive Guide.
- IE 4 DOM
-
Microsoft's Internet Explorer Version 4 extended the
legacy DOM with powerful new features for accessing and modifying all
content of a document. These features were never standardized, but
some of them are supported in non-Microsoft browsers.
The following sections explain each of these DOMs in more detail and
describe how you can use them to access and modify document content.
11.3.4. The Legacy DOM
The
original client-side JavaScript DOM defines provides access to
document content through properties of the Document object. Several
read-only properties, such as title,
URL, and lastModified provide
information about the document as a whole. See the reference section Document
for further details on these and all Document properties and methods.
Other properties are arrays that refer to specific types of document
content:
- forms[ ]
-
An array of Form objects representing the forms in a document.
- images[ ]
-
An array of Image objects representing the images that appear in a
document.
- applets[ ]
-
An array of objects that represent the Java applets embedded in a
document. JavaScript can actually be used to script Java and control
these applets, but doing so is beyond the scope of this pocket
reference.
- links[ ]
-
An array of Link objects representing the hyperlinks in the document.
- anchors[ ]
-
An array of Anchor objects representing the anchors (named positions
created with the name attribute of the HTML
<a> tag) in the document.
The arrays contain objects in the order they appear in the document.
The first form in a document is document.forms[0];
the third image is document.images[2]. Another way
to refer to document forms, images, and applets is to give them names
with the HTML name attribute:
<form name="address">...</form>
When an form, image, or applet is given a name like this, you can use
the name to look it up in the array, or to look it up directly as a
property of the document itself:
document.forms["address"] // A named form
document.address // The same thing
The Form object is particularly interesting. It has an
elements[ ] array that contains objects
representing the elements of the form, in the order they appear in
the form. See Input, Select, and Textarea in the reference section
for details on these form elements.
The elements[ ] array of a Form works much like
the forms[ ] array of a Document: it holds form
elements in the order they appear in the form, but it also allows
them to be referred to by name. Consider this HTML excerpt:
<form name='address'><input name='street'></form>
You can refer to the input element of the form in several ways:
document.forms[0].elements[0]
document.address.elements['street']
document.address.street
The legacy DOM does not provide any way to refer to document content
other than forms, form elements, images, applets, links, and anchors.
There is no array that provides a list of all
<h1> tags, for example, nor is there any way
for a script to obtain the actual text of a document. This is a
shortcoming that is addressed by the W3C and IE 4 DOMs, as
we'll see later. Although it is limited, the legacy
DOM does allow scripts to dynamically alter some document content, as
we'll see in the following subsections.
11.3.4.1. Dynamically generated documents
In addition to the properties already described, the Document object
defines several important methods for dynamically generating document
content. Use the write( ) method to output text
into the document at the location of the
<script> that contains the method calls. For
example:
document.write("<p>Today is: " + new Date());
document.write("<p>Document updated: " +
document.lastModified);
Note that text output in this way may contain arbitrary HTML tags;
the browser parses and displays any such text after executing the
script that output it.
The write( ) method
can be used from a <script> tag only while a
document is still loading. If you try to use it within an event
handler that is triggered after the document has loaded, it erases
the document and the event handler it contains. It is legal, however,
to use an event handler in one window or frame to trigger a
document.write( ) call into another window. When
you do this, however, you must write the complete contents of the new
document, and remember to call the document.close(
) method when you are done:
var clock = open("", "", "width=400,height=30");
var d = clock.document; // Save typing below
setInterval("d.write(new Date());d.close();", 1000);
11.3.4.2. Dynamic forms
As we've seen, the elements[ ]
array of a Form object contains objects that represent the input
elements of the form. Many of these objects have properties that you
can use to query or set the value displayed in the form element. This
provides another way to dynamically change document content. For
example, the following code sets the value
property of a Text object to display the current local time:
<form><input size=10></form> // An HTML form
<script> /* Display a clock in the form */
// The Text element we're working with.
var e = document.forms[0].elements[0];
// Code to display the time in that element
var s="e.value=(new Date()).toLocaleTimeString();"
setInterval(s, 1000); // Run it every second
</script>
11.3.6. IE 4 DOM
The IE 4 DOM was introduced in Version 4 of
Microsoft's Internet Explorer browser. It is a
powerful but nonstandard DOM with capabilities similar to those of
the W3C DOM. IE 5 and later include support for most basic W3C DOM
features, but this documentation on the IE 4 DOM is included because
IE 4 is still commonly used. The following subsections document the
IE 4 DOM in terms of its differences from the W3C DOM, so you should
be familiar with the W3C DOM first.
11.3.6.1. Accessing document elements
The IE 4 DOM does not support the getElementById(
) method. Instead, it allows you to look up arbitrary
document elements by id attribute within the
all[ ] array of the document object:
var list = document.all["mylist"];
list = document.all.mylist; // this also works
Instead of supporting the getElementsByTagName( )
method, the IE 4 DOM takes the unusual step of defining a
tags( ) method on the all[ ]
array, which exists on document elements as well as the Document
object itself. Here's how to find all
<li> tags within the first
<ul> tag:
var lists = document.all.tags("UL");
var items = lists[0].all.tags("LI");
Note that you must specify the desired HTML tag name in uppercase
with the all.tags( ) method.
11.3.6.2. Traversing the document tree
You can traverse an IE 4 document tree in much the same way that you
can traverse a W3C document tree. The difference is in the names of
the relevant properties: instead of childNodes[ ],
IE 4 uses children[ ], and instead of
parentNode, IE 4 uses
parentElement. IE 4 does not have any analogs to
firstChild, nextSibling, and
related W3C properties. One important difference between the IE 4 and
W3C DOMs is that the IE 4 document tree only include HTML tags:
comments are ignored and document text is not part of the tree
itself. Instead, the text contained by any element is available
through the innerHTML and
innerText properties of the element object.
(We'll see more about innerHTML
in the next section.)
11.3.6.3. Modifying document content and structure
The nodes of an IE 4 document tree are Element objects that are
similar to the Element node of the W3C DOM. Like the Element nodes of
a W3C document tree, these objects have properties that correspond to
the attributes of the HTML tags, and you can query and set the
properties as desired. To change the textual content of a document
element, set its innerText property to the desired
text. This deletes any existing tags or text within the element and
replaces it with the specified text.
The IE 4 DOM does not have any methods for explicitly creating,
inserting, removing, or replacing nodes of the document tree.
However, it does support the very important
innerHTML property, which allows you to replace
the content of any document element with an arbitrary string of HTML.
Doing this requires an invocation of the HTML parser, making it less
efficient than manipulating the nodes directly. On the other hand, it
is tremendously convenient, so much so that Mozilla, Netscape 6 and
later, and other modern browsers have implemented
innerHTML despite the fact that it is nonstandard
.
The IE 4 DOM also includes the related outerHTML
property, which replaces the element and its content, and the
insertAdjacentHTML( ) and
insertAdjacentText( ) methods. These are not as
commonly used, nor as commonly implemented outside of IE as
innerHTML; you can read about them in the
reference section under Element.
11.3.7. DHTML: Scripting CSS Styles
DHTML, or Dynamic HTML, is the result
of combining HTML, CSS, and JavaScript: it uses scripts to
dynamically modify the style—which may include the position and
visibility—of document elements. In the W3C and the IE 4 DOMs,
every document element has a style property that
corresponds to the HTML style attribute that
specifies inline styles. Instead of referring to a simple string,
however, the style property refers to a Style
object that has properties corresponding to each of the CSS
attributes of the style.
For example, if an element e has a
style attribute that specifies the CSS
color attribute, you can query the value of that
attribute as e.style.color. When a CSS attribute
name contains hyphens, the corresponding JavaScript property name
removes the hyphens and uses mixed-case capitalization. Thus, to set
the background-color CSS attribute of an element
e, you set e.style.backgroundColor. There is one
special case: the CSS float attribute is a
reserved word in JavaScript, so the corresponding JavaScript property
is cssFloat.
The CSS standard defines many properties that you can use to
fine-tune the visual appearance of your documents. The Style entry in
the reference section includes a table that lists them all. The
positioning and visibility properties are particularly relevant for
dynamic scripting. If the position property is set
to absolute, you can use the
top and left properties to
specify the absolute position (in pixels, percentages, or other
units) of the document element. Similarly, the
width and height properties
specify the size of the element. The visibility
property can initially be set to hidden to make a
document element invisible, and then dynamically set to
visible to make the element appear when
appropriate.
Note that the values of all Style properties are always strings, even
for properties like left and
width which represent numbers. When setting these
length and dimension properties, be sure to convert your numbers to
strings and to add the appropriate units specification (usually the
string px for pixels.) The following table
summarizes these positioning and visibility properties.
Property
|
Description/values
|
position
|
How the element is positioned: absolute,
relative, fixed, or
static (the default).
|
left, top
|
The X and Y coordinates of the left and top edges of the element.
|
width
|
The width of the element.
|
height
|
The height of the element.
|
zIndex
|
The stacking order. Values are integers; higher values are drawn on
top of lower values.
|
display
|
How to display the element. Common values are
block, inline, and
none for elements that don't get
laid out at all.
|
visibility
|
Whether the element is visible or
hidden. Space is still allocated for
non-positioned hidden elements.
|
overflow
|
What to do when element content exceeds element size. Values:
visible (content overflows);
hidden (excess content hidden);
scroll (display permanent scrollbar);
auto (scrollbars only when needed).
|
clip
|
What portion of element content to display. Syntax:
rect(top
right bottom left).
|
The following code shows a simple DHTML animation. Each time it is
called, the function nextFrame( ) moves an element
10 pixels to the right and uses setTimeout( ) to
tell JavaScript to call it again in 50 milliseconds. After 20
invocations, the function uses the visibility
property to hide the element and stops calling itself.
<h1 id='title'>DHTML Animation<h1>
<script>
// Look up the element to animate
var e = document.getElementById("title");
// Make it position-able.
e.style.position = "absolute";
var frame = 0; // Initialize frame counter.
// This function moves the element one frame
// at a time, then hides it when done.
function nextFrame() {
if (frame++ < 20) { // Only do 20 frames
e.style.left = (10 * frame) + "px";
// Call ourselves again in 50ms.
setTimeout("nextFrame()", 50);
}
else e.style.visibility="hidden"; // Hide it.
}
nextFrame(); // Start animating now!
</script>
11.3.8. Events and Event Handling
We saw at the beginning of this section that one way to embed
client-side JavaScript into HTML documents is to use event handler
attributes of HTML tags. The table below lists the standard event
handler attributes and the HTML tags to which they may be applied.
The first column of the table gives the event handler attribute name:
these names always begin with "on".
The second column of the table lists the HTML tags to which these
attributes can be applied, and explains, when necessary, what events
trigger the handler code to be executed.
Handler
|
Supported by/triggered when
|
onabort
|
<img>; image load aborted
|
onblur
|
<body> and form elements; window or element
loses keyboard focus
|
onchange
|
Form elements; displayed value changes
|
onclick
|
All elements; mouse press and release; return
false to cancel
|
ondblclick
|
All elements; mouse double-click
|
onerror
|
<img>; image loading fails
|
onfocus
|
<body> and form elements; window or element
gets keyboard focus
|
onkeydown
|
<body> and form elements; key pressed;
return false to cancel
|
onkeypress
|
<body> and form elements; key pressed and
released; return false to cancel
|
onkeyup
|
<body> and form elements; key released
|
onload
|
<body>, <frameset>,
<img>, <iframe>,
<object>; document, image, or object
completely loaded
|
onmousedown
|
All elements; mouse button pressed
|
onmousemove
|
All elements; mouse pointer moved
|
onmouseout
|
All elements; mouse moves off element
|
onmouseover
|
All elements; mouse moves over element; return
true to prevent link URL display in status bar
|
onmouseup
|
All elements; mouse button released
|
onreset
|
<form>; form reset requested; return
false to prevent reset
|
onresize
|
<body>, <frameset>;
window size changes
|
onsubmit
|
<form>; form submission requested; return
false to prevent submission
|
onunload
|
<body>, <frameset>;
document unloaded
|
Note that when the browser triggers certain event handlers, such as
onclick, onmouseover and
onsubmit, it examines the return value of the
handler (if there is one) to determine whether it should perform the
default action associated with the event or not. Typically, if an
event handler returns false, the default action
(such as following a hyperlink or submitting a form) is not
performed. The one exception is for the
onmouseover handler: when the mouse moves over a
hyperlink, the browser displays the link's URL in
the status line unless the event handler returns
true.
11.3.8.2. Advanced event handling
The previous sections describe the
basic event-handling model for client-side JavaScript. Advanced event
handling features are also available, but unfortunately, there are
three incompatible event models: the standard W3C DOM model, the
Internet Explorer model (Microsoft has not adopted the W3C standard),
and the Netscape 4 model. These event models are complex, so the
following list simply summarizes the advanced features supported by
these models. For details consult JavaScript: The
Definitive Guide.
- Event details
-
In the advanced event handling models, event details such as event
type, mouse buttons and coordinates, modifier key state, and so on,
are provided through the properties of an Event object. In the W3C
and Netscape event models, this Event object is passed as an argument
to the event handler. In the IE model, the Event object is not an
argument but is instead stored in the event
property of the Window on which the event occurs. Unfortunately, each
of the three advanced event models use different property names to
store event details, so cross-browser compatibility is difficult. See
Event in the reference section for documentation of each of the three
types of Event objects.
- Event propagation
-
In the basic event model, event handlers are triggered only for the
document element on which the event occurred. In the advanced models,
events can propagate up and/or down the element hierarchy and be
handled by one or more event handlers. In the Netscape and W3C
models, events start at the document object and propagate down
through the document tree to the element on which they occurred. If
any of the containing elements have special capturing event handlers
registered, these event handlers capture the event and get first
crack at handling it. In the IE and W3C models, certain types of
events (such as mouse clicks) bubble up the document tree after being
handled at their source. Thus, you might register an
onclick event handler on a
<div> object in order to handle all mouse
clicks that occur on elements within that
<div>. Capturing, bubbling, and normal event
handlers have the option of preventing the event from propagating any
further, although the way this is done is different in each model.
- Event handler registration
-
In the W3C event model, event handlers are not simply assigned to
properties of document objects. Instead, each document object has an
addEventListener( ) method that you call to
register an event handler function for a named type of event. This
allows advanced applications to register more than one handler for
the same event type.
11.3.9. JavaScript Security Restrictions
For security
reasons, client-side JavaScript implementations typically impose
restrictions on the tasks that scripts can perform. The most obvious
restrictions are omissions of dangerous capabilities: there is no way
for client-side JavaScript to delete files on a
user's local hard disk, for example. Other
restrictions exist to prevent the disclosure of private information
or to keep scripts from annoying users. There is no standard set of
security restrictions, but the following are restrictions found in
typical browser implementations. Don't attempt to
write scripts that do these things: even if they work for your
browser, they probably won't work in others.
- Same origin policy
-
Scripts can only read properties of windows and documents that were
loaded from the same web server. This is a substantial and pervasive
restriction on cross-window scripting, and prevents scripts from
reading information from other unrelated documents that the user is
viewing. This restriction also prevents scripts from registering
event handlers or spoofing events on unrelated documents.
- File uploads
-
Scripts cannot set the value property of the
FileUpload form element.
- Sending email and posting news
-
Scripts cannot submit forms to mailto: or
news: URLs without user confirmation.
- Closing windows
-
A script can only close browser windows that it created itself,
unless it gets user confirmation.
- Snooping in the cache
-
A script cannot load any about: URLs, such as
about:cache.
- Hidden windows and window decorations
-
A script cannot create small or offscreen windows or windows without
a titlebar.
Note that this list of security restrictions is not static. As the
use of JavaScript has grown, advertisers and unsavory characters have
started doing annoying things with it. As a result, newer browsers,
such as Mozilla 1.0, allow user-configurable security restrictions
that can prevent scripts from opening new windows (such as pop-up
ads), or from moving or resizing existing windows.
 |  |  | 11.2. Syntax |  | 11.4. JavaScript API Reference |
Copyright © 2003 O'Reilly & Associates. All rights reserved.
|