CHAPTER

4

JavaScript and the Document Object Model

Chapter Objectives

images Describe the basic features of the JavaScript programming language

images Introduce the Browser Object Model and how to manipulate it by using JavaScript

images Introduce the Document Object Model and how to modify it by using JavaScript

images Describe how to manipulate web page styles by using JavaScript

images Describe how to handle web browser events in JavaScript

4.1 JavaScript—the J in Ajax

 

JavaScript is an interpreted programming language like Perl, Python, Ruby, and countless others. JavaScript is used predominantly to add dynamic behavior to web pages. All modern web browsers, meaning practically any browser released later than Netscape version 4.5 or Internet Explorer (IE) version 4, include an interpreter that can execute JavaScript code.

JavaScript1 is actually the name of a language that was first created by Netscape for the Netscape 2 browser and is now maintained by the Mozilla Foundation.2 To compete with Netscape, Microsoft created a near copy of the original JavaScript language, which they called JScript, and added it to their IE3 browser. Developers who made use of this new dynamic capability found that it was frustrating to write code that was compatible with both browsers. To account for the differences between JavaScript and JScript (and other implementations), one had to add countless branches in the code, which was time-consuming to write and painstaking to maintain. So, Ecma International3 undertook an effort to standardize the language and eventually published ECMA-262,4 which is a vendor-neutral language specification called ECMAScript. Mozilla's JavaScript and Microsoft's JScript (mostly) now conform to ECMA-262 Edition 3. Despite the official name of the language (and the names of the various implementations), the name JavaScript is commonly used, which is the term used in the Ajax acronym and thus isthe term that will be used throughout this book.

JavaScript is similar in syntax to C++ and Java, but quite different. JavaScript is a full-featured language that is loosely typed and includes object-oriented capabilities. As you might expect, JavaScript, being a full-featured object-oriented language, has support for different datatypes; various statements, including if/else, switch, and different kinds of loops; notation for defining functions that will accept arguments and return a value; exception handling; notation for defining and creating objects; and support for inheritance. Unlike C++ and Java, in JavaScript you do not specify a type when declaring variables, objects map property names to arbitrary property values (like a hash table or associative array), and inheritance is prototype based—there is no formal notion of a class in JavaScript.

Ecma International is currently working on Edition 4 of ECMA-262,5 which is based on a proposal from Mozilla for JavaScript 2.0. JavaScript 2.0 proposes overhauling JavaScript to add strong typing and class-based inheritance. It is unknown when Edition 4 will be completed or how long thereafter it will take browsers to conform, so JavaScript 2.0 will not be covered in this book. The following sections cover the core JavaScript language as of ECMA-262 Edition 3.

Several JavaScript code examples are presented in the following sections and the rest of this book. You can easily test the JavaScript examples by executing the code in Firebug,6 a development tool for the Firefox7 web browser. Firebug provides a command line from which you can execute arbitrary JavaScript code. You can see the results of executing the sample JavaScript from this chapter by entering the code into the Firebug command line. Doing so is a great way to learn JavaScript and understand the code samples in this book. The Firebug command line gives you an excellent tool for experimenting with the JavaScript language in the context of a running web browser. See the Appendix for information on how to set up and use Firebug.

4.1.1 Comments

The syntax for comments in JavaScript is the same as that for C++ and Java. Single-line comments begin with two forward slashes (//). Multiline comments are opened with a forward slash followed by an asterisk (/*) and closed with an asterisk followed by a forward slash (*/). Be sure not to write “*/” within a multiline comment because doing so will close the comment and the rest of the comment will cause an error. Here are some examples.

images

4.1.2 Identifiers

Identifiers are used to name variables, functions, and labels. The first character of an identifier must be a letter, underscore (_), or dollar sign ($). Subsequent characters can be a letter, a digit, an underscore, or a dollar sign. You may not use any of the JavaScript-reserved words as identifiers. Tables 4.1.1-4.1.3 list JavaScript-reserved words and other identifiers to avoid.

4.1.3 Datatypes and Values

JavaScript supports the datatypes Null, Undefined, Number, Boolean, String, and Object. These datatypes are discussed in the following sections. They can be divided into two categories: primitive types and reference types. Object is the only reference type; the rest are primitive types. The primitive types Number, Boolean, and String have associated global wrapper objects that are discussed in Section 4.1.3.9.

Because JavaScript is loosely typed, any datatype can be used in place of any other datatype and JavaScript will automatically perform a conversion.

4.1.3.1 Null

Null has exactly one value, null, which represents a null, empty, or nonexistent reference. Variables that hold the value null do not contain a valid object, array, number, string, or Boolean value.

4.1.3.2 Undefined

Undefined has exactly one value, undefined, which is returned when you use a variable that has been declared but never assigned a value or you use an object property that does not exist. The values null and undefined are distinct; therefore, JavaScript's identity operator (===) and typeof operator do not treat them as equal. However, JavaScript's equality operator (==) does consider them equal because it performs a type conversion. The identity operator (===) checks whether two operands are identical, whereas the equality operator (==) checks whether two operands are equal. Values null and undefined are not identical because they are two distinct values; however, they do evaluate to equal because they both indicate an absence of value.

Table 4.1.1 JavaScript-Reserved Words

images

Table 4.1.2 Future JavaScript-Reserved Words

images

Table 4.1.3 Additional Identifiers to Avoid

images

4.1.3.3 Number

Number represents the set of values defined by the double-precision 64-bit format of the IEEE 754 standard and the special NaN (“Not a Number”) and Infinity (positive and negative) values. This means that JavaScript can represent numbers as large as ±1.7976931348623157 × 10308 and as small as ±5 × 10-324. Unlike C++ and Java, this single datatype encompasses both integer and floating-point values. JavaScript will exactly represent integers only between—9007199254740992 (253) and 9007199254740992 (253), inclusive—beyond that you may lose precision. However, certain integer operations, like the bitwise operators, are performed on 32-bit integers, which range from—2147483648 (231) to 2147483647 (231 1).

The ECMAScript standard defines support for hexadecimal (base 16) number values. You begin a hexadecimal value with “0x” or “0X” and follow that with a combination of 0 through 9 and a through f, case insensitive. For example, 0x1F is 31 in base 10 (1 × 16 + 15 = 31).

Although not defined by the ECMAScript standard, some implementations of JavaScript have support for octal (base 8) number values. Octal number values begin with a 0 followed by digits between 0 and 7. For example, 037 is 31 in base 8 (3×8 + 7 = 31). Writing an integer in JavaScript with a leading zero is bad practice because only some implementations support octal values and others do not.

JavaScript also supports exponential notation. For example, 5.43e12 = 5.43 × 1012 and 5.43E-12 = 5.43 × 10-12—“e” is case insensitive.

JavaScript has a few special numeric values. Infinity is a special value you will get when a number becomes larger than the largest representable finite number. There is also -Infinity for the negative end of the spectrum. NaN is returned by a mathematical operation that returns an undefined result (such as 0 divided by 0) or an error. NaN does not compare equal to any value, including itself, but JavaScript has a global function, isNaN(), for testing this value. A related function, isFinite(), tests whether a number is not NaN and is not positive or negative Infinity. The Number primitive type has an associated Number object that contains properties for the largest and smallest representable numbers, NaN, and positive and negative Infinity, as well as some useful conversion methods.8 Also, JavaScript provides the Mathobject, which contains common mathematical constants, like π, and common mathematical functions, like trigonometric, logarithmic, and exponential.

4.1.3.4 Boolean

Boolean has exactly two values, true and false. It is similar to Booleans in Java, except that Booleans in JavaScript can be converted to and from other datatypes.

4.1.3.5 String

String is the datatype for all string values. Strings are defined by enclosing a sequence of characters in matching pairs of double quotes (“hello”) or single quotes (‘hello’). Strings must be defined on one line. If your string must contain single quotes (or an apostrophe), then use double quotes to define the string (i.e., “that's cool”), or vice versa (i.e., ‘name=“bob”’). JavaScript also supports escape syntax like Java (i.e., ‘that's cool’), so you can add a new line to a string by using (i.e., “here is a string spanning two lines”). Also, JavaScript supports escape syntax for Unicode9 characters (e.g., uXXXX).

Strings are special in JavaScript in that they are not of type Object, yet you can use object notation for accessing their properties and methods (all of which are defined in the wrapper object for the String type, called String; see Section 4.1.3.9). For instance, you can get the length of a String through a property like this:

images

Or you can get a single character from a String like this (JavaScript strings are indexed starting with zero, like Java):

images

Strings in JavaScript can be concatenated using the + operator. This approach is useful when adding another datatype value to a string or breaking a string across lines for readability.

images

When using mathematical operators other than + (e.g., -, *, /) with strings and numbers, JavaScript will first attempt to convert the String to a Number before performing the operation.

images

You can also explicitly convert from a String to a Number by using the built-in Number function.

images

Or you can use the built-in functions parseInt() and parseFloat(). These functions convert and return any number at the beginning of a String, ignoring any trailing characters that are not numbers. However, if a Number in String form begins with 0x or 0X, parseInt() will convert it as a hexadecimal number. ECMAScript says that if a String begins with 0 (but not 0x or 0X), parstInt() may parse it as an octal number or a decimal number. Therefore, you should never use parseInt() to parse numbers with leading zeros, unless you use the second optional parameter to parseInt(), which allows you to specify the radix to be used.

images

Once you have defined a String, you cannot modify it. Strings are immutable, as they are in Java. Unlike Java, however, strings in JavaScript are compared by value. In Java, you have to use the equals() method to compare the value of strings; otherwise, you will compare the references. In JavaScript, strings are treated like primitives and the values are compared. Also, JavaScript does not have a datatype to represent one character, like char in Java.

4.1.3.6 Object

Object types are unordered collections of values, called properties, where each property may contain a primitive value, object, or function (functions are discussed in more detail in Section 4.1.8). JavaScript comes with a predefined (built-in) set of object types, and the user can also define custom object types (something like defining classes in Java).

Unlike C++ and Java, everything in a JavaScript object is a property. You can refer to properties of JavaScript objects by using dot notation, like in C++ and Java, or an arraylike notation. For example, in dot notation, document.body.bgColor refers to the bgColor property of the object stored in the body property of the document object. In JavaScript's arraylike notation, the previous example looks like document[“body”][“bgColor”]. This arraylike treatment of JavaScript objects is often referred to as associative arrays (works something like a hash table with key-value pairs). JavaScript associative arrays are powerful because they allow you to dynamically put together the name of the property and then reference it. For example, you may write code like myObject[“property” + i], where i is an incrementing index. If i were 5, then you would be referencing myObject.property5.

When a function is assigned to a property of an object, it is called a method, like in Java. To get a reference to an object's method you use the same syntax as you do with any other property of the object. For example, document.body.onload returns a reference to the onload() method of the object stored in the body property of the document object. Referencing the method this way does not invoke it; it just gives you a handle that you can pass around or invoke in another statement. Functions in JavaScript are actually a special kind of object. To invoke the method, you use the () operator on the handle like this: document.body.onload().

The syntax for referencing methods is the same for referencing other properties of the object. Therefore, there may be a time when you need to dynamically determine what type you have a reference to. The typeof operator gives you that ability. In the previous example, typeof document.body.onload would return “function” and typeof document.body would return “object”.

All objects in JavaScript inherit properties and methods from a built-in Object definition (something like the Java Object class), which includes methods like toString(), which returns a String representation of the object, and valueOf(), which returns the primitive value of the object (useful on primitive wrapper objects; see Section 4.1.3.9).

To create an object, you use either a constructor function or literal notation. A constructor function is a JavaScript function that can be used in conjunction with the new operator to create an instance of a type of object. For example, you can create an instance of the Object type by using the Object() constructor function.

images

Or you can create an instance of the Object type by using object literal notation, which has the same effect as using the constructor function.

images

Object literal notation is simply a set of comma-separated name-value pairs inside curly braces. The names can be identifiers or strings followed by a colon. The values can be any JavaScript datatypes or expressions of any type. So we can create an object with two properties like this:

images

The first property of myObj is a String and the second property is an Object that has three string properties.

In JavaScript you can dynamically add and delete properties to any object instance. You add properties by just assigning them a value, and you delete properties with the delete operator. Using myObj that we just created, we could delete the name property and add firstName and lastName properties.

images

When a nonnull object is used in a Boolean context, it converts to true. When used in a String context, JavaScript calls the toString() method of the object and uses the returned value. When used in a Number context, JavaScript first calls the valueOf() method of the object. If valueOf() returns a primitive value, that value is used. However, valueOf() typically returns the object itself, in which case JavaScript calls toString() on the object and then attempts to convert the resulting String to a Number.

4.1.3.7 Type Conversion

Some type conversion was discussed in the preceding datatype sections. Table 4.1.4 summarizes the type conversions that JavaScript will perform with specific values. A 0 Number converts to a false Boolean, and a 1 Number converts to a true Boolean, but “0” and “1” Strings both convert to a true Boolean. Also, null, undefined, NaN, and “” (empty String) all convert to a false Boolean.

4.1.3.8 Primitive vs. Reference Types

In general, primitive types in JavaScript are manipulated by value and reference types are manipulated by reference. “By value” means that when you pass a primitive type like a Number as a function argument, the number is copied and the copy is passed to the function. When you assign a variable the value of another variable, if that value is a primitive type, it is copied. If the value is a reference type, the value is not copied; instead, a new reference is made to the value. The only reference type in JavaScript is Object, however, which means that all objects—including built-in objects, user-defined objects, and special types of objects like arrays and functions—are manipulated by reference. If you pass an object as a function argument, that object is not copied; instead, the reference to the object is copied and passed to the function so that the function has its own reference. If a change is made to the object inside the function, using the function's reference, that change is also seen outside the function. However, if the function overwrites the reference with a reference to another object, the original reference passed to the function is unaffected.

Table 4.1.4 JavaScript Type Conversion

images

4.1.3.9 Primitive Datatype Wrapper Objects

JavaScript defines objects for the primitive types Boolean, Number, and String that wrap the primitive value and provide properties and methods to manipulate the value. You rarely need to create these objects explicitly because they are automatically created for you by JavaScript when necessary. When you use a primitive value in an Object context, JavaScript automatically creates the corresponding wrapper object and assigns it the primitive value. For example, when you have code like “12,51,31”.split(“,”), JavaScript creates an instance of the String object to handle the split() method call and then discards the object when done. In general, the wrapper objects are treated the same as their associated primitive values except for a few cases noted in the following discussion.

If you want to create an explicit instance of a wrapper object, you use the new operator. However, the wrapper object will always convert to true when used in a Boolean context (that applies to all objects)—for example, when you define a Boolean object with a value of false and then use it in a Boolean context.

images

Also, the typeof operator and the eval() built-in function both treat wrapper objects and their associated primitives as different types.

images

The wrapper object constructors are also JavaScript functions that can be used to convert a value to the associated primitive value by using JavaScript's conversion rules. Here are some examples. The new operator is not used because we are not constructing objects.

images

The Object() function, used to construct Object instances, is also a function that can be used to convert any value toAlso, JavaScript provides the Math an Object.

images

4.1.4 Built-In Objects and Host Objects

When the JavaScript interpreter starts up, it creates a unique global object before executing any JavaScript code. When you create a top-level variable in JavaScript, you are actually creating a property of the global object (by top-level we mean code not contained in a function or object). The global object contains several properties, including built-in objects (like the wrapper objects already mentioned) and host objects supplied by the host environment. The host environment for client-side JavaScript is the web browser.

The exact list of built-in objects depends on the implementation, but ECMAScript standardizes several of them that you will find in all implementations, which are collectively called the JavaScript core. The JavaScript core includes the wrapper objects (Number, Boolean, and String); the Object object; Array, Date, and Math objects; a regular expression object (RegExp); a Function object; an Error object (and several derivatives); and many built-in functions like parseInt() and parseFloat(). Mozilla's JavaScript reference labels their built-in objects as Global Objects10 and Global Functions11 (functions in JavaScript are types of objects).

Web browsers supply the host objects defined by the Document Object Model (DOM)12 and the Browser Object Model (BOM). The DOM provides a read/write model of the loaded HTML document for dynamically manipulating the content and behavior of the web page. The BOM provides an Application Programming Interface (API) for manipulating the web browser windows, built-in dialogs, toolbar buttons, etc. The DOM is standardized by the World Wide Web Consortium (W3C),13 but not all browsers fully implement it. The BOM is a kind of de facto standard, but it varies among browsers. The DOM and the BOM are often collectively referred to as the DOM, but it is more accurate to note that only the DOM is an official standard. Mozilla's host objects are documented in Mozilla's DOM reference.14 The BOM is covered in Section 4.3, and the DOM is covered in Section 4.4.

The BOM is made available to client-side JavaScript via properties of the window object, which is the global object in a web browser. Nested in the window object is the document object, which provides the DOM—an in-memory representation of the parsed web page. In top-level code you can refer to the global object by using the this keyword or the global window or self property. The this keyword refers to the containing object and therefore has different meanings depending on the context in which it is used. In top-level code, the containing object is the window object. Following are some examples using these global properties in top-level code.

images

4.1.5 Variables

Variables in JavaScript are used to associate a name with a value. To declare a variable in JavaScript, you use the var keyword—you do not specify the variable datatype as you do in Java or C++.

images

JavaScript will generate an error if you attempt to read the value of a variable that has not been declared. The initial value for declared variables is undefined. However, you can combine variable declaration with variable assignment.

images

A declared variable can be assigned and reassigned any datatype. A variable can also be declared more than once. If the repeated declaration includes an assignment, the value is simply assigned to the existing variable.

images

Variables declared outside a function by using the var keyword become properties of the global object. If you assign a value to a variable but you do not declare the variable with the var keyword, then JavaScript implicitly creates the variable for you as a property of the global object, even if the code is contained within a function. This concept may be clearer if you think of variables that you declare as just properties of some object—the global object, a function you define, an object you define, or some built-in object. As top-level code, independently, each of the following statements would create a variable that is a property of the global object.

images

4.1.5.1 Scope

Variables in JavaScript are visible only from within the object in which they were declared. Variables with global scope (called global variables) are variables that were declared as properties of the global object (either implicitly or explicitly) and are visible anywhere in your JavaScript program. Variables with local scope (called local variables) are declared within a function or as properties of some object other than the global object and are visible only within that object. If you declare a local variable in a function with the same name as an existing global variable, the local variable takes precedence over the global variable.

images

You should always use the var keyword to declare variables. If you do not use var to declare a variable, the variable will be created in the global namespace. This clutters the global namespace and often causes bugs. The only way to declare a local variable is to either assign a property to an object or use the var keyword.

images

You should even use var to declare the variables in a for loop. The variables declared in the loop become a property of the containing object. If the loop is top-level code, then the variables are added to the global object, i.e., global variables. If the loop is contained within a function, then the variables are added to the activation object for the function, i.e., local variables. A function's activation object is an object created by the JavaScript interpreter to contain a function's parameters and local variables as a means of providing local scope.

images

JavaScript allows nested functions of any arbitrary depth. A nested function has its own scope but can also read local variables declared in any of its containing functions as well as global variables (in this context it might help to think of the global object as the outermost containing function). As you might expect, a containing function cannot read a nested function's local variables.

images

JavaScript does not have block-level scope like Java, so all variables declared anywhere in a function are defined throughout the function, even before the function is executed. This can have unexpected results. For example, you may think that the following function will display the value of the global variable scope and then the value of the local variable scope; however, when the JavaScript interpreter reads the function definition, it declares the local variable scope before the line that assigns a value to it is executed. You might also think that variables i and count would be visible only within the for loop, but that is not the case. Therefore, you should always declare your function variables at the top of the function definition.

images

4.1.6 Statements

Statements in JavaScript can end in either a semicolon or a line break. For example, both of the following are complete statements.

images

Eliminating semicolons is considered sloppy programming and can lead to bugs, so you should get into the habit of always using semicolons at the end of a statement. Also, because JavaScript will automatically add a semicolon to a line without one, you must be careful where you make your line breaks. For example,

images

will generate an error because it will be interpreted as

images

JavaScript has many of the same statements you find in Java and C++, with a few differences. Table 4.1.5 summarizes the most common JavaScript statements.

Table 4.1.5 JavaScript Statements

Statement Syntax Purpose
break

break;

break label;

Break out of a loop or switch and continue after the loop or at a labeled statement.
continue

continue;

continue label;

Break from the current loop and continue with the next iteration or at a labeled statement.
do/while images A loop that executes the code block before evaluating the expression.
for images A loop that performs initialization, evaluates a Boolean condition before each iteration, and performs an increment after each iteration.
for/in images Loop through the properties of an object or the indexes of an array.Built-in methods and some built-in properties are not enumerated.
if/else images Conditionally execute code blocks.
return images Return from a function, optionally returning the result of an expression.
switch images Branch based on value of switch expression to execute matching case code blocks or default code block if no match is made.The break statements and the default code block are optional. The switch and case accept any arbitrary expression and may evaluate to any type.
throw throw expression; Throw an exception.
try/catch images Catch an exception from a code block, if any, and execute a final code block regardless of whether an exception is thrown.Either the catch block or the finally block can be left out, but not both.
while images A loop that evaluates the expression before executing the code block.

4.1.7 Operators

JavaScript has many of the same operators you find in Java and C++, with a few additions, some of which are discussed in this section (see Table 4.1.6).

4.1.8 Functions

Functions in JavaScript are like methods in Java, or subroutines or procedures in other languages—they define a block of code that can be invoked any number of times. Functions in JavaScript are first class objects that can be assigned to variables or added to arrays or passed as parameters to other functions, and they can be invoked at any time by using any one of potentially many references.

JavaScript functions can optionally specify a comma-separated list of any number of parameters and optionally return one value. Function declarations do not specify datatypes for the parameters or the return value. The parameter list serves only to declare local variable names for the parameters. The use of a return statement within the function causes the function to stop executing and return the value of the return statement expression, if any. If a return statement is not used or the return statement does not have an associated expression, JavaScript returns undefined. Once defined, a function can be invoked by using the () operator. Functions in JavaScript are defined by using the function statement.

images

Table 4.1.6 JavaScript Operators

images

Defined in top-level code, the preceding statement creates a property of the global object called sayHello that refers to a function object. Consequently, JavaScript also allows anonymous functions to be defined as statements called function literals. So that example can be written like the following. This is called an anonymous function because no name is given to the function when it is defined. Instead, the resulting object is assigned to a variable.

images

Or you could define the function as a property of your own object.

images

JavaScript allows you to optionally provide a name for anonymous functions that can be used only inside the function itself. This approach can be useful for defining recursive functions.

images

Using function literals, you can even define and invoke a function in the same statement. In the following example, the function definition is surrounded with parentheses, (), and then invoked using the () operator, passing the function the value 5, and the result is assigned to a variable, all in one statement.

images

Another awkward, and thus unpopular, way to create a function is using the built-in Function() constructor. The Function() constructor accepts the arguments and body of the function as strings. Even if nested in another function, the Function() constructor creates only top-level functions, so you cannot use the Function() constructor to create a nested function that accesses the containing function's local variables. The Function() constructor is also the Function object that all functions inherit from (and Function inherits from Object). Using the Function() constructor, we can create a function to perform addition like this.

images

4.1.8.1 Optional and Variable-Length Arguments

JavaScript functions can be invoked with any number of parameters, regardless of the number of parameters specified in the function definition. If some parameters are not passed to a function when it is invoked, those parameters are assigned a value of undefined. For example, the following function is written to optionally add three parameters. Note that undefined evaluates to false in a Boolean context, whereas any nonzero number evaluates to true.

images

images

Because any number of parameters can be passed to a function, JavaScript provides every function a built-in arguments property that references an arraylike Arguments object, which contains the list of the parameters that were passed to the function. For example, the add function could be rewritten to add any number of arguments.

images

Although the Arguments object provides arraylike access to the function parameters, it is not an array. It is a special object for functions. Named parameters are tied directly to their associated values in the arguments object. If you change a parameter value by using the parameter name, the value in the arguments object changes and vice versa. In addition to an indexed parameter list, the arguments object provides the ability to reference named parameters by using the names identified in the function definition (i.e., arguments[“x”]). The arguments object also provides the property callee that refers to the function currently being executed. For example, you could use the callee object to allow an anonymous function to call itself.

images

Whereas the length property of the arguments object specifies the number of parameters that were passed to a function, the length property of the function itself specifies the number of parameters that were defined in its parameter list.

images

4.1.8.2 Lexical Scoping and Closures

JavaScript functions use the scope in which they are defined, not the scope in which they are executed. This concept is called lexical scoping. When a function is defined, the current scope chain is saved and becomes part of the internal state of the function. The scope chain includes, in order, the function's Arguments object, parameters, local variables, and then any containing objects from inside out in order of containment. Therefore, as expected, the function has access to the variables in containing functions except those hidden by local variables with the same name. The last item in the scope chain is the global object. For functions defined at the top level, the global object is the only containing object.

The combination of the code to be executed and the scope to be executed in is called a closure. JavaScript functions are closures, as demonstrated in the following example. This example illustrates that the exported nested function (the closure) retains a reference to the values of the containing function's arguments as they were when the nested function was created.

images

An interesting use of this behavior is using closures to create a persistent and private variable. JavaScript does not have a notion of private variables like in Java. Yet in the following example we can create a variable that is accessible only by an exported nested function.

images

4.1.8.3 apply() and call()

As mentioned previously, when a function is a property of an object, it is called a method. Normally you invoke a method of an object by referencing the object.

images

JavaScript provides two methods for all function objects, call() and apply(), that allow a function to be invoked as if it were a method of another object; in other words, they change a function's scope chain. The first argument to call() and apply() is the object on which the function should be invoked, which becomes the value of this within the body of the function. The remaining arguments are the parameters that should be passed to the function. The call() method accepts a variable list of parameters to pass to the function being invoked, whereas apply() accepts an array of parameters. See Mozilla's online JavaScript reference for examples of interesting uses of call()16 and apply().17 An example using call() follows. Notice how the value of this in the displayName() function becomes the first argument that was passed to the call() method.

images

4.1.9 Arrays

Arrays in JavaScript are a special form of object that provides the ability to reference its properties by using a zero-based nonnegative integer index and a special length property. The length property holds the current length of the array and can be set to a different value to increase or shorten the length of the array. Arrays in JavaScript are not typed, so they can contain any combination of datatypes, including other arrays and functions. JavaScript does not support multidimensional arrays, but you can create arrays of arrays. Unlike Java or C++, JavaScript arrays dynamically grow to hold new elements that are added to them.

Arrays are created using either the Array() constructor function or array literal notation. The only reason to use the Array() constructor is to create an empty array of a specified length.

images

4.1.10 Regular Expressions

Regular expressions in JavaScript can be created using the RegExp() constructor or a regular expression literal notation. For example, the following two examples create a regular expression object that matches the word “ajax”, case insensitive.

images

images

You must use two backslashes for special characters when using the RegExp() constructor (i.e., “\b”). See the Mozilla online documentation18 on RegExp for details on the special characters that can be used.

4.1.11 Error Handling and Error Objects

JavaScript defines several objects that represent errors, which include Error, EvalError,RangeError, ReferenceError, SyntaxError, TypeError, and URIError. These error objects are generated by the JavaScript interpreter when a runtime error occurs. Each error object contains a message property that contains an error message.19

You can throw an exception by using the throw keyword followed by an expression that evaluates to any type. So you can throw an instance of Error or simply a string.

images

When an exception is thrown in JavaScript, the interpreter stops normal program execution and jumps to the nearest exception handler. If no exception handler is found, the error is reported to the user. You can define an exception handler by using the try/catch/finally statement. The try block surrounds the code that you expect to throw an exception, the catch block handles an exception if one occurs, and the finally block defines code that will be executed whether an exception is thrown or not. The catch block does not specify a type like in Java or C++, so there is no need for the ability to specify multiple catch blocks. The single catch block handles any error type. As in Java, you can use the try and finally blocks without a catch block.

images

When JavaScript executes in a web browser, the window object provides an onerror property that can be assigned a function to handle any JavaScript errors. The browser will pass three parameters to the error handler function. The first one is a message describing the error. The second parameter is a string of the URL of the document containing the JavaScript code that caused the error. The third parameter is the line number where the error occurred. So you could define an error handler like this.

images

4.1.12 Constructor Functions and Simulated Classes

JavaScript does not yet support true classes like Java or C++; however, you can simulate classes by using constructor functions and prototype objects. To define an object of which multiple instances can be created, you define a constructor function. A constructor function looks like any other function in JavaScript except that it typically adds properties to this and has no return statement. For example, the following defines a Person “class”.20 Because JavaScript has no formal notion of a class, the word “class” is used loosely in this book to describe a constructor function or the group of objects that were instantiated using the same constructor function.

images

In JavaScript, this always refers to the “owner” of the function being executed. When used in a top-level function, this refers to the global object. As an example, if the Person() function were defined as a top-level function (meaning not nested in another function) and executed as a function instead of a method (i.e., var john = Person(1, “John”, “Doe”);), this would refer to the global object, which is window in a web browser. In other words, the JavaScript interpreter would implicitly create the variables id, firstName, lastName, middleName, and suffixName as properties of the window object. That is not the result we want—we want to create an instance of Person.

To create an instance of a class in JavaScript, you must use the new operator. The new operator creates a new object with no properties and then invokes the specified function, passing the new object as the value of the this keyword. The constructor function can then use the this keyword to initialize the new object.

images

You do not typically return a value from a constructor function; however, JavaScript does allow you to. If the constructor function returns a value, that value becomes the result of the new operator and the newly created object is discarded. An interesting example of this is one method of creating a Singleton21 in JavaScript.

images

The new operator also sets the prototype of the object, which is the value of the prototype property of the constructor function. Every function in JavaScript automatically gets a prototype property when the function is defined. The prototype property is initially assigned an object with one constructor property that refers to the associated constructor function. You are allowed to assign properties to the prototype object and even reassign the prototype property to another value. Every property of the prototype object can be accessed as if it is a property of the object created by the new operator. For example, if you assign a function to the prototype object of Person, then you can invoke that function as though it is a method of a Person object.

images

4.1.12.1 Instance Properties and Methods

In object-oriented languages, there may be multiple objects of the same class. These objects are commonly called instances of the class. Instance properties and methods in Java are those associated with an instance of a class—i.e., they are accessible only by using an object that is an instance of the class in which they are defined. To draw a parallel in JavaScript, you can say that the properties assigned to this in a constructor function are instance properties of the class defined by the constructor function. These properties are assigned to the object created by the new operator, which you can think of as the instance of the class. Therefore, the id, firstName, last-Name, middleName, and suffixName properties of the Person class are instance properties of that class.

You can define instance methods in JavaScript by assigning a method to the prototype property of a constructor function, just as compareByLastName() was assigned to the prototype property of Person earlier. However, in JavaScript, functions are objects, so a function can also be assigned to an instance property in a constructor function, thereby creating an instance method of the class defined by the constructor function. For example, the compareByLastName() method could be assigned to this instead of the prototype property.

images

There is a notable difference between these two ways of creating instance methods in JavaScript. Assigning methods that are applicable to the entire class to the this keyword is inefficient because the JavaScript interpreter must create that function object every time that an instance of the class is created. In other words, in the example just given, every instance of Person will have its own compareByLastName function object. When the function is instead assigned to the prototype property of the constructor function, as we did earlier, then only one object of that function will exist and all instances of Person will share that same function object.

The compareByLastName() function in both examples used the this keyword to reference properties of the instance (id, lastName, etc.). In JavaScript you must always use this when referencing an instance property from an instance method.

4.1.12.2 Class Properties and Methods

Class properties and methods in Java are those associated with the class and can be referenced via either the class name or an instance of the class. You notate these in Java by using the static keyword. To create class properties and methods in JavaScript, you assign properties directly to the constructor function. For example, we could define a PwdUtils class that ensures that a given pwd has at least one character from a set of special characters.

images

Drawing a parallel to Java: you may think of SPECIAL_CHARS and validatePassword as public static members of PwdUtils. JavaScript does not have visibility modifiers like Java does, so in general, everything is public in JavaScript. However, you can simulate private members, which is discussed in the next section.

The convention for naming identifiers of class constants in Java (those marked as static final) is to use all uppercase letters and separate the words with underscores (e.g., SPECIAL_CHARS). ECMAScript does not define a notation for defining constant variables; however, the naming convention is still useful for class properties in JavaScript.

4.1.12.3 Private Members

JavaScript does not have visibility modifiers that allow you to make members of a class private. But you can achieve private members with a technique using closures. This approach has already been demonstrated earlier. Here is another example.

images

images

In this example we have created public instance methods that have access to private instance properties. As we have discussed earlier, doing so is inefficient because the interpreter must create each of the get/set function objects every time that an instance of Person is created. However, there is a way to simulate public instance methods at the class level (associated with the prototype), which you can read about online.22

4.1.12.4 Inheritance

Inheritance in JavaScript is accomplished through the prototype object of a function. As mentioned earlier, every function in JavaScript is given a prototype property when the function is defined. The prototype property is initialized with an object that has one property, constructor. The constructor property of the prototype object references the constructor function with which the prototype is associated. Objects created from a constructor function by using the new operator inherit all properties from the prototype object of that constructor function. Objects created using the object literal notation inherit from the built-in Object class, so for those objects, their prototype is the one associated with the Object() function.

For a simple example, consider the constructor property. The constructor property is a member of the prototype object of a function. Yet, when you create an object of that function (class) by using new, you can reference the constructor property as if it is a property of that new object. Here is an example.

images

images

The properties of the prototype object of a constructor function are inherited by all objects created using that function. Therefore, it is more efficient to add class methods to the prototype than to the this keyword. Properties added to the prototype object of a constructor function are inherited by objects of that class even if the properties were added after the instance was created.

When you reference a property of an object, JavaScript first checks to see if that property is a member of the object. If the object does not have the property, then JavaScript checks the prototype object for that property. Because the prototype is an object, it can also have an associated prototype, forming a chain of prototypes, which is the inheritance hierarchy. JavaScript will search up the chain of prototypes until it finds the referenced property. If it does not find the property, then undefined is returned. That is how inheritance in JavaScript works, which explains how all objects in JavaScript inherit from the built-in Object class. The prototype object is created using the Object() constructor function, so its prototype is, by default, the prototype of the Object() function. That is, unless we change what the prototype property references, which is how we can create an inheritance hierarchy among functions that we define. For example, we can create a subclass of Person called User.

images

images

A common practice is to add a superclass property to the subclass prototype that refers to the superclass constructor function. Doing so allows you to remove the use of the call() function.

images

Creating a class hierarchy in JavaScript is more complex than doing so in Java or C++, but it can also be more flexible. For instance, objects can inherit from objects.23

4.2 Embedding JavaScript in HTML

 

To get a web browser to execute your JavaScript code, you must embed it in an HTML page. There are several ways to do that.

1. Put your JavaScript code between opening and closing <scripts> tags. The web browser processes an HTML page from top to bottom, executing any JavaScript that it finds between <script> tags along the way. You can put as many <script> tags as you like anywhere between the opening and closing <head> or <body> tags. All the JavaScript code is executed under the same scope, so top-level variables defined in one <script> tag can refer to top-level variables defined in another. However, the web browser processes the page from top to bottom, so you cannot refer to a JavaScript variable or HTML tag until it is loaded by the web browser. To defer a script's execution, you can put the code in a function and assign that function to the window.onload event handler or use the defer attribute of the <script> tag. The onload event handler is invoked after the entire page has been loaded. Event handlers are discussed in more detail later. The defer attribute tells the browser to wait to execute the JavaScript code until it encounters a script that cannot be deferred or the page has been loaded, whichever comes first. Unfortunately, not all browsers implement the defer attribute properly, so use it with care. If you are using XHTML, you should put your JavaScript within a CDATA section to prevent XML special characters like < and & from being processed by the XML parser. An example embedding JavaScript between the <script> tags in HTML and XHTML follows.
images
images

2. Import an external JavaScript file by using the src attribute of the <script> tag. The src attribute specifies the URL of the file containing JavaScript code. JavaScript files typically have a. js extension and contain only JavaScript code. Inside the JavaScript file you do not need (and cannot have) <script> tags or any other HTML tags. Here is an example.
images

3. Assign JavaScript to the event handler attribute of an HTML tag. Many HTML tags support event handler attributes, so you can assign some code to do something when, for instance, the user clicks a button. An example follows.
images

4. Assign one line of JavaScript code to a URL prefixed by the javascript: pseudoprotocol. When you use this pseudoprotocol followed by a line of JavaScript code, the browser executes the JavaScript code and displays whatever the code returns but does not change the currently displayed page if the code returns nothing. Usually, you do not want the browser to display anything as a result of the URL, so you return nothing. To ensure that nothing is returned to the interpreter, it is common to follow the JavaScript code with a void statement. Here is an example that opens a new window when you click on a link.
images

For using JavaScript with HTML, the best practice is to import your JavaScript code by using the src attribute of the <script> tag. This technique has several benefits over the others. It completely separates your JavaScript from the HTML code, which makes understanding, reading, and maintaining the code much easier. The JavaScript code can be easily reused across different web pages. The JavaScript file can be cached by the web browser, which makes future page loads, and loads of other pages that use the same file, faster.

The rest of the techniques for embedding JavaScript in HTML are discouraged, particularly the technique of assigning JavaScript code to an HTML event handler attribute and the use of the javascript: pseudoprotocol. You can accomplish everything you need with external JavaScript files.

JavaScript may be the most popular scripting language for the Web, but it is not the only one. Therefore, the HTML specification, to be language neutral, allows you to tell the browser what language is used in your <script> tags. You identify what language you are using by declaring a MIME type. The MIME type for JavaScript has traditionally been text/javascript; however, because JavaScript programs are not really text documents, Internet standards have deprecated that type in favor of application/javascript. Unfortunately, the support for application/javascript is not yet widespread.

You can specify the default scripting language for all scripts in the HTML file by using the <meta> tag like this:

images

Or you can do so for a specific script with the type attribute of the <script> tag like this:

images

Most browsers default to assuming that your code is JavaScript if you do not specify a MIME type, but it is a good idea to specify one anyway.

4.3 The Browser Object Model (BOM)

 

The Browser Object Model (BOM) defines a set of host objects and their relationships, which are used to manipulate or obtain information about the browser. The BOM provides an API to display dialog windows, open and close new browser windows, resize windows, get the browser window size, move backward and forward through the browser history, get the browser name and version, get the operating system name, load a new document, and more. The BOM is not standardized by a standards body, such as the W3C, but is a de facto standard that you can rely on all modern browsers to provide. However, the BOM is not the same in each browser—only a core set of objects are the same, which this section will focus on. See the browser vendor documentation for non-common BOM functionality.24

images

Figurer 4.3.1

BOM

The BOM is a hierarchy of objects with the window object at the root. Beneath the window object are the navigator, screen, history, location, and document objects—as well as the frames[] array (see Figure 4.3.1). The document object contains the Document Object Model (DOM), which is discussed in the next section. The frames[] array contains references to all the frames loaded in the browser window. Each frame is also a window object. If the document loaded in the browser contains no named frames, then the frames[] array is empty.

4.3.1 The window Object

The window25 object is the global object in client-side JavaScript, so properties of the window object can be referenced with or without qualifying them with window. For example, the alert() function of the window object was used in several of the code samples in previous sections without having to invoke it as window.alert().

window properties

images closed—A Boolean value that identifies whether (true) or not (false) the window has been closed.

images document—A reference to the document object.

images frames—A reference to an array that contains references to all the frames loaded in the window.

images history—A reference to the history object.

images location—A reference to the location object.

images opener—A reference to the window that created the current window, if any.

images parent—A reference to the parent of the current window.

images self—A reference to the current window.

images top—A reference to the top-level window.

window methods

images alert()—Displays a dialog box with a message and an OK button.

images blur()—Removes focus from the current window.

images clearInterval()—Cancels a timeout set with setInterval().

images clearTimeout()—Cancels a timeout set with setTimeout().

images close()—Closes the current window.

images confirm()—Displays a dialog box with a message and OK and Cancel buttons. Returns true if the user clicked on the OK button, false otherwise.

images focus()—Sets focus to the current window.

images moveBy()—Moves the window relative to its current position.

images moveTo()—Moves the window to the specified position.

images open()—Opens a new browser window.

images print()—Opens the print dialog box to print document loaded in the browser.

images prompt()—Displays a dialog box that prompts the user for a line of input. Returns the text entered by the user, if any.

images resizeBy()—Resizes the window by the specified pixels.

images resizeTo()—Resizes the window to the specified width and height.

images scrollBy()—Scrolls the content by the specified number of pixels.

images scrollTo()—Scrolls the content to the specified coordinates.

images setInterval()—Evaluates an expression at specified intervals.

images setTimeout()—Evaluates an expression after a specified number of milliseconds.

images

Figure 4.3.2

Example of window.prompt()

Figure 4.3.2 is an example using the window object and the result when the code is executed in Firebug. Selecting the OK button will navigate the browser to the website http://ajaxian.com. Or you could enter a different address.

images

4.3.2 The navigator Object

The navigator26 object provides information about the browser, including the browser vendor, version, platform, language, and supported MIME types. The following are commonly used properties.

navigator properties

images appCodeName—The internal code name of the browser.

images appName—The official name of the browser.

images appVersion—The version of the browser as a string.

images mimeTypes—A list of the MIME types supported by the browser.

images platform—The hardware platform on which the browser is running.

images userAgent—The string that the browser sends in its USER-AGENT HTTP header.

Figure 4.3.3 is an example that displays the value of the navigator properties just listed.

images

images

images

Figure 4.3.3

Example of window.navigator

4.3.3 The screen Object

The screen27 object encapsulates information about the display on which the window is being rendered, including the size of the screen and the number of colors that it can display. Some properties of the screen object are listed next.

screen properties

images availHeight, availWidth—The height and width of the screen in pixels, minus the space required by operating system features, like a desktop taskbar.

images height, width—The height and width of the screen in pixels.

images colorDepth—The bit depth of the color palette of the screen.

The following example displays the width of the screen in pixels.

window.alert(window.screen.width());

4.3.4 The history Object

The history28 object maintains a list of the browser window's recently visited URLs. Scripts cannot directly access this list; however, scripts can call methods of the history object to move forward or backward in the list, similar to using the browser's Back and Forward buttons. The history object methods are listed next.

history methods

images back()—Move backward in a window's (or frame's) browsing history.

images forward()—Move forward in a window's (or frame's) browsing history.

images go()—Takes an integer argument and will move any number forward (for positive arguments) or backward (for negative arguments) in the browsing history.

The following example causes the browser window to load the document from three positions back in its history.

images

4.3.5 The location Object

The location29 object encapsulates information about the document currently loaded in the browser window (or frame). You can use the location object to change the document loaded by the browser window by assigning a URL to window.location.href. Some properties of the location object are listed next.

location properties

images host—The host name and port number (www.w3.org:80).

images hostname—The host name without the port number (www.w3.org).

images href—The entire URL (http://www.w3.org:80/TR/html401/)

images pathname—The path, relative to the host (/TR/html401).

images port—The port number of the URL (80).

images protocol—The protocol of the URL (http:).

An example using the location object was given in Figure 4.3.2.

4.3.6 The frames[] Array

Web browsers create one global object (a window object) for each window. Typically, the browser has only one window object; however, if the page being viewed has frames30 (a <frameset> or <iframe>(s)), then there is a window object for that page, as well as one window object for each frame (each <frame> or <iframe>). The window object for the page (document) containing the frames has a built-in frames[] array with references to the window object for each of its frames. Hence, window.frames[0] refers to the window object of the first frame. The window object of the top-level document (the page being viewed that contains all the frames) can be referenced from anywhere by using the built-in top property. Because frames can be nested to any arbitrary depth, there is also a built-in parent property that refers to the containing window of the current frame. In the top-level window, the properties self, window, parent, and top are all self-references.

Listing 4.3.1 defines an HTML file entitled Frameset0, which includes a frameset. Frame1 in Frameset0 loads the HTML file entitled Frameset1 defined in Listing 4.3.2, which also includes a frameset. In total, the following two listings define four frames, Frame0, Frame1, Frame1_0, and Frame1_1. Frame0 and Frame1 are loaded in Frameset0, whereas Frame1_0 and Frame1_1 are loaded in Frameset1 (which is loaded in Frame1). After the listings, Figure 4.3.4 shows how the listings look when viewed in a web browser. To make the framesets and frames readily identifiable, I have given the documents with framesets a dashed border and have given the documents loaded by the frames a solid border. The text in each frame describes how you can reference every window from that frame by using JavaScript.

images

Listing 4.3.1

frameset0.html

images

Listing 4.3.2

frameset0.html

images

Figure 4.3.4

Referencing Frames in JavaScript

4.4 The Document Object Model (DOM)

 

The Document Object Model (DOM) is a standard platform- and language-neutral programming interface for building, accessing, and manipulating valid HTML and well-formed XML documents. The DOM is just an interface that must be implemented in an actual programming language to be useful. The DOM has been implemented in many languages, including JavaScript in web browsers. The W3C standardized the DOM because the first developers to write scripts (JavaScript code) for browsers found that their scripts would not work properly on all browsers because of browser object model incompatibilities. Browser incompatibilities still exist, but the successful vendor adoption of the DOM standard has greatly reduced them.

Because the DOM is language neutral, its ultimate goal today is to make it possible for programmers to write applications that work properly on all browsers and servers and on all platforms. The DOM is not only used in web browsers to parse and manipulate HTML but is also commonly used in various applications to parse and manipulate XML. In fact, the basis of the DOM standard, the DOM Core, provides a low-level set of objects that can represent any structured document, whether it is XML, HTML, or anything else. Built on top of the DOM Core are two other parts to the DOM standard, HTML and XML specifications, which consist of objects and methods that provide easier and more direct access to those specific types of documents.

The DOM has been developed in levels.31 DOM levels 1, 2, and 3 are defined (3 is not fully complete), and more levels may be developed in the future. Unfortunately, browser support for the existing DOM levels varies a good bit.32 Modern browsers support most of DOM Level 1 and 2 and only about half of DOM Level 3 Core. The following outlines the levels.
 

images DOM Level 1: Defines the base Core, HTML, and XML document models, including functionality for document navigation and manipulation.

images DOM Level 2: Adds to the Level 1 Core and HTML document models. Defines a style sheet object model and functionality for manipulating the document style information. Also defines traver-sals on the document, an event model, and support for XML namespaces.

images DOM Level 3: Adds to the Level 1 Core document model. Defines document loading and saving, content models (such as DTDs and schemas) and validation, views and formatting, and key events and event groups.
 

DOM is a tree-based model in which the entire document is parsed and cached in memory as a tree structure of objects called nodes. The DOM defines a Node33

images

Figure 4.4.1

Core DOM and HTML DOM Interface Hierarchy

When a web browser parses an HTML document, it creates an instance of HTMLDocument,34

Each line in Figure 4.4.2 is a link between the nodes of the tree. The terminology for the relationships between the nodes is the same as that used for family trees. The node directly above a node in the hierarchy is the parent of that node (e.g., <html> is the parent of <body>). All nodes have exactly one parent, except the root node, which has no parent (HTMLDocument in the figure is the root of the HTML hierarchy; however, <html> is considered the root of the document that was parsed). The nodes directly below a node are the children of that node (e.g., <head> and <body> are both children of <html>). Nodes with no children are called leaves. Nodes at the same level and with the same parent are siblings (e.g., <head> and <body> are siblings). All nodes below a node in the hierarchy are the descendants of that node. All nodes above a node in the hierarchy are ancestors of that node.

images

Figure 4.4.2

Example DOM Tree

The DOM parser generates an object that implements the Node 35 interface for everything in the document, including the tags, the tag attributes, and the text between the tags. Also, all the HTML tags are parsed into objects that implement the Element36 interface. To contain and represent the entire document, the parser creates an object that implements the Document37 interface. Combined, the API provided by the Document, Node, and Element interfaces covers most everything that you need for traversing and manipulating a document. You will typically use those three interfaces more than any other in the DOM Core API. To access attributes of a specific HTML element, you will use the related interface in the DOM HTML API (e.g., HTMLFormElement36 for #x003C;form> tags).

images

Listing 4.4.1

Example XHTML

images

Figure 4.4.3

Relationship between HTMLDocument Instance and window.document

images

The JavaScript window.document property (mentioned in Section 4.1) is a reference to the HTMLDocument object depicted in Figure 4.4.2. You can easily test this by loading Listing 4.4.1 into Firefox and executing the following code in Firebug.

images

Figure 4.4.3 shows the result. When an object is passed to the alert() method, the toString() method of that object is called to get a string representation to display. The toString() method of most objects in JavaScript simply returns the name of the object's type, which here is “HTMLDocu-ment”.

The DOM is much too large to discuss in its entirety in this book, so the following sections will cover areas that you will typically use most.

4.4.1 Traversing and Manipulating the DOM

4.4.1.1 Accessors

The DOM provides several methods and properties for accessing the parts of a document. When you want to get a reference to a particular node, you generally start by using the Document interface.

images

The document element is the root of the document that was parsed, which is always <html> for an HTML document. There is only one document element in an instance of Document. The documentElement property of the Document interface is a convenient reference to the document element. If we load Listing 4.4.1 into Firefox, we can execute the following JavaScript code in Firebug to access the <html> tag's xmlns attribute. The getAttribute() method is defined in the Element interface and returns the attribute with the given name (see Figure 4.4.4).

images

The getElementById() method returns the element with an id attribute equal to the given ID or null if no object with that ID exists. You can assign an id attribute to any element in an HTML document. The ID you choose must be unique within the HTML document. When you create the HTML document, you typically know what element you will need to get a reference to in JavaScript code, so you simply assign that element an id attribute. The only element in Listing 4.4.1 with an ID is the second paragraph. The following code illustrates the use of getElementById() to get a reference to the second paragraph element (see Figure 4.4.5).

images

Figure 4.4.4

The document.documentElement Property

images

Figure 4.4.5

The document.getElementById() Method

images

The getElementsByTagName() method returns a NodeList39 node, which becomes the first child of that element. The text in the Text object can be referenced using the nodeValue property, as also illustrated in the code.

images

Figure 4.4.6

The document.getElementsByTag Name() Method

images

After you get a reference to an element by using the Document interface, you can traverse the document further by using the Element and Node interfaces.

images

The getAttribute() method returns the value for the attribute with the given name. Its usage was demonstrated in Figure 4.4.4 when the <html> element's xmlns attribute was output in Firebug.

images

The getElementsByTagName() method of the Element interface is similar to the method with the same name in the Document interface, demonstrated in Figure 4.4.6. The difference is that the Element's method searches only below the Element in the hierarchy, whereas the Document's method searches the entire document. The Element's method is faster because it does not have to search the entire document, but you must have a reference to the Element before you can use it.

images

The nodeName and nodeValue properties return the name of the node and the value of the node, respectively. The name of the node is the tag name for nodes representing HTML tags, such as “HEAD” for the <head> tag. For other nodes, it is a value representative of the node as defined by the DOM (e.g., “#text” for Text nodes).41

images

The childNodes property of a Node instance returns a NodeList containing all the node's immediate children. The childNodes property does not return grandchildren, i.e., a child of a child. Only Element nodes have children. If the node has no children, then the returned NodeList will be empty with a length of zero. The following code demonstrates using the childNodes property.

images

images

Figure 4.4.7

Node Parent-Child Relationship

images

The Node interface provides several properties for directly accessing immediate related nodes. The parentNode property returns the parent node (only Element nodes can be parents, but all nodes, except for Document, have a parent). The firstChild property returns the first node in the NodeList returned by childNodes, whereas the lastChild property returns the last node in the list. When two nodes have the same parent, they are called siblings, which means that both the nodes appear in the NodeList returned by the parent's childNodes property. The previousSibling property of a node returns the sibling node that comes before it in the childNodes list, whereas the nextSibling property returns the node that comes after it. Figure 4.4.7 illustrates these relationships.
 

4.4.1.2 Modifiers

The DOM also provides methods to modify the document structure. As with the accessors, the modifiers that you are most likely to use are defined in the Document, Element, and Node interfaces. If you want to add a new node to a document, you must first use the Document instance of the document that you are modifying to create a new node instance or import a node from another document. After you have a reference to the new node, from creation or importing, you use methods in the Node interface to add the new node to the document by setting it as a child of an existing node in the document.

images

The createElement() method creates an Element of the given type. The given tagName is the name of the element that you wish to create. For example, if you wanted to create a new horizontal rule element, you would pass the string “hr”. The new element has no parent, which means that it is not yet a part of the document that created it. To add the new element to the document, you must use one of the methods in the Node interface described next.

images

The createTextNode() method creates a new Text node containing the given text. The created node has no parent but can be added to the document that created it by using the Node methods described next. The following code demonstrates creating text for a new paragraph.

images

The importNode() method imports a node from another document to this document without modifying the other document. As with the create methods, the returned node has no parent but is ready to be added to the importing document by using the Node interface. Suppose that you were working with an HTML document that contained frames. Each frame has its own Document instance.You could import the first paragraph from the document of one frame into another by using the following code.

images

The setAttribute() method adds an attribute to the Element or, if the attribute already exists, sets the attribute to the given value. The removeAttribute() method removes the attribute with the given name. If the attribute does not exist, then the method has no effect. If the attribute removed has a default value, then the attribute is essentially just set to the default value.

images

The insertBefore() method inserts the new child in the childNodes list before the given existing child and returns the inserted node. In other words, the insertBefore() method makes the new child the previousSibling of the given existing child. If refChild is null, then the new child is added to the end of the list. If the new child is already in the list, then it is first removed. The following code example inserts a new paragraph before the first paragraph of the document.

images

The replaceChild() method replaces an existing child with a new child and returns the old child node. If the new child is already there, then it is first removed. The following code example replaces the first paragraph with a horizontal rule.

images

The removeChild() method removes the specified child and returns it. The following code example removes the first paragraph of the document.

images

The appendChild() method adds the given new child to the end of the childNodes list and returns the newly added node. If the new child is already there, it is first removed. The following code example adds a new paragraph to the document.

images

Listing 4.4.2 uses the accessors and modifiers together in a complete example. The example XHTML from Listing 4.4.1 is modified to add a second heading before the second paragraph, replace the second paragraph with a different paragraph, add an ID attribute to the first paragraph and the new paragraph, and insert a horizontal rule between the paragraphs.

images

Figure 4.4.8

Using the DOM to Modify Document Content

Figure 4.4.8 illustrates what the document of Listing 4.4.1 looks like after executing the code of Listing 4.4.2 in Firebug.

4.4.2 Manipulating Styles

Much of the detail describing how a document should be rendered in a web browser is defined in cascading style sheets. Consequently, much of the JavaScript code that developers write is to manipulate the document styles. The DOM exposes imported style sheets (via <style> or <link rel=“stylesheet”> tags) as instances of the CSSStyleSheet42 interface. Each style sheet object exposes the style rules, which you can inspect and modify. You access the style sheet objects via the document.styleSheets array. However, you typically do not need to access or directly modify these style sheet objects. The more common method of dynamically modifying style is via the Element interface.

Listing 4.4.2

Example use of DOM methods

images

4.4.2.1 The style Property

The DOM exposes the styles for each Element via the Element's style and className properties. The style property returns an instance of the CSSStyleDeclaration43 interface, which contains properties of all the style attributes supported by the browser's DOM. For example, you can set the color of the document's first paragraph to red with the following code.

images

The first parameter of the setProperty() method is the name of the property to set, the second parameter is the value for the property, and the third parameter is the CSS priority for the property (e.g., “important”). The CSSStyleDeclaration interface also has getPropertyValue(), getPropertyCSS-Value(), getPropertyPriority(), and removeProperty() methods; however, it is uncommon to use any of these methods.

The common way to access and set the style properties of an Element is via the CSS2Properties44 interface, which contains a publicly accessible property for every style attribute defined by the DOM. In most modern browsers, the object returned by the style property implements CSS2Properties. Doing so is not a requirement to be conformant with the DOM, but its implementation and usage is universal. With this interface, the previous example would look like the following.

images

Getting the value of a style property by using the CSS2Properties interface is equivalent to calling CSSStyleDeclaration.getPropertyValue(). Setting the value of a style property by using the CSS2Properties interface is equivalent to calling CSSStyleDeclaration.setProperty().

4.4.2.2 The className Property

When you need to change several styles for an Element at the same time, it is more convenient to define the rules in a style sheet for a class selector and then to use JavaScript to set the selector assigned to the Element's className property. For example, we can define the styles of Listing 4.4.3 for the example XHTML in Listing 4.4.1.

Listing 4.4.3

styles.css

images

Then define some simple JavaScript to switch the styles for the second paragraph as follows.

Listing 4.4.4

javascript.js

images

Then modify the example XHMTL to use the styles and JavaScript.

Listing 4.4.5

XHTML with styles

images

If you save the listings above to three separate files and then load the XHTML file into a browser, you can make the styles for the second paragraph change to italics, bold, underline, and red by clicking the button. The styles change back to normal by clicking the button again. The result is shown in Figure 4.4.9.

images

Figure 4.4.9

Styled XHTML

Changing the className has some advantages over changing specific properties of the style object. The first benefit is that your style information is retained in a style sheet (CSS file) instead of being sprinkled throughout your JavaScript code. A best practice in web development is to keep your content (HTML) separate from your style (CSS) and separate from your behavior (JavaScript), which means putting them in three separate files, as the preceding example illustrates. The second benefit is that browsers process a change in className faster than a change in the properties of the style object.45

4.4.3 Handling Events

In the previous section we attached the toggleStyles() JavaScript function to the “Toggle Styles” HTML button so that the function was called when the user clicked the button. The web browser generates an event whenever something interesting happens, and you can write JavaScript code to respond to those events by registering event handlers. This concept is called event-driven programming. In the previous example, when the user clicked the “Toggle Styles” button, the browser generated a click event. We registered the toggleStyles() function as a handler for the click event when we assigned the function to the onclick attribute of the <button> tag. In other words, we defined an onclick event handler for the <button> tag, which the browser invoked when the click event was generated.

The event handling techniques described thus far are commonly categorized as DOM Level 0 event handling. This form of event handling is fairly basic but nevertheless satisfies most event handling needs. The HTML tags support several event handler attributes that can be assigned arbitrary JavaScript code. In the previous example, we put the JavaScript code in a function and assigned the function to the event handler attribute, which is a good practice, but we could have put the JavaScript code directly in the attribute like this.

images

It is easy to see how doing this quickly makes the HTML difficult to read and thus difficult to maintain. Fortunately, HTML tag event handlers are also exposed as properties of the corresponding JavaScript object with the same name. So, we could alternatively remove the onclick attribute from the <button> tag and write the following JavaScript code to both define and register the event handler.

images

This is an even better practice than assigning a JavaScript function to the HTML tag attribute because it fully separates the HTML code and the JavaScript code, making both of them easier to read and maintain. No parentheses appear behind the name of the function when it is assigned to the onclick property. If parentheses were used, then the onclick event handler would have been assigned the result of invoking toggleStyles() instead of a reference to the function itself. Be sure not to make that mistake.

Because the event handler properties reference JavaScript functions, you can also directly invoke an event handler in your code, as the following code illustrates. In the context of our example, if the following code were executed it would invoke the toggleStyles() function because that is what onclick is a reference to.

images

So far we have mentioned only the onclick event handler, but the HTML 4 specification46 defines several other events, all of which are listed in the following table. Table 4.4.1 lists the event handlers and the HTML tags that support them, as well as the action that triggers the event. The event handlers are named after the event they handle. The name of the event is the name of the handler minus the “on” prefix. For example, onblur is the event handler and blur is the event.

Each browser also has its own set of events that are not part of the HTML 4 specification. Most of these events are not supported across browsers; however, those in Table 4.4.2 are fairly well supported.

You can generally cancel the browser's default response to an event by returning false from the event handler. Events whose default action can be canceled by returning false from the handler are onclick, onkeydown, onkeypress, onmousedown, onmouseup, onreset, and onsubmit. For example, it is common to return false from the onsubmit event handler if a form failed validation to prevent the form from being submitted.

images

Notice from the listing above that the keyword this used in an event handler refers to the object to which the handler is attached, or, in other words, the target of the event. A common mistake is to create an event handler as a function of an object in which this is used from within the event handler to make references to other functions or variables of that object and then to assign that event handler to an HTML element and expect the uses of this to refer to the object in which the handler was defined—when in fact the event handler's use of this will refer to the HTML element, not the object in which the handler was defined. Here is an example.

Table 4.4.1 HTML 4 Events

Event Handler HTML Tag Trigger
onblur <button>, <input>, <label>, <select>, <textarea>, <body> The element loses the input focus, which is typically caused by the user clicking on another element or tabbing to another element.
onchange <input>, <select>, <textarea> The element loses focus and its value has changed since it gained focus.
onclick Most45Tags that do not support this event handler are <applet>,<bdo>,<br>,<font>,<frame>,<frameset>,<head>,<html>,<iframe>,<isindex>,<meta>, and <style>. The user clicks on the element (mouse press and release, or keyboard equivalent).
ondblclick Most47 The user double-clicks on the element.
onfocus <button>, <input>, <label>, <select>, <textarea>, <body> The element gained the input focus.
onkeydown Form elements and <body> The user pressed down a keyboard key.
onkeypress Form elements and <body> The user pressed and released a keyboard key.
onkeyup Form elements and <body> The user released a keyboard key.
onload <body>, <frameset>, <img> The document finished downloading to the browser.
onmousedown Most47 The user pressed down a mouse button.
onmousemove Most47 The user moved the mouse.
onmouseout Most47 The user moved the mouse off the element.
onmouseover Most47 The user moved the mouse over the element.
onmouseup Most47 The user released a mouse button.
onreset <form> Form reset was requested, typically from the user clicking the form reset button.
onselect <input>, <textarea> The user selected text.
onsubmit <form> A request was made to submit a form, typically when a user clicks on the button of a form with type=“submit”.
onunload <body>, <frameset> A document is about to unload from a window or frame.

Table 4.4.2 Other Events

Event Handler HTML Tag Trigger
onabort <img> The user interrupts the loading of an image.
onerror <img>, <body>, or window object An error occurred loading an image when used with <img>; otherwise, an error occurred executing scripts in the document.
onresize <body>, <frameset>, or window object The user resized the window.
onscroll <body>, <frameset>, or any element with the style “overflow: auto”. The user scrolled a page, frame, or any element with the style “overflow: auto”.

images

4.4.3.1 DOM Level 2 Event Handling

DOM Level 0 event handling is convenient and easy to use, but it is limiting. For example, you cannot register more than one handler for the same event. In DOM Level 2, the W3C defined a significantly more advanced event handling model to overcome these limitations. The foundation of DOM Level 2 event handling is event propagation. In the DOM Level 0 model, the event is dispatched only to the element on which the event occurred. In DOM Level 2, the event is propagated through three phases. In phase one, called the capturing phase, the event is propagated from the top of the DOM tree down to the element on which the event occurred, called the target node. If any ancestors of the target node have a registered capturing event handler for the event, those handlers are run when the event passes by. In the second phase, any event handlers registered on the target node are run. In the third phase, called the bubbling phase, the event propagates back up the DOM tree (or bubbles up), and any registered event handlers for the event are executed. The event handlers for the capturing phase and the bubbling phase are different, and only the bubbling phase event handler of the target node is executed in the second phase. Also, not all event types propagate through the bubbling phase. In general, raw input events (like mouse events) bubble up, whereas semantically higher-level events (like the submit event) do not. You can look online to see exactly which events bubble and which do not.48 Figure 4.4.10 illustrates the propagation that would occur if the user clicked on the button in the listing.

images

Figure 4.4.10

DOM Level 2 Event Propagation

When invoked, the event handlers are passed an instance of the Event49 interface. If the event was generated by the use of the mouse, then the event is an instance of the MouseEvent50 interface, which extends the UIEvent51 interface, which in turn extends Event. During event propagation, any event handler can stop further propagation by calling the stopPropagation() method of the Event object. If the event normally causes some default browser behavior, like following the link of an <a> tag, then the event handler can prevent the default behavior by calling the preventDefault() method of the Event object.

To support registering multiple event handlers for one element, all nodes in DOM Level 2 implement the EventTarget52 interface, which defines the methods addEventListener() and removeEventListener(). These methods are for adding and removing, respectively, the event handlers (called listeners in Level 2) to be invoked in response to a particular event. Both methods require three arguments. The first argument specifies the event for which you want to “listen” (e.g., submit). The second argument specifies the event listener function that should be invoked when the event passes by the node. The third parameter is a Boolean that specifies whether the listener is to be used during the capturing phase (true) or the bubbling phase (false). You can add as many listeners to a node as you like, even for the same event. They will all be invoked when the event occurs; however, the DOM does not guarantee in which order the listeners will be invoked. The following code demonstrates adding and removing a listener for the submit event on the <submit> tag of Figure 4.4.10.

images

All modern browsers except Microsoft Internet Explorer support the DOM Level 2 event model. IE is typically slow to adopt standards set forth by the W3C, which is unfortunate for developers because we are forced to work around the incompatibilities. The IE event model does not have a capture phase, has different event objects, and uses a different method for registering events. Also, IE has memory leak problems that are exacerbated by event registration. Listing 4.4.6 provides code that you can use to handle cross-browser event handling and memory leaks.

Listing 4.4.6

EventHelper.js

images

images

EventHelper does not support binding capturing phase event listeners because IE does not support them, and the point of EventHelper is to aid with cross-browser event handling. If you attempt to use capturing-phase event listeners, your code will not work in IE. The IE methods for registering and unregistering event listeners are attachEvent() and detachEvent(), respectively. The IE attachEvent() method requires “on” to prefix the event name, and the IE event handling mechanism does not pass the event to the listener like DOM does but instead assigns it to the window.event property. These peculiarities of the IE event model are handled in the EventHelper.bindListener() method.

4.5 Summary

This chapter covered the basics of the JavaScript language, including its object-oriented features, the Browser Object Model, the Document Object Model, and how to manipulate styles and handle web browser events in JavaScript. JavaScript, the BOM, and the DOM are the foundation for client-side web programming. With what you have learned in this chapter, you can write extensive client-side JavaScript code to perform all kinds of fancy manipulation of the content loaded in a web browser. These techniques are commonly called DOM scripting.

Although you can change a page by using DOM scripting, you are limited to using the data and resources that were loaded with the page. If you want to update the page with new data, or save the user's input, you have to add communication with a server. In the next chapter you will learn how to combine DOM scripting with asynchronous server communication to create powerful web applications.

4.6 Self-Review Questions

1. JavaScript is strongly typed.

a. True

b. False

2. JavaScript is an object-oriented language.

a. True

b. False

3. JavaScript is compiled like Java or C.

a. True

b. False

4. When a user views a web page that contains JavaScript, what machine executes the JavaScript code?

a. The network

b. The web server

c. The web browser

5. Inside which HTML element may you put JavaScript code?

a. <js>

b. <scripting>

c. <javascript>

d. <script>

6. Where in an HTML page may you put JavaScript code?

a. The <head> section

b. Both the <head> section and the <body> section

c. The <body> section

7. What is the correct syntax for referring to an external script called “xxx.js”?

a. <script name=“xxx.js”>

b. <script href=“xxx.js”>

c. <script src=“xxx.js”>

8 An external JavaScript must contain the <script> tag.

a. True

b. False

10. How do you write “Hello World” in an alert box?

a. alert(“Hello World”)

b. msgBox(“Hello World”)

c. alertBox(“Hello World”)

d. alertBox=“Hello World”

11. How do you create a function?

a. function myFunction()

b. function:myFunction()

c. function=myFunction()

12. How do you call a function named “myFunction”?

a. call myFunction()

b. call function myFunction

c. myFunction()

13. How do you write a conditional statement for executing some statements only if “i” is equal to 5?

a. if i==5 then

b. if i=5 then

c. if i=5

d. if (i==5)

14. How do you write a conditional statement for executing some statements only if “i” is not equal to 5?

a. if <>5

b. if (i <> 5)

c. if (i != 5)

d. if =! 5 then

15. How does a “for” loop start?

a. for i = 1 to 5

b. for (i = 0; i <= 5; i++)

c. for (i <= 5; i++)

d. for (i = 0; i <= 5)

16. How can you add a comment in JavaScript code?

a. <!--This is a comment-->

b. //This is a comment

c. #This is a comment

17. What is the correct JavaScript syntax to insert a comment that has more than one line?

a. <!--This comment can have more than one line-->

b. /*This comment can have more than one line*/

c. //This comment can have more than one line//

18. What is the correct way to write a JavaScript array?

a. var txt = new Array(1:“tim”,2:“kim”,3:“jim”)

b. var txt = new Array(“tim“,”kim“,”jim”)

c. var txt = new Array:1=(“tim”)2=(“kim”)3=(“jim”)

d. var txt = new Array=“tim“,”kim“,”jim”

19. How do you round the number 7.25 to the nearest whole number?

a. rnd(7.25)

b. Math.round(7.25)

c. round(7.25)

d. Math.rnd(7.25)

20. What is the correct JavaScript syntax for opening a new window called “window2”?

a. open.new“(http://www.w3c.com”, “window2”)

b. new("http://www.w3c.com”, “window2”)

c. new.window("http://www.w3c.com”,“window2”)

d. window.open("http://www.w3c.com”, “window2”)

21. How do you find the client's browser name?

a. navigator.appName

b. browser.name

c. client.navName

22. Which of the following is not a valid JavaScript variable name?

a. 2names

b. _first_and_last_names

c. FirstAndLast

23. Which of the following is an acceptable case statement in a JavaScript switch expression?

a. case 1:

b. case “yes”:

c. case n + 1:

d. all of the above

Keys to the Self-Review Questions

1.b 2. a 3.b 4. c 5. c 6.b 7. c 8. a 9. a 10. a 11. c 12. d 13. c 14. b 15. b 16. b 17. b 18. b 19. d 20. a 21. a 22. d

4.7 Exercises

1. Are JavaScript and Java the same language? Explain.

2. What is the standard language specification that JavaScript is based on?

3. What datatypes does JavaScript support? Is JavaScript strongly typed or loosely typed? Explain the difference.

4. What is the value for each of the following variables after the code is executed?
images

5. Can JavaScript code executed in the web browser access the computer's file system? Explain.

6. Write JavaScript code to change the paragraph text in the following HTML to “New content”.
images

7. Write JavaScript code to add a row for the next month to the tabl* in the following HTML.
images

8. Write JavaScript code to change the div CSS class in the following HTML from hidden to visible.
images

9. What will be the output of the following JavaScript code?
images

10. What will be the output of the following JavaScript code?
images

11. What will be the value of variable x after the following JavaScript code is executed?
images

12. What object is this referring to in each of the following examples? Assume that all code is being executed in a web browser and that any code outside a function is top-level code.

a. this.now = new Date();

     images

     images

13. Explain lexical scoping in JavaScript, give an example of a closure, and describe what is within the closure's scope.

14. Define a constructor function for a custom type and use it to create an object of that type. Show an example of an instance property and method, a class property and method, and a private property and method.

15. Describe how inheritance works in JavaScript. Show a simple example that demonstrates polymorphism.

16. Compare and contrast DOM Level 0 and DOM Level 2 event handling, and describe the difference between the capturing phase and the bubbling phase of DOM Level 2.

4.8 Programming Exercises

1. Create an HTML page with a <form> containing fields for address (street, city, state, country, and postal code) and phone number, as well as a submit button. Write JavaScript code for the page that validates the fields of the form when the user clicks on the submit button and then displays an error message or a success message. The form does not have to submit to a web server. The JavaScript code should validate that all the fields are populated and that the postal code and phone number are valid for the country. The JavaScript code should be placed in a separate file and imported into the HTML page. To simplify the code, you may narrow the scope of the form to support one country.

2. Write JavaScript code to automatically create a table of contents at the top of an HTML page for the headings found in the same HTML page after the page is loaded by the web browser. Each list item in the table of contents should be a link to the associated document section. Write an HTML page with various levels of headings that demonstrates the use of the JavaScript code.

3. Write a JavaScript utility with a function that you can call to define a class or extend an existing class. You should be able to at least pass the function the name of the new class, the constructor function for the class, the methods for the class, and the class that is being extended. Some of these parameters, like the class to be extended, will be optional. Use the utility in an example that includes inheritance and creates an instance of the resulting class. An example use of the utility might look like the following.

images

4. Create a tabbed interface that is managed by JavaScript. One way to create a tabbed interface is to make each tab a separate HTML page. However, in this example you are to create a tabbed interface where all tabs are on the same HTML page and are hidden and displayed using JavaScript.

4.9 References

Cornford, Richard. “Private Static Members in JavaScript.” Richard Cornford. 2004. http://www.litotes.demon.co.uk/js_info/private_static.html (accessed February 28,2008).

Crockford, Douglas. “Prototypal Inheritance in JavaScript.” Douglas Crockford. 2008. http://javascript.crockford.com/prototypal.html (accessed February 28,2008).

Flanagan, David. 2006. JavaScript: The Definitive Guide. 5th ed. Sebastopol, CA: O'Reilly Media.

Goodman, Danny. 2002. Dynamic HTML: The Definitive Reference. 2nd ed. Sebastopol, CA: O'Reilly & Associates.

Hammond, David. “Web browser standards support.” David Hammond. 2008. http://www.webdevout.net/browser-support (accessed January 28,2008).

Keith, Jeremy. 2007. Bulletproof Ajax. Berkeley, CA: New Riders.

Koch, Peter-Paul. “W3C DOM Compatibility Tables.” Peter-Paul Koch. 2008. http://www.quirksmode.org/dom/compatibility.html (accessed January 28, 2008).

Mozilla.org. Core JavaScript 1.5 Reference, Mozilla.org. 2008. http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference (accessed January 28, 2008).

Mozilla.org. Gecko DOM Reference. Mozilla.org. 2008. http://developer.mozilla.org/en/docs/Gecko_DOM_Reference (accessed January 28,2008).

Standard ECMA-262. ECMAScript Language Specification. 3rd ed. December 1999. http://www.ecma-international.org/publications/standards/Ecma-262.htm.

W3C Recommendation. Document Object Model (DOM) Level 2 Core Specification, Version 1.0. November 13, 2000. http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/.

W3C Recommendation. Document Object Model (DOM) Level 2 Events Specification, Version 1.0. November 13, 2000. http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/.

W3C Recommendation. Document Object Model (DOM) Level 2 HTML Specification, Version 1.0. January 9, 2003. http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/.

W3C Recommendation. Document Object Model (DOM) Level 2 Style Specification, Version 1.0. November 13, 2000. http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113/.

W3C Recommendation. Document Object Model (DOM) Level 3 Core Specification, Version 1.0. April 7, 2004. http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/.

W3C Recommendation. HTML 4.01 Specification. December 24, 1999. http://www.w3.org/TR/html401/.


1 http://developer.mozilla.org/en/docs/About_JavaScript.

2 http://www.mozilla.org/foundation/.

3 http://www.ecma-international.org/.

4 http://developer.mozilla.org/en/docs/JavaScript_Language_Resources#JavaScript_2.0_and_ECMAScript_Edition_4.

5 http://developer.mozilla.org/en/docs/JavaScript_Language_Resources#JavaScript_2.0_and_ECMAScript_Edition_4.

6 http://www.getfirebug.com/.

7 http://www.mozilla.com/firefox/.

8 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects: Number.

9 http://en.wikipedia.org/wiki/Unicode.

10 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference#Global_Objects.

11 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference#Global_Functions.

12 http://www.w3.org/DOM/.

13 http://www.w3.org.

14 http://developer.mozilla.org/en/docs/Gecko_DOM_Reference.

15 alert() is a function of the BOM (discussed later) that is available to JavaScript in a web browser. It simply displays a dialog with the given message.

16 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Function:call#Example:_Using_call_to_chain_constructors_for_an_object.

17 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Fu nction:apply#Example:_Using_apply_to_chain_constructors.

18 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects: RegExp.

19 http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects: Error.

20 Because JavaScript has no formal notion of a class, the word “class” is used loosely in this book to describe a constructor function or the group of objects that were instantiated using the same constructor function.

21 http://en.wikipedia.org/wiki/Singleton_pattern.

22 http://www.litotes.demon.co.uk/js_info/private_static.html.

23 http://javascript.crockford.com/prototypal.html.

24 Mozilla (Firefox): http://developer.mozilla.org/en/docs/DOM:window. Internet Explorer: http://msdn2.microsoft.com/en-us/library/ms535873.aspx.

25 http://developer.mozilla.org/en/docs/DOM:window.

26 http://developer.mozilla.org/en/docs/DOM:window.navigator.

27 http://developer.mozilla.org/en/docs/DOM:window.screen

28 http://developer.mozilla.org/en/docs/DOM:window.history.

29 http://developer.mozilla.org/en/docs/DOM:window.location.

30 http://www.w3.org/TR/html401/present/frames.html.

31 http://www.w3.org/DOM/DOMTR.

32 Some online resources for identifying DOM browser support are http://www.quirksmode.org/dom/compatibility.html and http://www.webdevout.net/browser-support. A good book is Dynamic HTML: The Definitive Reference (http://www.quirksmode.org/dom/compatibility.html and http://www.webdevout.net/browser-support. A good book is Dynamic HTML: The Definitive Reference (http://www.dannyg.com/pubs/dhtml/ and http://www.webdevout.net/browser-support. A good book is Dynamic HTML: The Definitive Reference (http://www.dannyg.com/pubs/dhtml/).

33 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1950641247.

34 http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#ID-26809268.

35 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1950641247.

36 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-745549614.

37 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#i-Docu-ment.

38 http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#ID-40002357.

39 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-536297177.

40 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1312295772.

41 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node-TEXT_NODE.

42 http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet.

43 http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration.

44 http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSS2Properties.

45 http://www.quirksmode.org/dom/classchange.html.

46 http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.3.

47 Tags that do not support this event handler are <applet>,<bdo>,<br>,<font>,<frame>,<frameset>,<head>,<html>,<iframe>,<isindex>,<meta>, and <style>.

48 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-htmlevents.

49 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event.

50 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-MouseEvent.

51 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-UIEvent.

52 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset