DOM2范围

除了IE,其余主流浏览器都支持DOM2的范围,然而IE用其特有的方式实现了范围特性(但IE9+支持)!

Document类型中定义了createRange(),这个方法属于document对象,首先检测浏览器是否支持他:

1
2
var supportRange=document.implementation.hasFeature('Range','2.0');
var supportRange2=(typeof document.createRange=='function');



这是初步创建范围后在控制台输出的,拿其中较为关键的属性来说

1.startContainer与endContainer他们通常是指向相同元素(前者为选区中第一个元素的父节点,后者为选区中最后一个元素的父节点)

2.startOffset通常等于父节点的childNodes的第一个子节点的索引,在兼容DOM的浏览器中空格算为一个文本节点。
要使用范围选择文档中的一部分,可以使用selectNode()和selectNodeContents(),他们都接收一个参数,即范围的起点,前者选择自身与子,后者只选择子。
为了更精确更方便地控制范围引入了一些更为方便的方法,如下:

1
2
3
4
setStartBefore(refNode) =>  将范围设置在refNode之前,即refNode是范围开始的第一个子节点,所以startContainer就是refNode的父节点
setStartAfter(refNode) => 将范围设置在refNode之后,即refNode的下一个同辈节点才是选区的第一个子节点,所以refNode不在范围之内
setEndBefore(refNode) => 将范围的终点设置在refNode之前,即refNode的上一个同辈节点是选区的最后一个子节点,所以refNode不在范围之内
setEndAfter(refNode) => 将范围的终点设置在refNode之后,即refNode是选区的最后一个子节点,所以refNode在范围之内

复杂操作:

1
2
setStart(node, offset) => 设置起点的位置,node是对startContainer的引用,偏移则是startOffset
setEnd(node, offset => 设置结束点的位置,node是对endContainer的引用,偏移则是startOffset



这段代码最后剩下Herld 虽然把范围内的文本删了,但是DOM结构仍然不会变。

与deleteContents()类似的方法有extractContents(),但后者这个方法会返回选区的内容,因此可以利用他来插入到页面的其他位置。

cloneContents()这个方法,如果只是要创建一个范围的副本而不去删除或移除范围的内容可以用他,语法名称代表用法,即克隆内容。
插入DOM范围中的内容:使用insertNode()方法可以在范围选区开始处插入一个节点。


在使用完范围之后,最好调用detach()方法,清理范围,回收内存,一旦分离了范围就不能再使用了。

1
2
range.detach();     // 从文档中分离
range=null; // 解除引用

/===========接下来说IE8及更低版本中的DOM范围=============/

准确来说IE高版本以及低版本都支持文本范围,是IE独有的特性,其他浏览器不支持,语法名称代表用法,所以主要用于文本。


选择某一区域用方法findText(),他会找到第一次出现的文本,然而他第二个参数如果为负值就会找最后一个匹配成功的文本,正值就会找到第一个匹配成功的文本,这也就说明了图中为什么找到hELLO而不是另外两个的原因了!

当中的变量found只要在匹配到文本时就会返回true,匹配不区分大小写在某些操作上也许会带来方便,可以用属性text,来获取范围选中的文本。

DOM范围有selectNode()而IE中有=>moveToElementText() =>这个方法接收一个DOM元素,并选择该元素的所有文本,包括HTML标签。如果在范围选区中包含HTML标签可以用属性htmlText读取范围全部内容。

属性text可以读取文本也可以修改文本,如下:



可见hELLO的部分已经被替代成hello,但标签没有被替代,如果想把标签替换掉可以用pasteHTML(),例如:range1.pasteHTML(‘hello‘);
但是上述做法会引起冲突,不提倡!

IE中使用方法duplicate()复制文本范围,如同cloneContents(),新创建的范围带有原范围相同的属性。例:var range=range.duplicate();