Javascript 标准 DOM Range 操作 (3)

从 Range 中插入一些数据

前一节的几个方法解决了如何移除 Range 中所选中的 fragment 。 现在来看, insertNode() 方法可以插入一个节点到 Range 中。

假如我想把以下的节点插如 Range 中,将如何操作呢?

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

看下面的代码:

<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>

那么原来的 HTML 将会变成这样:

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

surroundContents() 的参数为一个 node ,它将这个 node 加入到 Range 里,看这个示例:

<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>

在 「 oRange 」 选取的范围内有一个我们新生成的节点 「 span 」,因此选取的 Range 的背景变成了黄色。

collapse() 方法

collapse() 方法只有一个布尔型的参数,该参数为可选的,默认为 false 。
为 true 时折叠到 Range 边界的首部,为 false 时折叠到 Range 尾部。

<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>

如果你想知道该 Range 是否已经折叠,可以用 collapsed 属性来得到 true 或者 false 。
示例:

<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>

上面的代码输为 true 。

虽然我们没有用 collapse 方法,但是由于我们的 Range 设置开始为 1 末端到 p2 的首端,没有任何元素。即</p>(Range 开始 )(Range 结束 )<p id="p2">,所以显示的是 true 。

Range 边界的比较

compareBoundaryPoints() 方法,语法:

compare = comparerange.compareBoundaryPoints(how,sourceRange)

参数含义:

  • compare —— 返回 1, 0, -1 。
    • 0 为相等。
    • 1 为 comparerange 在 sourceRange 之后。
    • -1 为 comparerange 在 sourceRange 之前。
  • how —— 为 Range 常数:
    • END_TO_END
    • END_TO_START
    • START_TO_END
    • START_TO_START
  • sourceRange —— 一个 Range 对象的边界。

看下面的例子:

<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>

下图为这两个 Range 的示意图,结合代码和上面的说明,可以清晰的分析出结果了。

克隆 (clone)Range

这个操作很简单,只需要一句语句即可:

var oNewRange = oRange.cloneRange();

cloneRange() 方法将返回一个当前 Range 的副本。当然,它也是 Range 对象。

清除 Range 所占的系统资源

当你创建了 Range 对象最好用 detach() 方法来清除它所占的系统资源。
虽然不清除, GC (垃圾收集器)也会将其收集,但用 detach() 释放是一个好习惯。

语法为:

oRange.detach();

下面一个示例在 Mozilla 中,利用 Range 可以模拟出 IE 中的 element.insertAdjacentHTML() 方法,

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;
		 }
	 };
}

参考文档:

  • Professional JavaScript for Web Developers(Wrox)
  • Mozilla Develop Center Document

-- EOF --

Comments