JavaScript DOM2和DOM3——“范围”的注意要点

  • A+
所属分类:JavaScript

“DOM2级遍历和范围”模块定义了“范围”接口。通过范围可以选择文档中的一个区域,而不必考虑节点的界限(选择在后台完成,对用户是不可见的)。

DOM中的范围

DOM2级在Document类型中定义了createRange()方法,可以用来创建DOM范围,如下所示:

每个范围由一个Range类型的实例表示,这个实例有很多属性和方法:

  • startContainer:包含范围起点的节点(选区中第一个节点的父节点);
  • startOffset:范围在startContainer中起点的偏移量;
  • endContainer:包含范围终点的节点(选区中最后一个节点的父节点);
  • endOffset:范围在endContainer中终点的偏移量;
  • commonAncestorContainer:startContainer和endContainer共同的祖先节点在文档树中位置最深的那个;

用DOM范围实现简单选择

selectNode()或selectNodeContents()

前者选择整个节点,包括子节点;后者选择节点的子节点。如:

在调用selectNode()时,startContainer、endContainer和commonAncestorContainer等都等于传入节点的父节点,也就是其中的document.body。而startOffset属性等于给定节点在其父节点的childNodes集合中的索引。endOffset等于startOffset加上1;

在调用selectNodeContents()时,startContainer、endContainer和commonAncestorContainer等于传入的节点。而startOffset属性始终等于0.最后,endOffset等于子节点的数量(node.childNodes.length);

更精细的选择

为了更精细的控制将哪些节点包含在范围中,还可以使用下列方法:

  • setStartBefore(refNode):将范围的起点设置在refNode之前;
  • setStartAfter(refNode):将范围的起点设置在refNode之后;
  • setEndBefore(refNode):将范围的终点设置在refNode之前;
  • setEndAfter(refNode):将范围的终点设置在refNode之后;

如下html:

js:

用DOM范围实现更加复杂的选择

setStart()和setEnd()方法

这两个方法都接受两个参数:一个参照节点和一个偏移量值。对前者来说,参照节点会变成startContainer,偏移值则会变成startOffset。对于后者来说,参照节点会变成endContainer,偏移值会变成endOffset。

html:

js:

这样就完成了对“llo wo”的选择,但仅仅完成对该选区的选择意义不大,重要的是对其进行操作。

操作DOM范围中的内容

deleteContents()删除范围所包含的内容

如:

举例:

又如:

举例:

extractContents()移除范围所包含的内容并返回文档片段

如:

举例:

又如:

举例:

cloneContents()创建范围对象的一个副本

如:

插入DOM范围中的内容

insertNode()向范围选区的开始处插入一个节点(范围内部插入内容)

如:

代码:

又如:

代码:

surroundContents()向范围选区周围插入一个节点(围绕范围插入内容)

通常与selectNode()配合,因为范围必须包含整个DOM选区,不能仅仅包含选中的DOM节点。

如:

代码:

为了插入span标签,范围必须包含整个DOM选区,所以推荐使用selectNode()配合。

折叠DOM范围

collapse()方法

折叠就是指范围中未选择文档的任何部分。该函数接收一个参数,一个布尔值。true表示折叠到范围的起点,参数false表示折叠到范围的终点。要确定范围已经折叠完毕,可以检查collapsed属性:

如:

代码:

又如:

代码:

比较DOM范围

comopareBoundaryPoints()方法来比较

该方法涌来比较这些范围是否有公共的边界。接收两个参数:表示比较方式的常量值和要比较的范围。如:

  • Range.START_TO_START - 比较两个 Range 节点的开始点
  • Range.END_TO_END - 比较两个 Range 节点的结束点
  • Range.START_TO_END - 用 sourceRange 的开始点与当前范围的结束点比较
  • Range.END_TO_START - 用 sourceRange 的结束点与当前范围的开始点比较

注意:《高级程序设计》一书中,对后两个的说明太模糊(不正确?);下面是w3school的解释:

您可能认为,首先需要用参数 how 的范围常量指定当前范围的边界点,然后再用它指定 sourceRange 的边界点。但事实上,

  1. 常量 Range.START_TO_END 指定与当前范围的 end 点和 sourceRange 的 start 点进行比较。
  2. 常量 Range.END_TO_START 指定比较当前范围的 start 点和指定范围的 end 点。

如果第一个范围中的点位于第二个范围中的点之前,返回-1;如果相等返回0;如果第一个范围中的点位于第二个范围中的点之后,返回1

如:

代码:

又如:

代码:

复制DOM范围

cloneRange()方法复制范围;

清理DOM范围

detach()方法清理范围;

上面的是从文档中分离范围;下面的是解除引用。

下节再讨论IE8及更早版本中的范围

weinxin
我的微信公众号
我的微信公众号扫一扫

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: