Detailed explanation of the DOM scope in Javascript, detailed explanation of javascriptdom

Source: Internet
Author: User
Tags html sample

Detailed explanation of the DOM scope in Javascript, detailed explanation of javascriptdom

Preface

To make it easier for developers to control pages, DOM defines the range interface. You can select a region in the document through the range without having to consider the node boundary (the selection is done in the background and invisible to users ). When regular DOM operations cannot modify the text block more effectively, the scope of use can often achieve the goal. This article will introduce the DOM scope in detail. Let's take a look at it.

Scope of creation

The Document type is definedcreateRange()Method. In a DOM-compatible browser, this method is a document object. UsehasFeature()You can also directly check whether the browser supports this method.

[Note] IE8-not supported by browsers

var supportsRange = document.implementation.hasFeature("Range", "2.0");var alsoSupportsRange =(typeof document.createRange == "function");

If the browser supports a range, you can usecreateRange()To create a DOM range, as shown below:

var range = document.createRange();

Similar to a node, the newly created range is directly associated with the document that created it, and cannot be used for other documents. After the range is created, you can use it to select a specific part of the document in the background. After creating a range and setting its location, you can perform many operations on the content of the range to achieve more refined control of the underlying DOM tree.

Each Range is represented by an instance of the Range type. This instance has many attributes and methods.

The following attributes provide the location information of the current range in the document.

  • StartContainer: the node that contains the start point of the range (that is, the parent node of the first node in the selection)
  • Startoffset: the offset of the range starting from startiner iner. If startContainer is a text node, comment node, or CDATA node, startoffset indicates the number of characters skipped before the start of the range. Otherwise, startoffset is the index of the first subnode in the range.
  • EndContainer: the node that contains the end of the range (that is, the parent node of the last node in the constituency)
  • EndOffset: the offset of the end point of the range in endiner iner (same as that of startoffset)
  • CommonAncestorContainer: The ancestor node that shares startContainer and endContainer in the deepest position in the Document Tree

These attributes are assigned values when the range is placed in a specific position in the document.

Simple selection

To use the scope to select a part of the document, the simplest way is to useselectNode()OrselectNodeContents() . Both methods accept a parameter, that is, a DOM node, and then use the information in the node to fill the range. Where,selectNode()Select the entire node, including its subnodes.selectNodeContents()Select only the child nodes of the node.

<!DOCTYPE html>

We can use the following code to create a range

var range1 = document.createRange();var range2 = document.createRange();var p1 = document.getElementById("p1");//Range {startContainer: body, startOffset: 1, endContainer: body, endOffset: 2, collapsed: false…}range1.selectNode(p1);//Range {startContainer: p#p1, startOffset: 0, endContainer: p#p1, endOffset: 2, collapsed: false…}range2.selectNodeContents(p1);

The two scopes created here contain different parts of the document: rangl contains <p> elements and all their child elements, rang2 contains <B> elements, text nodes "Hello", and text nodes "world! "

Before callingselectNode()StartContainer, endContainer, and commonAncestorContainer are both the parent nodes of the input node. In this exampledocument.body. The startoffset attribute is equivalent to the index of the given node in the childNodes set of its parent node (in this example, it is 1-because the DOM-compatible browser counts spaces as a text node ), endOffset equals to startoffset plus 1 (because only one node is selected)

Before callingselectNodeContents()StartContainer, endContainer, and commonAncestorContainer are equal to the input node, that is, the <p> element in this example. The startoffset attribute is always equal to 0 because the range starts from the first subnode of a given node. Finally, the endOffset is equal to the number of sub-nodes (node.childNodes.lengthIn this example

To more precisely control which nodes are included in the range, you can use the following methods:

  1. setStartBefore(refNode) : Set the start point of the range before the refNode. Therefore, the refNode is the first subnode in the range selection. At the same time, the startContainer attribute is set to refNode. parentNode, And the startoffset attribute is set to the index of the refNode in the childNodes set of its parent node.
  2. setStartAfter(refNode) : Set the start point of the range after the refNode, so the refNode is out of the range, and its next peer node is the first subnode in the range selection. At the same time, the startContainer attribute is set to refNode. parentNode, And the startoffset attribute is set to refNode in the parent node's childNodes set and the index is added to 1.
  3. setEndBefore(refNode) : Set the end point of the range before the refNode, so the refNode is out of the range, and the last peer node is the last subnode in the range selection. At the same time, the endContainer attribute is set to refNode. parentNode, And the endOffset attribute is set to the index of the refNode in the childNodes set of its parent node.
  4. setEndAfter(refNode): Set the end point of the range after the refNode, so the refNode is the last subnode in the range selection. At the same time, the endContainer attribute is set to refNode. parentNode, And the endOffset attribute is set to add 1 to the index of the refNode in the childNodes set of its parent node.

All attributes are automatically set when these methods are called. However, to create a complex range selection, you can also directly specify the values of these attributes.

Complex Selection

To create a complex range, you must usesetStart()AndsetEnd()Method. Both methods accept two parameters: a reference node and an offset value. PairsetStart()The reference node is changed to startContainer. The offset value is changed to startoffset. ForsetEnd()For example, the reference node is changed to endContainer, And the offset value is changed to endOffset. You can use these two methods to simulateselectNode()AndselectNodeContents().

Let's take a look at the example below

var range1 = document.createRange();var range2 = document.createRange();var p1 = document.getElementById("p1"); var p1Index = -1;var i, len; for (i=0, len=p1.parentNode.childNodes.length; i < len; i++) { if (p1.parentNode.childNodes[i] == p1) { p1Index = i; break; }} range1.setStart(p1.parentNode, p1Index);range1.setEnd(p1.parentNode, p1Index + 1);range2.setStart(p1, 0);range2.setEnd(p1, p1.childNodes.length);

Obviously, to select this node (using range1), you must determine the index of the current node (p1) in the childNodes set of its parent node. You do not need to calculate the content of this node (using range2). You only need to set the default value through setStart () and setEnd. ImitationselectNode()AndselectNodeContents()NotsetStart()AndsetEnd()The main purpose of the node is to be able to select a part of the node.

Suppose you only want to select "llo" from "Hello" to "world" in the preceding HTML sample code! "O" -- easy to do

The first step is to obtain reference from all nodes, as shown below:

var p1 = document.getElementById("p1");var helloNode = p1.firstChild.firstChild;var worldNode = p1.lastChild;

In fact, the "Hello" text node is the child node of the <p> element because it is a child node of the <B> element. Therefore,p1.firstchild<B> whilep1.firstchild.firstchildThis text node is obtained. "World! "The text node is the second child node of the <p> element (also the last child node), so you can usep1.lastChildObtain the node.

Then, you must specify the start and end points when creating a range, as shown below:

var range = document.createRange();range.setStart(helloNode, 2);range.setEnd(worldNode, 3);

Because the constituency of this range should start after "e" in "Hello ",setStart()When the helloNode is passed in, the offset 2 (that is, the next position of "e"; the position of "H" is 0) is passed in ). When you set the end point of a constituencysetEnd()In the input worldNode at the same time, the input offset 3, indicating the location of the first character outside the constituency, this character is "r ", its position is 3 (there is a space on the position 0 ).

As shown below

Because helloNode and worldNode are both text nodes, they are converted into startContainer and endContainer in the new range. In this case, startoffset and endOffset are used to determine the location of the text contained in the two nodes, rather than to determine the location of the child node (as when the input parameter is an element node ). At this time, commonAncestorContainer is the <p> element, that is, the first ancestor element that contains both nodes.

Of course, it is not very useful to select a part of the document. But it is important that you can operate the constituency only after selecting

Operation scope content

When you create a range, a file segment is created for this range. All nodes of the range are added to this file segment. To create this document clip, the format of the range content must be correct and valid. In the previous example, the created constituency starts and ends in the interior of the two text nodes, so it cannot be regarded as a well-formatted DOM structure and cannot be represented by DOM. However, the range knows which open and closed tags are missing, and it can re-build a valid DOM structure to operate on them.

For the preceding example, the range is calculated to know that the selected area does not contain a start <B> label. Therefore, this label is dynamically added to the background, at the same time, a label indicating the end is added to the front to end "He ". The modified DOM becomes as follows:

<p><b>He</b><b>llo</b> world!</p>

In addition, the text node "world! "Is also split into two text nodes, one containing" wo "and the other containing" rid! ". As shown in the final DOM tree, the right side is the content of the document fragment that represents the range

After a range is created, you can use various methods to perform operations on the content of the range.

[Note] All nodes in the internal document segment of the range are pointers to the corresponding nodes in the document.

[DeleteContents ()]

The first method of the operation scope content isdeleteContents()This method can delete the content contained in the scope from the document.

var p1 = document.getElementById("p1");var helloNode = p1.firstChild.firstChild;var worldNode = p1.lastChild;var range = document.createRange();range.setStart(helloNode, 2);range.setEnd(worldNode, 3);range.deleteContents();

After the above code is executed, the page displays the following HTML code

<p><b>He</b>rld!</p>

Because the range selection can ensure good format when modifying the underlying DOM structure, even if the content is deleted, the final DOM structure is still in good format.

[ExtractContents ()]

AnddeleteContents()Similar methods,extractContents()The range selection is also removed from the document. But the difference is that,extractContents()The part of the document in the returned range. The returned value can be used to insert the content in the range to other places in the document. As follows:

var p1 = document.getElementById("p1");var helloNode = p1.firstChild.firstChild;var worldNode = p1.lastChild;var range = document.createRange();range.setStart(helloNode, 2);range.setEnd(worldNode, 3);var fragment = range.extractContents();p1.parentNode.appendChild(fragment);

In this example, the extracted document segment is added to the end of the <body> element of the document.

[Note] When a document fragment is passed into the appendChild () method, only the child nodes of the fragment are added to the document, not the fragment itself.

<p><b>He</b>rld!</p><b>llo</b> wo

[CloneContents]

Another approach is to usecloneContents()Create a copy of the range object and insert it elsewhere in the document

var p1 = document.getElementById("p1");var helloNode = p1.firstChild.firstChild;var worldNode = p1.lastChild;var range = document.createRange();range.setStart(helloNode, 2);range.setEnd(worldNode, 3);var fragment = range.cloneContents();p1.parentNode.appendChild(fragment);

This method is similarextractContents()They are very similar because they all return document fragments. The main difference between them is that,cloneContents()The returned document fragment contains copies of nodes in the range, rather than actual nodes. After performing the preceding operations, the HTML code on the page is as follows:

<p><b>Hello</b> world!</p><b>llo</b> wo

[Note] before calling the cloneContents () method, the split node does not produce well-formatted file fragments. In other words, the original HTML remains unchanged until the DOM is modified.

Insert range content

You can use a range to delete or copy content, and operate the content in a range as described earlier. UseinsertNode()You can insert a node to the beginning of the range selection. Assume that the following HTML code is inserted before HTML in the preceding example.

<span style="color: red">Inserted text</span>

You can use the following code:

var p1 = document.getElementById("p1");var helloNode = p1.firstChild.firstChild;var worldNode = p1.lastChild;var range = document.createRange();var span = document.createElement("span");range.setStart(helloNode, 2);range.setEnd(worldNode, 3);span.style.color = "red";span.appendChild(document.createTextNode("Inserted text"));range.insertNode(span);

Run the preceding javascript code to obtain the following HTML code:

<p id="p1"><b>He<span styie="color:red">Inserted text</span>llo</b> world</p>

[Note] <span> is inserted before "llo" in "Hello", and this position is the start position of the range selection. Using this technology, you can insert some help information, such as inserting an image next to the link that opens a new window.

[SurroundContents ()]

In addition to inserting content inside the range, you can also insert content around the range.surroundContents()Method. This method accepts a parameter, that is, the node in the surrounding range. When content is inserted in the surrounding range, the background will perform the following steps

1. Extract the content in the scope (similar to the executionextractContents())

2. Insert a given node to the original location in the document.

3. Add the content of the document fragment to the specified node.

This technique can be used to highlight certain words in a webpage, such as the following code

var p1 = document.getElementById("p1");var helloNode = p1.firstChild.firstChild;var worldNode = p1.lastChild;var range = document.createRange();range.selectNode(helloNode);var span = document.createElement("span");span.style.backgroundColor = "yellow";range.surroundContents(span);

The above Code adds a yellow background to the range selection. The HTML code is as follows:

<p><b><span style="background-color:yellow">Hello</b> world!</p>

To insert <span>, the range must contain the entire DOM selection, not just the selected DOM node.

Folding range

The folding range refers to any part of the document not selected in the range. You can use text boxes to describe the folding range process. Assume that there is a line of text in the text box and a complete word is selected with the mouse. Then, click the left mouse button, the selection disappears, and the cursor falls between two letters. Similarly, when the range is folded, its position falls between two parts of the document, which may be the start position or end position of the range selection. Displays the situations that occur when the folding range is used.

[Collapse ()]

Usecollapse()Method to collapse the range. This method accepts a parameter, which is a Boolean value that indicates the end of the range to be folded. The "true" parameter indicates the start point of the collapsed range, and the "false" parameter indicates the end point of the collapsed range. To confirm that the range has been folded, check the collapsed attribute as follows:

Range. collapse (true); // fold to the start console. log (range. collapsed); // Output true

Checking whether a range is folded helps us determine whether two nodes in the range are closely adjacent. For example, for the following HTML code

<p id="p1">Paragraph 1</p><p id="p2">Paragraph 2</p>

If you do not know the actual structure (for example, this line of code is dynamically generated), you can create a range as follows:

Var p1 = document. getElementById ("p1"); var p2 = document. getElementById ("p2"); var range = document. createRange (); range. setStartAfter (p1); range. setStartBefore (p2); console. log (range. collapsed); // outputs true

In this example, the newly created range is collapsed, because there is nothing behind p1 and front of p2

Comparison Scope

[CompareBoundaryPoints ()]

You can usecompareBoundaryPoints()To determine whether these ranges have common boundary (start point or end point ). This method accepts two parameters: the constant value of the comparison method and the range to be compared. The constant value indicating the comparison method is as follows:

  1. Range.START_TO_START(0): Compare the start point of the first range and the second range
  2. Range.START_TO_END(1): Compare the start point of the first range and the end point of the second range
  3. Range.END_TO_END⑵ : Compare the endpoints of the first range and the second range
  4. Range.END_T0_START(3) : Compare the end point of the first range and the start point of the first range

compareBoundaryPoints()Possible return values of the method are as follows:-1 is returned if the vertex in the first range is before the vertex in the second range; 0 is returned if the two vertices are equal; if the vertex in the first range is located after the vertex in the second range, 1 is returned.

Let's take a look at the example below

var range1 = document.createRange();var range2 = document.createRange();var p1 = document.getElementById("p1");range1.selectNodeContents(p1);range2.selectNodeContents(p1);range2.setEndBefore(p1.lastChild);alert(range1.compareBoundaryPoints(Range.START_TO_START, range2)); //outputs 0alert(range1.compareBoundaryPoints(Range.END_TO_END, range2)); //outputs 1

In this example, the starting points of the two ranges are actually the same, because their starting points areselectNodeContents()The default value of the method. Therefore, the first comparison returns 0. However, the end of range2 is calledsetEndBefore()The result is that the destination of range1 is behind the destination of range2. Therefore, 1 is returned for the second comparison.

Replication range

[CloneRange]

AvailablecloneRange()Method replication range. This method creates a copy of The called range.

var newRange = range.cloneRange();

The newly created range has the same attributes as the original range, but modifying its endpoint does not affect the original range.

Cleanup range

[Detach ()]

After the range is used, it is best to calldetach()To separate the range from the document that created the range. Calldetach()Then, you can safely remove the reference to the range, so that the garbage collection mechanism can recycle its memory. Let's take a look at the example below

Range. detach (); // detach range = null from the document; // unreference

It is recommended to perform these two steps at the end of the scope of use. Once they are separated, they cannot be used again.

IE compatibility

IE8-the browser does not support DOM ranges. However, it supports a similar concept, that is, the text range (textrange ). The text scope is proprietary to IE and is not supported by other browsers. As the name suggests, text ranges mainly process text (not necessarily DOM nodes ). You can callcreateTextRange()To create a text range. The following is an example

var range = document.body.createTextRange();

In this way, the range created through document can be used anywhere on the page (the range created through other elements can only be used in the corresponding element ). Similar to DOM range, there are many ways to use IE text range.

1. Simple selection

[FindText ()]

The easiest way to select a region on the page is to usefindText()Method. This method finds the given text that appears for the first time and shifts the range to wrap the text. If no text is found, false is returned; otherwise, true is returned. Similarly, the following HTML code is used as an example.

<p id="p1"><b>Hello</b> world!</p>

To select "Hello", you can use the following code:

var range = document.body.createTextRange();var found = range.findText("Hello");

After the second line of code is executed, the text "Hello" is surrounded by a range. For this reason, you can check the text attribute of the response range to confirm (the text contained in the returned range), or checkfindText()-- Returns true if the text is found.

For example:

alert(found); //truealert(range.text); //"Hello"

You can alsofindText()Input another parameter, which indicates the direction in which the search continues. A negative value indicates that the search should be performed backward from the current position, and a positive value indicates that the search should be performed forward from the current position. Therefore, to find the first two "Hello" instances in the document, use the following code:

var found = range.findText("Hello");var foundAgain = range.findText("Hello", 1);

[MoveToElementText ()]

The method closest to the selectNode () method in DOM in IE ismoveToElementText() This method accepts a DOM element and selects all the text of the element, including the HTML Tag. The following is an example.

var range = document.body.createTextRange();var p1 = document.getElementById("p1")range.moveToElementText(p1);

When the text range contains HTML, you can use the htmlText attribute to obtain all the content of the range, including HTML and text, as shown below:

alert(range.htmlText);

The range of IE does not have any attributes that can be dynamically updated as the range selection changes. However,parentElement()The method is similar to the commonAncestorContainer attribute of DOM.

var ancestor = range.parentElement();

The parent element always reflects the parent node of the Text Selection area.

2. Complex Selection

The method used to create a complex range in IE is to move the range to the surrounding area with a specific increment. Therefore, IE provides four methods:move(),moveStart() ,moveEnd()Andexpand(). These methods both accept two parameters: the number of mobile units and the number of mobile units.

The unit of movement is the following string values:

  1. "Character": Move character by character
  2. "Word": Move words one by one (a series of non-space characters)
  3. "Sentence": Move sentences one by one (a series of characters ending with periods, question marks, or exclamation points)
  4. "Textedit": Move to the start or end position of the selected range.

PassmoveStart()The method can move the starting point of the range throughmoveEnd()The method can be used to move the end point of a range. The moving range is specified by the number of units, as shown below:

Range. moveStart ("word", 2); // the start point moves 2 words range. moveEnd ("character", 1); // The end point moves 1 character

Useexpand()The range can be normalized. In other words,expand()The method selects all selected text. For example, if you select two characters in the middle of a word, callexpand("word")The entire word can be included in the range.

The move () method first folds the current range (to make the start point and end point equal), and then moves the range to the specified number of units, as shown below:

Range. move ("character", 5); // move 5 Characters

Callmove()Then, the start and end of the range are the same, so you must usemoveStart()OrmoveEnd()Create a new constituency

Iii. operation scope

The text attribute orpasteHTML()Method. As mentioned above, you can obtain the content text in the range through the text attribute. However, you can also set the content text in the range through this attribute. Let's look at an example.

var range = document.body.createTextRange();range.findText("Hello");range.text = "Howdy";

If the preceding Hello World code is still used as an example, the HTML code after the above code is executed is as follows:

<p id="p1"><b>Howdy</b> world!</p>

[Note] when setting the text attribute, the HTML Tag remains unchanged.

[PasteHTML ()]

To insert HTML code into a range, you must usepasteHTML()Method, as shown below

var range = document.body.createTextRange();range.findText("Hello");range.pasteHTML("<em>Howdy</em>");

After the code is executed, the following HTML

<p id="p1"><b><em>Howdy</em></b> world!</p>

However, when the range contains HTML code, you should not usepasteHTML(), Because this can easily lead to unexpected results-it is likely that the format is incorrect HTML

Iv. Collapse IE range

[Collapse ()]

Internet Explorer providescollapse()The method is the same as the corresponding DOM method usage: Pass true to fold the range to the start point, and pass false to fold the range to the end point. For example:

Range. collapse (true); // fold to the start point

Unfortunately, there is no corresponding collapsed attribute to let us know whether the range has been folded. Therefore, you must use the boundingWidth attribute, which returns the width of the range (in pixels ). If the boundingwidth attribute is equal to 0, the range is collapsed.

var isCollapsed = (range.boundingWidth == 0);

In addition, attributes such as boundingHeight, boundingLeft, and boundingTop are available. Although they are not as useful as boundingWidth, they can also provide information about the range position.

V. Comparison of IE Scope

[CompareEndPoints ()]

In IEcompareEndPoints()Method and DOM rangecompareBoundaryPoints()The method is similar. This method accepts two parameters: the comparison type and the scope to be compared. The value range of the comparison type is the following string values: "StartToStart", "StartToEnd", "EndToEnd", and "EndToStart ". The comparison types are the same as those used to compare DOM ranges.

Similar to DOM,compareEndPoints()The method will return values according to the same rule, that is, if the boundary of the first range is located before the boundary of the second range,-1 is returned. If the boundary of the two is the same, 0 is returned; if the boundary of the first range is behind the boundary of the second range, 1 is returned. The preceding Hello World code is used as an example. The following Code creates two ranges: "Hello world! "(Including the <B> label) and" Hello"

var range1 = document.body.createTextRange();var range2 = document.body.createTextRange();range1.findText("Hello world!");range2.findText("Hello");alert(range1.compareEndPoints("StartToStart", range2)); //outputs 0alert(range1.compareEndPoints("EndToEnd", range2)); //outputs 1;

Because the two ranges share the same starting pointcompareEndPoints()Returns 0 for the start point of the comparison. The destination of range1 is behind the destination of range2, socompareEndPoints()Return 1

There are two other methods in IE, which are also used to compare the range: isEqual () is used to determine whether the two ranges are equal,inRange()Used to determine whether a range contains another range.

The following is an example.

var range1 = document.body.createTextRange();var range2 = document.body.createTextRange();range1.findText("Hello world!");range2.findText("Hello");alert("range1.isEqual(range2): " + range1.isEqual(range2));//falsealert("range1.inRange(range2): " + range1.inRange(range2));//true

In this example, we use the same scope as above to demonstrate the two methods. Because the endpoints of these two ranges are different, they are not equal. If isEqual is called, false is returned. Range2 is actually located inside rangel, and its end point is located before and after the end point of the latter. Therefore, range2 is included in rangel and calledinRange()Returns true.

Vi. Copying IE Scope

Use in IEduplicate()You can copy the text range. A copy of the original range is created as follows:

var newRange = range.duplicate();

The newly created range has the same attributes as the original range.

Summary

The above is all about this article. I hope this article will help you in your study or work. If you have any questions, please leave a message.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.