Javascript standard DOM range operation

Source: Internet
Author: User
Tags ranges

Level 2 Dom defines a createRange () method. If the browser follows the DOM standard (ie does not support this standard, however, the attributes or methods in IE are much larger than those defined in the standard.) It belongs to the Document Object. Therefore, you must create a range object as follows:

VaR Orange = Document. createRange ();

If you want to check whether your browser supports this standard range object, you can use hasfeature () to check:

VaR supportsdomranges = Document. Implementation. hasfeature ("range", "2.0 ");
If (supportsdomrange ){
VaR Orange = Document. createRange ();
// Range code here
}
Simple selection of range objects
The simplest method is to use range for selection. The selectnode () or selectnodecontents () methods are used. The two methods have only one receiving parameter and one dom node.

The selectnode () method selects all nodes, including its children, while the Node Selected by selectnodecontents () is only its children. For example

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
VaR Orange1 = Document. createRange ();
VaR orange2 = Document. createRange ();
VaR OP1 = Document. getelementbyid ("p1 ");
Orange1.selectnode (OP1 );
Orange2.selectnodecontents (OP1 );
</SCRIPT>

Orange1 and orange2 contain the two methods mentioned above, but I believe that you can quickly understand the differences between the two methods after reading the diagram below:

When you create a range object, the range instance has the following attributes:
Startcontainer-return the Node object where the range object starts (the first node of the parent node)
Startoffset-returns the offset from the start of range. If startcontainer is a text node, comment node, or CDATA node, this attribute returns the text offset. Otherwise, the index of the first node is returned.
Endcontainer-returns the last Node object of the range object (the last node of the parent node)
Endoffset-the offset property at the end of the returned range is the same as that of startoffset.
Commonancestorcontainer-returns the first node that contains the range object.

Note: These attributes are read-only. startoffset and endoffset will be explained in detail below.

The following sectionCodeThese attributes will be described. Run them in Mozilla Firefox (the standard browser-dom2 level is supported, and IE will be invalid ):

<HTML>
<Head>
<Title> Dom range example </title>
<SCRIPT type = "text/JavaScript">
Function useranges (){
VaR Orange1 = Document. createRange ();
VaR orange2 = Document. createRange ();
VaR OP1 = Document. getelementbyid ("p1 ");
Orange1.selectnode (OP1 );
Orange2.selectnodecontents (OP1 );

Document. getelementbyid ("txtstartcontainer1"). Value
= Orange1.startcontainer. tagname;
Document. getelementbyid ("txtstartoffset1"). value =
Orange1.startoffset;
Document. getelementbyid ("txtendcontainer1"). value =
Orange1.endcontainer. tagname;
Document. getelementbyid ("txtendoffset1"). value =
Orange1.endoffset;
Document. getelementbyid ("txtcommonancestor1"). value =
Orange1.commonancestorcontainer. tagname;
Document. getelementbyid ("txtstartcontainer2"). value =
Orange2.startcontainer. tagname;
Document. getelementbyid ("txtstartoffset2"). value =
Orange2.startoffset;
Document. getelementbyid ("txtendcontainer2"). value =
Orange2.endcontainer. tagname;
Document. getelementbyid ("txtendoffset2"). value =
Orange2.endoffset;
Document. getelementbyid ("txtcommonancestor2"). value =
Orange2.commonancestorcontainer. tagname;
}
</SCRIPT>
</Head>
<Body> <p id = "p1"> <B> Hello </B> world </P>
<Input type = "button" value = "use ranges" onclick = "useranges ()"/>
<Table border = "0">
<Tr>
<TD>
<Fieldset>
<Legend> Orange1 </legend>
Start container:
<Input type = "text" id = "txtstartcontainer1"/> <br/>
Start offset:
<Input type = "text" id = "txtstartoffset1"/> <br/>
End container:
<Input type = "text" id = "txtendcontainer1"/> <br/>
End offset:
<Input type = "text" id = "txtendoffset1"/> <br/>
Common Ancestor:
<Input type = "text" id = "txtcommonancestor1"/> <br/>
</Fieldset>
</TD>
<TD>
<Fieldset>
<Legend> orange2 </legend>
Start container:
<Input type = "text" id = "txtstartcontainer2"/> <br/>
Start offset:
<Input type = "text" id = "txtstartoffset2"/> <br/>
End container:
<Input type = "text" id = "txtendcontainer2"/> <br/>
End offset:
<Input type = "text" id = "txtendoffset2"/> <br/>
Common Ancestor:
<Input type = "text" id = "txtcommonancestor2"/> <br/>
</Fieldset>
</TD>
</Tr>
</Table>
</Body>
</Html>

The above code will not be commented out. If you have any questions, leave a message in the comment.

There are other methods in range:
Setstartbefore (node)-set the starting position of the range relative to the node Node
Setstartafter (node)-Same as above
Setendbefore-set the end position of the range relative to the node Node
Setendafter-Same as above

Complex Dom range

To create a complex Dom range, you must use the setstart () and setend () methods. These two methods have two parameters: one is a node reference and the other is an offset ).
The reference of the setstart method node is startcontainer, And the offset is startoffset;
When setend () is used, the node reference is endcontainer, And the offset is endoffset.

The two methods are similar to the selectnode () and selectnodecontents () methods. For example, in the previous example of the following useranges () function, you can use setstart () and setend ():

Function useranges (){
VaR Orange1 = Document. createRange ();
VaR orange2 = Document. createRange ();
VaR OP1 = Document. getelementbyid ("p1 ");
VaR ip1index =-1;
For (VAR I = 0; I <op1.parentnode. childnodes. length; I ++ ){
If (op1.parentnode. childnodes [I] = OP1 ){
Ip1index = I;
Break;
}
}

Orange1.setstart (op1.parentnode, ip1index );
Orange1.setend (op1.parentnode, ip1index + 1 );
Orange2.setstart (OP1, 0 );
Orange2.setend (OP1, op1.childnodes. Length );
// Textbox assignments here
}

Note the code (Orange1) when selecting a node. You must specify an index for all the childnodes sets in the parent node of OP1.

The Code (orange2) when selecting content does not require additional consideration,

From the example above, we can use this section of HTML (Code <p id = "p1"> <B> Hello </B> world </P>)
Select the range from llo in hello to start from Wo in world. We can use setstart () and setend () to easily do this.

First, we must use the conventional DOM method to get the reference of the text node and the reference of container P1.

VaR OP1 = Document. getelementbyid ("p1 ");
VaR ohello = op1.firstchild. firstchild;
VaR oworld = op1.lastchild;

Note:
The text hello is actually the child node of container P1, so we can use op1.firstchild to get the <B> element, op1.firstchild. firstchild is the reference of the hello text node, while world is the last node of container P1.

Next, create a range and set the offset ):

VaR OP1 = Document. getelementbyid ("p1 ");
VaR ohello = op1.firstchild. firstchild;
VaR oworld = op1.lastchild;
VaR Orange = Document. createRange ();
Orange. setstart (ohello, 2 );
Orange. setend (oworld, 3 );

Note:
For setstart (), the offset is 2, because the position of the letter L in the text node (that is, in Hello) is 2 (the position is calculated from 0 ), set the offset of the setend () method to 3. The reason is the same as above. Note that there is a space in front of world, and spaces are also occupied.

Note:
(Mozilla Dom range bug #135928) when executing this range method in earlier Mozilla browsers, if both setstart () and setend () point to the same text node, an exception will occur.

Do some operations with Dom range
When you create a range object, a fragment node of the document has been created on top of all objects in the range. Before that, the range object must pass the certificate that the range you selected is a well-formed (in good format ).
For example, the range

Obviously, here, it is not a well-formed. As mentioned above, when a range is created, a fragment is automatically generated. Here, framgment automatically and dynamically adds some elements to ensure the correctness of the range:

<P> <B> he </B> <B> llo </B> world </P>

That is, the start label <B> is automatically added to change the entire range to <B> llo </B> WO. The fragment is:

After this fragment is created, you can use the range method to operate it.

The simplest operation is the deletecontents () method. This method will delete the selected part of the range and perform deletecontents () after the preceding operation. The remaining HTML will be:

<P> <B> he </B> RLD </P>

The reason for adding a closed tag </B> is that range is also used to ensure that it is well-formed.

Extractcontents ()
The method is similar to deletecontents (), but the specific operation is different, extractcontents () is to move the selected range from the DOM tree to
Fragment, and return this fragment. Copy the following code and
Run in Firefox and you will understand the result. -- Delete <B> llo </B>
Wo is added to the end of the body as a fragment.

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
VaR OP1 = Document. getelementbyid ("p1 ");
VaR ohello = op1.firstchild. firstchild;
VaR oworld = op1.lastchild;
VaR Orange = Document. createRange ();
Orange. setstart (ohello, 2 );
Orange. setend (oworld, 3 );
VaR ofragment = Orange. extractcontents ();
Document. Body. appendchild (ofragment );
</SCRIPT>

The clonecontents () method can clone the fragment of the selected range, for example:

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
VaR OP1 = Document. getelementbyid ("p1 ");
VaR ohello = op1.firstchild. firstchild;
VaR oworld = op1.lastchild;
VaR Orange = Document. createRange ();
Orange. setstart (ohello, 2 );
Orange. setend (oworld, 3 );
VaR ofragment = Orange. clonecontents ();
Document. Body. appendchild (ofragment );
</SCRIPT>

This method is similar to extractcontents (), but instead of deleting, It is cloned.

Insert some data from Range

The methods in the previous section solve how to remove the selected fragment from the range. This section describes how to add content to the range.
The insertnode () method inserts a node into the range. What if I want to insert the following nodes into the range field?
<Span style = "color: Red"> inserted text </span>

See the following code:

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
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 );
</SCRIPT>

Then the original HTML will become like this:
<P id = "p1"> <B> he <span style = "color: Red"> inserted text </span> llo </B> world </P>

The surroundcontents () parameter is a node that adds the node to the range. The following is an example.

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
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 );
</SCRIPT>

There is a new node span in the range selected by orange, so the background of the selected range turns yellow.

Collapse () method:

The collapse () method has only one Boolean parameter. this parameter is optional. That is, it can be, or not. The default value is false.
If it is true, it is folded to the header of the range boundary. If it is false, it is folded to the end of the range. That is

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
VaR OP1 = Document. getelementbyid ("p1 ");
VaR ohello = op1.firstchild. firstchild;
VaR oworld = op1.lastchild;
VaR Orange = Document. createRange ();
Orange. setstart (ohello, 2 );
Orange. setend (oworld, 3 );
Orange. Collapse (true );
</SCRIPT>

If you want to know whether the range has been folded, you can use the collapsed attribute to get true or false. Let's look at the example below.

<P id = "p1"> paragraph 1 </P> <p id = "p2"> paragraph 2 </P>
<SCRIPT>
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"
</SCRIPT>

The above code is set to true. Although we didn't use the collapse method, because our range settings start from 1 to the first end of P2, there is no element. That is, </P> (start of range) (end of range) <p id = "p2">, so true is displayed.

Comparison of range Boundary

The format of the compareboundarypoints () method is as follows:
Compare = comparerange. compareboundarypoints (how, sourcerange)

Parameter description:
Compare -- returns 1, 0,-1. (0 is equal, 1 is used, comparerange is after sourcerange,-1 is comparerange before sourcerange)
How -- For the range constant: end_to_end | end_to_start | start_to_end | start_to_start
Sourcerange -- the boundary of a range object.

See the following example:

<P id = "p1"> <B> Hello </B> world </P>
<SCRIPT>
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;
</SCRIPT>

For these two ranges, the results can be clearly analyzed based on the Code and the above description.

Clone range

This operation is simple. You only need one statement:

VaR onewrange = Orange. clonerange ();

The clonerange () method returns a copy of the current range. Of course, it is also a Range object.

Clear system resources occupied by range

When you create a range object, you 'd better use the detach () method to clear the system resources it occupies. GC (Garbage Collector) collects garbage collection, but releasing with detach () is a good habit. Syntax:

Orange. Detach ();

The following example uses range in Mozilla to simulate the element. insertadjacenthtml () method in IE,

If (browser. ismozilla ){
Htmlelement. Prototype. insertadjacenthtml = function (swhere, shtml ){
VaR DF; var r = This. ownerdocument. createRange ();
Switch (string (swhere). tolowercase ()){
Case "beforebegin ":
R. setstartbefore (this );
DF = R. createcontextualfragment (shtml );
This. parentnode. insertbefore (DF, this );
Break;
Case "afterbegin ":
R. selectnodecontents (this );
R. Collapse (true );
DF = R. createcontextualfragment (shtml );
This. insertbefore (DF, this. firstchild );
Break;
Case "beforeend ":
R. selectnodecontents (this );
R. Collapse (false );
DF = R. createcontextualfragment (shtml );
This. appendchild (DF );
Break;
Case "afterend ":
R. setstartafter (this );
DF = R. createcontextualfragment (shtml );
This. parentnode. insertbefore (DF, this. nextsibling );
Break;
}
};
}

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.