溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Javascript中DOM范圍的示例分析

發(fā)布時間:2021-07-27 14:47:29 來源:億速云 閱讀:175 作者:小新 欄目:web開發(fā)

這篇文章主要介紹Javascript中DOM范圍的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

創(chuàng)建范圍

Document類型中定義了createRange()方法。在兼容DOM的瀏覽器中,這個方法屬于document對象。使用hasFeature()或者直接檢測該方法,都可以確定瀏覽器是否支持范圍

[注意]IE8-瀏覽器不支持

var supportsRange = document.implementation.hasFeature("Range", "2.0");
var alsoSupportsRange =(typeof document.createRange == "function");

如果瀏覽器支持范圍,那么就可以使用createRange()來創(chuàng)建DOM范圍,如下所示

var range = document.createRange();

與節(jié)點類似,新創(chuàng)建的范圍也直接與創(chuàng)建它的文檔關聯(lián)在一起,不能用于其他文檔。創(chuàng)建了范圍之后,接下來就可以使用它在后臺選擇文檔中的特定部分。而創(chuàng)建范圍并設置了其位置之后,還可以針對范圍的內(nèi)容執(zhí)行很多種操作,從而實現(xiàn)對底層DOM樹的更精細的控制

每個范圍由一個Range類型的實例表示,這個實例擁有很多屬性和方法。

下列屬性提供了當前范圍在文檔中的位置信息

  • startContainer:包含范圍起點的節(jié)點(即選區(qū)中第一個節(jié)點的父節(jié)點)

  • startoffset:范圍在startContainer中起點的偏移量。如果startContainer是文本節(jié)點、注釋節(jié)點或CDATA節(jié)點,那么startoffset就是范圍起點之前跳過的字符數(shù)量。否則,startoffset就是范圍中第一個子節(jié)點的索引

  • endContainer:包含范圍終點的節(jié)點(即選區(qū)中最后一個節(jié)點的父節(jié)點)

  • endOffset:范圍在endContainer中終點的偏移量(與startoffset遵循相同的取值規(guī)則)

  • commonAncestorContainer:startContainer和endContainer共同的祖先節(jié)點在文檔樹中位置最深的那個

在把范圍放到文檔中特定的位置時,這些屬性都會被賦值

簡單選擇

要使用范圍來選擇文檔中的一部分,最簡單的方式就是使用selectNode()selectNodeContents() 。這兩個方法都接受一個參數(shù),即一個DOM節(jié)點,然后使用該節(jié)點中的信息來填充范圍。其中,selectNode()方法選擇整個節(jié)點,包括其子節(jié)點;而selectNodeContents()方法則只選擇節(jié)點的子節(jié)點

<!DOCTYPE html>
<html>
 <body>
 <p id="p1"><b>Hello</b> world!</p>
 </body>
</html>

我們可以使用下列代碼來創(chuàng)建范圍

var range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById("p1");
//Range {startContainer: body, startOffset: 1, endContainer: body, endOffset: 2, collapsed: false…}
range1.selectNode(p1);
//Range {startContainer: p#p1, startOffset: 0, endContainer: p#p1, endOffset: 2, collapsed: false…}
range2.selectNodeContents(p1);

這里創(chuàng)建的兩個范圍包含文檔中不同的部分:rangl包含<p>元素及其所有子元素,而rang2包含<b>元素、文本節(jié)點"Hello"和文本節(jié)點"world!"

Javascript中DOM范圍的示例分析

在調(diào)用selectNode()時,startContainer、endContainer和commonAncestorContainer都等于傳入節(jié)點的父節(jié)點,也就是這個例子中的document.body。而startoffset屬性等于給定節(jié)點在其父節(jié)點的childNodes集合中的索引(在這個例子中是1——因為兼容DOM的瀏覽器將空格算作一個文本節(jié)點),endOffset等于startoffset加1(因為只選擇了一個節(jié)點)

在調(diào)用selectNodeContents()時,startContainer、endContainer和commonAncestorContainer等于傳入的節(jié)點,即這個例子中的<p>元素。而startoffset屬性始終等于0,因為范圍從給定節(jié)點的第一個子節(jié)點開始。最后,endOffset等于子節(jié)點的數(shù)量(node.childNodes.length),在這個例子中是2

此外,為了更精細地控制將哪些節(jié)點包含在范圍中,還可以使用下列方法

  1. setStartBefore(refNode) :將范圍的起點設置在refNode之前,因此refNode也就是范圍選區(qū)中的第一個子節(jié)點。同時會將startContainer屬性設置為refNode.parentNode,將startoffset屬性設置為refNode在其父節(jié)點的childNodes集合中的索引

  2. setStartAfter(refNode) :將范圍的起點設置在refNode之后,因此refNode也就不在范圍之內(nèi)了,其下一個同輩節(jié)點才是范圍選區(qū)中的第一個子節(jié)點。同時會將startContainer屬性設置為refNode.parentNode,將startoffset屬性設置為refNode在其父節(jié)點的childNodes集合中的索引加1

  3. setEndBefore(refNode) :將范圍的終點設置在refNode之前,因此refNode也就不在范圍之內(nèi)了,其上一個同輩節(jié)點才是范圍選區(qū)中的最后一個子節(jié)點。同時會將endContainer屬性設置為refNode.parentNode,將endOffset屬性設置為refNode在其父節(jié)點的childNodes集合中的索引

  4. setEndAfter(refNode) :將范圍的終點設置在refNode之后,因此refNode也就是范圍選區(qū)中的最后一個子節(jié)點。同時會將endContainer屬性設置為refNode.parentNode,將endOffset屬性設置為refNode在其父節(jié)點的childNodes集合中的索引加1

調(diào)用這些方法時,所有屬性會自動設置好。不過,要想創(chuàng)建復雜的范圍選區(qū),也可以直接指定這些屬性的值

復雜選擇

要創(chuàng)建復雜的范圍就得使用setStart()setEnd()方法。這兩個方法都接受兩個參數(shù):一個參照節(jié)點和一個偏移量值。對setStart()來說,參照節(jié)點會變成startContainer。而偏移量值會變成startoffset。對于setEnd()來說,參照節(jié)點會變成endContainer,而偏移量值會變成endOffset??梢允褂眠@兩個方法來模仿selectNode()selectNodeContents() 。

來看下面的例子

var range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById("p1"); 
var p1Index = -1;
var i, len;
 
for (i=0, len=p1.parentNode.childNodes.length; i < len; i++) {
 if (p1.parentNode.childNodes[i] == p1) {
 p1Index = i;
 break;
 }
}
 
range1.setStart(p1.parentNode, p1Index);
range1.setEnd(p1.parentNode, p1Index + 1);
range2.setStart(p1, 0);
range2.setEnd(p1, p1.childNodes.length);

顯然,要選擇這個節(jié)點(使用range1),就必須確定當前節(jié)點(p1)在其父節(jié)點的childNodes集合中的索引。而要選擇這個節(jié)點的內(nèi)容(使用range2),也不必計算什么;只要通過setStart()和setEnd()設置默認值即可。模仿selectNode()selectNodeContents()并不是setStart()setEnd()的主要用途,它們更勝一籌的地方在于能夠選擇節(jié)點的一部分

假設只想選擇前面HTML示例代碼中從“Hello"的"llo"到"world!"的"o"——很容易做到

第一步是取得所有節(jié)點的引用,如下所示:

var p1 = document.getElementById("p1");
var helloNode = p1.firstChild.firstChild;
var worldNode = p1.lastChild;

實際上,"Hello”文本節(jié)點是<p>元素的孫子節(jié)點,因為它本身是<b>元素的一個子節(jié)點。因此,p1.firstchild取得的是<b>,而p1.firstchild.firstchild取得的才是這個文本節(jié)點。"world!"文本節(jié)點是<p>元素的第二個子節(jié)點(也是最后一個子節(jié)點),因此可以使用p1.lastChild取得該節(jié)點。

然后,必須在創(chuàng)建范圍時指定相應的起點和終點,如下所示

var range = document.createRange();
range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);

因為這個范圍的選區(qū)應該從"Hello"中"e"的后面開始,所以在setStart()中傳入helloNode的同時,傳入了偏移量2(即"e"的下一個位置;"H"的位置是0)。設置選區(qū)的終點時,在setEnd()中傳入worldNode的同時傳入了偏移量3,表示選區(qū)之外的第一個字符的位置,這個字符是”r",它的位置是3(位置0上還有一個空格)。

如下所示

Javascript中DOM范圍的示例分析

由于helloNode和worldNode都是文本節(jié)點,因此它們分別變成了新建范圍的startContainer和endContainer。此時startoffset和endOffset分別用以確定兩個節(jié)點所包含的文本中的位置,而不是用以確定子節(jié)點的位置(就像傳入的參數(shù)為元素節(jié)點時那樣)。此時的commonAncestorContainer是<p>元素,也就是同時包含這兩個節(jié)點的第一個祖先元素

當然,僅僅是選擇了文檔中的某一部分用處并不大。但重要的是,選擇之后才可以對選區(qū)進行操作

操作范圍內(nèi)容

在創(chuàng)建范圍時,內(nèi)部會為這個范圍創(chuàng)建一個文檔片段,范圍所屬的全部節(jié)點都被添加到了這個文檔片段中。為了創(chuàng)建這個文檔片段,范圍內(nèi)容的格式必須正確有效。在前面的例子中,創(chuàng)建的選區(qū)分別開始和結束于兩個文本節(jié)點的內(nèi)部,因此不能算是格式良好的DOM結構,也就無法通過DOM來表示。但是,范圍知道自身缺少哪些開標簽和閉標簽,它能夠重新構建有效的DOM結構以便對其進行操作

對于前面的例子而言,范圍經(jīng)過計算知道選區(qū)中缺少一個開始的<b>標簽,因此就會在后臺動態(tài)加入一個該標簽,同時還會在前面加入一個表示結束的</b>標簽以結束"He"。于是,修改后的DOM就變成了如下所示

<p><b>He</b><b>llo</b> world!</p>

另外,文本節(jié)點"world!"也被拆分為兩個文本節(jié)點,一個包含"wo",另一個包含"rid!"。最終的DOM樹下圖所示,右側是表示范圍的文檔片段的內(nèi)容

Javascript中DOM范圍的示例分析

像這樣創(chuàng)建了范圍之后,就可以使用各種方法對范圍的內(nèi)容進行操作了

[注意]表示范圍的內(nèi)部文檔片段中的所有節(jié)點,都只是指向文檔中相應節(jié)點的指針

【deleteContents()】

操作范圍內(nèi)容的第一個方法是deleteContents() ,這個方法能夠從文檔中刪除范圍所包含的內(nèi)容

var p1 = document.getElementById("p1");
var helloNode = p1.firstChild.firstChild;
var worldNode = p1.lastChild;
var range = document.createRange();

range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);
range.deleteContents();

執(zhí)行以上代碼后,頁面中會顯示如下HTML代碼

<p><b>He</b>rld!</p>

由于范圍選區(qū)在修改底層DOM結構時能夠保證格式良好,因此即使內(nèi)容被刪除了,最終的DOM結構依舊是格式良好的

【extractContents()】

deleteContents()方法相似,extractContents()方法也會從文檔中移除范圍選區(qū)。但區(qū)別在于,extractContents()會返回范圍的文檔片段。利用這個返回的值,可以將范圍的內(nèi)容插入到文檔中的其他地方。如下所示:

var p1 = document.getElementById("p1");
var helloNode = p1.firstChild.firstChild;
var worldNode = p1.lastChild;
var range = document.createRange();

range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);

var fragment = range.extractContents();
p1.parentNode.appendChild(fragment);

在這個例子中,將提取出來的文檔片段添加到了文檔<body>元素的末尾

[注意]在將文檔片段傳入appendChild()方法中時,添加到文檔中的只是片段的子節(jié)點,而非片段本身

