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脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

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

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。
