Inserting DOM range content
The previous three methods all dealt with removing information from the range in one way or another. It is also possible to add content to the range using a couple of different methods.
insertNode() method enables you to insert a node at the beginning of the selection. Suppose you wanted to insert the following HTML code into the range defined in the previous section:
<span style="color: red">Inserted text</span>
The following code accomplishes this:
var oP1 = document.getElementById("p1"); var oHello = oP1.firstChild.firstChild; var oWorld = oP1.lastChild; var oRange = document.createRange(); var oSpan = document.createElement("span"); oSpan.style.color = "red"; oSpan.appendChild(document.createTextNode("Inserted text")); oRange.setStart(oHello, 2); oRange.setEnd(oWorld, 3); oRange.insertNode(oSpan);
<p id="p1"><b>He<span style="color: red">Inserted text</span>llo</b> World</p>
Note that the
<span/> is inserted just before the llo in Hello, which is the first part of the range selection. Also note that the original HTML didn't add or remove
<b/> elements because none of the methods introduced in the previous section were used. You can use this technique to insert helpful information, such as an image next to links that open in a new window.
Along with inserting into the range, it is possible to insert content surrounding the range by using the
surroundContents() method. This method accepts one parameter, which is the node that surrounds the range contents. Behind the scenes, the following steps are taken:
- The contents of the range are extracted (similar to
- The given node is inserted into the position in the original document where the range was.
- The contents of the document fragment is added to the given node.
This sort of functionality is useful online to highlight certain words in a web page, like this:
var oP1 = document.getElementById("p1"); var oHello = oP1.firstChild.firstChild; var oWorld = oP1.lastChild; var oRange = document.createRange(); var oSpan = document.createElement("span"); oSpan.style.backgroundColor = "yellow"; oRange.setStart(oHello, 2); oRange.setEnd(oWorld, 3); oRange.surroundContents(oSpan);
The previous code highlights the range selection with a yellow background.
Collapsing a DOM Range
To empty a range, (that is, to have it select no part of the document), you collapse it. Collapsing a range resembles the behavior of a text box. When you have text in a text box, you can highlight an entire word using the mouse. However, if you left-click the mouse again, the selection is removed and the cursor is located between two letters. When you collapse a range, you are setting its locations between parts of a document, either at the beginning of the range selection or at the end. Figure 6 illustrates what happens when a range is collapsed.
You can collapse a range by using the
collapse() method, which accepts a single argument: a Boolean value indicating which end of the range to collapse to. If the argument is
true, then the range is collapsed to its starting point; if
false, the range is collapsed to its ending point. To determine if a range is collapsed, you can use the
oRange.collapse(true); //collapse to the starting point alert(oRange.collapsed); //outputs "true"
Testing whether a range is collapsed is helpful if you aren't sure if two nodes in the range are next to each other. For example, consider this HTML code:
<p id="p1">Paragraph 1</p><p id="p2">Paragraph 2</p>
If you don't know the exact makeup of this code (because, perhaps, it is automatically generated), you might try creating a range like this:
var oP1 = document.getElementById("p1"); var oP2 = document.getElementById("p2"); var oRange = document.createRange(); oRange.setStartAfter(oP1); oRange.setStartBefore(oP2); alert(oRange.collapsed); //outputs "true"
In this case, the created range is collapsed because there is nothing between the end of
p1 and the beginning of
Comparing DOM ranges
If you have more than one range, you can use the
compareBoundaryPoints() method to determine if the ranges have any boundaries (start or end) in common. The method accepts two arguments: the range to compare to and how to compare, which is a constant value:
START_TO_START(0) — Compares the starting point of the first range to the starting point of the second
START_TO_END(1) — Compares the starting point of the first range to the end point of the second
END_TO_END(2) — Compares the end point of the first range to the end point of the second.
END_TO_START(3) — Compares the end point of the first range to the start point of the second
compareBoundaryPoints() method returns -1 if the point from the first range comes before the point from the second range, 0 if the points are equal, or 1 if the point from the first range comes after the point from the second range.
var oRange1 = document.createRange(); var oRange2 = document.createRange(); var oP1 = document.getElementById("p1"); oRange1.selectNodeContents(oP1); oRange2.selectNodeContents(oP1); oRange2.setEndBefore(oP1.lastChild); alert(oRange1.compareBoundaryPoints(Range.START_TO_START, oRange2)); //outputs 0 alert(oRange1.compareBoundaryPoints(Range.END_TO_END, oRange2)); //outputs 1;
In this code, the starting points of the two ranges are exactly the same because both use the default value from
selectNodeContents(); therefore, the method returns 0. For
oRange2, however, the end point is changed using
setEndBefore(), making the end point of
oRange1 come after the end point of
oRange2 (see Figure 7), so the method returns 1.
Cloning DOM ranges
If you find the need, you can duplicate any range by calling the
cloneRange() method. This method creates an exact duplicate of the range on which it is called:
var oNewRange = oRange.cloneRange();
The new range contains all of the same properties as the original and can be modified without affecting the original in any way.
When you are done using a range, it is best to call the
detach() method to free up system resources. This isn't required because dereferenced ranges are picked up by the garbage collector eventually. If, however, the range is used initially and then no longer required, calling
detach() ensures that it isn't taking up any more memory than necessary: