W3C

DOM4

W3C Working Draft 5 April 2012

This Version:
http://www.w3.org/TR/2012/WD-dom-20120405/
Latest Version:
http://www.w3.org/TR/dom/
Latest Editors' Draft:
http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
Previous Versions:
http://www.w3.org/TR/2012/WD-dom-20120105/
http://www.w3.org/TR/2011/WD-dom-20110915/
http://www.w3.org/TR/2011/WD-domcore-20110531/
http://www.w3.org/TR/2010/WD-domcore-20101007/
Editors:
Anne van Kesteren (Opera Software ASA) <annevk@opera.com>
Aryeh Gregor (Mozilla Foundation) <ayg@aryeh.name>
Ms2ger (Mozilla Foundation) <ms2ger@gmail.com>

Abstract

DOM4 defines the event and document model the Web platform uses. The DOM is a language- and platform neutral interface that allows programs and scripts to dynamically access and update the content and structure of documents.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This is the 5 April 2012 W3C Working Draft of DOM4. Please send comments to www-dom@w3.org (archived) with [DOM] at the start of the subject line, or file a bug.

This document is produced by the Web Applications (WebApps) Working Group. The WebApps Working Group is part of the Rich Web Clients Activity in the W3C Interaction Domain.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

Table of Contents

  1. Goals
  2. 1 Conformance
    1. 1.1 Dependencies
    2. 1.2 Extensibility
  3. 2 Terminology
    1. 2.1 Trees
    2. 2.2 Strings
    3. 2.3 Common microsyntaxes
      1. 2.3.1 Common parser idioms
      2. 2.3.2 Space-separated tokens
    4. 2.4 Namespaces
  4. 3 Errors
    1. 3.1 Exception DOMException
    2. 3.2 Interface DOMError
    3. 3.3 Error types
  5. 4 Events
    1. 4.1 Introduction to "DOM Events"
    2. 4.2 Interface Event
    3. 4.3 Interface CustomEvent
    4. 4.4 Constructing events
    5. 4.5 Interface EventTarget
    6. 4.6 Dispatching events
    7. 4.7 Firing events
  6. 5 Nodes
    1. 5.1 Introduction to "The DOM"
    2. 5.2 Node tree
      1. 5.2.1 Mutation algorithms
      2. 5.2.2 Mutation methods
      3. 5.2.3 Legacy mutation methods
      4. 5.2.4 Mutation observers
      5. 5.2.5 Interface MutationRecord
    3. 5.3 Interface Node
    4. 5.4 Interface Document
      1. 5.4.1 Interface DOMImplementation
    5. 5.5 Interface DocumentFragment
    6. 5.6 Interface DocumentType
    7. 5.7 Interface Element
      1. 5.7.1 Interface Attr
    8. 5.8 Interface CharacterData
    9. 5.9 Interface Text
    10. 5.10 Interface ProcessingInstruction
    11. 5.11 Interface Comment
  7. 6 Ranges
    1. 6.1 Interface Range
  8. 7 Traversal
    1. 7.1 Interface NodeIterator
    2. 7.2 Interface TreeWalker
    3. 7.3 Interface NodeFilter
  9. 8 Collections
    1. 8.1 Interface NodeList
    2. 8.2 Interface HTMLCollection
  10. 9 Lists
    1. 9.1 Interface DOMStringList
    2. 9.2 Interface DOMTokenList
    3. 9.3 Interface DOMSettableTokenList
  11. 10 Historical
    1. 10.1 DOM Events
    2. 10.2 DOM Core
    3. 10.3 DOM Range
    4. 10.4 DOM Traversal
  12. References
    1. Normative references
    2. Informative references
  13. Acknowledgments

Goals

This specification standardizes the DOM. It does so as follows:

  1. By consolidating DOM Level 3 Core [DOM3CORE], Element Traversal [ELEMENTTRAVERSAL], the "DOM Event Architecture" and "Basic Event Interfaces" chapters of DOM Level 3 Events [DOM3EVENTS] (specific type of events do not belong in the base specification), and DOM Level 2 Traversal and Range [DOM2TR], and:

  2. By moving features from HTML5 that ought to be part of the DOM platform here, while preventing a dependency on HTML5. [HTML]

  3. By defining a replacement for the "Mutation Events" and "Mutation Name Event Types" chapters of DOM Level 3 Events [DOM3EVENTS] as the old model was problematic.

    The old model is expected to be removed from implementations in due course.

  4. By defining new features that simplify common DOM operations.

1 Conformance

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and terminate these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)

User agents may impose implementation-specific limits on otherwise unconstrained inputs, e.g. to prevent denial of service attacks, to guard against running out of memory, or to work around platform-specific limitations.

When a method or an attribute is said to call another method or attribute, the user agent must invoke its internal API for that attribute or method so that e.g. the author can't change the behavior by overriding attributes or methods with custom properties or functions in ECMAScript.

Unless otherwise stated, string comparisons are done in a case-sensitive manner.

1.1 Dependencies

The IDL fragments in this specification must be interpreted as required for conforming IDL fragments, as described in the Web IDL specification. [WEBIDL]

Some of the terms used in this specification are defined in Web IDL, XML and Namespaces in XML. [WEBIDL] [XML] [XMLNS]

1.2 Extensibility

Vendor-specific proprietary extensions to this specification are strongly discouraged. Authors must not use such extensions, as doing so reduces interoperability and fragments the user base, allowing only users of specific user agents to access the content in question.

If vendor-specific extensions are needed, the members should be prefixed by vendor-specific strings to prevent clashes with future versions of this specification. Extensions must be defined so that the use of extensions neither contradicts nor causes the non-conformance of functionality defined in the specification.

When vendor-neutral extensions to this specification are needed, either this specification can be updated accordingly, or an extension specification can be written that overrides the requirements in this specification. When someone applying this specification to their activities decides that they will recognize the requirements of such an extension specification, it becomes an applicable specification for the purposes of conformance requirements in this specification.

2 Terminology

The term context object means the object on which the method or attribute being discussed was called. When the context object is unambiguous, the term can be omitted.

The preferred MIME name of a character encoding is the name or alias labeled as "preferred MIME name" in the IANA Character Sets registry, if there is one, or the encoding's name, if none of the aliases are so labeled. [IANACHARSET]

2.1 Trees

Just like most programming paradigms the Web platform has finite hierarchical tree structures, simply named trees. The tree order is preorder, depth-first traversal.

An object that participates in a tree has a parent, which is either another object or null, and an ordered list of zero or more child objects.

The root of an object is itself, if it has no parent, or else it is the root of its parent.

An object A is called a descendant of an object B, if either A is a child of B or A is a child of an object C that is a descendant of B.

An inclusive descendant is an object or one of its descendants.

An object A is called an ancestor of an object B if and only if B is a descendant of A.

An inclusive ancestor is an object or one of its ancestors.

An object A is called a sibling of an object B, if and only if B and A share the same non-null parent.

An object A is preceding an object B if A and B are in the same tree and A comes before B in tree order.

An object A is following an object B if A and B are in the same tree and A comes after B in tree order.

The first child of an object is its first child or null if it has no child.

The last child of an object is its last child or null if it has no child.

The previous sibling of an object is its first preceding sibling or null if it has no preceding sibling.

The next sibling of an object is its first following sibling or null if it has no following sibling.

The index of an object is its number of preceding siblings.

2.2 Strings

Comparing two strings in a case-sensitive manner means comparing them exactly, code point for code point.

Comparing two strings in a ASCII case-insensitive manner means comparing them exactly, code point for code point, except that the characters in the range U+0041 .. U+005A (i.e. LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) and the corresponding characters in the range U+0061 .. U+007A (i.e. LATIN SMALL LETTER A to LATIN SMALL LETTER Z) are considered to also match.

Converting a string to ASCII uppercase means replacing all characters in the range U+0061 to U+007A (i.e. LATIN SMALL LETTER A to LATIN SMALL LETTER Z) with the corresponding characters in the range U+0041 to U+005A (i.e. LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z).

Converting a string to ASCII lowercase means replacing all characters in the range U+0041 to U+005A (i.e. LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) with the corresponding characters in the range U+0061 to U+007A (i.e. LATIN SMALL LETTER A to LATIN SMALL LETTER Z).

A string pattern is a prefix match for a string s when pattern is not longer than s and truncating s to pattern's length leaves the two strings as matches of each other.

The space characters, for the purposes of this specification, are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF), U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN (CR).

2.3 Common microsyntaxes

2.3.1 Common parser idioms

Some of the micro-parsers described below follow the pattern of having an input variable that holds the string being parsed, and having a position variable pointing at the next character to parse in input.

For parsers based on this pattern, a step that requires the user agent to collect a sequence of characters means that the following algorithm must be run, with characters being the set of characters that can be collected:

  1. Let input and position be the same variables as those of the same name in the algorithm that invoked these steps.

  2. Let result be the empty string.

  3. While position does not point past the end of input and the character at position is one of the characters, append that character to the end of result and advance position to the next character in input.

  4. Return result.

The step skip whitespace means that the user agent must collect a sequence of characters that are space characters. The collected characters are not used.

2.3.2 Space-separated tokens

A set of space-separated tokens is a string containing zero or more words (known as tokens) separated by one or more space characters, where words consist of any string of one or more characters, none of which are space characters.

A string containing a set of space-separated tokens may have leading or trailing space characters.

An unordered set of unique space-separated tokens is a set of space-separated tokens where none of the tokens are duplicated.

An ordered set of unique space-separated tokens is a set of space-separated tokens where none of the tokens are duplicated but where the order of the tokens is meaningful.

Sets of space-separated tokens sometimes have a defined set of allowed values. When a set of allowed values is defined, the tokens must all be from that list of allowed values; other values are non-conforming. If no such set of allowed values is provided, then all values are conforming.

How tokens in a set of space-separated tokens are to be compared (e.g. case-sensitively or not) is defined on a per-set basis.

When a user agent has to split a string on spaces, it must use the following algorithm:

  1. Let input be the string being parsed.

  2. Let position be a pointer into input, initially pointing at the start of the string.

  3. Let tokens be a list of tokens, initially empty.

  4. Skip whitespace.

  5. While position is not past the end of input:

    1. Collect a sequence of characters that are not space characters.

    2. Add the string collected in the previous step to tokens.

    3. Skip whitespace.

  6. Return tokens.

When a user agent has to remove a token from a string, it must use the following algorithm:

  1. Let input be the string being modified.

  2. Let token be the token being removed. It will not contain any space characters.

  3. Let output be the output string, initially empty.

  4. Let position be a pointer into input, initially pointing at the start of the string.

  5. Loop: If position is beyond the end of input, terminate these steps.

  6. If the character at position is a space character:

    1. Append the character at position to the end of output.

    2. Advance position so it points at the next character in input.

    3. Return to the step labeled loop.

  7. Otherwise, the character at position is the first character of a token. Collect a sequence of characters that are not space characters, and let that be s.

  8. If s is exactly equal to token, then:

    1. Skip whitespace (in input).

    2. Remove any space characters currently at the end of output.

    3. If position is not past the end of input, and output is not the empty string, append a single U+0020 SPACE character at the end of output.

  9. Otherwise, append s to the end of output.

  10. Return to the step labeled loop.

This causes any occurrences of the token to be removed from the string, and any spaces that were surrounding the token to be collapsed to a single space, except at the start and end of the string, where such spaces are removed.

2.4 Namespaces

The HTML namespace is http://www.w3.org/1999/xhtml.

The XML namespace is http://www.w3.org/XML/1998/namespace.

The XMLNS namespace is http://www.w3.org/2000/xmlns/.

3 Errors

3.1 Exception DOMException

exception DOMException {
  const unsigned short INDEX_SIZE_ERR = 1;
  const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
  const unsigned short HIERARCHY_REQUEST_ERR = 3;
  const unsigned short WRONG_DOCUMENT_ERR = 4;
  const unsigned short INVALID_CHARACTER_ERR = 5;
  const unsigned short NO_DATA_ALLOWED_ERR = 6; // historical
  const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
  const unsigned short NOT_FOUND_ERR = 8;
  const unsigned short NOT_SUPPORTED_ERR = 9;
  const unsigned short INUSE_ATTRIBUTE_ERR = 10; // historical
  const unsigned short INVALID_STATE_ERR = 11;
  const unsigned short SYNTAX_ERR = 12;
  const unsigned short INVALID_MODIFICATION_ERR = 13;
  const unsigned short NAMESPACE_ERR = 14;
  const unsigned short INVALID_ACCESS_ERR = 15;
  const unsigned short VALIDATION_ERR = 16; // historical
  const unsigned short TYPE_MISMATCH_ERR = 17;
  const unsigned short SECURITY_ERR = 18;
  const unsigned short NETWORK_ERR = 19;
  const unsigned short ABORT_ERR = 20;
  const unsigned short URL_MISMATCH_ERR = 21;
  const unsigned short QUOTA_EXCEEDED_ERR = 22;
  const unsigned short TIMEOUT_ERR = 23;
  const unsigned short INVALID_NODE_TYPE_ERR = 24;
  const unsigned short DATA_CLONE_ERR = 25;
  unsigned short code;
};

The code exception field must return the value it was initialized to. When an exception is created it must be initialized to zero.

To throw a type exception these steps must be run:

  1. Create a new DOMException exception whose type is type.

  2. Set its message to a user agent-defined value.

  3. If its type is in the first column of the error types table and has a corresponding legacy code exception field value in the third column, set its code exception field to that value.

  4. Throw the exception.

To throw a "TimeoutError" exception, a user agent would construct a DOMException exception whose type is "TimeoutError" and code exception field value is 23, and actually throw that object as an exception. In JavaScript, this exception will have a name property whose value is "TimeoutError".

3.2 Interface DOMError

This interface is intended for other specifications that want to introduce error handling through other means than exceptions. As with exceptions, the error types table is used.

interface DOMError {
  readonly attribute DOMString name;
};

The name attribute must return the value it was initialized to.

A type DOMError means a DOMError object whose name attribute is initialized to type.

A specification could say that an error attribute must return a "SyntaxError" DOMError.

3.3 Error types

The error types table below lists all the allowed error types, a description, and legacy code exception field values (when the error type is used for throwing an exception).

If your specification requires an error type not listed here, please file a bug as indicated at the top of this specification and it will be addressed shortly. Thanks!

TypeDescriptionLegacy code exception field value (if any)
"IndexSizeError" The index is not in the allowed range. INDEX_SIZE_ERR (1)
"HierarchyRequestError" The operation would yield an incorrect node tree. HIERARCHY_REQUEST_ERR (3)
"WrongDocumentError" The object is in the wrong document. WRONG_DOCUMENT_ERR (4)
"InvalidCharacterError" The string contains invalid characters. INVALID_CHARACTER_ERR (5)
"NoModificationAllowedError" The object can not be modified. NO_MODIFICATION_ALLOWED_ERR (7)
"NotFoundError" The object can not be found here. NOT_FOUND_ERR (8)
"NotSupportedError" The operation is not supported. NOT_SUPPORTED_ERR (9)
"InvalidStateError" The object is in an invalid state. INVALID_STATE_ERR (11)
"SyntaxError" The string did not match the expected pattern. SYNTAX_ERR (12)
"InvalidModificationError" The object can not be modified in this way. INVALID_MODIFICATION_ERR (13)
"NamespaceError" The operation is not allowed by Namespaces in XML. [XMLNS] NAMESPACE_ERR (14)
"InvalidAccessError" The object does not support the operation or argument. INVALID_ACCESS_ERR (15)
"TypeMismatchError" The type of the object does not match the expected type. TYPE_MISMATCH_ERR (17)
"SecurityError" The operation is insecure. SECURITY_ERR (18)
"NetworkError" A network error occurred. NETWORK_ERR (19)
"AbortError" The operation was aborted. ABORT_ERR (20)
"URLMismatchError" The given URL does not match another URL. URL_MISMATCH_ERR (21)
"QuotaExceededError" The quota has been exceeded. QUOTA_EXCEEDED_ERR (22)
"TimeoutError" The operation timed out. TIMEOUT_ERR (23)
"InvalidNodeTypeError" The supplied node is incorrect or has an incorrect ancestor for this operation. INVALID_NODE_TYPE_ERR (24)
"DataCloneError" The object can not be cloned. DATA_CLONE_ERR (25)

4 Events

4.1 Introduction to "DOM Events"

Throughout the web platform events are dispatched to objects to signal an occurrence, such as network activity or user interaction. These objects implement the EventTarget interface and can therefore add event listeners to observe events:

obj.addEventListener("load", imgFetched)

function imgFetched(ev) {
  // great success
  …
}

Event listeners can be removed by utilizing the removeEventListener() method, passing the same arguments.

Events are objects too and implement the Event interface (or a derived interface). In the example above ev is the event. It is passed as argument to event listener's callback (typically a JavaScript Function as shown above). Event listeners key off the event's type attribute value ("load" in the above example). The event's target attribute value returns the object to which the event was dispatched (obj above).

Now while typically events are dispatched by the user agent as the result of user interaction or the completion of some task, applications can dispatch events themselves, commonly known as synthetic events:

// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) })

// create and dispatch the event
var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}})
obj.dispatchEvent(event)

Apart from signaling, events are sometimes also used to let an application control what happens next in an operation. For instance as part of form submission an event whose type attribute value is "submit" is dispatched. If this event's preventDefault() method is invoked, form submission will be terminated. Applications who wish to make use of this functionality through events dispatched by the application (synthetic events) can make use of the return value of the dispatchEvent() method:

if(obj.dispatchEvent(event)) {
  // event was not canceled, time for some magic
  …
}

When an event is dispatched to an object that participates in a tree (e.g. an element), it can reach event listeners on that object's ancestors too. First all object's ancestor event listeners whose capture variable is set to true are invoked, in tree order. Second, object's own event listeners are invoked. And finally, and only if event's bubbles attribute value is true, object's ancestor event listeners are invoked again, but now in reverse tree order.

Lets look at an example on how events work in a tree:

<!doctype html>
<html>
 <head>
  <title>Boring example</title>
 </head>
 <body>
  <p>Hello <span id=x>world</span>!</p>
  <script>
   function test(e) {
     debug(e.target, e.currentTarget, e.eventPhase)
   }
   document.addEventListener("hey", test, true)
   document.body.addEventListener("hey", test)
   var ev = new Event("hey", {bubbles:true})
   document.getElementById("x").dispatchEvent(ev)
  </script>
 </body>
</html>

The debug function will be invoked twice. Each time the events's target attribute value will be the span element. The first time currentTarget attribute's value will be the document, the second time the body element. eventPhase attribute's value switches from CAPTURING_PHASE to BUBBLING_PHASE. If an event listener was registered for the span element, eventPhase attribute's value would have been AT_TARGET.

4.2 Interface Event

[Constructor(DOMString type, optional EventInit eventInitDict)]
interface Event {
  readonly attribute DOMString type;
  readonly attribute EventTarget? target;
  readonly attribute EventTarget? currentTarget;

  const unsigned short CAPTURING_PHASE = 1;
  const unsigned short AT_TARGET = 2;
  const unsigned short BUBBLING_PHASE = 3;
  readonly attribute unsigned short eventPhase;

  void stopPropagation();
  void stopImmediatePropagation();

  readonly attribute boolean bubbles;
  readonly attribute boolean cancelable;
  void preventDefault();
  readonly attribute boolean defaultPrevented;

  readonly attribute boolean isTrusted;
  readonly attribute DOMTimeStamp timeStamp;

  void initEvent(DOMString type, boolean bubbles, boolean cancelable);
};

dictionary EventInit {
  boolean bubbles;
  boolean cancelable;
};

An event allows for signaling that something has occurred. E.g. that an image has completed downloading. It is represented by the Event interface or an interface that inherits from the Event interface.

var event = new Event(type [, eventInitDict])

Returns a new event whose type attribute value is set to type. The optional eventInitDict argument allows for setting the bubbles and cancelable attributes via object members of the same name.

event . type

Returns the type of event, e.g. "click", "hashchange", or "submit".

event . target

Returns the object event is dispatched to.

event . currentTarget

Returns the object whose event listener's callback is invoked.

event . eventPhase

Returns the event's phase, which is one of CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE.

event . stopPropagation()

When dispatched in a tree, invoking this method prevents event from reaching any other objects than the current.

event . stopImmediatePropagation()

Invoking this method prevents event from reaching any event listeners registered after the current one and when dispatched in a tree also prevents event from reaching any other objects.

event . bubbles

Returns true if event's goes through its target attribute value's ancestors in reverse tree order, or false otherwise.

event . cancelable

Returns true or false depending on how event was initialized. Its return value does not always carry meaning, but true can indicate that part of the operation during which event was dispatched, can be canceled by invoking the preventDefault() method.

event . preventDefault()

If invoked when the cancelable attribute value is true, signals to the operation that caused event to be dispatched that it needs to be canceled.

event . defaultPrevented

Returns true if preventDefault() was invoked while the cancelable attribute value is true, or false otherwise.

event . isTrusted

Returns true if event was dispatched by the user agent, or false otherwise.

event . timeStamp

Returns the creation time of event in the number of milliseconds that passed since 00:00:00 UTC on 1 January 1970.

The type attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

The target and currentTarget attributes must return the values they were initialized to. When an event is created the attributes must be initialized to null.

The eventPhase attribute must return the value it was initialized to, which must be one of the following:

CAPTURING_PHASE (numeric value 1)

When an event is dispatched to an object that participates in a tree it will be in this phase before it reaches its target attribute value.

AT_TARGET (numeric value 2)

When an event is dispatched it will be in this phase on its target attribute value.

BUBBLING_PHASE (numeric value 3)

When an event is dispatched to an object that participates in a tree it will be in this phase after it reaches its target attribute value.

Initially the attribute must be initialized to AT_TARGET.


Each event has the following associated flags that are all initially unset:

When the stopPropagation() method is invoked the stop propagation flag must be set.

When the stopImmediatePropagation() method is invoked both the stop propagation flag and stop immediate propagation flag must be set.

The bubbles and cancelable attributes must return the values they were initialized to. When an event is created the attributes must be initialized to false.

When the preventDefault() method is invoked and the cancelable attribute is true, the canceled flag must be set.

The defaultPrevented attribute must return true if the canceled flag is set and false otherwise.


The isTrusted attribute must return the value it was initialized to. When an event is created the attribute must be initialized to false.

The timeStamp attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the number of milliseconds that has passed since 00:00:00 UTC on 1 January 1970.


When the initEvent(type, bubbles, cancelable) method is invoked these steps must be run:

  1. Set the initialized flag.

  2. If the dispatch flag is set, terminate these steps.

  3. Unset the stop propagation flag, stop immediate propagation flag, and canceled flag.

  4. Set the isTrusted attribute to false.

  5. Set the target attribute to null.

  6. Set the type attribute to the type argument.

  7. Set the bubbles attribute to the bubbles argument.

  8. Set the cancelable attribute to the cancelable argument.

As events have constructors initEvent() is superfluous. However, it has to be supported for legacy content.

4.3 Interface CustomEvent

[Constructor(DOMString type, optional CustomEventInit eventInitDict)]
interface CustomEvent : Event {
  readonly attribute any detail;
};

dictionary CustomEventInit : EventInit {
  any detail;
};

Events using the CustomEvent interface can be used to carry custom data.

var event = new CustomEvent(type [, eventInitDict])

Works analogously to the constructor for Event except that the optional eventInitDict argument now allows for setting the detail attribute too.

event . detail

Returns any custom data event was created with. Typically used for synthetic events.

The detail attribute must return the value it was initialized to. When an event is created the attribute must be initialized to null.

4.4 Constructing events

When a constructor of the Event interface, or of an interface that inherits from the Event interface, is invoked, these steps must be run:

  1. Create an event that uses the interface the constructor was invoked upon.

  2. Set its initialized flag.

  3. Initialize the type attribute to the type argument.

  4. If there is an eventInitDict argument then for each dictionary member defined therein find the attribute on event whose identifier matches the key of the dictionary member and then set the attribute to the value of that dictionary member.

  5. Return the event.

4.5 Interface EventTarget

interface EventTarget {
  void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
  void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
  boolean dispatchEvent(Event event);
};

callback interface EventListener {
  void handleEvent(Event event);
};

EventTarget is an object to which an event is dispatched when something has occurred. Each EventTarget has an associated list of event listeners.

An event listener is a handler for a specific event. Each event listener consists of a type (of the event), callback, and capture variable.

target . addEventListener(type, callback [, capture = false])

Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. When set to true, the capture argument ensures callback is only invoked when the event's eventPhase attribute value is CAPTURING_PHASE.

The event listener is appended to target's list of event listeners and is not appended if it is a duplicate (the event listeners in the list are unique).

target . removeEventListener(type, callback [, capture = false])

Remove the event listener in target's list of event listeners with the same type, callback, and capture.

target . dispatchEvent(event)

Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or it's preventDefault() method was not invoked, or false otherwise.

When the addEventListener(type, callback, capture) method is invoked these steps must be run:

  1. If callback is null terminate these steps.

  2. Append an event listener to the associated list of event listeners with type set to type, callback set to callback, and capture set to capture, unless there already is an event listener in that list with the same type, callback, and capture.

When the removeEventListener(type, callback, capture) method is invoked these steps must be run:

  1. Remove an event listener from the associated list of event listeners, whose type is name, callback is callback, and capture is capture.

When the dispatchEvent(event) method is invoked these steps must be run:

  1. If event's dispatch flag is set, or if its initialized flag is not set, throw an "InvalidStateError" exception and terminate these steps.

  2. Initialize event's isTrusted attribute to false.

  3. Dispatch the event and return the value that returns.

4.6 Dispatching events

To dispatch an event to a given object run these steps:

  1. Let event be the event that is dispatched.

  2. Set event's dispatch flag.

  3. Initialize event's target attribute to the object to which event is dispatched.

  4. If event's target attribute value is participating in a tree, let event path be a static ordered list of all its ancestors in tree order, or let event path be the empty list otherwise.

  5. Initialize event's eventPhase attribute to CAPTURING_PHASE.

  6. For each object in the event path invoke its event listeners with event event, as long as event's stop propagation flag is unset.

  7. Initialize event's eventPhase attribute to AT_TARGET.

  8. Invoke the event listeners of event's target attribute value with event, if event's stop propagation flag is unset.

  9. If event's bubbles attribute value is true, run these substeps:

    1. Reverse the order of event path.

    2. Initialize event's eventPhase attribute to BUBBLING_PHASE.

    3. For each object in the event path invoke its event listeners, with event event as long as event's stop propagation flag is unset.

  10. Unset event's dispatch flag.

  11. Initialize event's eventPhase attribute to AT_TARGET.

  12. Initialize event's currentTarget attribute to null.

  13. Return false if event's canceled flag is set, or true otherwise.

To invoke the event listeners for an object with an event run these steps:

  1. Let event be the event for which the event listeners are invoked.

  2. Let listeners be a static list of the event listeners associated with the object for which these steps are run.

  3. Initialize event's currentTarget attribute to the object for which these steps are run.

  4. Then run these substeps for each event listener in listeners:

    1. If event's stop immediate propagation flag is set, terminate the invoke algorithm.

    2. Let listener be the event listener.

    3. If event's type attribute value is not listener's type, terminate these substeps (and run them for the next event listener).

    4. If event's eventPhase attribute value is CAPTURING_PHASE and listener's capture is false, terminate these substeps (and run them for the next event listener).

    5. If event's eventPhase attribute value is BUBBLING_PHASE and listener's capture is true, terminate these substeps (and run them for the next event listener).

    6. If listener's callback is a Function object, its callback this value is the event's currentTarget attribute value.

    7. Call listener's callback, with the event passed to this algorithm as the first argument.

4.7 Firing events

To fire an event named e means that an event using the Event interface, with its type attribute initialized to e, and its isTrusted attribute initialized to true, is to be dispatched to the given object.

Fire is short for initializing and dispatching an event.

Fire an event is a concept to make initializing and dispatching an event easier to write down. If the event needs its bubbles or cancelable attribute initialized, one could write "fire an event named submit with its cancelable attribute initialized to true".

5 Nodes

5.1 Introduction to "The DOM"

The API to access and manipulate markup-based resources, such as HTML and XML, on the web platform is the tree of nodes, commonly referred to as "The DOM". And although typically a document ends up being the root of such a tree, it is a "document" only in the broadest sense.

To illustrate, lets see how this HTML gets represented:

<!DOCTYPE html>
<html class=e>
 <head><title>Aliens?</title></head>
 <body>Why yes.</body>
</html>

The root document is omitted for brevity and thanks to the magic that is HTML parsing not all space characters were turned into Text nodes, but the general concept is clear. Markup goes in, a tree of nodes comes out.

If you are interested in exploring this further, take a look at the most excellent Live DOM Viewer.

How much should be explained here? Ideas?

5.2 Node tree

Objects implementing the Document, DocumentFragment, DocumentType, Element, Text, ProcessingInstruction, or Comment interface (simply called nodes) participate in a tree.

A tree of nodes is constrained as follows, expressed as a relationship between the type of node and its allowed children:

Document

In tree order:

  1. Zero or more nodes each of which is either ProcessingInstruction or Comment.

  2. Optionally one DocumentType node.

  3. Zero or more nodes each of which is either ProcessingInstruction or Comment.

  4. Optionally one Element node.

  5. Zero or more nodes each of which is either ProcessingInstruction or Comment.

DocumentFragment
Element

Zero or more nodes each of which is one of Element, ProcessingInstruction, Comment, or Text.

DocumentType
Text
ProcessingInstruction
Comment

None.

5.2.1 Mutation algorithms

To pre-insert a node into a parent before a child, run these steps:

  1. If parent is not a Document, DocumentFragment, or Element node, throw a "HierarchyRequestError" and terminate these steps.

  2. If node is an inclusive ancestor of parent, throw a "HierarchyRequestError" and terminate these steps.

  3. If child is not null and its parent is not parent, throw a "NotFoundError" exception and terminate these steps.

  4. If parent is a document, run these substeps:

    1. If node is not a DocumentFragment, DocumentType, Element, ProcessingInstruction, or Comment node, throw a "HierarchyRequestError" and terminate these steps.

    2. If node is a DocumentFragment node, run these inner substeps:

      1. If node has more than one element child or has a Text node child, throw a "HierarchyRequestError" and terminate these steps.

      2. If node has one element child and either parent has an element child or child is not null and a doctype is following child, throw a "HierarchyRequestError" and terminate these steps.

    3. If node is an element and either parent has an element child or child is not null and a doctype is following child, throw a "HierarchyRequestError" and terminate these steps.

    4. If node is a doctype and either parent has a doctype child, an element is preceding child, or child is null and parent has an element child, throw a "HierarchyRequestError" and terminate these steps.

  5. Otherwise if parent is a DocumentFragment or Element node and node is not a DocumentFragment, Element, Text, ProcessingInstruction, or Comment node, throw a "HierarchyRequestError" and terminate these steps.

  6. Adopt node with parent's node document.

  7. Insert node into parent before child.

  8. Return node.

