start page | rating of books | rating of authors | reviews | copyrights

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.1.1. The <script> tag

Most JavaScript code appears in HTML files between a <script> tag and a </script> tag. For example:

<script>
document.write("The time is: " + new Date());
</script>

In JavaScript 1.1 and later you can use the src attribute of the <script> tag to specify the URL of an external script to be loaded and executed. Files of JavaScript code typically have a .js extension. Note that the </script> tag is still required when this attribute is used:

<script src="library.js"></script>

HTML allows scripts to be written in languages other than JavaScript, and some browsers, such as Internet Explorer, support languages such as VBScript. You can use the language attribute to specify what language a script is written in. This attribute defaults to "JavaScript" in all browsers, so you do not usually have to set it. You can also use attribute values such as "JavaScript1.3" and "JavaScript1.5" to specify the version of JavaScript your code uses. Browsers that do not support the specified version of the language simply ignore the script.

HTML 4 doesn'tt actually recognize the language attribute of the <script> tag. Instead, the official way to specify the language a script is written in is with the type attribute. For JavaScript, set this attribute to the MIME type "text/javascript":

<script src="functions.js"
        language="JavaScript1.5"
        type="text/javascript"></script>

11.3.1.2. Event handlers

JavaScript code may also appear as the value of an event handler attribute of an HTML tag. Event handler attribute names always begin with "on". The code specified by one of these attributes is executed when the named event occurs. For example, the following HTML creates a button, and the onclick attribute specifies an event handler that displays an alert (a dialog box) when the user clicks the button:

<input type="button" value="Press Me"
       onclick="alert('Hello World!');">

A list of other available event handler attributes is included later in this section.

11.3.1.3. JavaScript URLs

JavaScript code may appear in a URL that uses the special javascript: pseudo-protocol. The content of such a URL is determined by evaluating the JavaScript code and converting the resulting value to a string. If you want to use a JavaScript URL to execute JavaScript code without returning any document content that would overwrite the current document, use the void operator:

<form action="javascript:void validate( )">

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.1. Simple dialog boxes

Three methods allow you to display simple dialog boxes to the user. alert( ) lets you display a message to the user, confirm( ) lets you ask the user a yes-or-no question, and prompt( ) lets you ask the user to enter a single line of text. For example:

alert("Welcome to my home page!"); 
if (confirm("Do you want to play?")) {
    var n = prompt("Enter your name");
}

11.3.2.2. The status line

Most web browser include a status line at the bottom of the window that is used to display the destination of links and other information. You can specify text to appear in the status line with the status property. The text you set on this property appears in the status area until you or the browser overwrites it with some new value. You can also set defaultStatus to specify text to appear by default when the browser is not displaying any other information in the status line. Here is an HTML hyperlink that uses JavaScript in an event handler to set the status text to something other than the URL of the link:

<a href="help.html"
   onmouseover="status='Help'; return true;">
Help</a>

11.3.2.3. Timers

Client-side JavaScript uses event handlers to specify code to be run when a specific event occurs. You can also use timers to specify code to be run when a specific number of milliseconds has elapsed. To run a string of JavaScript code after a specified amount of time, call the setTimeout( ) method, passing the string of code and the number of milliseconds. If you want to run a string of code repeatedly, use setInterval( ) to specify the code to run and the number of milliseconds between invocations. Both functions return a value that you can pass to clearTimeout( ) or clearInterval( ), respectively, to cancel the pending execution of code. For example:

var count = 0; 
// Update status line every second
var timer = setInterval("status=++count",1000);
// But stop updating after 5 seconds;
setTimeout("clearInterval(timer)", 5000);

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.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.4.3. Form validation

The <form> tag supports an onsubmit event handler, which is triggered when the user tries to submit a form. You can use this event handler to perform validation: checking that all required fields have been filled in, for example. If the onsubmit handler returns false, the form is not submitted. For example:

<form name="address" onsubmit="checkAddress()">
<!-- form elements go here -->
</form>
<script>
// A simple form validation function
function checkAddress() {
  var f = document.address; // The form to check
  // Loop through all elements
  for(var i = 0; i < f.elements.length; i++) {
    // Ignore all but text input elements
    if (f.elements[i].type != "text") continue;
    // Get the user's entry
    var text = f.elements[i].value;
    // If it is not filled in, alert the user
    if (text == null || text.length == 0) {
      alert("Please fill in all form fields.");
      return false;
    }
  }
}
</script>

11.3.4.4. Image rollovers

The legacy DOM allows you to accomplish one common special effect: dynamically replacing one image on the page with another. This is often done for image rollovers, in which an image changes when the mouse moves over it. The images[ ] array of the Document object contains Image objects that represent the document's images. Each Image object has a src property that specifies the URL of the image to be displayed. To change the image that is displayed, simply set this property to a new URL:

document.images[0].src = "newbanner.gif";

To use this technique for an image rollover, you must use it in conjunction with the onmouseover and onmouseout event handlers that are triggered when the mouse moves on to and off of the image. Here is some basic HTML code with JavaScript event handlers to accomplish a rollover:

<img name="button" src="b1.gif"
     onmouseover="document.button.src='b2.gif';"
     onmouseout="document.button.src='b1.gif';">

When an image is going to be dynamically displayed, it is helpful to preload it into the browser cache so that there is no network delay before it appears. You can do this with a dynamically created off-screen Image object:

var i = new Image(); // Create Image object
i.src="b2.gif";      // Load, but don't display image

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.1. Finding elements by ID

When creating a document that contains special elements that will be manipulated by a script, you can identify each special element by giving it an id attribute with a unique value. Then, you can use the getElementById( ) method of the Document object to look up those elements by their ID:

<h1 id="title">Title</h1>  
<script>
var t = document.getElementById("title");
</script>

11.3.5.2. Finding elements by tag name

Another way to access document elements is to look them up by tag name. The getElementsByTagName( ) method of the Document object returns an array of all elements of that type. Each document element also supports the same method, so you can obtain an array of specific types of tags that are descendants of an element:

// Get an array of all <ul> tags
var lists = document.getElementsByTagName("ul");
// Find the 3rd <li> tag in the second <ul>
var item = lists[1].getElementsByTagName("li")[2];

11.3.5.3. Traversing a document tree

The W3C DOM represents every document as a tree. The nodes of this tree represent the HTML tags, the strings of text, and the HTML comments that comprise the document. Each node of the tree is represented by a JavaScript object, and each has properties that allow you to traverse the tree, as illustrated by the following code fragment:

// Look up a node in the document
var n = document.getElementById("mynode");
var p = n.parentNode;  // The containing tag
var c0 = n.firstChild;    // First child of n
var c1 = c0.nextSibling;  // 2nd child of n
var c2 = n.childNodes[2]; // 3rd child of n
var last = n.lastChild;   // last child of n

See Node in the reference section for further details.

The Document object itself is a kind of node, and supports these same properties. The documentElement property of the Document object refers to the single <html> tag element at the root of all HTML documents, and the body property refers to the <body> tag.

11.3.5.4. Node types

Every node in a document tree has a nodeType property that specifies what type of node it is. Different types of nodes are represented by different subclasses of the Node object. The following nodeType values are relevant to JavaScript programmers working with HTML documents (other values exist for XML documents):

nodeType

Represents

1

Element: an HTML tag

2

Text: text in a document

8

Comment: an HTML comment

9

Document: the HTML document

Use the nodeName property of an Element node to determine the name of the HTML tag it represents. Use the nodeValue property of Text and Comment nodes to obtain the document text or comment text represented by the node. See Element, Text, Comment, and Document in the reference section for details on each of these node types. Also see Node for information on the common properties and methods they all share.

11.3.5.5. HTML attributes

As we've seen above, HTML tags in a document tree are represented by Element objects. In HTML documents, each Element object has properties that correspond directly to the attributes of the HTML tag. For example, you can query or set the value of the caption attribute of a <table> tag by setting the caption property of the corresponding Element object. See Element in the reference section for details.

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.5.7. Changing document text

You can change the textual content of a document simply by setting the nodeValue property of a Text node:

// Find the first <h1> tag in the document
var h1 = document.getElementsByTagName("h1")[0];
// Set new text of its first child
h1.firstChild.nodeValue = "New heading";

In addition to manipulating the nodeValue property, the Text object also allows you to modify the data property, or to use methods to append, insert, delete, or replace text.

Note that the problem with the previous code is that it assumes that the content of the <h1> tag is plain text. The code would fail for a document with the following heading because the text of the heading is a grandchild of the <h1> tag rather than a direct child:

<h1><i>Original Heading</i></h1>

One way around this problem is to set the innerHTML property of the heading node. This property is part of the IE 4 DOM, not the W3C DOM, but it is supported by most modern browsers because it is so useful. We'll see it again when we consider the IE 4 DOM. Another way around the problem is to replace the heading node with a newly created <h1> tag and text node containing the desired text, as shown in the next section.

11.3.5.8. Changing document structure

In addition to changing document text and the attributes of document elements, the W3C DOM allows you to alter the tree structure of the document itself. This is done with Node methods that allow you to insert, append, remove, and replace children of a node and with Document methods that allow you to create new Element and Text nodes. The following code illustrates:

// Find a <ol> element by name:
var list = document.getElementById("mylist");
// Create a new <li> element
var item = document.createElement("li");
// Append it to the list
list.appendChild(item);
// Create a Text node
var text = document.createTextNode("new item");
// Append it to the new <li> node
item.appendChild(text);
// Remove the new item from the list
list.removeChild(item);
// Place the new item at the start of the list
list.insertBefore(item,list.firstChild);

As a further example, here is a JavaScript function that uses the W3C DOM to embolden an arbitrary document node by reparenting it within a newly created <b> tag:

function embolden(node) {  // Embolden node n
  var b = document.createElement("b");
  var p = n.parentNode; // Get parent of n
  p.replaceChild(b, n); // Replace n with <b> 
  b.appendChild(n);     // Insert n into <b> tag
}

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.6.4. DOM compatibility

If you want to write a script that uses the W3C DOM when it is available, and otherwise uses the IE 4 DOM if it is available, you can use a capability-testing approach that first checks for the existence of a method or property to determine whether the browser has the capability you desire. For example:

if (document.getElementById) {
  // If the W3C method exists, use it
}
else if (document.all) {
  // If the all[] array exists, use it
}
else {
  // Otherwise use the legacy DOM
}

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.1. Event handlers as JavaScript functions

We've seen that the various document object models represent HTML tags as JavaScript objects, with the attributes of those tags as properties of the objects. The same is true of event handlers. If your HTML document includes a single <form> tag with an onsubmit event handler attribute, that event handler is available as:

document.forms[0].onsubmit

Although HTML event handler attributes are written as strings of JavaScript code, the value of the corresponding JavaScript properties are not strings of code, but actual JavaScript functions. You can create a new event handler simply by assigning a function to the appropriate property:

function validate() { // Form validation function
  // check validity here
  return valid;       // return true or false
}
// Now check user input before submitting it
document.forms[0].onsubmit = validate;

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.