Section 15.4. Overview of the W3C DOM


15.4. Overview of the W3C DOM

Having examined the simple legacy DOM, let's now move on to the powerful and standardized W3C DOM that extends and replaces it. The API of the W3C DOM is not particularly complicated, but before beginning the discussion of programming with the DOM, there are a number of things you should understand about the DOM architecture.

15.4.1. Representing Documents as Trees

HTML documents have a hierarchical structure of nested tags that is represented in the DOM as a tree of objects. The tree representation of an HTML document contains nodes representing HTML tags or elements, such as <body> and <p>, and nodes representing strings of text. An HTML document may also contain nodes representing HTML comments.[*] Consider the following simple HTML document:

[*] The DOM can also be used to represent XML documents, which have a more complex syntax than HTML documents, and the tree representation of such a document may contain nodes that represent XML entity references, processing instructions, CDATA sections, and so on. For more about using the DOM with XML, see Chapter 21.

 <html>   <head>     <title>Sample Document</title>   </head>   <body>     <h1>An HTML Document</h1>     <p>This is a <i>simple</i> document. </html> 

The DOM representation of this document is the tree pictured in Figure 15-1.

Figure 15-1. The tree representation of an HTML document


If you are not already familiar with tree structures in computer programming, it is helpful to know that they borrow terminology from family trees. The node directly above a node is the parent of that node. The nodes one level directly below another node are the children of that node. Nodes at the same level, and with the same parent, are siblings. The set of nodes any number of levels below another node are the descendants of that node. And the parent, grandparent, and all other nodes above a node are the ancestors of that node.

15.4.2. Nodes

The DOM tree structure illustrated in Figure 15-1 is represented as a tree of various types of Node objects. The Node interface[*] defines properties and methods for traversing and manipulating the tree. The childNodes property of a Node object returns a list of children of the node, and the firstChild, lastChild, nextSibling, previousSibling, and parentNode properties provide a way to traverse the tree of nodes. Methods such as appendChild(), removeChild(), replaceChild(), and insertBefore() enable you to add and remove nodes from the document tree. You'll see examples of the use of these properties and methods later in this chapter.

[*] The DOM standard defines interfaces, not classes. If you are not familiar with the term interface in object-oriented programming, think of it as an abstract kind of class. I'll describe the difference in more detail later in this DOM overview.

15.4.2.1. Types of nodes

Different types of nodes in the document tree are represented by specific subinterfaces of Node. Every Node object has a nodeType property that specifies what kind of node it is. If the nodeType property of a node equals the constant Node.ELEMENT_NODE, for example, you know the Node object is also an Element object, and you can use all the methods and properties defined by the Element interface with it. Table 15-1 lists the node types commonly encountered in HTML documents and the nodeType value for each one.

Table 15-1. Common node types

Interface

nodeType constant

nodeType value

Element

Node.ELEMENT_NODE

1

Text

Node.TEXT_NODE

3

Document

Node.DOCUMENT_NODE

9

Comment

Node.COMMENT_NODE

8

DocumentFragment

Node.DOCUMENT_FRAGMENT_NODE

11

Attr

Node.ATTRIBUTE_NODE

2


The Node at the root of the DOM tree is a Document object. The documentElement property of this object refers to an Element object that represents the root element of the document. For HTML documents, this is the <html> tag that is either explicit or implicit in the document. (The Document node may have other children, such as Comment nodes, in addition to the root element.) In HTML documents, you'll typically be more interested in the <body> element than in the <html> element, and as a convenience, you can use document.body to refer to this element.

There is only one Document object in a DOM tree. Most nodes in the tree are Element objects, which represent tags such as <html> and <i>, and Text objects, which represent strings of text. If the document parser preserves comments, those comments are represented in the DOM tree by Comment objects. Figure 15-2 shows a partial class hierarchy for these and other core DOM interfaces.

Figure 15-2. A partial class hierarchy of the core DOM API


15.4.2.2. Attributes

The attributes of an element (such as the src and width attributes of an <img> tag) may be queried, set, and deleted using the getAttribute(), setAttribute(), and removeAttribute() methods of the Element interface. As shown later, standard attributes of HTML tags are available as properties of the Element nodes that represent those tags.

Another, more awkward way to work with attributes is with the getAttributeNode() method, which returns an Attr object representing an attribute and its value. (One reason to use this more awkward technique is that the Attr interface defines a specified property that allows you to determine whether the attribute is literally specified in the document or whether its value is a default value.) The Attr interface appears in Figure 15-2 and is a type of node. Note, however, that Attr objects do not appear in the childNodes[] array of an element and are not directly part of the document tree in the way that Element and Text nodes are. The DOM specification allows Attr nodes to be accessed through the attributes[] array of the Node interface, but Internet Explorer defines a different and incompatible attributes[] array that makes it impossible to use this feature portably.

15.4.3. The DOM HTML API

The DOM standard was designed for use with both XML and HTML documents. The core DOM APIthe Node, Element, Document, and other interfacesis relatively generic and applies to both types of documents. The DOM standard also includes interfaces that are specific to HTML documents. As you can see from Figure 15-2, HTMLDocument is an HTML-specific subinterface of Document and HTMLElement is an HTML-specific subinterface of Element. Furthermore, the DOM defines tag-specific interfaces for many HTML elements. These tag-specific interfaces, such as HTMLBodyElement and HTMLTitleElement, typically define a set of properties that mirror the HTML tag's attributes.

The HTMLDocument interface defines various document properties and methods that were supported by browsers prior to W3C standardization. These include the location property, forms[] array, and write() method, which were described earlier in this chapter.

The HTMLElement interface defines id, style, title, lang, dir, and className properties. These properties allow convenient access to the values of the id, style, title, lang, dir, and class attributes, which are allowed on all HTML tags. ("class" is a reserved word in JavaScript, so the class attribute in HTML becomes the className property in JavaScript.) Some HTML tags, listed in Table 15-2, accept no attributes other than these six and so are fully represented by the HTMLElement interface.

Table 15-2. Simple HTML tags

<abbr>

<acronym>

<address>

<b>

<bdo>

<big>

<center>

<cite>

<code>

<dd>

<dfn>

<dt>

<em>

<i>

<kbd>

<noframes>

<noscript>

<s>

<samp>

<small>

<span>

<strike>

<strong>

<sub>

<sup>

<tt>

<u>

<var>


All other HTML tags have corresponding interfaces defined by the HTML portion of the DOM specification. For many HTML tags, these interfaces do nothing more than provide a set of properties that mirror their HTML attributes. For example, the <ul> tag has a corresponding HTMLUListElement interface, and the <body> tag has a corresponding HTMLBodyElement interface. Because these interfaces simply define properties that are part of the HTML standard, they are not documented in detail in this book. You can safely assume that the HTMLElement object that represents a particular HTML tag has properties for each standard attribute of that tag (but see the naming conventions described in the next section). See the HTMLElement entry in Part IV for a table of HTML tags and their corresponding JavaScript properties.

Note that the DOM standard defines properties for HTML attributes as a convenience for script writers. The general way to query and set attribute values is with the getAttribute() and setAttribute() methods of the Element object, and you need to use these methods when working with attributes that are not part of the HTML standard.

Some of the interfaces specified by the HTML DOM define properties or methods other than those that simply mirror HTML attribute values. For example, the HTMLInputElement interface defines focus() and blur() methods and a form property, and the HTMLFormElement interface defines submit() and reset() methods and a length property. When the JavaScript representation of an HTML element includes properties or methods that do more than simply mirror an HTML attribute, those elements are documented in Part IV. Note, however, that the reference section does not use the verbose interface names defined by the DOM. Instead, for simplicity (and backward compatibility with historical usage); they are documented under simpler names. See, for example, the reference entries for Anchor, Image, Input, Form, Link, Option, Select, Table, and Textarea.

15.4.3.1. HTML naming conventions

When working with the HTML-specific portions of the DOM standard, you should be aware of some simple naming conventions. First, remember that although HTML is not case-sensitive, JavaScript is. Properties of the HTML-specific interfaces begin with lowercase letters. If the property name consists of multiple words, the first letters of the second and subsequent words are capitalized. Thus, the maxlength attribute of the <input> tag translates into the maxLength property of HTMLInputElement.

When an HTML attribute name conflicts with a JavaScript keyword, it is prefixed with the string "html" to avoid the conflict. Thus, the for attribute of the <label> tag translates to the htmlFor property of the HTMLLabelElement. An exception to this rule is the class attribute (which can be specified for any HTML element); it translates to the className property of HTMLElement.[*]

[*] The term className is misleading because in addition to specifying a single class name, this property (and the HTML attribute it represents) can also specify a space-separated list of class names.

15.4.4. DOM Levels and Features

There are two versions, or "levels," of the DOM standard. DOM Level 1 was standardized in October 1998. It defines the core DOM interfaces, such as Node, Element, Attr, and Document, and also defines various HTML-specific interfaces. DOM Level 2 was standardized in November 2000. In addition to some updates to the core interfaces, this new version of the DOM is greatly expanded to define standard APIs for working with document events and CSS stylesheets and to provide additional tools for working with ranges of documents.

As of Level 2, the DOM standard has been "modularized." The Core module, which defines the basic tree structure of a document with the Document, Node, Element, and Text interfaces (among others), is the only required module. All other modules are optional and may or may not be supported, depending on the needs of the implementation. The DOM implementation of a web browser would obviously support the HTML module because web documents are written in HTML. Browsers that support CSS stylesheets typically support the StyleSheets and CSS modules because (as shown in Chapter 16) CSS styles play a crucial role in Dynamic HTML programming. Similarly, since almost all interesting client-side JavaScript programming requires event-handling capabilities, you would expect web browsers to support the Events module of the DOM specification. Unfortunately, Microsoft has never implemented the DOM Events module for Internet Explorer, and, as described in Chapter 17, events are handled differently in the legacy DOM, the W3C DOM, and the IE DOM.

This book documents DOM levels 1 and 2; you can find the corresponding reference material in Part IV.

The W3C has continued to refine and expand the DOM standard and has released specifications for several Level 3 modules, including the Level 3 version of the Core module. Level 3 features are not yet widely supported by web browsers (although Firefox has partial support) and are not documented in this edition of this book.

In addition to DOM Levels 1, 2, and 3, you may also sometimes see a reference to DOM Level 0. This term does not refer to any formal standard but does refer informally to the common features of the HTML document object models implemented by Netscape and Internet Explorer prior to W3C standardization. That is, "DOM Level 0" is a synonym for the "legacy DOM."

15.4.5. DOM Conformance

At the time of this writing, recent releases of modern browsers such as Firefox, Safari, and Opera have good or excellent support of the DOM Level 2 standard. Internet Explorer 6 is compliant with the Level 1 DOM but does not support the Level 2 DOM nearly as well. In addition to incomplete support of the Level 2 Core, it has no support at all for the Level 2 Events module, which is the topic of Chapter 17. Internet Explorer 5 and 5.5 have substantial gaps in their Level 1 conformance but support key DOM Level 1 methods well enough to run most of the examples in this chapter.

The number of available browsers has become too large and the rate of change in the area of standards support has grown too fast for this book to even attempt to provide definitive statements about which browsers support which particular DOM features. Therefore, you'll have to rely on other information sources to determine exactly how conformant the DOM implementation is in any particular web browser.

One source for conformance information is the implementation itself. In a conformant implementation, the implementation property of the Document object refers to a DOMImplementation object that defines a method named hasFeature(). You can use this method (if it exists) to ask an implementation whether it supports a specific feature (or module) of the DOM standard. For example, to determine whether the DOM implementation in a web browser supports the basic DOM Level 1 interfaces for working with HTML documents, you can use the following code:

 if (document.implementation &&     document.implementation.hasFeature &&     document.implementation.hasFeature("html", "1.0")) {     // The browser claims to support Level 1 Core and HTML interfaces } 

The hasFeature() method takes two arguments: the name of the feature to check and a version number, both expressed as a string. It returns TRue if the specified version of the specified feature is supported. Table 15-3 lists the feature name/version number pairs that are defined by the DOM Level 1 and Level 2 standards. Note that the feature names are case-insensitive: you can capitalize them any way you choose. The fourth column of the table specifies what other features are required for support of a feature and are therefore implied by a return value of TRue. For example, if hasFeature() indicates that the MouseEvents module is supported, this implies that UIEvents is also supported, which in turn implies that the Events, Views, and Core modules are supported.

Table 15-3. Features that can be tested with hasFeature()

Feature name

Version

Description

Implies

HTML

1.0

Level 1 Core and HTML interfaces

XML

1.0

Level 1 Core and XML interfaces

Core

2.0

Level 2 Core interfaces

HTML

2.0

Level 2 HTML interfaces

Core

XML

2.0

Level 2 XML-specific interfaces

Core

Views

2.0

AbstractView interface

Core

StyleSheets

2.0

Generic stylesheet traversal

Core

CSS

2.0

CSS styles

Core, Views

CSS2

2.0

CSS2Properties interface

CSS

Events

2.0

Event-handling infrastructure

Core

UIEvents

2.0

User-interface events (plus Events and Views)

Events, Views

MouseEvents

2.0

Mouse events

UIEvents

HTMLEvents

2.0

HTML events

Events


In Internet Explorer 6, hasFeature() returns true only for the feature HTML and version 1.0. It does not report compliance to any of the other features listed in Table 15-3 (although, as shown in Chapter 16, it supports the most common uses of the CSS2 module).

This book documents the interfaces that make up all the DOM modules listed in Table 15-3. The Core and HTML modules are covered in this chapter. The StyleSheets, CSS, and CSS2 modules are covered in Chapter 16, and the various Event modules are covered in Chapter 17. Part IV includes complete coverage of all modules.

The hasFeature() method is not always perfectly reliable. As previously noted, IE 6 reports Level 1 compliance to HTML features even though there are some problems with its compliance. On the other hand, Netscape 6.1 reported noncompliance to the Level 2 Core feature even though it was mostly compliant. In both cases, you need fine-grained information about exactly what is and is not compliant. This is exactly the type of information that is too voluminous and volatile to include in a printed book.

If you are an active web developer, you undoubtedly already know or will discover many browser-specific support details on your own. There are also resources on the Web that can help you. The W3C has published a partial test suite for certain DOM modules at http://www.w3c.org/DOM/Test/. Unfortunately, it has not published its results from applying this suite to common browsers.

Perhaps the best place to find compatibility and compliance information is at independent sites on the Web. One notable site is http://www.quirksmode.org by Peter-Paul Koch; it includes the results of the author's extensive research into browser compatibility with the DOM and CSS standards. Another is http://webdevout.net/browser_support.php by David Hammond.

15.4.5.1. DOM conformance in Internet Explorer

Because IE is the most widely used web browser, a few special notes about its compliance to the DOM specifications are appropriate here. IE 5 and later support the Level 1 Core and HTML features well enough to run the examples in this chapter, and they support the key Level 2 CSS features well enough to run most of the examples in Chapter 16. Unfortunately, IE 5, 5.5, and 6 do not support the DOM Level 2 Events module, even though Microsoft participated in the definition of this module and had ample time to implement it for IE 6. IE's lack of support for the standard event model impedes the development of advanced client-side web applications.

Although IE 6 claims (through its hasFeature() method) to support the Core and HTML interfaces of the DOM Level 1 standard, this support is actually incomplete. The most egregious problem, and the one you are most likely to encounter, is a minor but annoying one: IE does not support the node-type constants defined by the Node interface. Recall that each node in a document has a nodeType property that specifies what type of node it is. The DOM specification also says that the Node interface defines constants that represent each defined node type. For example, the constant Node.ELEMENT_NODE represents an Element node. In IE (at least as high as version 6), these constants simply do not exist.

The examples in this chapter have been modified to work around this problem by using integer literals instead of the corresponding symbolic constants. For example, you'll see code like this:

 if (n.nodeType == 1 /*Node.ELEMENT_NODE*/)  // Check if n is an Element 

It is good programming style to use constants instead of hardcoded integer literals in your code, and if you'd like to do this portably, you can include the following code in your programs to define these constants if they are missing:

 if (!window.Node) {     var Node = {            // If there is no Node object, define one         ELEMENT_NODE: 1,    // with the following properties and values.         ATTRIBUTE_NODE: 2,  // Note that these are HTML node types only.         TEXT_NODE: 3,       // For XML-specific nodes, you need to add         COMMENT_NODE: 8,    // other constants here.         DOCUMENT_NODE: 9,         DOCUMENT_FRAGMENT_NODE: 11     }; } 

15.4.6. Language-Independent DOM Interfaces

Although the DOM standard grew out of a desire to have a common API for dynamic HTML programming, the DOM is not of interest only to web scripters. In fact, the standard is currently most heavily used by server-side Java and C++ programs that parse and manipulate XML documents. Because of its many uses, the DOM standard is defined as language-independent. This book describes only the JavaScript binding of the DOM API, but you should be aware of a few other points. First, note that object properties in the JavaScript binding are typically mapped to pairs of get/set methods in other language bindings. Thus, when a Java programmer asks you about the getFirstChild() method of the Node interface, you need to understand that the JavaScript binding of the Node API doesn't define a getFirstChild() method. Instead, it simply defines a firstChild property, and reading the value of this property in JavaScript is equivalent to calling getFirstChild() in Java.

Another important feature of the JavaScript binding of the DOM API is that certain DOM objects behave like JavaScript arrays. If an interface defines a method named item(), objects that implement that interface behave like read-only numerical arrays. For example, suppose you've obtained a NodeList object by reading the childNodes property of a node. You can obtain the individual Node objects in the list by passing the desired node number to the item() method, or, more simply, you can simply treat the NodeList object as an array and index it directly. The following code illustrates these two options:

 var n = document.documentElement;  // This is a Node object. var children = n.childNodes;       // This is a NodeList object. var head = children.item(0);       // Here is one way to use a NodeList. var body = children[1];            // But this way is easier! 

Similarly, if a DOM object has a namedItem() method, passing a string to this method is the same as using the string as an array index for the object. For example, the following lines of code are all equivalent ways to access a form element:

 var f = document.forms.namedItem("myform"); var g = document.forms["myform"]; var h = document.forms.myform; 

Although you can use array notation to access the elements of a NodeList, it is important to remember that a NodeList is simply an array-like object (see Section 7.8.), not a true Array. A NodeList does not have a sort() method, for example.

Because the DOM standard may be used in a variety of ways, the architects of the standard were careful to define the DOM API in a way that would not restrict the ability of others to implement the API as they saw fit. Specifically, the DOM standard defines interfaces instead of classes. In object-oriented programming, a class is a fixed data type that must be implemented exactly as specified. An interface, on the other hand, is a collection of methods and properties that must be implemented together. Thus, an implementation of the DOM is free to define whatever classes it sees fit, but those classes must define the methods and properties of the various DOM interfaces.

This architecture has a couple of important implications. First, the class names used in an implementation might not correspond directly to the interface names used in the DOM standard. Second, a single class may implement more than one interface. For example, consider the Document object. This object is an instance of some class defined by the web browser implementation. We don't know what the specific class is, but we do know that it implements the DOM Document interfacethat is, all methods and properties defined by Document are available to us through the Document object. Since web browsers work with HTML documents, we also know that the Document object implements the HTMLDocument interface and that all methods and properties defined by that interface are available to us as well. Furthermore, since web browsers support CSS, the Document object also implements the DocumentStyle and DocumentCSS DOM interfaces. And if the web browser supports the DOM Events and Views modules, Document implements the DocumentEvent and DocumentView interfaces as well.

In general, Part IV focuses on the objects that client-side JavaScript programmers actually interact with, rather than the more abstract interfaces that specify the API of those objects. Therefore, you'll find that the reference section contains entries for Document and HTMLDocument, but not for the minor add-on interfaces like DocumentCSS and DocumentView. The methods defined by those interfaces are simply integrated into the entry for the Document object.

Another important fact you need to understand is that because the DOM standard defines interfaces instead of classes, it does not define any constructor methods. If you want to create a new Text object to insert into a document, for example, you cannot write:

 var t = new Text("this is a new text node");  // No such constructor! 

Since it cannot define constructors, the DOM standard instead defines a number of useful factory methods in the Document interface. So, to create a new Text node for a document, you would write the following:

 var t = document.createTextNode("this is a new text node"); 

Factory methods defined by the DOM have names that begin with the word "create". In addition to the factory methods defined by Document, a few others are defined by DOMImplementation and available through document.implementation.




JavaScript. The Definitive Guide
JavaScript: The Definitive Guide
ISBN: 0596101996
EAN: 2147483647
Year: 2004
Pages: 767

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net