Javascript标准DOM Range操作全集_基础知识
2级DOM定义了一个createRange()方法,如果是按照DOM此标准的浏览器(IE并不是支持此标准的,但是IE里的属性或方法却远比标准中定义的多得多),它属于document对象,所以创建一个range对象要这样做:
var oRange = document.createRange();
如果你要检测你的浏览器是否支持此标准Range对象,可以用hasFeature()方法来检测:
var supportsDOMRanges = document.implementation.hasFeature("Range", "2.0");
if (supportsDOMRange) {
var oRange = document.createRange();
//range code here
}
Range对象进行简单的选择
最简单用Range进行选择,用selectNode()或者selectNodeContents()方法,这两个方法只有一个接收参数,一个DOM节点。
selectNode()方法选择全部节点,包括它的孩子,而selectNodeContents()选择的节点只是它的孩子。如
Hello World
<script><br>var oRange1 = document.createRange();<br>var oRange2 = document.createRange();<br>var oP1 = document.getElementById("p1");<br>oRange1.selectNode(oP1);<br>oRange2.selectNodeContents(oP1);<br></script>
oRange1和oRange2包含上面所说的两种方法,但是看了下面的示图相信你能很快明白这两个方法的区别:
当你创建了一个Range对象时,Range实例就会有以下的属性:
startContainer — 返回range对象从何开始的节点对象(父节点的第一个节点)
startOffset — 返回Range开始的偏移量(offset),如果startContainer是一个文本节点,注释节点,或者是CDATA节点,这个属性返回文本的偏移量,否则返回第一个节点的索引。
endCOntainer — 返回Range对象最后一个节点对象(父节点的最后一个节点)
endOffset — 返回Range结束时的偏移量(offset)特性与startOffset相同。
commonAncestorContainer — 返回第一个包含该Range对象的节点。
注:这些属性均为只读属性(read-only),startOffset和endOffset将在下文中有较详细的解释。
下面这段代码将说明这些属性,请在Mozilla firefox里运行(支持此标准的浏览器——DOM2级,IE里将无效):
Hello World
上面的代码将不作注释了,有什么问题,在评论中留言。
Range中还有一些其它的方法:
setStartBefore(node) — 设置Range的相对于node节点的起始位置
setStartAfter(node) — 同上
setEndBefore — 设置Range的相对于node节点的结束位置
setEndAfter — 同上
复杂的DOM Range
建立复杂的DOM range需要使用setStart()和setEnd()两个方法,这两个方法有两个参数:一个是一个节点(node)引用和一个偏移(offset)。
setStart方法节点的引用是startContainer,偏移则是startOffset;
setEnd()方法时,节点引用为endContainer,偏移就是endOffset。
使用这两个方法与selectNode()和selectNodeContents()方法相似。比如,下面的useRanges()函数的前一个示例,可以使用setStart()和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
}
注意这个选择节点时的代码(oRange1),你必须指定oP1父节点里所有childNodes集合里的一个索引。
而选择内容时的代码(oRange2),则不需要额外的考虑,
从刚才的例子来从这段HTML里(code
Hello World
)选择从hello中的llo开始到从World中的Wo开始的Range,我们用setStart()和setEnd(),很容易就可以做到。
首先,我们必须用常规的DOM方法得到文本节点的引用还有就是容器p1的引用。
var oP1 = document.getElementById("p1");
var oHello = oP1.firstChild.firstChild;
var oWorld = oP1.lastChild;
说明:
文本Hello实际上是容器p1的孙子节点,所以我们可以用oP1.firstChild得到元素,oP1.firstChild.firstChild也就是Hello文本节点的引用了,而World则就是容器p1的最后一个节点了。
下一步,建立range然后设置偏移(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);
说明:
对于setStart(),偏移(offset)为2,因为字母l在该文本节点中(即Hello中)的位置是2,(位置是从0开始计算的),设置setEnd()方法中的偏移为3,原因同上,需要注意的是World前面有一个空格,空格也是占位置的。如图:
注意:
(Mozilla DOM Range bug #135928)在 Mozilla低版本浏览器 执行此Range方法时,如果setStart()和setEnd()都指向同一个文本节点会出现异常
用DOM Range做一些操作
当创建一个Range对象时,在Range里的所有对象之上,已经创建了一个文档的fragment节点。在这之前,Range对象必须合格证你选择的这段Range是一个well-formed(格式良好)。
比如以面这段Range
很明显的,在这里,并不是一个well-formed,上面说过了,当创建一个Range时,会自动产生一个fragment,在这里,framgment自动动态的添加一些元素,以保证Range的正确性:
Hello World
也就是自动加上了开始标签,使得整个Range变为llo Wo,fragment的示意图为:
当此fragment创建后,你就可以用Range的一些方法来操作它了。
最简单的一个操作就是:deleteContents()方法,这个方法将删除Range选中的部分,在上面的操作之后进行deleteContents(),那么余下的HTML就为:
Herld
之所以加上闭合标签,上面也说了,也是Range为了确保它是well-formed。
extractContents()方法类似于deleteContents(),但具体操作不同,extractContents()是将选中的Range从DOM树中移到一个fragment中,并返回此fragment,复制下面这些代码然后在Mozilla Firefox里运行,看看结果你就明白了。——删除的llo Wo作为一个fragment被添加到body的末端。
Hello World
<script><br>var oP1 = document.getElementById("p1");<br>var oHello = oP1.firstChild.firstChild;<br>var oWorld = oP1.lastChild;<br>var oRange = document.createRange();<br>oRange.setStart(oHello, 2);<br>oRange.setEnd(oWorld, 3);<br>var oFragment = oRange.extractContents();<br>document.body.appendChild(oFragment);<br></script>
cloneContents()方法可以克隆选中Range的fragment,比如:
Hello World
<script><br>var oP1 = document.getElementById("p1");<br>var oHello = oP1.firstChild.firstChild;<br>var oWorld = oP1.lastChild;<br>var oRange = document.createRange();<br>oRange.setStart(oHello, 2);<br>oRange.setEnd(oWorld, 3);<br>var oFragment = oRange.cloneContents();<br>document.body.appendChild(oFragment);<br></script>
这个方法类似于extractContents(),但是不是删除,而是克隆。
从Range中插入一些数据
前一节的几个方法解决了如何移除range中所选中的fragment。现在说明如何添加内容到Range中。
insertNode()方法可以插入一个节点到Range中。假如我想把以下的节点插如Range中,将如何操作呢?
Inserted text
看下面的代码:
Hello World
<script><br>var oP1 = document.getElementById("p1");<br>var oHello = oP1.firstChild.firstChild;<br>var oWorld = oP1.lastChild;<br>var oRange = document.createRange();<br>var oSpan = document.createElement("span");<br>oSpan.style.color = "red";<br>oSpan.appendChild(document.createTextNode("Inserted text"));<br><br>oRange.setStart(oHello, 2);<br>oRange.setEnd(oWorld, 3);<br>oRange.insertNode(oSpan);<br></script>
那么原来的HTML将会变成这样:
HeInserted textllo World
surroundContents()的参数为一个node,它将这个node加入到Range,下面看这个示例。
Hello World
<script><br>var oP1 = document.getElementById("p1");<br>var oHello = oP1.firstChild.firstChild;<br>var oWorld = oP1.lastChild;<br>var oRange = document.createRange();<br>var oSpan = document.createElement("span");<br>oSpan.style.backgroundColor = "yellow";<br><br>oRange.setStart(oHello, 2);<br>oRange.setEnd(oWorld, 3);<br>oRange.surroundContents(oSpan);<br></script>
在oRange选取的范围内有一个我们新生成的节点span,因此选取的Range的背景变成了黄色。
collapse()方法:
collapse()方法只有一个布尔型的参数,该参数为可选的,也就是说,可以有,也可以没有,默认为false。
true时折叠到Range边界的首部,为false时折叠到Range尾部。即
Hello World
<script><br>var oP1 = document.getElementById("p1");<br>var oHello = oP1.firstChild.firstChild;<br>var oWorld = oP1.lastChild;<br>var oRange = document.createRange();<br>oRange.setStart(oHello, 2);<br>oRange.setEnd(oWorld, 3);<br>oRange.collapse(true); <br></script>
如果你想知道该Range是否已经折叠,可以用collapsed属性来得到true或者false。看下面的例子。
Paragraph 1
Paragraph 2
<script><br>var oP1 = document.getElementById("p1");<br>var oP2 = document.getElementById("p2");<br>var oRange = document.createRange();<br>oRange.setStartAfter(oP1);<br>oRange.setStartBefore(oP2);<br>alert(oRange.collapsed); //outputs "true"<br></script>
上面的代码输为true。虽然我们没有用collapse方法,但是由于我们的Range设置开始为1末端到p2的首端,没有任何元素。即
(Range开始)(Range结束),所以显示的是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对象的边界。
看下面的例子:
Hello World
<script><br>var oRange1 = document.createRange();<br>var oRange2 = document.createRange();<br>var oP1 = document.getElementById("p1");<br>oRange1.selectNodeContents(oP1);<br>oRange2.selectNodeContents(oP1);<br>oRange2.setEndBefore(oP1.lastChild);<br>alert(oRange1.compareBoundaryPoints(Range.START_TO_START, oRange2)); <br>//outputs 0<br>alert(oRange1.compareBoundaryPoints(Range.END_TO_END, oRange2)); <br>//outputs 1;<br></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;
}
};
}

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

本文系列在2017年中期进行了最新信息和新示例。 在此JSON示例中,我们将研究如何使用JSON格式将简单值存储在文件中。 使用键值对符号,我们可以存储任何类型的

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可

jQuery是一个很棒的JavaScript框架。但是,与任何图书馆一样,有时有必要在引擎盖下发现发生了什么。也许是因为您正在追踪一个错误,或者只是对jQuery如何实现特定UI感到好奇

该帖子编写了有用的作弊表,参考指南,快速食谱以及用于Android,BlackBerry和iPhone应用程序开发的代码片段。 没有开发人员应该没有他们! 触摸手势参考指南(PDF) Desig的宝贵资源
