DOM2级在Document类型中定义了createRange()方法。在兼容DOM浏览器的浏览器中,这个方法属于document对象。使用hasFeature()或者直接检测该方法,都可以确定浏览器是否支持范围
var supportRange=document.implementation.hasFeature("Range","2.0");
如果浏览器支持范围,那么就可以使用createRange()来创建Dom范围
var range=document.createRange();新创建的范围直接与创建它的文档关联在一起,不能用于其他文档。每个范围由一个Range类型的实例表示,这个实例拥有很多属性和方法
startContainer:包含范围起点的几点(即选区中第一个节点的父节点)
startOffset:范围在startOffset中起点的偏移量。如果startContainer是文本节点、注释节点或CDATA节点,那么startOffset就是范围起点之前跳过的字符数量。否则,startOffset就是范围中第一个子节点的索引
endContainer:包含范围终点的节点(即选区中最后一个节点的父节点)
endOffset:范围在endContainer中终点的偏移量
1 用DOM实现简单选择
要使用范围来选择文档中的一部分,最简的方式就是使用selectNode()或selectNodeContents(),这两个方法都接受一个参数,即一个DOM节点,然后使用该节点中的信息来填充范围。其中selectNode()方法选择整个节点,包括其子节点;而selectNodeContents()方法则只选择节点的子节点
在调用selectNode时,startContainer、endContainer都等于传入节点的父节点,startOffset属性等于给定节点在其父节点的childNodes集合中的索引。
<body> <span style="white-space:pre"> </span><p id="p">范围</p> <script type="text/javascript"> var p=document.getElementById("p"); var range1=document.createRange(); console.log(range1.startContainer); </script> </body>为了更精细地控制将那些节点包含在范围中,还可以使用下列方法
setStartBefore(refNode):将范围的起点设置在refNode之前,因此refNode就是范围选区中的第一个子节点,同时将startContainer属性设置为refNode.parentNode,将startOffset属性设置为refNode在父节点的childNodes集合中的索引
setStartAfter(refNode):将范围的起点设置在refNode之后,因此refNode就不在范围之内,其下一个同辈节点才是选区中的第一个子节点。同时将startContainer属性设置为refNode.parentNode,将startOffset属性设置为refNode在父节点的childNodes集合中的索引加1
setEndBefore(refNode):将范围的终点设置在refNode之前,,因此refNode就不在范围之内,其上一个同辈节点才是选区中的最后一个子节点,同时将endContainer属性设置为refNode.parentNode,将endOffset属性设置为refNode在父节点的childNodes集合中的索引
setEndAfter(refNode):将范围的终点设置在refNode之后,因此refNode就是范围选区中的最后一个子节点,同时将endContainer属性设置为refNode.parentNode,将endOffset属性设置为refNode在父节点的childNodes集合中的索引加1
2 用DOM范围实现复杂选区
要创建复杂的范围需要使用setStart()和setEnd()方法。这两个方法都接受两个参数:一个参照节点和一个偏移量。对setStart()来说,参照节点会变成startContainer,而偏移量会变成startOffset;对于setEnd(),参照节点会变成endContainer,而偏移量会变成endOffset。
<div id="con" style="height:100px;width:100px;border:1px solid red;"> <p id="p1">hello <b>world</b></p> </div> var p1=document.getElementById("p1"); var helloNode=p1.firstChild; var worldNode=p1.lastChild.firstChild; var range2=document.createRange(); range2.setStart(helloNode,2); range2.setEnd(worldNode,3);在创建范围时,内部会为这个范围创建一个文档片段,范围所属的全部节点都被添加到了这个文档片段中。对于上面的例子,范围经过计算知道选区中缺少一个结束的</b>标签,因此就会在后台动态加载一个该标签。修改后的DOM如下所示
<p>hello <b>wor</b><b>ld</d></p>利用deleteContents()可以从文档中删除范围所包含的内容 range2.deleteContents()
利用insertNode()方法可以向范围选区的开始处插入一个节点。
除了向范围内部插入内容之外,还可以环绕范围插入内容,此时就使用surroundContents()方法,这个方法接受一个参数,即环绕范围内容的节点。
<p id="p">范围</p>
var p=document.getElementById("p"); var pText=p.firstChild; var range1=document.createRange(); range1.selectNode(pText); var span=document.createElement("span"); span.style.backgroundColor="yellow"; range1.surroundContents(span);