To insert a node into a parent before a child, optionally with a suppress observers flag, run these steps:

  1. Let count be the number of children of node if it is a DocumentFragment node, or one otherwise.

  2. For each range whose start node is parent and start offset is greater than child's index, increase its start offset by count.

  3. For each range whose end node is parent and end offset is greater than child's index, increase its end offset by count.

  4. Let nodes be node's children if node is a DocumentFragment node, or a list containing solely node otherwise.

  5. If node is a DocumentFragment node, queue a "childList" record with target node, addedNodes null, removedNodes nodes, nextSibling null, and previousSibling null.

    This step does intentionally not pay attention to the suppress observers flag.

  6. If node is a DocumentFragment node, remove its children with the suppress observers flag set.

  7. If suppress observers flag is unset, queue a "childList" record with target parent, addedNodes nodes, removedNodes null, nextSibling child, and previousSibling child's previous sibling or parent's last child if child is null.

  8. Insert all nodes in nodes before child or at the end of parent if child is null.

To append a node to a parent, pre-insert node into parent before null.

To replace a child with node within a parent, run these steps:

  1. If child's parent is not parent, throw a "NotFoundError" exception and terminate these steps.

  2. If node is an inclusive ancestor of parent, throw a "HierarchyRequestError" and terminate these steps.

  3. If parent is not a Document, DocumentFragment, or Element node, throw a "HierarchyRequestError" and terminate these steps.

  4. If parent is a document, run these substeps:

    1. If node is not a DocumentFragment, DocumentType, Element, ProcessingInstruction, or Comment node, throw a "HierarchyRequestError" and terminate these steps.

    2. If node is a DocumentFragment node, run these inner substeps:

      1. If node has more than one element child or has a Text node child, throw a "HierarchyRequestError" and terminate these steps.

      2. If node has one element child and either parent has an element child that is not child or a doctype is following child, throw a "HierarchyRequestError" and terminate these steps.

    3. If node is an element and either parent has an element child that is not child or a doctype is following child, throw a "HierarchyRequestError" and terminate these steps.

    4. If node is a doctype and either parent has a doctype child that is not child, or an element is preceding child, throw a "HierarchyRequestError" and terminate these steps.

  5. Otherwise if parent is a DocumentFragment or Element node and node is not a DocumentFragment, Element, Text, ProcessingInstruction, or Comment node, throw a "HierarchyRequestError" and terminate these steps.

  6. Let reference child be child's next sibling.

  7. Adopt node with parent's node document.

  8. Remove child from its parent with the suppress observers flag set.

  9. Insert node into parent before reference child with the suppress observers flag set.

  10. Let nodes be node's children if node is a DocumentFragment node, or a list containing solely node otherwise.

  11. queue a "childList" record with target parent, addedNodes nodes, removedNodes a list solely containing child, nextSibling reference child, and previousSibling child's previous sibling.

  12. Return child.

To replace all with a node within a parent, run these steps:

  1. Adopt node with parent's node document.

  2. Remove all parent's children, with the suppress observers flag set.

  3. If node is not null, insert node into parent before null with the suppress observers flag set.

  4. Let nodes be null if node is null, node's children if node is a DocumentFragment node, or a list containing node otherwise.

  5. queue a "childList" record with target parent, addedNodes nodes, removedNodes parent's children, nextSibling null, and previousSibling null.

This algorithm does not make any checks with regards to the node tree. Use it wisely.

To pre-remove a child from a parent, run these steps:

  1. If child's parent is not parent, throw a "NotFoundError" exception and terminate these steps.

  2. Remove child from parent.

  3. Return child.

To remove a node from a parent, optionally with suppress observers flag set, run these steps:

  1. Let index be node's index.

  2. For each range whose start node is a descendant of node, set its start to (parent, index).

  3. For each range whose end node is a descendant of node, set its end to (parent, index).

  4. For each range whose start node is parent and start offset is greater than index, decrease its start offset by one.

  5. For each range whose end node is parent and end offset is greater than index, decrease its end offset by one.

  6. If suppress observers flag is unset, queue a "childList" record with target parent, addedNodes null, removedNodes a list solely containing node, nextSibling node's next sibling, and previousSibling node's previous sibling.

  7. For each ancestor ancestor of node, if ancestor has any registered observers whose options's subtree is true, then for each such registered observer, append a transient registered observer whose observer and options are identical to the registered observer to node's list of registered observers.

  8. Remove node from its parent.

5.2.2 Mutation methods

The mutation method macro:

  1. Let node be null.

  2. Replace each string in nodes with a Text node whose data is the string value.

  3. If nodes contains more than one node, set node to a new DocumentFragment and append each node in nodes to it. If this throws an exception, re-throw the exception and terminate these steps.

    Otherwise, set node to the single node nodes contains.

The prepend(nodes) method must run these steps:

  1. Run the mutation method macro.
  2. Pre-insert node into the context object before the context object's first child.

The append(nodes) method must run these steps:

  1. Run the mutation method macro.
  2. Append node to the context object.

The before(nodes) method must run these steps:

  1. If the context object does not have a parent, terminate these steps.

  2. Run the mutation method macro.
  3. Pre-insert node into the context object's parent before the context object.

The after(nodes) method must run these steps:

  1. If the context object does not have a parent, terminate these steps.

  2. Run the mutation method macro.
  3. Pre-insert node into the context object's parent before the context object's next sibling.

The replace(nodes) method must run these steps:

  1. If the context object does not have a parent, terminate these steps.

  2. Run the mutation method macro.
  3. Replace the context object with node within the context object's parent.

The remove() method must run these steps:

  1. If the context object does not have a parent, terminate these steps.

  2. Remove the context object from the context object's parent.

5.2.3 Legacy mutation methods

The insertBefore(node, child) method must return the result of pre-inserting node into the context object before child.

The appendChild(node) method must return the result of appending node to the context object.

The replaceChild(node, child) method must return the result of replacing child with node within the context object.

The removeChild(child) method must return the result of pre-removing child from the context object.

5.2.4 Mutation observers

Each scripting environment has an associated list of MutationObserver objects which is initially empty. To invoke MutationObserver objects, run these steps:

  1. Let notify list be a copy of scripting environment's list of MutationObserver objects whose record queue is non-empty.

  2. For each MutationObserver object mo in notify list, run these substeps:

    1. Let queue be a copy of mo's record queue.

    2. Empty mo's record queue.

    3. Remove all transient registered observers whose observer is mo.

    4. Invoke mo's callback with queue as first argument, and mo (itself) as second argument and callback this value.

  3. If any MutationObserver object in scripting environment's list of MutationObserver objects has a non-empty record queue at this point, run these steps again (indeed, all of them).

The DOM standard does not define the scripting environment nor its scope. The HTML standard defines how this concept integrates with the rest of the platform as well as when invoke is invoked. This somewhat artificial boundary is made to prevent a dependency from DOM on HTML. [HTML]


Each node has an associated list of registered observers.

A registered observer consists of an observer (a MutationObserver object) and options (a MutationObserverInit dictionary). A transient registered observer is a specific type of registered observer.

[Constructor(MutationCallback callback)]
interface MutationObserver {
  void observe(Node target, MutationObserverInit options);
  void disconnect();
};

callback MutationCallback = void (MutationRecord[] mutations, MutationObserver observer);

dictionary MutationObserverInit {
  boolean childList;
  boolean attributes;
  boolean characterData;
  boolean subtree;
  boolean attributeOldValue;
  boolean characterDataOldValue;
  DOMString[] attributeFilter;
};

A MutationObserver object can be used to observe mutations to the tree of nodes.

Each MutationObserver object has these associated concepts:

To queue an "attributes" record with target target, name name, namespace namespace, and oldValue oldValue, run these steps:

  1. Let record be a new MutationRecord object with its type set to "attributes", target set to target, attributeName set to name, and attributeNamespace set to namespace.

  2. Let recordWithOldValue be a copy of record with its oldValue set to oldValue.

  3. For each registered observer observer (with observer's options as options) in target's list of registered observers, run these substeps:

    1. If options's attributes is not true, terminate these substeps (and run them for the next registered observer).

    2. If options's attributeFilter is non-empty, and name is not in it, terminate these substeps (and run them for the registered observer).

    3. If options's attributeOldValue is true, append recordWithOldValue to observer's observer record queue.

    4. Otherwise, append record to observer's observer record queue.

  4. For each ancestor ancestor of target, and for each registered observer observer (with observer's options as options) in ancestor's list of registered observers, run these substeps:

    1. If options's subtree is not true, terminate these substeps (and run them for the next registered observer).

    2. If options's attributes is not true, terminate these substeps (and run them for the next registered observer).

    3. If options's attributeFilter is non-empty, and name is not in it, terminate these substeps (and run them for the next registered observer).

    4. If options's attributeOldValue is true, append recordWithOldValue to observer's observer record queue.

    5. Otherwise, append record to observer's observer record queue.

To queue a "characterData" record with target target and oldValue oldValue, run these steps:

  1. Let record be a new MutationRecord object with its type set to "characterData" and target set to target.

  2. Let recordWithOldValue be a copy of record with its oldValue set to oldValue.

  3. For each registered observer observer (with observer's options as options) in target's list of registered observers, run these substeps:

    1. If options's characterData is not true, terminate these substeps (and run them for the next registered observer).

    2. If options's characterDataOldValue is true, append recordWithOldValue to observer's observer record queue.

    3. Otherwise, append record to observer's observer record queue.

  4. For each ancestor ancestor of target, and for each registered observer observer (with options options) in ancestor's list of registered observers, run these substeps:

    1. If options's subtree is not true, terminate these substeps (and run them for the next registered observer).

    2. If options's characterData is not true, terminate these substeps (and run them for the next registered observer).

    3. If options's characterDataOldValue is true, append recordWithOldValue to observer's observer record queue.

    4. Otherwise, append record to observer's observer record queue.

To queue a "childList" record with target target, addedNodes addedNodes, removedNodes removedNodes, previousSibling previousSibling, and nextSibling nextSibling, run these steps:

  1. Let record be a new MutationRecord object with its type set to "childList", target set to target, addedNodes set to addedNodes, removedNodes set to removedNodes, previousSibling set to previousSibling, and nextSibling set to nextSibling.

  2. For each registered observer observer (with observer's options as options) in target's list of registered observers, run these substeps:

    1. If options's childList is not true, terminate these substeps (and run them for the next registered observer).

    2. Append record to observer's observer record queue.

  3. For each ancestor ancestor of target, and for each registered observer observer (with observer's options as options) in ancestor's list of registered observers, run these substeps:

    1. If options's subtree is not true, terminate these substeps (and run them for the next registered observer).

    2. If options's childList is not true, terminate these substeps (and run them for the next registered observer).

    3. Append record to observer's observer record queue.

var observer = new MutationObserver(callback)

Constructs a MutationObserver object and sets its callback to callback. The callback is invoked with a list of MutationRecord objects as first argument and the constructed MutationObserver object as second argument. It is invoked after nodes registered with the observe() method, are mutated.

observer . observe(target, options)

Instructs the user agent to observe a given target (a node) and report any mutations based on the criteria given by options (an object).

The options argument allows for setting mutation observation options via object members. These are the object members that can be used:

childList

Set to true if mutations to target's children are to be observed.

attributes

Set to true if mutations to target's attributes are to be observed.

characterData

Set to true if mutations to target's data are to be observed.

subtree

Set to true if mutations to not just target, but also target's descendants are to be observed.

attributeOldValue

Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.

characterDataOldValue

Set to true if characterData is set to true and target's data before the mutation needs to be recorded.

attributeFilter

Set to a list of attribute names if not all attribute mutations need to be observed.

observer . disconnect()

Stops the observer from observing any mutations. Until the observe() method is used again, observer's callback will not be invoked.

The MutationObserver(callback) constructor must create a new MutationObserver object with callback set to callback, return it, and append it object to the scripting environment's list of MutationObserver objects.

The observe(target, options) method must run these steps:

  1. Run these substeps, with options as the context object:

    1. If neither childList, attributes, nor characterData is true, throw a "SyntaxError" and terminate these steps.

    2. If attributeOldValue is true and attributes is not true, throw a "SyntaxError" and terminate these steps.

    3. If attributeFilter is a non-empty array and attributes is not true, throw a "SyntaxError" and terminate these steps.

    4. If characterDataOldValue is true and characterData is not true, throw a "SyntaxError" and terminate these steps.

  2. If target's list of registered observers already includes a registered observer associated with the context object, replace that registered observer's options with options.

  3. Otherwise, add a new registered observer to target's list of registered observers with the context object as the observer and options as the options, and add target to context object's list of nodes on which it is registered.

The disconnect() method must, for each node node in the context object's list of nodes, remove any registered observer on node for which the context object is the observer, and also empty context object's record queue.

5.2.5 Interface MutationRecord

interface MutationRecord {
  readonly attribute DOMString type;
  readonly attribute Node target;
  readonly attribute NodeList? addedNodes;
  readonly attribute NodeList? removedNodes;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;
  readonly attribute DOMString? attributeName;
  readonly attribute DOMString? attributeNamespace;
  readonly attribute DOMString? oldValue;
};
record . type

Returns "attributes" if it was an attribute mutation. "characterData" if it was a mutation to a CharacterData node. And "childList" if it was a mutation to the tree of nodes.

record . target

Returns the node the mutation affected, depending on the type. For "attributes", it is the element whose attribute changed. For "characterData", it is the CharacterData node. For "childList", it is the node whose children changed.

record . addedNodes
record . removedNodes

Return the nodes added and removed respectively, or null otherwise.

record . previousSibling
record . nextSibling

Return the previous and next sibling respectively of the added and/or removed nodes, or null otherwise.

record . attributeName

Returns the name of the changed attribute, or null otherwise.

record . attributeNamespace

Returns the namespace of the changed attribute, or null otherwise.

record . oldValue

The return value depends on type. For "attributes", it is the value of the changed attribute before the change. For "characterData", it is the data of the changed node before the change. For "childList", it is null.

The type and target attributes must return the values they were initialized to.

The addedNodes, removedNodes, previousSibling, nextSibling, attributeName, attributeNamespace, and oldValue attributes must return the values they were initialized to. Unless stated otherwise, when a MutationRecord object is created, they must be initialized to null.

5.3 Interface Node

interface Node : EventTarget {
  const unsigned short ELEMENT_NODE = 1;
  const unsigned short ATTRIBUTE_NODE = 2; // historical
  const unsigned short TEXT_NODE = 3;
  const unsigned short CDATA_SECTION_NODE = 4; // historical
  const unsigned short ENTITY_REFERENCE_NODE = 5; // historical
  const unsigned short ENTITY_NODE = 6; // historical
  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
  const unsigned short COMMENT_NODE = 8;
  const unsigned short DOCUMENT_NODE = 9;
  const unsigned short DOCUMENT_TYPE_NODE = 10;
  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
  const unsigned short NOTATION_NODE = 12; // historical
  readonly attribute unsigned short nodeType;
  readonly attribute DOMString nodeName;

  readonly attribute DOMString? baseURI;

  readonly attribute Document? ownerDocument;
  readonly attribute Node? parentNode;
  readonly attribute Element? parentElement;
  boolean hasChildNodes();
  readonly attribute NodeList childNodes;
  readonly attribute Node? firstChild;
  readonly attribute Node? lastChild;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;

  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; // historical
  unsigned short compareDocumentPosition(Node other);
  boolean contains(Node? other);

           attribute DOMString? nodeValue;
           attribute DOMString? textContent;
  Node insertBefore(Node node, Node? child);
  Node appendChild(Node node);
  Node replaceChild(Node node, Node child);
  Node removeChild(Node child);
  void normalize();

  
  Node cloneNode(optional boolean deep = true);
  boolean isEqualNode(Node? node);

  DOMString lookupPrefix(DOMString? namespace);
  DOMString lookupNamespaceURI(DOMString? prefix);
  boolean isDefaultNamespace(DOMString? namespace);
};

Node is an abstract interface and does not exist as node. It is used by all nodes (Document, DocumentFragment, DocumentType, Element, Text, ProcessingInstruction, and Comment).

Each node has an associated node document, set upon creation, that is a document.

A node's node document can be changed by the "adopt" algorithm.

Each node also has an associated base URL.

Other specifications define the value of the base URL and its observable behavior. This specification solely defines the concept and the baseURI attribute.


node . nodeType

Returns the type of node, represented by a number from the following list:

Node . ELEMENT_NODE (1)
node is an element.
Node . TEXT_NODE (3)
node is a Text node.
Node . PROCESSING_INSTRUCTION_NODE (7)
node is a ProcessingInstruction node.
Node . COMMENT_NODE (8)
node is a Comment node.
Node . DOCUMENT_NODE (9)
node is a document.
Node . DOCUMENT_TYPE_NODE (10)
node is a doctype.
Node . DOCUMENT_FRAGMENT_NODE (11)
node is a DocumentFragment node.
node . nodeName

Returns a string appropriate for the type of node, as follows:

Element
Its tagName attribute value.
Text
"#text".
ProcessingInstruction
Its target.
Comment
"#comment".
Document
"#document".
DocumentType
Its name.
DocumentFragment
"#document-fragment".

The nodeType attribute must return the type of the node, which must be one of the following:

The nodeName attribute must return the following, depending on the context object:

Element

Its tagName attribute value.

Text

"#text".

ProcessingInstruction

Its target.

Comment

"#comment".

Document

"#document".

DocumentType

Its name.

DocumentFragment

"#document-fragment".


node . baseURI

Returns the base URL.

The baseURI attribute must return the associated base URL.


node . ownerDocument

Returns the node document.

Returns null for documents.

node . parentNode

Returns the parent.

node . parentElement

Returns the parent element.

node . hasChildNodes

Returns whether node has children.

node . childNodes

Returns the children.

node . firstChild

Returns the first child.

node . lastChild

Returns the last child.

node . previousSibling

Returns the previous sibling.

node . nextSibling

Returns the next sibling.

The ownerDocument attribute must run these steps:

  1. If the context object is a document, return null and terminate these steps.
  2. Return the node document.

The node document of a document is that document itself.

All nodes have a document at all times.

The parentNode attribute must return the parent.

The parentElement attribute must return the parent element.

The hasChildNodes() method must return true if the context object has children, or false otherwise.

The childNodes attribute must return a NodeList rooted at the context object matching only children.

The firstChild attribute must return the first child.

The lastChild attribute must return the last child.

The previousSibling attribute must return the previous sibling.

The nextSibling attribute must return the next sibling.


node . compareDocumentPosition(other)

Returns a bitmask indicating the position of other relative to node. These are the bits that can be set:

Node . DOCUMENT_POSITION_DISCONNECTED (1)
Set when node and other are not in the same document.
Node . DOCUMENT_POSITION_PRECEDING (2)
Set when other is preceding node.
Node . DOCUMENT_POSITION_FOLLOWING (4)
Set when other is following node.
Node . DOCUMENT_POSITION_CONTAINS (8)
Set when other is an ancestor of node.
Node . DOCUMENT_POSITION_CONTAINED_BY (16, 10 in hexadecimal)
Set when other is a descendant of node.
node . contains(other)

Returns true if other is an inclusive descendant of node, or false otherwise.

These are the constants compareDocumentPosition() returns as mask:

The compareDocumentPosition(other) method must run these steps:

  1. Let reference be the context object.

  2. If other and reference are the same object, return zero and terminate these steps.

  3. If other and reference are not in the same tree, return DOCUMENT_POSITION_DISCONNECTED and terminate these steps.

  4. If other is an ancestor of reference, return the result of adding DOCUMENT_POSITION_CONTAINS to DOCUMENT_POSITION_PRECEDING and terminate these steps.

  5. If other is a descendant of reference, return the result of adding DOCUMENT_POSITION_CONTAINED_BY to DOCUMENT_POSITION_FOLLOWING and terminate these steps.

  6. If other is preceding reference return DOCUMENT_POSITION_PRECEDING and terminate these steps.

  7. Return DOCUMENT_POSITION_FOLLOWING.

The contains(other) method must return true if other is an inclusive descendant of the context object, or false otherwise.


The nodeValue attribute must return the following, depending on the context object:

Text
Comment
ProcessingInstruction

The context object's data.

Any other node

Null.

Setting the nodeValue attribute must do as described below, depending on the context object:

Text
Comment
ProcessingInstruction

Replace data with node context object, offset 0, count length attribute value, and data new value.

Any other node

Do nothing.

The textContent attribute must return the following, depending on the context object:

DocumentFragment
Element

The concatenation of data of all the Text node descendants of the context object, in tree order.

Text
ProcessingInstruction
Comment

The context object's data.

Any other node

Null.

The textContent attribute must, on setting, if the new value is null, act as if it was the empty string instead, and then do as described below, depending on the context object:

DocumentFragment
Element
  1. Let node be null.

  2. If new value is not the empty string, set node to a new Text node whose data is new value.

  3. Replace all with node within the context object.

Text
ProcessingInstruction
Comment

Replace data with node context object, offset 0, count length attribute value, and data new value.

Any other node

Do nothing.


node . normalize()

Concatenates contiguous Text nodes into a single Text node.

The normalize() method must run these steps:

For each Text node descendant of the context object:

  1. Let node be the Text node descendant.

  2. Let length be node's length attribute value.

  3. Let data be the concatenation of the data of node's contiguous Text nodes (excluding itself), in tree order.

  4. Replace data with node node, offset length, count 0, and data data.

  5. Let current node be node's next sibling.

  6. While current node is a Text node:

    1. For each range whose start node is current node, add length to its start offset and set its start node to node.

    2. For each range whose end node is current node, add length to its end offset and set its end node to node.

    3. Add current node's length attribute value to length.

    4. Set current node to its next sibling.

  7. Remove node's contiguous Text nodes (excluding itself), in tree order.


node . cloneNode([deep])

Returns a copy of node. If deep is true or omitted, the copy also includes the node children.

node . isEqualNode(other)

Returns whether node and other have the same properties.

Specifications may define cloning steps for all or some nodes.

To clone a node, optionally with a document ownerDocument and a clone children flag, run these steps:

  1. If document is not given let ownerDocument be node's node document.

  2. Let copy be a node that implements the same interfaces as node.

  3. If copy is a document set its node document and ownerDocument to copy.

    Otherwise, set copy's node document to ownerDocument.

  4. Copy the following, depending on the type of node:

    Element

    Its namespace, namespace prefix, local name, and its attribute list.

    DocumentType

    Its name, public ID, and system ID.

    ProcessingInstruction

    Its target and data.

    Text
    Comment

    Its data.

    Any other node

  5. Run any cloning steps defined for node in other applicable specifications.

  6. If the clone children flag is set, clone all the children of node and append them to copy, with ownerDocument as specified and the clone children flag being set.

  7. Return copy.

The cloneNode(deep) method must return a clone of the context object, with the clone children flag set if deep is true.

The isEqualNode(node) method must return true if all of the following conditions are true, and false otherwise:


To locate a namespace prefix for an element using namespace run these steps:

  1. If element's namespace is namespace and its namespace prefix is not null return its namespace prefix and terminate these steps.

  2. If, element has an attribute whose namespace prefix is "xmlns" and value is namespace, then return that attribute's local name and terminate these steps.

  3. If element's parent element is not null, return the result of running locate a namespace prefix on that element using namespace. Otherwise, return null.

To locate a namespace for a node using prefix depends on the node:

Element
  1. If its namespace is not null and its namespace prefix is prefix return namespace and terminate these steps.

  2. If it has an attribute whose namespace prefix is "xmlns" and local name is prefix, or whose namespace prefix is null and local name is "xmlns":

    1. Let value be its value if it is not the empty string, or null otherwise.

    2. Return value and terminate these steps.

  3. If its parent element is null, return null and terminate these steps.

  4. Return the result of running locate a namespace on its parent element using prefix.

Document
  1. If its document element is null, return null and terminate these steps.

  2. Return the result of running locate a namespace on its document element using prefix.

DocumentType
DocumentFragment

Return null.

Any other node
  1. If its parent element is null, return null and terminate these steps.

  2. Return the result of running locate a namespace on its parent element using prefix.

The lookupPrefix(namespace) method must run these steps:

  1. If namespace is null or the empty string, return null.

  2. Otherwise it depends on the context object:

    Element

    Return the result of locating a namespace prefix for the node using namespace.

    Document

    Return the result of locating a namespace prefix for its document element, if that is not null, or null otherwise.

    DocumentType
    DocumentFragment

    Return null.

    Any other node

    Return the result of locating a namespace prefix for its parent element, or if that is null, null.

The lookupNamespaceURI(prefix) method must run these steps:

  1. If prefix is the empty string, set it to null.

  2. Return the result of running locate a namespace for the context object using prefix.

The isDefaultNamespace(namespace) method must run these steps:

  1. If namespace is the empty string, set it to null.

  2. Let defaultNamespace be the result of running locate a namespace for the context object using null.

  3. Return true if defaultNamespace is the same as namespace, or false otherwise.


The list of elements with local name localName for a node root is the HTMLCollection returned by the following algorithm:

  1. If localName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches only elements.

  2. Otherwise, if root's node document is an HTML document, return a HTMLCollection rooted at root, whose filter matches only the following elements:

  3. Otherwise, return a HTMLCollection rooted at root, whose filter matches only elements whose local name is localName.

When invoked with the same argument, the same HTMLCollection object may be returned as returned by an earlier call.

The list of elements with namespace namespace and local name localName for a node root is the HTMLCollection returned by the following algorithm:

  1. If namespace is the empty string, set it to null.

  2. If both namespace and localName are "*" (U+002A) return a HTMLCollection rooted at root, whose filter matches only elements.

  3. Otherwise, if just namespace is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches only elements whose local name is localName.

  4. Otherwise, if just localName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches only elements whose namespace is namespace.

  5. Otherwise, return a HTMLCollection rooted at root, whose filter matches only elements whose namespace is namespace and local name is localName.

When invoked with the same arguments, the same HTMLCollection object may be returned as returned by an earlier call.

The list of elements with class names classNames for a node root is the HTMLCollection returned by the following algorithm:

  1. Let classes be the set of tokens found by splitting classNames on spaces. (Duplicates are ignored.)

  2. If classes is the empty set, return an empty HTMLCollection and terminate these steps.

  3. Return a HTMLCollection rooted at root, whose filter matches only elements that have all the classes in classes.

    If root's node document is in quirks mode, then the comparisons for the classes must be done in an ASCII case-insensitive manner, or in a case-sensitive manner otherwise.

When invoked with the same argument, the same HTMLCollection object may be returned as returned by an earlier call.

5.4 Interface Document

interface Document : Node {
  readonly attribute DOMImplementation implementation;
  readonly attribute DOMString URL;
  readonly attribute DOMString documentURI;
  readonly attribute DOMString compatMode;
  readonly attribute DOMString characterSet;
  readonly attribute DOMString contentType;

  readonly attribute DocumentType? doctype;
  readonly attribute Element? documentElement;
  HTMLCollection getElementsByTagName(DOMString localName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);
  Element? getElementById(DOMString elementId);

  Element createElement(DOMString localName);
  Element createElementNS(DOMString? namespace, DOMString qualifiedName);
  DocumentFragment createDocumentFragment();
  Text createTextNode(DOMString data);
  Comment createComment(DOMString data);
  ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);

  Node importNode(Node node, optional boolean deep = true);
  Node adoptNode(Node node);

  Event createEvent(DOMString eventInterfaceName);

  Range createRange();

  NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = SHOW_ALL, optional NodeFilter? filter = null);
  TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = SHOW_ALL, optional NodeFilter? filter = null);

  // NEW
  void prepend((Node or DOMString)... nodes);
  void append((Node or DOMString)... nodes);
};

interface XMLDocument : Document {};

Document nodes are simply known as documents.

Each document has an associated encoding, content type, and URL.

Unless explicitly given when a document is created its encoding is utf-8, its content type is "application/xml", and its URL is "about:blank".

A document is assumed to be an XML document unless it is flagged as being an HTML document. Whether a document is an HTML document or an XML document affects the behavior of certain APIs.

A document is always set to one of three modes: no-quirks mode, the default; quirks mode, used typically for legacy documents; and limited-quirks mode. Unless other applicable specifications define otherwise, a document must be in no-quirks mode.

The mode is only ever changed from the default if the document is created by the HTML parser, based on the presence, absence, or value of the DOCTYPE string. [HTML]

No-quirks mode was originally known as "standards mode" and limited-quirks mode was once known as "almost standards mode". They have been renamed because their details are now defined by standards. (And because Ian Hickson vetoed their original names on the basis that they are nonsensical.)


document . implementation

Returns the associated DOMImplementation object.

document . URL
document . documentURI

Returns the URL.

document . compatMode

Returns the string "CSS1Compat" if document is in no-quirks mode or limited-quirks mode, and "BackCompat", if document is in quirks mode.

document . characterSet

Returns the encoding.

document . contentType

Returns the content type.

The implementation attribute must return the DOMImplementation object that is associated with the document.

The URL and documentURI attributes must return the URL.

The compatMode attribute must return "BackCompat" if the context object is in quirks mode, or "CSS1Compat" otherwise.

The characterSet attribute must return the preferred MIME name of the encoding.

The contentType attribute must return the content type.


document . doctype

Returns the doctype or null if there is none.

document . documentElement

Returns the document element.

collection = document . getElementsByTagName(localName)

If localName is "*" returns a HTMLCollection of all descendant elements.

Otherwise, returns a HTMLCollection of all descendant elements whose local name is localName. (Matches case-insensitively against elements in the HTML namespace within an HTML document.)

collection = document . getElementsByTagNameNS(namespace, localName)

If namespace and localName are "*" returns a HTMLCollection of all descendant elements.

If only namespace is "*" returns a HTMLCollection of all descendant elements whose local name is localName.

If only localName is "*" returns a HTMLCollection of all descendant elements whose namespace is namespace.

Otherwise, returns a HTMLCollection of all descendant elements whose namespace is namespace and local name is localName.

collection = document . getElementsByClassName(classes)
collection = element . getElementsByClassName(classes)

Returns a HTMLCollection of the elements in the object on which the method was invoked (a document or an element) that have all the classes given by classes.

The classes argument is interpreted as a space-separated list of classes.

element = document . getElementById(elementId)

Returns the first element in document with the given ID.

The doctype attribute must return the child of the document that is a doctype, or null otherwise.

The documentElement attribute must return the document element.

The getElementsByTagName(localName) method must return the list of elements with local name localName for the context object.

Thus, in an HTML document, document.getElementsByTagName("FOO") will match FOO elements that are not in the HTML namespace, and foo elements that are in the HTML namespace, but not FOO elements that are in the HTML namespace.

The getElementsByTagNameNS(namespace, localName) method must return the list of elements with namespace namespace and local name localName for the context object.

The getElementsByClassName(classNames) method must return the list of elements with class names classNames for the context object.

Given the following XHTML fragment:

<div id="example">
  <p id="p1" class="aaa bbb"/>
  <p id="p2" class="aaa ccc"/>
  <p id="p3" class="bbb ccc"/>
</div>

A call to document.getElementById('example').getElementsByClassName('aaa') would return a HTMLCollection with the two paragraphs p1 and p2 in it.

A call to getElementsByClassName('ccc bbb') would only return one node, however, namely p3. A call to document.getElementById('example').getElementsByClassName('bbb  ccc ') would return the same thing.

A call to getElementsByClassName('aaa,bbb') would return no nodes; none of the elements above are in the aaa,bbb class.

The getElementById(elementId) method must return the first element, in tree order, within the context object's tree, whose ID is elementId, or null if there is none.


element = document . createElement(localName)

Returns an element in the HTML namespace with localName as local name. (In an HTML document localName is lowercased.)

If localName does not match the Name production an "InvalidCharacterError" exception will be thrown.

element = document . createElementNS(namespace, qualifiedName)

Returns an element with namespace namespace. Its namespace prefix will be everything before ":" (U+003E) in qualifiedName or null. Its local name will be everything after ":" (U+003E) in qualifiedName or qualifiedName.

If localName does not match the Name production an "InvalidCharacterError" exception will be thrown.

If one of the following conditions is true a "NamespaceError" exception will be thrown:

documentFragment = document . createDocumentFragment()

Returns a DocumentFragment node.

text = document . createTextNode(data)

Returns a Text node whose data is data.

comment = document . createComment(data)

Returns a Comment node whose data is data.

processingInstruction = document . createProcessingInstruction(target, data)

Returns a ProcessingInstruction node whose target is target and data is data.

If target does not match the Name production an "InvalidCharacterError" exception will be thrown.

If data contains "?>" an "InvalidCharacterError" exception will be thrown.

The createElement(localName) method must run the these steps:

  1. If localName does not match the Name production, throw an "InvalidCharacterError" exception and terminate these steps.

  2. If the context object is an HTML document, let localName be converted to ASCII lowercase.

  3. Return a new element with no attributes, namespace set to the HTML namespace, local name set to localName, and node document set to the context object.

The createElementNS(namespace, qualifiedName) method must run these steps:

  1. If namespace is the empty string, set it to null.

  2. If qualifiedName does not match the Name production, throw an "InvalidCharacterError" exception and terminate these steps.

  3. If qualifiedName does not match the QName production, throw a "NamespaceError" exception and terminate these steps.

  4. If qualifiedName contains a ":" (U+003E), then split the string on it and let prefix be the part before and localName the part after. Otherwise, let prefix be null and localName be qualifiedName.

  5. If prefix is not null and namespace is null, throw a "NamespaceError" exception and terminate these steps.

  6. If prefix is "xml" and namespace is not the XML namespace, throw a "NamespaceError" exception and terminate these steps.

  7. If qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace, throw a "NamespaceError" exception and terminate these steps.

  8. If namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns", throw a "NamespaceError" exception and terminate these steps.

  9. Return a new element with no attributes, namespace set to namespace, namespace prefix set to prefix, local name set to localName, and node document set to the context object.

The createDocumentFragment() method must return a new DocumentFragment node with its node document set to the context object.

The createTextNode(data) method must return a new Text node with its data set to data and node document set to the context object.

No check is performed that data consists of characters that match the Char production.

The createComment(data) method must return a new Comment node with its data set to data and node document set to the context object.

No check is performed that data consists of characters that match the Char production or that it contains two adjacent hyphens or ends with a hyphen.

The createProcessingInstruction(target, data) method must run these steps:

  1. If target does not match the Name production, throw an "InvalidCharacterError" exception and terminate these steps.

  2. If data contains the string "?>", throw an "InvalidCharacterError" exception and terminate these steps.

  3. Return a new ProcessingInstruction node, with target set to target, data set to data, and node document set to the context object.

No check is performed that target contains "xml" or ":", or that data contains characters that match the Char production.


clone = document . importNode(node [, deep])

Returns a copy of node. If deep is true or omitted, the copy also includes the node children.

If node is a document throws a "NotSupportedError" exception.

node = document . adoptNode(node)

Moves node from another document and returns it.

If node is a document throws a "NotSupportedError" exception.

The importNode(node, deep) method must run these steps:

  1. If node is a document, throw a "NotSupportedError" exception and terminate these steps.

  2. Return a clone of node, with document context object and the clone children flag set if deep is true.

To adopt a node, with an ownerDocument, run these steps:

  1. If node is an element, it is affected by a base URL change.

  2. If node's parent is not null, remove node from its parent.

  3. Set node document for node and all its descendants to ownerDocument.

The adoptNode(node) method must run these steps:

  1. If node is a document, throw a "NotSupportedError" exception and terminate these steps.

  2. Adopt node with the context object.

  3. Return node.


event = document . createEvent(eventInterfaceName)

Returns an event using an interface for which the interface name is a case-insensitive match for eventInterfaceName.

When the createEvent(eventInterfaceName) methed is invoked these steps must be run:

  1. If eventInterfaceName is an ASCII case-insensitive match for any of the strings in the first column in the following table, let eventInterfaceName be the string in the second column on the same row as the matching string:

    Input interface Replacement interface
    "events""event"
    "htmlevents""event"
    "mouseevents""mouseevent"
    "mutationevents""mutationevent"
    "uievents""uievent"
  2. If eventInterfaceName is not an ASCII case-insensitive match for "event" or for the name of an interface that inherits from the Event interface and is supported by the user agent, throw a "NotSupportedError" and terminate these steps.

  3. Create an event implementing the interface whose name eventInterfaceName is an ASCII case-insensitive match for and return it.

This method is pretty much obsolete as events have constructors these days, but needs to be supported for legacy content. Tough.


event = document . createRange()

Returns a new range.

The createRange() method must return a new range with (context object, 0) as its start and end.


When the createNodeIterator(root, whatToShow, filter) method is invoked these steps must be run:

  1. Create a NodeIterator object.

  2. Set root and initialize the referenceNode attribute to the root argument.

  3. Set whatToShow to the whatToShow argument.

  4. Set filter to filter.

  5. Return the newly created NodeIterator object.

When the createTreeWalker(root, whatToShow, filter) method is invoked these steps must be run:

  1. Create a TreeWalker object.

  2. Set root and initialize the currentNode attribute to the root argument.

  3. Set whatToShow to the whatToShow argument.

  4. Set filter to filter.

  5. Return the newly created TreeWalker object.

5.4.1 Interface DOMImplementation

User agents must create a DOMImplementation object whenever a document is created and associate it with that document.

interface DOMImplementation {
  DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
  XMLDocument createDocument(DOMString? namespace, DOMString qualifiedName, DocumentType? doctype);
  Document createHTMLDocument(DOMString title);

  boolean hasFeature(DOMString feature, [TreatNullAs=EmptyString] DOMString version);
};
doctype = document . implementation . createDocumentType( qualifiedName, publicId, systemId )

Returns a doctype, with the given qualifiedName, publicId, and systemId. If qualifiedName does not match the Name production, an "InvalidCharacterError" exception is thrown, and if it does not match the QName production, a "NamespaceError" exception is thrown.

doc = document . implementation . createDocument( namespace, qualifiedName, doctype )

Returns an XMLDocument, with a document element whose local name is qualifiedName and whose namespace is namespace (unless qualifiedName is the empty string), and with doctype, if it is given, as its doctype.

This method throws the same exceptions as the createElementNS method, when invoked with the same arguments.

doc = document . implementation . createHTMLDocument( title )

Returns a document, with a basic tree already constructed including a title element.

The createDocumentType(qualifiedName, publicId, systemId) method must run these steps:

  1. If qualifiedName does not match the Name production, throw an "InvalidCharacterError" exception and terminate these steps.

  2. If qualifiedName does not match the QName production in, throw a "NamespaceError" exception and terminate these steps.

  3. Return a new doctype, with qualifiedName as its name, publicId as its public ID, and systemId as its system ID, and with its node document set to the associated document of the context object.

No check is performed that the publicId matches the PublicChar or that the systemId does not contain both a '"' and "'".

The createDocument(namespace, qualifiedName, doctype) method must run these steps:

  1. Let document be a new XMLDocument.

    This method creates an XMLDocument rather than a normal document. They are identical except for the addition of the load() method deployed content relies upon. [HTML]

  2. Let element be null.

  3. If qualifiedName is not the empty string, set element to the result of invoking the createElementNS() method with the arguments namespace and qualifiedName on document. If that threw an exception, re-throw the exception and terminate these steps.

  4. If doctype is not null, append doctype to document.

  5. If element is not null, append element to document.

  6. Return document.

The createHTMLDocument(title) method must run these steps:

  1. Let doc be a newly created document.

  2. Mark doc as being an HTML document.

  3. Set doc's content type to "text/html".

  4. Create a doctype, with "html" as its name and with its node document set to doc. Append the newly created node to doc.

  5. Create an html element in the HTML namespace, and append it to doc.

  6. Create a head element in the HTML namespace, and append it to the html element created in the previous step.

  7. Create a title element in the HTML namespace, and append it to the head element created in the previous step.

  8. Create a Text node, set its data to title (which could be the empty string), and append it to the title element created in the previous step.

  9. Create a body element in the HTML namespace, and append it to the html element created in the earlier step.

  10. Return doc.

The hasFeature(feature, version) method must return true for any of (feature, version) tuples listed below where feature is an ASCII case-insensitive and version is a case-sensitive match, or false otherwise.

Any others?

The hasFeature() is a badly designed method (features are notoriously unreliable and imprecise) that is now effectively obsolete and only needs to be supported for deployed content.

5.5 Interface DocumentFragment

interface DocumentFragment : Node {
  // NEW
  void prepend((Node or DOMString)... nodes);
  void append((Node or DOMString)... nodes);
};

5.6 Interface DocumentType

interface DocumentType : Node {
  readonly attribute DOMString name;
  readonly attribute DOMString publicId;
  readonly attribute DOMString systemId;

  // NEW
  void before((Node or DOMString)... nodes);
  void after((Node or DOMString)... nodes);
  void replace((Node or DOMString)... nodes);
  void remove();
};

DocumentType nodes are simply known as doctypes.

Doctypes have an associated name, public ID, and system ID.

When a doctype is created, its name is always given. Unless explicitly given when a doctype is created, its public ID and system ID are the empty string.

The name attribute must return the name.

The publicId attribute must return the public ID.

The systemId attribute must return the system ID.

5.7 Interface Element

interface Element : Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString tagName;

           attribute DOMString id;
           attribute DOMString className;
  readonly attribute DOMTokenList classList;

  readonly attribute Attr[] attributes;
  DOMString? getAttribute(DOMString name);
  DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
  void setAttribute(DOMString name, DOMString value);
  void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
  void removeAttribute(DOMString name);
  void removeAttributeNS(DOMString? namespace, DOMString localName);
  boolean hasAttribute(DOMString name);
  boolean hasAttributeNS(DOMString? namespace, DOMString localName);

  HTMLCollection getElementsByTagName(DOMString localName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  readonly attribute HTMLCollection children;
  readonly attribute Element? firstElementChild;
  readonly attribute Element? lastElementChild;
  readonly attribute Element? previousElementSibling;
  readonly attribute Element? nextElementSibling;
  readonly attribute unsigned long childElementCount;

  // NEW
  void prepend((Node or DOMString)... nodes);
  void append((Node or DOMString)... nodes);
  void before((Node or DOMString)... nodes);
  void after((Node or DOMString)... nodes);
  void replace((Node or DOMString)... nodes);
  void remove();
};

Element nodes are simply known as elements.

Elements have an associated namespace, namespace prefix, and local name. When an element is created, its local name is always given. Unless explicitly given when an element is created, its namespace and namespace prefix are null.

Elements also have an ordered attribute list. Unless explicitly given when an element is created, its attribute list is empty. An element has an attribute A if A is in its attribute list.

Elements can have a unique identifier (ID) and classes associated with them.

Historically elements could have multiple identifiers e.g. by using the HTML id attribute and a DTD. This specification makes ID a concept of the DOM and allows for only one per element, given by an id attribute.

An element has an ID if it has an id attribute whose value is not the empty string. The ID is that attribute's value.

An element has classes if it has a class attribute, and splitting that attribute's value does not return an empty list. The classes are that attribute's value split on spaces.

While this specification defines user agent processing requirements for id and class attributes on any element, it makes no claims as to whether using them is conforming or not.


A node's parent of type Element is known as a parent element. If the node has a parent of a different type, its parent element is null.

The document element of a document is the element whose parent is that document, if it exists, and null otherwise.

As explained in the node tree section, there can only be one such element.

When an element or one of its ancestors is the document element, it is in a document.


Specifications may define base URL change steps.

When an element is affected by a base URL change, the user agent must run the base URL change steps, as defined in other applicable specifications.


namespace = element . namespaceURI

Returns the namespace.

prefix = element . prefix

Returns the namespace prefix.

localName = element . localName

Returns the local name.

qualifiedName = element . tagName

If namespace prefix is not null returns the concatenation of namespace prefix, ":", and local name. Otherwise it returns the local name. (The return value is uppercased in an HTML document.)

The namespaceURI attribute must return the context object's namespace.

The prefix attribute must return the context object's namespace prefix.

The localName attribute must return the context object's local name.

The tagName attribute must run these steps:

  1. If context object's namespace prefix is not null, let qualified name be its namespace prefix, followed by a ":" (U+003A), followed by its local name. Otherwise, let qualified name be its local name.

  2. If the context object is in the HTML namespace and its node document is an HTML document, let qualified name be converted to ASCII uppercase.

  3. Return qualified name.


Some attributes are defined to reflect a particular content attribute. This means that on getting, these steps must be run:

  1. Let value be the result of invoking getAttributeNS() with null as first argument and the name of the content attribute as second argument.
  2. If value is null, return the empty string and terminate these steps.
  3. Return value.

On setting, the setAttributeNS() must be invoked with null as first argument, the name of the content attribute as second argument, and the new value as third argument.

The id attribute must reflect the "id" content attribute.

The className attribute must reflect the "class" content attribute.

The classList attribute must return a DOMTokenList whose underlying string is the className attribute value.


The attributes attribute must return a read only array of the context object's attribute list. The returned read only array must be live. I.e. changes to the associated attributes are reflected.

The getAttribute(name) method must run these steps:

  1. If the context object is in the HTML namespace and its node document is an HTML document, let name be converted to ASCII lowercase.

  2. Return the value of the first attribute in the context object's attribute list whose name is name, or null otherwise.

The getAttributeNS(namespace, localName) method must return the following steps:

  1. If namespace is the empty string, set it to null.

  2. Return the value of the attribute in the context object's attribute list whose namespace is namespace and local name is localName, if it has one, or null otherwise.

The setAttribute(name, value) method must run these steps:

  1. If name does not match the Name production in XML, throw an "InvalidCharacterError" exception and terminate these steps.

  2. If the context object is in the HTML namespace and its node document is an HTML document, let name be converted to ASCII lowercase.

  3. If "xmlns" is a prefix match for name, throw a "NamespaceError" and terminate these steps.

  4. Let attribute be the first attribute in the context object's attribute list whose name is name, or null if there is no such attribute.

  5. If attribute is null, create an attribute whose name is name and value is value, and then append this attribute to the context object and terminate these steps.

  6. Queue an "attributes" record with target context object, name attribute's name, namespace attribute's namespace, and oldValue attribute's value.

  7. Set attribute's value to value.

The setAttributeNS(namespace, name, value) method must run these steps:

  1. If namespace is the empty string, set it to null.

  2. If name does not match the Name production in XML, throw an "InvalidCharacterError" exception and terminate these steps.

  3. If name does not match the QName production in Namespaces in XML, throw a "NamespaceError" exception and terminate these steps.

  4. If name contains a ":" (U+003E), then split the string on it and let prefix be the part before and localName the part after. Otherwise, let prefix be null and localName be name.

  5. If prefix is not null and namespace is null, throw a "NamespaceError" exception and terminate these steps.

  6. If prefix is "xml" and namespace is not the XML namespace, throw a "NamespaceError" exception and terminate these steps.

  7. If name or prefix is "xmlns" and namespace is not the XMLNS namespace, throw a "NamespaceError" exception and terminate these steps.

  8. If namespace is the XMLNS namespace and neither name nor prefix is "xmlns", throw a "NamespaceError" exception and terminate these steps.

  9. Let attribute be the first attribute in the context object's attribute list whose namespace is namespace and whose local name is localName, or null if there is no such attribute.

  10. If attribute is null, create an attribute whose name is name, namespace is namespace, namespace prefix is prefix, local name is localName, and value is value, and then append this attribute to the context object and terminate these steps.

  11. Queue an "attributes" record with target context object, name name, namespace namespace, and oldValue attribute's value.

  12. Set attribute's value to value.

The removeAttribute(name) method must run these steps:

  1. If the context object is in the HTML namespace and its node document is an HTML document, let name be converted to ASCII lowercase.

  2. Remove the first attribute from the context object whose name is name, if any.

The removeAttributeNS(namespace, localName) method must return the following steps:

  1. If namespace is the empty string, set it to null.

  2. Remove the attribute from the context object whose namespace is namespace and local name is localName, if any.

The hasAttribute(name) method must run these steps:

  1. If the context object is in the HTML namespace and its node document is an HTML document, let name be converted to ASCII lowercase.

  2. Return true if the context object has an attribute whose name is name, or false otherwise.

The hasAttributeNS(namespace, localName) method must return the following steps:

  1. If namespace is the empty string, set it to null.

  2. Return true if the context object has an attribute whose namespace is namespace and local name is localName, or false otherwise.


When the getElementsByTagName(localName) method must return the list of elements with local name localName for the context object.

When the getElementsByTagNameNS(namespace, localName) method must return the list of elements with namespace namespace and local name localName for the context object.

When the getElementsByClassName(classNames) method must return the list of elements with class names classNames for the context object.


collection = element . children

Returns the child elements.

element = element . firstElementChild

Returns the first child that is an element, or null otherwise.

element = element . lastElementChild

Returns the last child that is an element, or null otherwise.

element = element . previousElementSibling

Returns the first preceding sibling that is an element, or null otherwise.

element = element . nextElementSibling

Returns the first following sibling that is an element, or null otherwise.

The children attribute must return an HTMLCollection collection rooted at the context object matching only element children.

The firstElementChild attribute must return the first child that is an element, or null otherwise.

The lastElementChild attribute must return the last child that is an element, or null otherwise.

The previousElementSibling attribute must return the first preceding sibling that is an element, or null otherwise.

The nextElementSibling attribute must return the first following sibling that is an element, or null otherwise.

The childElementCount attribute must return the number of children of the context object that are elements.

5.7.1 Interface Attr

interface Attr {
  readonly attribute DOMString name;
           attribute DOMString value;

  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
};

Attr objects are simply known as attributes.

Attributes have a name and value.

For legacy reasons, attributes also have an associated namespace, namespace prefix, and local name.

When an attribute is created, its name and value are always given. Unless explicitly given when an attribute is created, its local name is identical to its name, and its namespace and namespace prefix are null.

An A attribute is an attribute whose name is A and whose namespace and namespace prefix are null.


To append an attribute attribute to an element element, run these steps:

  1. Queue an "attributes" record with target element, name attribute's name, namespace attribute's namespace, and oldValue null.

  2. Append the attribute to the element's attribute list.

To remove an attribute attribute from an element element, run these steps:

  1. Queue an "attributes" record with target element, name attribute's name, namespace attribute's namespace, and oldValue attribute's value.

  2. Remove the attribute from the element's attribute list.


The name attribute must return the name.

The value attribute must return the value.

Setting the value attribute must set value to the new value.


The namespaceURI attribute must return the namespace.

The prefix attribute must return the namespace prefix.

The localName attribute must return the local name.

5.8 Interface CharacterData

interface CharacterData : Node {
  [TreatNullAs=EmptyString] attribute DOMString data;
  readonly attribute unsigned long length;
  DOMString substringData(unsigned long offset, unsigned long count);
  void appendData(DOMString data);
  void insertData(unsigned long offset, DOMString data);
  void deleteData(unsigned long offset, unsigned long count);
  void replaceData(unsigned long offset, unsigned long count, DOMString data);

  // NEW
  void before((Node or DOMString)... nodes);
  void after((Node or DOMString)... nodes);
  void replace((Node or DOMString)... nodes);
  void remove();
};

CharacterData is an abstract interface and does not exist as node. It is used by Text, Comment, and ProcessingInstruction nodes.

Each node inheriting from the CharacterData interface has an associated mutable string called data.

To replace data of node node with offset offset, count count, and data data, run these steps:

  1. Let length be the node's length attribute value.

  2. If offset is greater than length, throw an "IndexSizeError" exception and terminate these steps.

  3. If offset plus count is greater than length let count be length minus offset.

  4. Queue a "characterData" record with target node and oldValue node's data.

  5. Insert data into node's data after offset code units.

  6. Let delete offset be offset plus the number of code units in data.

  7. Starting from delete offset code units, remove count code units from node's data.

  8. For each range whose start node is node and start offset is greater than offset but less than or equal to offset plus count, set its start offset to offset.

  9. For each range whose end node is node and end offset is greater than offset but less than or equal to offset plus count, set its end offset to offset.

  10. For each range whose start node is node and start offset is greater than offset plus count, increase its start offset by the number of code units in data, then decrease it by count.

  11. For each range whose end node is node and end offset is greater than offset plus count, increase its end offset by the number of code units in data, then decrease it by count.

To substring data with node node, offset offset, and count count, run these steps:

  1. Let length be node's length attribute value.

  2. If offset is greater than length, throw an "IndexSizeError" exception and terminate these steps.

  3. If offset plus count is greater than length, return a string whose value is the code units from the offsetth code unit to the end of node's data, and then terminate these steps.

  4. Return a string whose value is the code units from the offsetth code unit to the offset+countth code unit in node's data.

The data attribute must return data, and on setting, must replace data with node context object offset 0, count length attribute value, and data new value.

The length attribute must return the number of code units in data.

The substringData(offset, count) method must substring data with node context object, offset offset, and count count.

The appendData(data) method must replace data with node context object, offset length attribute value, count 0, and data data.

The insertData(offset, data) method must replace data with node context object, offset offset, count 0, and data data.

The deleteData(offset, count) method must replace data with node context object, offset offset, count count, and data the empty string.

The replaceData(offset, count, data) method must replace data with node context object, offset offset, count count, and data data.

5.9 Interface Text

interface Text : CharacterData {
  Text splitText(unsigned long offset);
  readonly attribute DOMString wholeText;
};

To split a Text node node with offset offset, run these steps:

  1. Let length be the length attribute value.

  2. If offset is greater than length, throw an "IndexSizeError" exception and terminate these steps.

  3. Let count be length minus offset.

  4. Let new data be the result of substringing data with node node, offset offset, and count count.

  5. Let new node be a new Text node, with the same node document as node. Set new node's data to new data.

  6. Let parent be the node's parent.

  7. If parent is not null, run these substeps:

    1. Insert new node into parent before node's next sibling.

    2. For each range whose start node is node and start offset is greater than offset, set its start node to new node and decrease its start offset by offset.

    3. For each range whose end node is node and end offset is greater than offset, set its end node to new node and decrease its end offset by offset.

  8. Replace data with node node, offset offset, count count, and data the empty string.

  9. If parent is null, run these substeps:

    1. For each range whose start node is node and start offset is greater than offset, set its start offset to offset.

    2. For each range whose end node is node and end offset is greater than offset, set its end offset to offset.

  10. Return new node.

The splitText(offset) method must split the context object with offset offset.

The contiguous Text nodes of a node are the node itself, the previous sibling Text node (if any) and its contiguous Text nodes, and the next sibling Text node (if any) and its contiguous Text nodes, avoiding any duplicates.

The wholeText attribute must return a concatenation of the data of the contiguous Text nodes of the context object, in tree order.

5.10 Interface ProcessingInstruction

interface ProcessingInstruction : CharacterData {
  readonly attribute DOMString target;
};

ProcessingInstruction nodes have an associated target.

The target attribute must return the target.

5.11 Interface Comment

interface Comment : CharacterData {
};

6 Ranges

The length of a node node depends on node:

DocumentType

0.

Text
ProcessingInstruction
Comment

Its length attribute value.

Any other node

Its number of children.

6.1 Interface Range

interface Range {
  readonly attribute Node startContainer;
  readonly attribute unsigned long startOffset;
  readonly attribute Node endContainer;
  readonly attribute unsigned long endOffset;
  readonly attribute boolean collapsed;
  readonly attribute Node commonAncestorContainer;

  void setStart(Node refNode, unsigned long offset);
  void setEnd(Node refNode, unsigned long offset);
  void setStartBefore(Node refNode);
  void setStartAfter(Node refNode);
  void setEndBefore(Node refNode);
  void setEndAfter(Node refNode);
  void collapse(boolean toStart);
  void selectNode(Node refNode);
  void selectNodeContents(Node refNode);

  const unsigned short START_TO_START = 0;
  const unsigned short START_TO_END = 1;
  const unsigned short END_TO_END = 2;
  const unsigned short END_TO_START = 3;
  short compareBoundaryPoints(unsigned short how, Range sourceRange);

  void deleteContents();
  DocumentFragment extractContents();
  DocumentFragment cloneContents();
  void insertNode(Node node);
  void surroundContents(Node newParent);

  Range cloneRange();
  void detach();

  boolean isPointInRange(Node node, unsigned long offset);
  short comparePoint(Node node, unsigned long offset);

  boolean intersectsNode(Node node);

  stringifier;
};

Range objects are simply known as ranges.

Ranges can be created using the createRange() method.

A boundary point is a (node, offset) tuple, where offset is a non-negative integer.

Generally speaking, a boundary point's offset will be between zero and the boundary point's node length, inclusive. Algorithms that modify a tree (in particular the insert, remove, replace data, and split algorithms) also modify ranges associated with that tree.

If the two nodes of boundary points (node A, offset A) and (node B, offset B) have the same root, the position of the first relative to the second is either before, equal, or after, as returned by the following algorithm:

  1. If node A is the same as node B, return equal if offset A is the same as offset B, before if offset A is less than offset B, and after if offset A is greater than offset B.

  2. If node A is following node B, compute the position of (node B, offset B) relative to (node A, offset A). If it is before, return after. If it is after, return before. In either case terminate these steps.

  3. If node A is an ancestor of node B:

    1. Let child equal node B.

    2. While child is not a child of node A, set child to its parent.

    3. If the index of child is less than offset A, return after.

  4. Return before.

Each range has two associated boundary points — a start and end — an associated detached flag, which is initially unset.

For convenience, start node is start's node, start offset is start's offset, end node is end's node, and end offset is end's offset.

The root of a range is the root of its start node, or null if its detached flag is set.

A node node is contained in a range range if node's root is the same as range's root, and (node, 0) is after range's start, and (node, length of node) is before range's end.

A node is partially contained in a range if it is an inclusive ancestor of the range's start node but not its end node, or vice versa.

Some facts to better understand these definitions:


node = range . startContainer

Returns range's start node.

offset = range . startOffset

Returns range's start offset.

node = range . endContainer

Returns range's end node.

offset = range . endOffset

Returns range's end offset.

collapsed = range . collapsed

Returns true if range's start and end are the same, or false otherwise.

container = range . commonAncestorContainer

Returns the node, furthest away from the document, that is an ancestor of both range's start node and end node.

The startContainer attribute must throw an "InvalidStateError" exception if the detached flag is set, or return the start node otherwise.

The startOffset attribute must throw an "InvalidStateError" exception if the detached flag is set, or return the start offset otherwise.

The endContainer attribute must throw an "InvalidStateError" exception if the detached flag is set, or return the end node otherwise.

The endOffset attribute must throw an "InvalidStateError" exception if the detached flag is set, or return the end offset otherwise.

The collapsed attribute must throw an "InvalidStateError" exception if the detached flag is set, return true if start is the same as end, or return false otherwise.

The commonAncestorContainer attribute must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let container be start node.

  3. While container is not an inclusive ancestor of end node, let container be container's parent.

  4. Return container.


To set the start or end of a range to a boundary point (node, offset), run these steps:

  1. If range's detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If node is a doctype, throw an "InvalidNodeTypeError" exception and terminate these steps.

  3. If offset is greater than node's length, throw an "IndexSizeError" exception and terminate these steps.

  4. Let bp be the boundary point (node, offset).

  5. If these steps were invoked as "set the start"
    1. If bp is after the range's end, or if the range's root is not equal to node's root, set range's end to bp.

    2. Set range's start to bp.

    If these steps were invoked as "set the end"
    1. If bp is before the range's start, or if the range's root is not equal to node's root, set range's start to bp.

    2. Set range's end to bp.

The setStart(node, offset) method must set the start of the context object to boundary point (node, offset).

The setEnd(refNode, offset) method must set the end of the context object to boundary point (node, offset).

The setStartBefore(node) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let parent be node's parent.

  3. If parent is null, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. Set the start of the context object to boundary point (parent, node's index).

The setStartAfter(node) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let parent be node's parent.

  3. If parent is null, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. Set the start of the context object to boundary point (parent, node's index plus one).

The setEndBefore(node) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let parent be node's parent.

  3. If parent is null, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. Set the end of the context object to boundary point (parent, node's index).

The setEndAfter(node) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let parent be node's parent.

  3. If parent is null, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. Set the end of the context object to boundary point (parent, node's index plus one).

The collapse(toStart) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If toStart is true, set end to start. Otherwise, set start to end.

The selectNode(refNode) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let parent be refNode's parent.

  3. If parent is null, throw an "InvalidNodeTypeError" and terminate these steps.

  4. Let index be the index of refNode.

  5. Set start to the boundary point (parent, index).

  6. Set end to the boundary point (parent, index plus one).

The selectNodeContents(refNode) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If refNode is a doctype, throw an "InvalidNodeTypeError" and terminate these steps.

  3. Let length be the length of refNode.

  4. Set start to the boundary point (refNode, 0).

  5. Set end to the boundary point (refNode, length).


The compareBoundaryPoints(how, sourceRange) method must run these steps:

  1. If context object's or sourceRange's detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If how is not one of

    throw a "NotSupportedError" exception and terminate these steps.

  3. If context object's root is not the same as sourceRange's root, throw a "WrongDocumentError" exception and terminate these steps.

  4. If how is:

    START_TO_START:

    Let this point be the context object's start.

    Let other point be sourceRange's start.

    START_TO_END:

    Let this point be the context object's end.

    Let other point be sourceRange's start.

    END_TO_END:

    Let this point be the context object's end.

    Let other point be sourceRange's end.

    END_TO_START:

    Let this point be the context object's start.

    Let other point be sourceRange's end.

  5. If the position of this point relative to other point is

    before
    Return −1.
    equal
    Return 0.
    after
    Return 1.

The deleteContents() method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If start equals end, terminate these steps.

  3. Let original start node, original start offset, original end node, and original end offset be the context object's start node, start offset, end node, and end offset, respectively.

  4. If original start node and original end node are the same, and they are a Text or Comment node, replace data with node original start node, offset original start offset, count original end offset minus original start offset, and data the empty string, and then terminate these steps.

  5. Let nodes to remove be a list of all the nodes that are contained in the context object, in tree order, omitting any node whose parent is also contained in the context object.

  6. If original start node is an inclusive ancestor of original end node, set new node to original start node and new offset to original start offset.

  7. Otherwise:

    1. Let reference node equal original start node.

    2. While reference node's parent is not null and is not an inclusive ancestor of original end node, set reference node to its parent.

    3. Set new node to the parent of reference node, and new offset to one plus the index of reference node.

      If reference node's parent were null, it would be the root of the context object, so would be an inclusive ancestor of original end node, and we could not reach this point.

  8. If original start node is a Text or Comment node, replace data with node original start node, offset original start offset, count original start node's length minus original start offset, data the empty string.

  9. For each node in nodes to remove, in tree order, remove node from its parent.

  10. If original end node is a Text or Comment node, replace data with node original end node, offset 0, count original end offset), and data the empty string.

  11. Set start and end to (new node, new offset).

The extractContents() method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let frag be a new DocumentFragment whose node document is the same as the node document of the context object's start node.

  3. If start equals end, return frag, and terminate these steps.

  4. Let original start node, original start offset, original end node, and original end offset be the context object's start node, start offset, end node, and end offset, respectively.

  5. If original start node equals original end node, and they are a Text or Comment node:

    1. Let clone be a clone of original start node.

    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original end offset minus original start offset.

    3. Append clone to frag.

    4. Replace data with node original start node, offset original start offset, count original end offset minus original start offset, and data the empty string.

    5. Return frag and terminate these steps.

  6. Let common ancestor be original start node.

  7. While common ancestor is not an inclusive ancestor of original end node, set common ancestor to its own parent.

  8. If original start node is an inclusive ancestor of original end node, let first partially contained child be null.

  9. Otherwise, let first partially contained child be the first child of common ancestor that is partially contained in the context object.

  10. If original end node is an inclusive ancestor of original start node, let last partially contained child be null.

  11. Otherwise, let last partially contained child be the last child of common ancestor that is partially contained in the context object.

    These variable assignments do actually always make sense. For instance, if the original start node is not an inclusive ancestor of the original end node, the original start node is itself partially contained in the range, and so are all its ancestors up until a child of the common ancestor. The common ancestor can't be original start node, because it must be an inclusive ancestor of the original end node. The other case is similar. Also, notice that the two children will never be equal if both are defined.

  12. Let contained children be a list of all children of common ancestor that are contained in the context object, in tree order.

  13. If any member of contained children is a DocumentType, throw a "HierarchyRequestError" exception and terminate these steps.

    We do not have to worry about the first or last partially contained node, because a DocumentType can never be partially contained. It cannot be a boundary point of a range, and it cannot be the ancestor of anything.

  14. If original start node is an inclusive ancestor of original end node, set new node to original start node and new offset to original start offset.

  15. Otherwise:

    1. Let reference node equal original start node.
    2. While reference node's parent is not null and is not an inclusive ancestor of original end node, set reference node to its parent.
    3. Set new node to the parent of reference node, and new offset to one plus the index of reference node.

      If reference node's parent were null, it would be the root of the context object, so would be an inclusive ancestor of original end node, and we couldn't reach this point.

  16. If first partially contained child is a Text or Comment node:

    In this case, the first partially contained child is the original start node.

    1. Let clone be a clone of original start node.

    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original start node's length minus original start offset.

    3. Append clone to frag.

    4. Replace data with node original start node, offset original start offset, count original start node's length minus original start offset, and data the empty string.

  17. Otherwise, if first partially contained child is not null:

    1. Let clone be a clone of first partially contained child.

    2. Append clone to frag.

    3. Let subrange be a new Range whose start is (original start node, original start offset) and whose end is (first partially contained child, length of first partially contained child).
    4. Let subfrag be the result of calling extractContents() on subrange.

      Is this method of recursing black-box detectable? E.g., would it fire extra DOM mutation events or something? What we really mean is to get a list of nodes to insert, then insert them directly into frag, without an intermediate document fragment.

    5. For each child of subfrag, in tree order, append that child to clone.
  18. For each contained child in contained children, append contained child to frag.

  19. If last partially contained child is a Text or Comment node:

    In this case, the last partially contained child is the original end node.

    1. Let clone be a clone of original end node.

    2. Set the data of clone to the result of substringing data with node original end node, offset 0, and count original end offset.

    3. Append clone to frag.

    4. Replace data with node original end node, offset 0, count original end offset, and data the empty string.

  20. Otherwise, if last partially contained child is not null:

    1. Let clone be a clone of last partially contained child.

    2. Append clone to frag.

    3. Let subrange be a new Range whose start is (last partially contained child, 0) and whose end is (original end node, original end offset).
    4. Let subfrag be the result of calling extractContents() on subrange.
    5. For each child of subfrag, in tree order, append that child to clone.

  21. Set start and end to (new node, new offset).

  22. Return frag.

The cloneContents() method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let frag be a new DocumentFragment whose node document is the same as the node document of the context object's start node.

  3. If start equals end, return frag, and terminate these steps.

  4. Let original start node, original start offset, original end node, and original end offset be the context object's start node, start offset, end node, and end offset, respectively.

  5. If original start node equals original end node, and they are a Text or Comment node:

    1. Let clone be a clone of original start node.

    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original end offset minus original start offset.

    3. Append clone to frag.

    4. Return frag and terminate these steps.

  6. Let common ancestor be original start node.

  7. While common ancestor is not an inclusive ancestor of original end node, set common ancestor to its own parent.

  8. If original start node is an inclusive ancestor of original end node, let first partially contained child be null.

  9. Otherwise, let first partially contained child be the first child of common ancestor that is partially contained in the context object.

  10. If original end node is an inclusive ancestor of original start node, let last partially contained child be null.

  11. Otherwise, let last partially contained child be the last child of common ancestor that is partially contained in the context object.

    These variable assignments do actually always make sense. For instance, if the original start node is not an inclusive ancestor of the original end node, the original start node is itself partially contained in the range, and so are all its ancestors up until a child of the common ancestor. The common ancestor can't be original start node, because it must be an inclusive ancestor of the original end node. The other case is similar. Also, notice that the two children will never be equal if both are defined.

  12. Let contained children be a list of all children of common ancestor that are contained in the context object, in tree order.

  13. If any member of contained children is a DocumentType, throw a "HierarchyRequestError" exception and terminate these steps.

    We don't have to worry about the first or last partially contained node, because a DocumentType can never be partially contained. It can't be a boundary point of a range, and it can't be the ancestor of anything.

  14. If first partially contained child is a Text or Comment node:

    In this case, the first partially contained child is the original start node.

    1. Let clone be a clone of original start node.

    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original start node's length minus original start offset.

    3. Append clone to frag.

  15. Otherwise, if first partially contained child is not null:

    1. Let clone be a clone of first partially contained child.

    2. Append clone to frag.

    3. Let subrange be a new Range whose start is (original start node, original start offset) and whose end is (first partially contained child, length of first partially contained child).
    4. Let subfrag be the result of calling cloneContents() on subrange.

      Is this method of recursing black-box detectable? E.g., would it fire extra DOM mutation events or something? What we really mean is to get a list of nodes to insert, then insert them directly into frag, without an intermediate document fragment.

    5. For each child of subfrag, in tree order, append that child to clone.

  16. For each contained child in contained children:

    1. Let clone be a clone of contained child.

    2. Append clone to frag.

  17. If last partially contained child is a Text or Comment node:

    In this case, the last partially contained child is the original end node.

    1. Let clone be a clone of original end node.

    2. Set the data of clone to the result of substringing data with node original end node, offset 0, and count original end offset.

    3. Append clone to frag.

  18. Otherwise, if last partially contained child is not null:

    1. Let clone be a clone of last partially contained child.

    2. Append clone to frag.

    3. Let subrange be a new Range whose start is (last partially contained child, 0) and whose end is (original end node, original end offset).
    4. Let subfrag be the result of calling cloneContents() on subrange.
    5. For each child of subfrag, in tree order, append that child to clone.

  19. Return frag.

The insertNode(node) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If start node is a Comment node, or a Text node whose parent is null, throw an "HierarchyRequestError" exception and terminate these steps.

  3. If start node is a Text node, split it with offset context object's start offset, and let reference node be the result.

  4. Otherwise, let reference node be the child of start node whose index is start offset, or null if there is no such child.

  5. If reference node is null, let parent be start node.

  6. Otherwise, let parent be the parent of reference node.

  7. Let new offset be the index of reference node, or parent's length if reference node is null.

  8. Add node's length to new offset, if node is a DocumentFragment. Otherwise add one to new offset.

  9. Pre-insert node into parent before reference node.

  10. If start and end are the same, set end to (parent, new offset).

The surroundContents(newParent) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If a non-Text node is partially contained in the context object, throw an "InvalidStateError" exception and terminate these steps.

  3. If newParent is a Document, DocumentType, or DocumentFragment node, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. Call extractContents() on the context object, and let fragment be the result.
  5. While newParent has children, remove its first child.

  6. Call insertNode(newParent) on the context object.
  7. Call appendChild(fragment) on newParent.
  8. Call selectNode(newParent) on the context object.

The cloneRange() method must throw an "InvalidStateError" exception if the detached flag is set. Otherwise, it must return a new range with the same start and end as the context object.

The detach() method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Set the detached flag.


position = range . comparePoint( parent, offset )

Returns −1 if the point is before the range, 0 if the point is in the range, and 1 if the point is after the range.

intersects = range . intersectsNode( node )

Returns whether range intersects node.

The isPointInRange(node, offset) must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If node's root is different from the context object's root, return false and terminate these steps.

  3. If node is a doctype, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. If offset is greater than node's length, throw an "IndexSizeError" exception and terminate these steps.

  5. If (node, offset) is before start or after end, return false and terminate these steps.

  6. Return true.

The comparePoint(node, offset) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If node's root is different from the context object's root, throw a "WrongDocumentError" exception and terminate these steps.

  3. If node is a doctype, throw an "InvalidNodeTypeError" exception and terminate these steps.

  4. If offset is greater than node's length, throw an "IndexSizeError" exception and terminate these steps.

  5. If (node, offset) is before start, return −1 and terminate these steps.

  6. If (node, offset) is after end, return 1 and terminate these steps.

  7. Return 0.


The intersectsNode(node) method must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. If node's root is different from the context object's root, return false and terminate these steps.

  3. Let parent be node's parent.

  4. If parent is null, throw a "NotFoundError" exception and terminate these steps.

    All implementations throw in this case, but would it make more sense to simply return true? This case can only occur when the roots are the same, so it means that node is the range's root, so the range is fully contained in node.

  5. Let offset be node's index.

  6. If (parent, offset) is before end and (parent, offset + 1) is after start, return true and terminate these steps.

  7. Return false.


The stringifier must run these steps:

  1. If the detached flag is set, throw an "InvalidStateError" exception and terminate these steps.

  2. Let s be the empty string.

  3. If start node equals end node, and it is a Text node, return the substring of that Text node's data beginning at start offset and ending at end offset, and terminate these steps.

  4. If start node is a Text node, append to s the substring of that node's data from the start offset until the end.

  5. Append to s the concatenation, in tree order, of the data of all Text nodes that are contained in the context object.

  6. If end node is a Text node, append to s the substring of that node's data from its start until the end offset.

  7. Return s.


The following extensions to the Range interface are defined in various other specifications:

7 Traversal

NodeIterator and TreeWalker objects can be used to filter and traverse node trees.

Each NodeIterator and TreeWalker object has an associated active flag to avoid recursive invocations. It is initially unset.

Each NodeIterator and TreeWalker object also has an associated root node, whatToShow bitmask, and filter callback.

To filter node run these steps:

  1. If active flag is set throw an "InvalidStateError", terminate these steps, and terminate the steps of the algorithm that invoked this algorithm.

  2. Let n be node's nodeType attribute value minus 1.

  3. If the nth bit (where 0 is the least significant bit) of whatToShow is not set, return FILTER_SKIP and terminate these steps.

  4. If filter is null return FILTER_ACCEPT and terminate these steps.

  5. Set the active flag.

  6. Let result be the return value of invoking filter.

  7. Unset the active flag.

  8. If an exception was thrown, re-throw the exception, terminate these steps, and terminate the steps of the algorithm that invoked this algorithm.

  9. Return result.

7.1 Interface NodeIterator

interface NodeIterator {
  readonly attribute Node root;
  readonly attribute Node? referenceNode;
  readonly attribute boolean pointerBeforeReferenceNode;
  readonly attribute unsigned long whatToShow;
  readonly attribute NodeFilter? filter;

  Node? nextNode();
  Node? previousNode();

  void detach();
};

NodeIterator objects can be created using the createNodeIterator() method.

Each NodeIterator object has an associated iterator collection, which is a collection rooted at root, whose filter matches any node.

Before a node is removed from the iterator collection, these steps must be run:

  1. If the node is not a descendant of root and is not an ancestor of the referenceNode attribute value or the referenceNode attribute value itself, terminate these steps.

  2. If the pointerBeforeReferenceNode attribute value is false, set the referenceNode attribute to the first node preceding the node that is being removed, and terminate these steps.

  3. If the pointerBeforeReferenceNode attribute value is true and there is a node following the node that is being removed, set the referenceNode attribute to the first such node, and terminate these steps.

  4. Set the referenceNode attribute to the first node preceding the node that is being removed and set the pointerBeforeReferenceNode attribute to false.

Each NodeIterator object also has an associated detached flag which is initially unset.

As mentioned earlier NodeIterator objects have an associated active flag, root node, whatToShow bitmask, and filter callback as well.


The root attribute must return root.

The referenceNode attribute must return what it was initialized to.

The pointerBeforeReferenceNode attribute must return what it was initialized to. When a NodeIterator is created it must be initialized to true.

The whatToShow attribute must return whatToShow.

The filter attribute must return filter.

To traverse in direction direction run these steps:

  1. If the detached flag is set throw an "InvalidStateError" exception and terminate these steps.

  2. Let node be the value of the referenceNode attribute.

  3. Let before node be the value of the pointerBeforeReferenceNode attribute.

  4. Run these substeps:

    1. If direction is next

      If before node is false, let node be the first node following node in the iterator collection. If there is no such node return null and terminate these steps.

      If before node is true, set it to false.

      If direction is previous

      If before node is true, let node be the first node preceding node in the iterator collection. If there is no such node return null and terminate these steps.

      If before node is false, set it to true.

    2. Filter node and let result be the return value.

    3. If the detached flag is set throw an "InvalidStateError" exception and terminate these steps.

    4. If result is FILTER_ACCEPT, go to the next step in the overall set of steps.

      Otherwise, run these substeps again.

  5. Set the referenceNode attribute to node, set the pointerBeforeReferenceNode attribute to before node, and return node.

The nextNode() method must traverse in direction next.

The previousNode() method must traverse in direction previous.

When the detach() method is invoked set the detached flag and set the referenceNode attribute to null.

7.2 Interface TreeWalker

interface TreeWalker {
  readonly attribute Node root;
  readonly attribute unsigned long whatToShow;
  readonly attribute NodeFilter? filter;
           attribute Node currentNode;

  Node? parentNode();
  Node? firstChild();
  Node? lastChild();
  Node? previousSibling();
  Node? nextSibling();
  Node? previousNode();
  Node? nextNode();
};

TreeWalker objects can be created using the createTreeWalker() method.

As mentioned earlier TreeWalker objects have an associated active flag, root node, whatToShow bitmask, and filter callback.

The root attribute must return root.

The whatToShow attribute must return whatToShow.

The filter attribute must return filter.

The currentNode attribute must return what it was initialized to.

Setting the currentNode attribute must set it to the new value.

The parentNode() method must run these steps:

  1. Let node be the value of the currentNode attribute.

  2. While node is not null and is not root, run these substeps:

    1. Let node be node's parent.

    2. If node is not null and filtering node returns FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

  3. Return null.

To traverse children of type type run these steps:

  1. Let node and current be the value of the currentNode attribute.

  2. While node is not null, run these substeps:

    1. Filter node and let result be the return value.

    2. If result is FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

    3. If result is FILTER_SKIP and node has a child, then set node as follows and run these substeps again:

      If type is first

      Set it to the first child

      If type is last

      Set it to the last child

    4. While node is not null, run these inner substeps:

      1. If type is first

        Let sibling be the next sibling of node.

        If type is last

        Let sibling be the previous sibling of node.

      2. If sibling is not null, set node to it and terminate these inner substeps.

      3. If node has a parent that is not root or current then set node to it.

        Otherwise, return null and terminate these steps.

The firstChild() method must traverse children of type first.

The lastChild() method must traverse children of type last.

To traverse siblings of type type run these steps:

  1. Let node be the value of the currentNode attribute.

  2. If node is root return null and terminate these steps.

  3. Run these substeps:

    1. If type is next

      Let sibling be the next sibling of node.

      If type is previous

      Let sibling be the previous sibling of node.

    2. While sibling is not null run these inner substeps:

      1. Set node to sibling.

      2. Filter node and let result be the return value.

      3. If result is FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

      4. If type is next

        Let sibling be the first child of node.

        If type is previous

        Let sibling be the last child of node.

      5. If result is FILTER_REJECT or sibling is null, then set sibling as follows:

        If type is next

        Let sibling be the next sibling of node.

        If type is previous

        Let sibling be the previous sibling of node.

    3. Set node to its parent.

    4. If node is null or is root return null and terminate these steps.

    5. Filter node and if the return value is FILTER_ACCEPT, then return null and terminate these steps.

    6. Run these substeps again.

The nextSibling() method must traverse children of type next.

The previousSibling() method must traverse children of type previous.

The previousNode() method must run these steps:

  1. Let node be the value of the currentNode attribute.

  2. While node is not root run these substeps:

    1. Let sibling be the previous sibling of node.

    2. While sibling is not null run these inner substeps:

      1. Set node to sibling.

      2. Filter node and let result be the return value.

      3. While result is not FILTER_REJECT and node has a child, run these innermost substeps:

        1. Set node to its last child.

        2. Filter node and set result to the return value.

      4. If result is FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

    3. If node is root or has no parent, return null and terminate these steps.

    4. Set node to its parent.

    5. Filter node and if the return value is FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

The nextNode() method must run these steps:

  1. Let node be the value of the currentNode attribute.

  2. Let result be FILTER_ACCEPT.

  3. Run these substeps:

    1. While result is not FILTER_ACCEPT and node has a child, run these inner substeps:

      1. Set node to its first child

      2. Filter node and let result be the return value.

      3. If result is FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

    2. If a node is following node and is not following root, set node to the first such node.

      Otherwise, run these substeps again (skipping the next step).

    3. Filter node and if the return value is FILTER_ACCEPT, then set the currentNode attribute to node, return node, and terminate these steps.

7.3 Interface NodeFilter

callback interface NodeFilter {
  // Constants for acceptNode()
  const unsigned short FILTER_ACCEPT = 1;
  const unsigned short FILTER_REJECT = 2;
  const unsigned short FILTER_SKIP = 3;

  // Constants for whatToShow
  const unsigned long SHOW_ALL = 0xFFFFFFFF;
  const unsigned long SHOW_ELEMENT = 0x1;
  const unsigned long SHOW_ATTRIBUTE = 0x2; // historical
  const unsigned long SHOW_TEXT = 0x4;
  const unsigned long SHOW_CDATA_SECTION = 0x8; // historical
  const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical
  const unsigned long SHOW_ENTITY = 0x20; // historical
  const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40;
  const unsigned long SHOW_COMMENT = 0x80;
  const unsigned long SHOW_DOCUMENT = 0x100;
  const unsigned long SHOW_DOCUMENT_TYPE = 0x200;
  const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400;
  const unsigned long SHOW_NOTATION = 0x800; // historical

  unsigned short acceptNode(Node node);
};

NodeFilter objects can be used as filter callback and provide constants for the whatToShow bitmask.

It is typically implemented as an ECMAScript function.

These constants can be used as callback return value:

These constants can be used for the whatToShow bitmask:

8 Collections

A collection is an object that represents a lists of DOM nodes. A collection can be either live or static. Unless otherwise stated, a collection must be live.

If a collection is live, then the attributes and methods on that object must operate on the actual underlying data, not a snapshot of the data.

When a collection is created, a filter and a root are associated with it.

The collection then represents a view of the subtree rooted at the collection's root, containing only nodes that match the given filter. The view is linear. In the absence of specific requirements to the contrary, the nodes within the collection must be sorted in tree order.

An attribute that returns a live collection must return the same object every time it is retrieved.

8.1 Interface NodeList

A NodeList object is a collection of nodes.

[ArrayClass]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
};
collection . length

Returns the number of nodes in the collection.

element = collection . item(index)
element = collection[index]

Returns the node with index index from the collection. The nodes are sorted in tree order.

The object's supported property indices are the numbers in the range zero to one less than the number of nodes represented by the collection. If there are no such elements, then there are no supported property indices.

The length attribute must return the number of nodes represented by the collection.

The item(index) method must return the indexth node in the collection. If there is no indexth node in the collection, then the method must return null.

8.2 Interface HTMLCollection

An HTMLCollection object is a collection of elements.

This interface is called HTMLCollection for historical reasons. The namedItem() method returns an object for interfaces that inherit from this interface, which return other objects for historical reasons.

interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter object? namedItem(DOMString name); // only returns Element
};
collection . length

Returns the number of elements in the collection.

element = collection . item(index)
element = collection[index]

Returns the element with index index from the collection. The elements are sorted in tree order.

element = collection . namedItem(name)
element = collection[name]

Returns the first element with ID or name name from the collection.

Only a, applet, area, embed, form, frame, frameset, iframe, img, and object element in the HTML namespace can have a name for the purpose of this method; their name is given by the value of their name attribute.

The object's supported property indices are the numbers in the range zero to one less than the number of nodes represented by the collection. If there are no such elements, then there are no supported property indices.

The length attribute must return the number of nodes represented by the collection.

The item(index) method must return the indexth element in the collection. If there is no indexth element in the collection, then the method must return null.

The supported property names consist of the values of the name attributes of each a, applet, area, embed, form, frame, frameset, iframe, img, and object element in the HTML namespace, represented by the collection with a name attribute, plus the list of IDs that the elements represented by the collection have.

The namedItem(key) method must return the first element in the collection that falls into one of the following categories:

If no such elements are found, then the method must return null.

9 Lists

9.1 Interface DOMStringList

DOMStringList will be removed from this specification in the near future. If you are using it now, please use DOMString[] instead. Thanks!

[NoInterfaceObject]
interface DOMStringList {
  readonly attribute unsigned long length;
  getter DOMString? item(unsigned long index);
  boolean contains(DOMString string);
};

The DOMStringList interface represents an interface to an ordered list of strings.

stringlist . length

Returns the number of tokens in the string.

string = stringlist . item(index)
stringlist[index]

Returns the string with index index.

hasstring = stringlist . contains(string)

Returns true if the string is present; false otherwise.

The length attribute must return the number of strings in the list.

The object's supported property indices are the numbers in the range zero to the length attribute value minus 1, unless the length attribute value is zero, in which case there are no supported property indices.

The item(index) method must return the indexth string in the list. If index is equal to or greater than the number of strings, then the method must return null.

The contains(string) method must return true if the list of strings contains string, or false otherwise.

9.2 Interface DOMTokenList

The DOMTokenList interface represents an interface to an underlying string that consists of a set of space-separated tokens.

DOMTokenList objects are always case-sensitive, even when the underlying string might ordinarily be treated in a case-insensitive manner.

interface DOMTokenList {
  readonly attribute unsigned long length;
  getter DOMString? item(unsigned long index);
  boolean contains(DOMString token);
  void add(DOMString token);
  void remove(DOMString token);
  boolean toggle(DOMString token);
  stringifier DOMString ();
};
tokenlist . length

Returns the number of tokens in the string.

element = tokenlist . item(index)
tokenlist[index]

Returns the token with index index. The tokens are returned in the order they are found in the underlying string.

hastoken = tokenlist . contains(token)

Returns true if the token is present; false otherwise.

Throws a "SyntaxError" exception if token is empty.

Throws an "InvalidCharacterError" exception if token contains any spaces.

tokenlist . add(token)

Adds token, unless it is already present.

Throws a "SyntaxError" exception if token is empty.

Throws an "InvalidCharacterError" exception if token contains any spaces.

tokenlist . remove(token)

Removes token if it is present.

Throws a "SyntaxError" exception if token is empty.

Throws an "InvalidCharacterError" exception if token contains any spaces.

hastoken = tokenlist . toggle(token)

Adds token if it is not present, or removes it if it is. Returns true if token is now present (it was added); returns false if it is not (it was removed).

Throws a "SyntaxError" exception if token is empty.

Throws an "InvalidCharacterError" exception if token contains any spaces.

The length attribute must return the number of tokens that result from splitting the underlying string on spaces.

The object's supported property indices are the numbers in the range zero to the length attribute value minus 1, unless the length attribute value is zero, in which case there are no supported property indices.

The item(index) method must run these steps:

  1. If index is equal to or greater than the length attribute value, return null and terminate these steps.
  2. Split the underlying string on spaces, preserving the order of the tokens as found in the underlying string, to get the list of tokens.
  3. Return the indexth item in this list.

For example, if the string is "a b a c" then there are four tokens: the token with index 0 is "a", the token with index 1 is "b", the token with index 2 is "a", and the token with index 3 is "c".

The contains(token) method must run these steps:

  1. If token is the empty string, then throw a "SyntaxError" exception and terminate these steps.
  2. If token contains any space characters, then throw an "InvalidCharacterError" exception and terminate these steps.
  3. Split the underlying string on spaces to get the list of tokens.
  4. Return true if token is a case-sensitive match for one of the tokens in the list found in the previous step, or false otherwise.

The add(token) method must run these steps:

  1. If token is the empty string, then throw a "SyntaxError" exception and terminate these steps.
  2. If token contains any space characters, then throw an "InvalidCharacterError" exception and terminate these steps.
  3. Split the underlying string on spaces to get the list of tokens.
  4. If token is a case-sensitive match for one of the tokens in the list found in the previous step, then terminate these steps.
  5. If the underlying string is not the empty string and the last character of that string is not a space character, then append a U+0020 SPACE character to that string.
  6. Append token to the underlying string.

The remove(token) method must run these steps:

  1. If token is the empty string, then throw a "SyntaxError" exception and terminate these steps.
  2. If token contains any space characters, then throw an "InvalidCharacterError" exception and terminate these steps.
  3. Remove token from the underlying string.

The toggle(token) method must run these steps:

  1. If token is the empty string, then throw a "SyntaxError" exception and terminate these steps.
  2. If token contains any space characters, then throw an "InvalidCharacterError" exception and terminate these steps.
  3. Split the underlying string on spaces to get the list of tokens.
  4. If token is a case-sensitive match for one of the tokens in the list found in the previous step, then remove token from the underlying string, return false and terminate these steps.
  5. If the underlying string is not the empty string and the last character of that string is not a space character, then append a U+0020 SPACE character to that string.
  6. Append the value of token to the underlying string.
  7. Return true.

DOMTokenList objects must stringify to the underlying string.

9.3 Interface DOMSettableTokenList

The DOMSettableTokenList interface is the same as the DOMTokenList interface, except that it allows the underlying string to be directly changed.

interface DOMSettableTokenList : DOMTokenList {
            attribute DOMString value;
};
tokenlist . value

Returns the underlying string.

Can be set, to change the underlying string.

An object implementing the DOMSettableTokenList interface must act as defined for the DOMTokenList interface, except for the value attribute defined here.

The value attribute must return the underlying string and, on setting must replace the underlying string with the new value.

10 Historical

As explained in goals this specification is a significant revision of various DOM specifications. This section attempts to enumerate the changes.

10.1 DOM Events

These are the changes made to the features described in the "DOM Event Architecture", "Basic Event Interfaces", "Mutation Events", and "Mutation Name Event Types" chapters of DOM Level 3 Events. The other chapters are expected to move to a separate specification.

10.2 DOM Core

These are the changes made to the features described in DOM Level 3 Core.

DOMString and DOMTimeStamp are now defined in Web IDL.

Node now inherits from EventTarget.

Nodes are implicitly adopted across document boundaries.

Doctypes now always have a node document and can be moved across document boundaries.

ProcessingInstruction now inherits from CharacterData.

DOMError is completely redesigned.

The remainder of interfaces and interface members listed in this section were removed to simplify the DOM platform. Implementations conforming to this specification will not support them.

Interfaces:

Interface members:

Node
Document
DOMImplementation
Attr

No longer inherits from Node and therefore completely changed.

Element
DocumentType
Text

10.3 DOM Range

These are the changes made to the features described in the "Document Object Model Range" chapter of DOM Level 2 Traversal and Range.

RangeException has been removed.

Range objects can now be moved between documents and used on nodes that are not in a document.

Probably incomplete.

10.4 DOM Traversal

These are the changes made to the features described in the "Document Object Model Traversal" chapter of DOM Level 2 Traversal and Range.

Differences with respect to createNodeIterator() and createTreeWalker():

acceptNode() and its constants have been changed to use unsigned short, rather than just short.

The expandEntityReferences attribute has been removed from the NodeIterator and TreeWalker objects.

The referenceNode and pointerBeforeReferenceNode attributes have been added to NodeIterator objects to align with user agents.

nextNode() and previousNode() node now throw when invoked from a NodeFilter to align with user agents.

References

Normative references

[IANACHARSET]
Character Sets. IANA.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, Scott Bradner. IETF.
[WEBIDL]
Web IDL, Cameron McCormack. W3C.
[XML]
Extensible Markup Language, Tim Bray, Jean Paoli, C. M. Sperberg-McQueen et al.. W3C.
[XMLNS]
Namespaces in XML, Tim Bray, Dave Hollander, Andrew Layman et al.. W3C.

Informative references

[CSSOMVIEW]
CSSOM View, Glenn Adams, Shane Stephens and Anne van Kesteren. W3C.
[DOM2TR]
Document Object Model (DOM) Level 2 Traversal and Range Specification, Joe Kesselman, Jonathan Robie, Mike Champion et al.. W3C.
[DOM3CORE]
Document Object Model (DOM) Level 3 Core Specification, Arnaud Le Hors, Philippe Le Hégaret, Lauren Wood et al.. W3C.
[DOM3EVENTS]
Document Object Model (DOM) Level 3 Events Specification, Doug Schepers and Jacob Rossi. W3C.
[DOMPS]
DOM Parsing and Serialization, Ms2ger. WHATWG.
[ELEMENTTRAVERSAL]
Element Traversal Specification, Doug Schepers. W3C.
[HTML]
HTML5, Ian Hickson. W3C.

Acknowledgments

Thanks to Adam Klein, Adrian Bateman, Arun Ranganathan, Boris Zbarsky, Brandon Slade, Cameron McCormack, Dethe Elza, David Flanagan, Erik Arvidsson, Glenn Maynard, Henri Sivonen, Jacob Rossi, Jake Verbaten, James Graham, Jens Lindström, João Eiras, Jonas Sicking, 呂康豪 (Kang-Hao Lu), Kevin Sweeney, Manish Tripathi, Ojan Vafai, Olli Pettay, Ryosuke Niwa, Shiki Okasaka, Stig Halvorsen, and Travis Leithead for their useful comments.

Special thanks to Geoffrey Sneddon and Simon Pieters for first specifying the Nodes section of this specification and their useful comments.

Special thanks also to Ian Hickson for first specifying some parts of this specification in HTML and his useful comments. [HTML]

Finally, while this specification has been written from scratch, special thanks should also be extended to the editors of the various specifications that previously defined the features in this specification: Arnaud Le Hors, Björn Höhrmann, Doug Schepers, Gavin Nicol, Joe Kesselman, Jonathan Robie, Lauren Wood, Mike Champion, Peter Sharpe, Philippe Le Hégaret, Robin Berjon, Steve Byrne, Tom Pixley, and Vidur Apparao.