1. Introduction
DOM4 defines a Range
object (originally from DOM2 Traversal/Range) which
can be used to represent a sequence of content in the DOM tree. A Range
consists of a start boundary (a node and an offset) and an end boundary
(also a node and an offset). A key benefit of using a Range
is that once
it is created, it will maintain the integrity of the range as best it can
even in the face of DOM mutations.
A problem with Range
is that whenever a DOM mutation occurs, all of the
active Range
objects affected by the mutation need to be updated. This
can be an expensive operation, especially if there are a large number of
active Range
objects. This cost may be acceptable if all of these Range
objects are actually needed by the application, but Range
is
used whenever we need to record start- and end-positions. Because of this,
many of the Range
objects that are created are not actually used by the
application, and many of the Range
objects that are being used don’t
actually need their range start and end to be resilient to DOM mutations.
This problem is exacerbated when an application caches an object that
happens to contain a Range
along with other data that the application
needs. As long as this object is active, the Range
will be active and it
will need to be updated for every DOM mutation. In this manner, an
application can end up with many active Range
objects even if none of
them are being used.
A StaticRange is a simple, lightweight range that contains only a start and an end boundary (node + offset) and does not update when the DOM is mutated.
1.1. Interface StaticRange
The StaticRange
interface provides readonly attributes that track the start
and end position of the range, and a readonly boolean attribute that
indicates whether or not the current range is collapsed to a single
position (where the start equals the end position).
Any StaticRange
that is generated by the user agent MUST be valid.
interface StaticRange { readonly attribute Node startContainer; readonly attribute unsigned long startOffset; readonly attribute Node endContainer; readonly attribute unsigned long endOffset; readonly attribute boolean collapsed; };
-
startContainer
-
The start
Node
for the range. -
startOffset
-
The offset into the start node identifying the start position for the range.
-
endContainer
-
The end
Node
for the range. -
endOffset
-
The offset into the start node identifying the end position for the range.
-
collapsed
-
True if the range’s start position and end position are the same, as determined by executing is collapsed.
2. Algorithms
A StaticRange
position is the combination of a Node
position node and an unsigned long position offset into that node. The position offset is the offset from the start of the position node to the desired position.
The start position of a StaticRange
r is the position defined by r’s startContainer and startOffset.
The end position of a StaticRange
r is the position defined by r’s endContainer and endOffset.
2.1. a position p1 is less than another position p2
-
Input
-
p1, a
StaticRange
positionp2, a
StaticRange
position -
Output
-
Boolean
-
If p1’s position node is earlier in the DOM tree than p2’s position node, return True.
-
If p1’s position node is the same as p2’s position node,
-
If p1’s position offset is less than p2’s position offset, return True.
-
Else, return False.
-
-
Return False.
2.2. a position p1 is equal to another position p2
-
Input
-
p1, a
StaticRange
positionp2, a
StaticRange
position -
Output
-
Boolean
-
If p1’s position node is the same as p2’s position node,
-
If p1’s position offset is equal to p2’s position offset,
-
Return True.
-
-
-
Return False.
2.3. a StaticRange
is collapsed
-
Input
-
sr, a
StaticRange
-
Output
-
Boolean
-
If sr’s start position is equal to sr’s end position,
-
Return True
-
-
Return False
2.4. a StaticRange
is valid
-
Input
-
sr, a
StaticRange
to be validated -
Output
-
Boolean
-
If sr’s end position is less than sr’s start position,
-
Return False
-
-
If sr’s startOffset is less than 0 or sr’s endOffset is less than 0,
-
Return False
-
-
If sr’s startOffset is greater than the size of the startContainer,
-
Return False
-
-
If sr’s endOffset is greater than the size of the endContainer,
-
Return False
-
-
If sr’s collapsed is not equal to the result of calling is collapsed with sr,
-
Return False
-
-
Return True
3. Acknowledgements
Thanks to the following people for the discussions that lead to the creation of this proposal:
Enrica Casucci (Apple), Bo Cupp (Microsoft), Emil Eklund (Google), Wenson Hsieh (Apple), Gary Kacmarcik (Google), Ian Kilpatrick (Google), Grisha Lyukshin (Microsoft), Miles Maxfield (Apple), Ryosuke Niwa (Apple), Olli Pettay (Mozilla), Dave Tapuska (Google), Ojan Vafai (Google), Johannes Wilm (Fidus), Chong Zhang (Gooogle)