home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeWebmaster in a Nutshell, 3rd EditionSearch this book

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.1. JavaScript in HTML

JavaScript code may be embedded in HTML files in the form of scripts, event handlers and URLs, as detailed below.

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.4. System information

The navigator and screen properties of the Window object refer to the Navigator and Screen objects, which themselves define properties that contain system information, such as the name and version of the web browser, the operating system it is running on, and the resolution of the user's screen. See Navigator and Screen in the reference section for details. The Navigator object is commonly used when writing code specific to a particular web browser or web browser version:

if (navigator.appName == "Netscape" &&
    parseInt(navigator.appVersion) == 4) {
  // Code for Netscape 4 goes here.
}

11.3.2.5. Browser navigation

The location property of the Window object refers to the contents of the browser's location bar (the field that you type URLs into). Reading the value of this property gives you the URL that is currently being displayed. More importantly, setting the location property to a new URL tells the browser to load and display the document referred to by that URL:

// In old browsers, load a different page
if (parseInt(navigator.appVersion) <= 4)
    location = "staticpage.html";

Note that any script or event handler that sets the location property of its own window (we'll discuss multiple windows and multiple frames later in this section) is overwritten when the new document is loaded and will not continue running!

Although the location property can be queried and set as if it were a string, it actually refers to a Location object. The Location object has properties that allow you to query and set individual portions of the currently displayed URL:

// Get the substring of the URL following ?
var query = location.search.substring(1);
// Scroll to a named portion of the document
location.hash = "#top";

In addition, the reload( ) method makes the browser reload the currently displayed URL.

The history property of the Window object refers to the History object for the browser window. This object defines methods that allow you to move the browser backward and forward through its browsing history, just as the user can with the browser's Back and Forward buttons:

history.back();    // Go back once
history.forward(); // Go forward
history.go(-3);    // Go back three times

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.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.4.5. Working with cookies

The cookie property of the Document object is a peculiar one that allows you to set and query the cookies associated with your document. To associate a transient cookie with the document, simply set the cookie property to a string of the form:

name=value

This creates a cookie with the specified name and value for this document. If you want to create a cookie that is stored even when the user quits the browser, add an expiration date using a string of the form:

name=value; expires=date

The expiration date should be in the form returned by Date.toGMTString( ). If you want the cookie to be accessible to other documents from your web site, you can specify a path prefix:

name=value; expires=date; path=prefix

A single document may have more than one cookie associated with it. To query a document's cookies, simply read the value of the cookie property. This string contains name=value strings separated from each other by a semicolon and a space. When reading cookies, you'll never see a "path=" or "expires=" clause; you'll just get the cookie name and value. Here's a function that retrieves the value of a single named cookie from the cookie property. It assumes that cookie values never contain semicolons.

function getCookie(name) {
  // Split cookies into an array
  var cookies = document.cookie.split('; ');
  for(var i = 0; i < cookies.length; i++) {
    var c = cookies[i];         // One cookie
    var pos = c.indexOf('=');   // Find = sign
    var n = c.substring(0,pos); // Get name
    if (n == name)              // If it matches
      return c.substring(pos+1);  // Return value
  }
  return null;  // Can't find the named cookie
}

11.3.5. The W3C DOM

The W3C DOM standardizes most of the features of the legacy DOM, but also adds important new ones. In addition to supporting forms[ ], images[ ], and other array properties of the Document object, it defines methods that allow scripts to access and manipulate any document element, not just special-purpose elements like forms and images.

11.3.5.6. Manipulating document elements

One easy way to manipulate HTML documents with the W3C DOM is simply to set the properties that correspond to HTML attributes. As we saw in the legacy DOM, this allows you to change images by setting the src property of the document element that represents an <img> tag, for example. It also allows you to set colors, sizes, and alignments of document elements. One particularly fruitful way to manipulate document elements is through the style property which controls CSS styles. We'll cover this important topic in more detail later in this chapter.

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.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.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.