<p><b>He</b>rld!</p>
<b>llo</b> wo

【cloneContents】

還有一種做法是使用cloneContents()創(chuàng)建范圍對象的一個副本,然后在文檔其他地方插入該副本

var p1 = document.getElementById("p1");
var helloNode = p1.firstChild.firstChild;
var worldNode = p1.lastChild;
var range = document.createRange();

range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);

var fragment = range.cloneContents();
p1.parentNode.appendChild(fragment);

這個方法與extractContents()非常類似,因為它們都返回文檔片段。它們的主要區(qū)別在于,cloneContents()返回的文檔片段包含的是范圍中節(jié)點的副本,而不是實際的節(jié)點。執(zhí)行上面的操作后,頁面中的HTML代碼如下所示:

<p><b>Hello</b> world!</p>
<b>llo</b> wo

[注意]在調(diào)用cloneContents()方法之前,拆分的節(jié)點并不會產(chǎn)生格式良好的文檔片段。換句話說,原始的HTML在DOM被修改之前會始終保持不變

插入范圍內(nèi)容

利用范圍,可以刪除或復制內(nèi)容,還可以像前面介紹的那樣操作范圍中的內(nèi)容。使用insertNode()方法可以向范圍選區(qū)的開始處插入一個節(jié)點。假設在前面例子中的HTML前面插入以下HTML代碼

<span >Inserted text</span>

那么可以使用下列代碼:

var p1 = document.getElementById("p1");
var helloNode = p1.firstChild.firstChild;
var worldNode = p1.lastChild;
var range = document.createRange();
var span = document.createElement("span");

range.setStart(helloNode, 2);
range.setEnd(worldNode, 3);

span.style.color = "red";
span.appendChild(document.createTextNode("Inserted text"));
range.insertNode(span);

運行以上javascript代碼,就會得到如下HTML代碼

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

[注意]<span>正好被插入到了"Hello"中的"llo"前面,而該位置就是范圍選區(qū)的開始位置。使用這種技術可以插入一些幫助提示信息,例如在打開新窗口的鏈接旁邊插入一幅圖像

【surroundContents()】

除了向范圍內(nèi)部插入內(nèi)容之外,還可以環(huán)繞范圍插入內(nèi)容,此時就要使用surroundContents()方法。這個方法接受一個參數(shù),即環(huán)繞范圍內(nèi)容的節(jié)點。在環(huán)繞范圍插入內(nèi)容時,后臺會執(zhí)行下列步驟

  1、提取出范圍中的內(nèi)容(類似執(zhí)行extractContents() )

  2、將給定節(jié)點插入到文檔中原來范圍所在的位置上

  3、將文檔片段的內(nèi)容添加到給定節(jié)點中

可以使用這種技術來突出顯示網(wǎng)頁中的某些詞句,例如下列代碼

var p1 = document.getElementById("p1");
var helloNode = p1.firstChild.firstChild;
var worldNode = p1.lastChild;
var range = document.createRange();

range.selectNode(helloNode);

var span = document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);

以上代碼會給范圍選區(qū)加上一個黃色的背景。得到的HTML代碼如下所示

<p><b><span >Hello</b> world!</p>

為了插入<span>,范圍必須包含整個DOM選區(qū),而不能僅僅包含選中的DOM節(jié)點

折疊范圍

所謂折疊范圍,就是指范圍中未選擇文檔的任何部分??梢杂梦谋究騺砻枋稣郫B范圍的過程。假設文本框中有一行文本,用鼠標選擇了其中一個完整的單詞。然后,單擊鼠標左鍵,選區(qū)消失,而光標則落在了其中兩個字母之間。同樣,在折疊范圍時,其位置會落在文檔中的兩個部分之間,可能是范圍選區(qū)的開始位置,也可能是結束位置。下圖展示了折疊范圍時發(fā)生的情形

Javascript中DOM范圍的示例分析

【collapse()】

使用collapse()方法來折疊范圍,這個方法接受一個參數(shù),該參數(shù)是一個布爾值,表示要折疊到范圍的哪一端。參數(shù)true表示折疊到范圍的起點,參數(shù)false表示折疊到范圍的終點。要確定范圍已經(jīng)折疊完畢,可以檢査collapsed屬性,如下所示:

range.collapse(true);//折疊到起點
console.log(range.collapsed);//輸出true

檢測某個范圍是否處于折疊狀態(tài),可以幫我們確定范圍中的兩個節(jié)點是否緊密相鄰。例如,對于下面的HTML代碼

<p id="p1">Paragraph 1</p><p id="p2">Paragraph 2</p>

如果不知道其實際構成(比如說,這行代碼是動態(tài)生成的),那么可以像下面這樣創(chuàng)建一個范圍

var p1 = document.getElementById("p1");
var p2 = document.getElementById("p2");
var range = document.createRange();

range.setStartAfter(p1);
range.setStartBefore(p2);
console.log(range.collapsed);//輸出true

在這個例子中,新創(chuàng)建的范圍是折疊的,因為p1的后面和p2的前面什么也沒有

比較范圍

【compareBoundaryPoints()】

在有多個范圍的情況下,可以使用compareBoundaryPoints()方法來確定這些范圍是否有公共的邊界(起點或終點)。這個方法接受兩個參數(shù):表示比較方式的常量值和要比較的范圍。表示比較方式的常量值如下所示

  1. Range.START_TO_START(0) :比較第一個范圍和第二個范圍的起點

  2. Range.START_TO_END(1) :比較第一個范圍的起點和第二個范圍的終點

  3. Range.END_TO_END⑵ :比較第一個范圍和第二個范圍的終點

  4. Range.END_T0_START(3) :比較第一個范圍的終點和第一個范圍的起點

compareBoundaryPoints()方法可能的返回值如下:如果第一個范圍中的點位于第二個范圍中的點之前,返回-1;如果兩個點相等,返回0;如果第一個范圍中的點位于第二個范圍中的點之后,返回1。

來看下面的例子

var range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById("p1");

range1.selectNodeContents(p1);
range2.selectNodeContents(p1);
range2.setEndBefore(p1.lastChild);

alert(range1.compareBoundaryPoints(Range.START_TO_START, range2)); //outputs 0
alert(range1.compareBoundaryPoints(Range.END_TO_END, range2)); //outputs 1

在這個例子中,兩個范圍的起點實際上是相同的,因為它們的起點都是由selectNodeContents()方法設置的默認值來指定的。因此,第一次比較返回0。但是,range2的終點由于調(diào)用setEndBefore()已經(jīng)改變了,結果是range1的終點位于range2的終點后面,因此第二次比較返回1

復制范圍

【cloneRange】

可以使用cloneRange()方法復制范圍。這個方法會創(chuàng)建調(diào)用它的范圍的一個副本

var newRange = range.cloneRange();

新創(chuàng)建的范圍與原來的范圍包含相同的屬性,而修改它的端點不會影響原來的范圍

清理范圍

【detach()】

在使用完范圍之后,最好是調(diào)用detach()方法,以便從創(chuàng)建范圍的文檔中分離出該范圍。調(diào)用detach()之后,就可以放心地解除對范圍的引用,從而讓垃圾回收機制回收其內(nèi)存了。來看下面的例子

range.detach();//從文檔中分離
range = null;//解除引用

在使用范圍的最后再執(zhí)行這兩個步驟是推薦的方式。一且分離范圍,就不能再恢復使用了

IE兼容

IE8-瀏覽器不支持DOM范圍。但支持一種類似的概念,即文本范圍(textrange)。文本范圍是IE專有的特性,其他瀏覽器都不支持。顧名思義,文本范圍處理的主要是文本(不一定是DOM節(jié)點)。通過<body>、<button>、<input>和<textarea>等這幾個元素,可以調(diào)用createTextRange()方法來創(chuàng)建文本范圍。以下是一個例子

var range = document.body.createTextRange();

像這樣通過document創(chuàng)建的范圍可以在頁面中的任何地方使用(通過其他元素創(chuàng)建的范圍則只能在相應的元素中使用)。與DOM范圍類似,使用IE文本范圍的方式也有很多種

一、簡單選擇

【findText()】

選擇頁面中某一區(qū)域的最簡單方式,就是使用范圍的findText()方法。這個方法會找到第一次出現(xiàn)的給定文本,并將范圍移過來以環(huán)繞該文本。如果沒有找到文本,這個方法返回false;否則返回true。同樣,仍然以下面的HTML代碼為例

<p id="p1"><b>Hello</b> world!</p>

要選擇"Hello",可以使用下列代碼

var range = document.body.createTextRange();
var found = range.findText("Hello");

執(zhí)行完第二行代碼后,文本"Hello"就被包圍在范圍之內(nèi)了。為此,可以檢査范圍的text屬性來確認(這個屬性返回范圍中包含的文本),或者也可以檢查findText()的返回值——在找到了文本的情況下返回值為true。

例如:

alert(found); //true
alert(range.text); //"Hello"

還可以為findText()傳入另一個參數(shù),即一個表示向哪個方向繼續(xù)搜索的數(shù)值。負值表示應該從當前位置向后搜索,而正值表示應該從當前位置向前搜索。因此,要査找文檔中前兩個"Hello"的實例,應該使用下列代碼

var found = range.findText("Hello");
var foundAgain = range.findText("Hello", 1);

【moveToElementText()】

IE中與DOM中的selectNode()方法最接近的方法是moveToElementText() ,這個方法接受一個DOM元素,并選擇該元素的所有文本,包括HTML標簽。下面是一個例子

var range = document.body.createTextRange();
var p1 = document.getElementById("p1")
range.moveToElementText(p1);

在文本范圍中包含HTML的情況下,可以使用htmlText屬性取得范圍的全部內(nèi)容,包括HTML和文本,如下所示

alert(range.htmlText);

IE的范圍沒有任何屬性可以隨著范圍選區(qū)的變化而動態(tài)更新。不過,parentElement()方法倒是與DOM的 commonAncestorContainer屬性類似

var ancestor = range.parentElement();

這樣得到的父元素始終都可以反映文本選區(qū)的父節(jié)點

二、復雜選擇

在IE中創(chuàng)建復雜范圍的方法,就是以特定的增量向四周移動范圍。為此,IE提供了4個方法:move() 、moveStart() 、moveEnd()expand() 。這些方法都接受兩個參數(shù):移動單位和移動單位的數(shù)量。

其中,移動單位是下列一種字符串值

  1. "character":逐個字符地移動

  2. "word":逐個單詞(一系列非空格字符)地移動

  3. "sentence":逐個句子(一系列以句號、問號或嘆號結尾的字符)地移動

  4. "textedit":移動到當前范圍選區(qū)的開始或結束位置

通過moveStart()方法可以移動范圍的起點,通過moveEnd()方法可以移動范圍的終點,移動的幅度由單位數(shù)量指定,如下所示

range.moveStart("word", 2);//起點移動2個單詞
range.moveEnd("character", 1);//終點移動1個字符

使用expand()方法可以將范圍規(guī)范化。換句話說,expand()方法的作用是將任何部分選擇的文本全部選中。例如,當前選擇的是一個單詞中間的兩個字符,調(diào)用expand("word")可以將整個單詞都包含在范圍之內(nèi)

而move()方法則首先會折疊當前范圍(讓起點和終點相等),然后再將范圍移動指定的單位數(shù)量,如下所示

range.move("character", 5);//移動5個字符

調(diào)用move()之后,范圍的起點和終點相同,因此必須再使用moveStart()moveEnd()創(chuàng)建新的選區(qū)

三、操作范圍內(nèi)容

在IE中操作范圍中的內(nèi)容可以使用text屬性或pasteHTML()方法。如前所述,通過text屬性可以取得范圍中的內(nèi)容文本;但是,也可以通過這個屬性設置范圍中的內(nèi)容文本。來看一個例子

var range = document.body.createTextRange();
range.findText("Hello");
range.text = "Howdy";

如果仍以前面的Hello World代碼為例,執(zhí)行以上代碼后的HTML代碼如下

<p id="p1"><b>Howdy</b> world!</p>

[注意]在設置text屬性的情況下,HTML標簽保持不變

【pasteHTML()】

要向范圍中插入HTML代碼,就得使用pasteHTML()方法,如下所示

var range = document.body.createTextRange();
range.findText("Hello");
range.pasteHTML("<em>Howdy</em>");

執(zhí)行這些代碼后,會得到如下HTML

<p id="p1"><b><em>Howdy</em></b> world!</p>

不過,在范圍中包含HTML代碼時,不應該使用pasteHTML() ,因為這樣很容易導致不可預料的結果——很可能是格式不正確的HTML

四、折疊IE范圍

【collapse()】

IE為范圍提供的collapse()方法與相應的DOM方法用法一樣:傳入true把范圍折疊到起點,傳入false把范圍折疊到終點。例如:

range.collapse(true); //折疊到起點

可惜的是,沒有對應的collapsed屬性讓我們知道范圍是否已經(jīng)折疊完畢。為此,必須使用boundingWidth屬性,該屬性返回范圍的寬度(以像素為單位)。如果boundingwidth屬性等于0,就說明范圍已經(jīng)折疊了

var isCollapsed = (range.boundingWidth == 0);

此外,還有boundingHeight、boundingLeft和boundingTop等屬性,雖然它們都不像boundingWidth那么有用,但也可以提供一些有關范圍位置的信息

五、比較IE范圍

【compareEndPoints()】

IE中的compareEndPoints()方法與DOM范圍的compareBoundaryPoints()方法類似。這個方法接受兩個參數(shù):比較的類型和要比較的范圍。比較類型的取值范圍是下列幾個字符串值:"StartToStart"、"StartToEnd"、"EndToEnd"和"EndToStart"。這幾種比較類型與比較DOM范圍時使用的幾個值是相同的

同樣與DOM類似的是,compareEndPoints()方法也會按照相同的規(guī)則返回值,即如果第一個范圍的邊界位于第二個范圍的邊界前面,返回-1;如果二者邊界相同,返回0;如果第一個范圍的邊界位于第二個范圍的邊界后面,返回1。仍以前面的Hello World代碼為例,下列代碼將創(chuàng)建兩個范圍,一個選擇"Hello world!"(包括<b>標簽),另一個選擇"Hello"

var range1 = document.body.createTextRange();
var range2 = document.body.createTextRange();

range1.findText("Hello world!");
range2.findText("Hello");

alert(range1.compareEndPoints("StartToStart", range2)); //outputs 0
alert(range1.compareEndPoints("EndToEnd", range2)); //outputs 1;

由于這兩個范圍共享同一個起點,所以使用compareEndPoints()比較起點返回0。而range1的終點在range2的終點后面,所以compareEndPoints()返回1

IE中還有兩個方法,也是用于比較范圍的:isEqual()用于確定兩個范圍是否相等,inRange()用于確定一個范圍是否包含另一個范圍。

下面是相應的示例

var range1 = document.body.createTextRange();
var range2 = document.body.createTextRange();
range1.findText("Hello world!");
range2.findText("Hello");
alert("range1.isEqual(range2): " + range1.isEqual(range2));//false
alert("range1.inRange(range2): " + range1.inRange(range2));//true

這個例子使用了與前面相同的范圍來示范這兩個方法。由于這兩個范圍的終點不同,所以它們不相等,調(diào)用isEqual返回false。由于range2實際位于rangel內(nèi)部,它的終點位于后者的終點之前、起點之后,所以range2被包含在rangel內(nèi)部,調(diào)用inRange()返回true

六、復制IE范圍

在IE中使用duplicate()方法可以復制文本范圍,結果會創(chuàng)建原范圍的一個副本,如下所示

var newRange = range.duplicate();

新創(chuàng)建的范圍會帶有與原范圍完全相同的屬性

以上是“Javascript中DOM范圍的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI