[1]創建範圍 [2]簡單選擇 [3]複雜選擇 [4]操作範圍內容 [5]插入範圍內容 [6]摺疊範圍 [7]比較範圍 [8]複製範圍 [9]清理範圍 [10]IE相容 ...
前面的話
為了讓開發人員更方便地控制頁面,DOM定義了“範圍”(range)介面。通過範圍可以選擇文檔中的一個區域,而不必考慮節點的界限(選擇在後臺完成,對用戶是不可見的)。在常規的DOM操作不能更有效地修改文擋時,使用範圍往往可以達到目的。本文將詳細介紹DOM範圍
創建範圍
Document類型中定義了createRange()方法。在相容DOM的瀏覽器中,這個方法屬於document對象。使用hasFeature()或者直接檢測該方法,都可以確定瀏覽器是否支持範圍
[註意]IE8-瀏覽器不支持
var supportsRange = document.implementation.hasFeature("Range", "2.0");
var alsoSupportsRange =(typeof document.createRange == "function");
如果瀏覽器支持範圍,那麼就可以使用createRange()來創建DOM範圍,如下所示
var range = document.createRange();
與節點類似,新創建的範圍也直接與創建它的文檔關聯在一起,不能用於其他文檔。創建了範圍之後,接下來就可以使用它在後臺選擇文檔中的特定部分。而創建範圍並設置了其位置之後,還可以針對範圍的內容執行很多種操作,從而實現對底層DOM樹的更精細的控制
每個範圍由一個Range類型的實例表示,這個實例擁有很多屬性和方法。下列屬性提供了當前範圍在文檔中的位置信息
startContainer:包含範圍起點的節點(即選區中第一個節點的父節點)
startoffset:範圍在startContainer中起點的偏移量。如果startContainer是文本節點、註釋節點或CDATA節點,那麼startoffset就是範圍起點之前跳過的字元數量。否則,startoffset就是範圍中第一個子節點的索引
endContainer:包含範圍終點的節點(即選區中最後一個節點的父節點)
endOffset:範圍在endContainer中終點的偏移量(與startoffset遵循相同的取值規則)
commonAncestorContainer:startContainer和endContainer共同的祖先節點在文檔樹中位置最深的那個
在把範圍放到文檔中特定的位置時,這些屬性都會被賦值
簡單選擇
要使用範圍來選擇文檔中的一部分,最簡單的方式就是使用selectNode()或selectNodeContents()。這兩個方法都接受一個參數,即一個DOM節點,然後使用該節點中的信息來填充範圍。其中,selectNode()方法選擇整個節點,包括其子節點;而selectNodeContents()方法則只選擇節點的子節點
<!DOCTYPE html> <html> <body> <p id="p1"><b>Hello</b> world!</p> </body> </html>
我們可以使用下列代碼來創建範圍
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);
這裡創建的兩個範圍包含文檔中不同的部分:rangl包含<p>元素及其所有子元素,而rang2包含<b>元素、文本節點"Hello"和文本節點"world!"
在調用selectNode()時,startContainer、endContainer和commonAncestorContainer都等於傳入節點的父節點,也就是這個例子中的document.body。而startoffset屬性等於給定節點在其父節點的childNodes集合中的索引(在這個例子中是1——因為相容DOM的瀏覽器將空格算作一個文本節點),endOffset等於startoffset加1(因為只選擇了一個節點)
在調用selectNodeContents()時,startContainer、endContainer和commonAncestorContainer等於傳入的節點,即這個例子中的<p>元素。而startoffset屬性始終等於0,因為範圍從給定節點的第一個子節點開始。最後,endOffset等於子節點的數量(node.childNodes.length),在這個例子中是2
此外,為了更精細地控制將哪些節點包含在範圍中,還可以使用下列方法
setStartBefore(refNode):將範圍的起點設置在refNode之前,因此refNode也就是範圍選區中的第一個子節點。同時會將startContainer屬性設置為refNode.parentNode,將startoffset屬性設置為refNode在其父節點的childNodes集合中的索引
setStartAfter(refNode):將範圍的起點設置在refNode之後,因此refNode也就不在範圍之內了,其下一個同輩節點才是範圍選區中的第一個子節點。同時會將startContainer屬性設置為refNode.parentNode,將startoffset屬性設置為refNode在其父節點的childNodes集合中的索引加1
setEndBefore(refNode):將範圍的終點設置在refNode之前,因此refNode也就不在範圍之內了,其上一個同輩節點才是範圍選區中的最後一個子節點。同時會將endContainer屬性設置為refNode.parentNode,將endOffset屬性設置為refNode在其父節點的childNodes集合中的索引
setEndAfter(refNode):將範圍的終點設置在refNode之後,因此refNode也就是範圍選區中的最後一個子節點。同時會將endContainer屬性設置為refNode.parentNode,將endOffset屬性設置為refNode在其父節點的childNodes集合中的索引加1
調用這些方法時,所有屬性會自動設置好。不過,要想創建複雜的範圍選區,也可以直接指定這些屬性的值
複雜選擇
要創建複雜的範圍就得使用setStart()和setEnd()方法。這兩個方法都接受兩個參數:一個參照節點和一個偏移量值。對setStart()來說,參照節點會變成startContainer。而偏移量值會變成startoffset。對於setEnd()來說,參照節點會變成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);
顯然,要選擇這個節點(使用range1),就必須確定當前節點(p1)在其父節點的childNodes集合中的索引。而要選擇這個節點的內容(使用range2),也不必計算什麼;只要通過setStart()和setEnd()設置預設值即可。模仿selectNode()和selectNodeContents()並不是setStart()和setEnd()的主要用途,它們更勝一籌的地方在於能夠選擇節點的一部分
假設只想選擇前面HTML示例代碼中從“Hello"的"llo"到"world!"的"o"——很容易做到
第一步是取得所有節點的引用,如下所示:
var p1 = document.getElementById("p1"); var helloNode = p1.firstChild.firstChild; var worldNode = p1.lastChild;
實際上,"Hello”文本節點是<p>元素的孫子節點,因為它本身是<b>元素的一個子節點。因此,p1.firstchild取得的是<b>,而p1.firstchild.firstchild取得的才是這個文本節點。"world!"文本節點是<p>元素的第二個子節點(也是最後一個子節點),因此可以使用p1.lastChild取得該節點。然後,必須在創建範圍時指定相應的起點和終點,如下所示
var range = document.createRange(); range.setStart(helloNode, 2); range.setEnd(worldNode, 3);
因為這個範圍的選區應該從"Hello"中"e"的後面開始,所以在setStart()中傳入helloNode的同時,傳入了偏移量2(即"e"的下一個位置;"H"的位置是0)。設置選區的終點時,在setEnd()中傳入worldNode的同時傳入了偏移量3,表示選區之外的第一個字元的位置,這個字元是”r",它的位置是3(位置0上還有一個空格)。如下所示
由於helloNode和worldNode都是文本節點,因此它們分別變成了新建範圍的startContainer和endContainer。此時startoffset和endOffset分別用以確定兩個節點所包含的文本中的位置,而不是用以確定子節點的位置(就像傳入的參數為元素節點時那樣)。此時的commonAncestorContainer是<p>元素,也就是同時包含這兩個節點的第一個祖先元素
當然,僅僅是選擇了文檔中的某一部分用處並不大。但重要的是,選擇之後才可以對選區進行操作
操作範圍內容
在創建範圍時,內部會為這個範圍創建一個文檔片段,範圍所屬的全部節點都被添加到了這個文檔片段中。為了創建這個文檔片段,範圍內容的格式必須正確有效。在前面的例子中,創建的選區分別開始和結束於兩個文本節點的內部,因此不能算是格式良好的DOM結構,也就無法通過DOM來表示。但是,範圍知道自身缺少哪些開標簽和閉標簽,它能夠重新構建有效的DOM結構以便對其進行操作
對於前面的例子而言,範圍經過計算知道選區中缺少一個開始的<b>標簽,因此就會在後臺動態加入一個該標簽,同時還會在前面加入一個表示結束的</b>標簽以結束"He"。於是,修改後的DOM就變成瞭如下所示
<p><b>He</b><b>llo</b> world!</p>
另外,文本節點"world!"也被拆分為兩個文本節點,一個包含"wo",另一個包含"rid!"。最終的DOM樹下圖所示,右側是表示範圍的文檔片段的內容
像這樣創建了範圍之後,就可以使用各種方法對範圍的內容進行操作了
[註意]表示範圍的內部文檔片段中的所有節點,都只是指向文檔中相應節點的指針
【deleteContents()】
操作範圍內容的第一個方法是deleteContents(),這個方法能夠從文檔中刪除範圍所包含的內容
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();
執行以上代碼後,頁面中會顯示如下HTML代碼
<p><b>He</b>rld!</p>
由於範圍選區在修改底層DOM結構時能夠保證格式良好,因此即使內容被刪除了,最終的DOM結構依舊是格式良好的
【extractContents()】
與deleteContents()方法相似,extractContents()方法也會從文檔中移除範圍選區。但區別在於,extractContents()會返回範圍的文檔片段。利用這個返回的值,可以將範圍的內容插入到文檔中的其他地方。如下所示:
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()方法中時,添加到文檔中的只是片段的子節點,而非片段本身
<p><b>He</b>rld!</p> <b>llo</b> wo
【cloneContents】
還有一種做法是使用cloneContents()創建範圍對象的一個副本,然後在文檔其他地方插入該副本
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()非常類似,因為它們都返迴文檔片段。它們的主要區別在於,cloneContents()返回的文檔片段包含的是範圍中節點的副本,而不是實際的節點。執行上面的操作後,頁面中的HTML代碼如下所示:
<p><b>Hello</b> world!</p> <b>llo</b> wo
[註意]在調用cloneContents()方法之前,拆分的節點並不會產生格式良好的文檔片段。換句話說,原始的HTML在DOM被修改之前會始終保持不變
插入範圍內容
利用範圍,可以刪除或複製內容,還可以像前面介紹的那樣操作範圍中的內容。使用insertNode()方法可以向範圍選區的開始處插入一個節點。假設在前面例子中的HTML前面插入以下HTML代碼
<span style="color: red">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"前面,而該位置就是範圍選區的開始位置。使用這種技術可以插入一些幫助提示信息,例如在打開新視窗的鏈接旁邊插入一幅圖像
【surroundContents()】
除了向範圍內部插入內容之外,還可以環繞範圍插入內容,此時就要使用surroundContents()方法。這個方法接受一個參數,即環繞範圍內容的節點。在環繞範圍插入內容時,後臺會執行下列步驟
1、提取出範圍中的內容(類似執行extractContents())
2、將給定節點插入到文檔中原來範圍所在的位置上
3、將文檔片段的內容添加到給定節點中
可以使用這種技術來突出顯示網頁中的某些詞句,例如下列代碼
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);
以上代碼會給範圍選區加上一個黃色的背景。得到的HTML代碼如下所示
<p><b><span style="background-color:yellow">Hello</b> world!</p>
為了插入<span>,範圍必須包含整個DOM選區,而不能僅僅包含選中的DOM節點
摺疊範圍
所謂摺疊範圍,就是指範圍中未選擇文檔的任何部分。可以用文本框來描述摺疊範圍的過程。假設文本框中有一行文本,用滑鼠選擇了其中一個完整的單詞。然後,單擊滑鼠左鍵,選區消失,而游標則落在了其中兩個字母之間。同樣,在摺疊範圍時,其位置會落在文檔中的兩個部分之間,可能是範圍選區的開始位置,也可能是結束位置。下圖展示了摺疊範圍時發生的情形
【collapse()】
使用collapse()方法來摺疊範圍,這個方法接受一個參數,該參數是一個布爾值,表示要摺疊到範圍的哪一端。參數true表示摺疊到範圍的起點,參數false表示摺疊到範圍的終點。要確定範圍已經摺疊完畢,可以檢査collapsed屬性,如下所示:
range.collapse(true);//摺疊到起點 console.log(range.collapsed);//輸出true
檢測某個範圍是否處於摺疊狀態,可以幫我們確定範圍中的兩個節點是否緊密相鄰。例如,對於下麵的HTML代碼
<p id="p1">Paragraph 1</p><p id="p2">Paragraph 2</p>
如果不知道其實際構成(比如說,這行代碼是動態生成的),那麼可以像下麵這樣創建一個範圍
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
在這個例子中,新創建的範圍是摺疊的,因為p1的後面和p2的前面什麼也沒有
比較範圍
【compareBoundaryPoints()】
在有多個範圍的情況下,可以使用compareBoundaryPoints()方法來確定這些範圍是否有公共的邊界(起點或終點)。這個方法接受兩個參數:表示比較方式的常量值和要比較的範圍。表示比較方式的常量值如下所示
Range.START_TO_START(0):比較第一個範圍和第二個範圍的起點 Range.START_TO_END(1):比較第一個範圍的起點和第二個範圍的終點 Range.END_TO_END⑵:比較第一個範圍和第二個範圍的終點 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的終點由於調用setEndBefore()已經改變了,結果是range1的終點位於range2的終點後面,因此第二次比較返回1
複製範圍
【cloneRange】
可以使用cloneRange()方法複製範圍。這個方法會創建調用它的範圍的一個副本
var newRange = range.cloneRange();
新創建的範圍與原來的範圍包含相同的屬性,而修改它的端點不會影響原來的範圍
清理範圍
【detach()】
在使用完範圍之後,最好是調用detach()方法,以便從創建範圍的文檔中分離出該範圍。調用detach()之後,就可以放心地解除對範圍的引用,從而讓垃圾回收機制回收其記憶體了。來看下麵的例子
range.detach();//從文檔中分離 range = null;//解除引用
在使用範圍的最後再執行這兩個步驟是推薦的方式。一且分離範圍,就不能再恢復使用了
IE相容
IE8-瀏覽器不支持DOM範圍。但支持一種類似的概念,即文本範圍(textrange)。文本範圍是IE專有的特性,其他瀏覽器都不支持。顧名思義,文本範圍處理的主要是文本(不一定是DOM節點)。通過<body>、<button>、<input>和<textarea>等這幾個元素,可以調用createTextRange()方法來創建文本範圍。以下是一個例子
var range = document.body.createTextRange();
像這樣通過document創建的範圍可以在頁面中的任何地方使用(通過其他元素創建的範圍則只能在相應的元素中使用)。與DOM範圍類似,使用IE文本範圍的方式也有很多種
一、簡單選擇
【findText()】
選擇頁面中某一區域的最簡單方式,就是使用範圍的findText()方法。這個方法會找到第一次出現的給定文本,並將範圍移過來以環繞該文本。如果沒有找到文本,這個方法返回false;否則返回true。同樣,仍然以下麵的HTML代碼為例
<p id="p1"><b>Hello</b> world!</p>
要選擇"Hello",可以使用下列代碼
var range = document.body.createTextRange(); var found = range.findText("Hello");
執行完第二行代碼後,文本"Hello"就被包圍在範圍之內了。為此,可以檢査範圍的text屬性來確認(這個屬性返回範圍中包含的文本),或者也可以檢查findText()的返回值——在找到了文本的情況下返回值為true。例如:
alert(found); //true alert(range.text); //"Hello"
還可以為findText()傳入另一個參數,即一個表示向哪個方向繼續搜索的數值。負值表示應該從當前位置向後搜索,而正值表示應該從當前位置向前搜索。因此,要査找文檔中前兩個"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屬性取得範圍的全部內容,包括HTML和文本,如下所示
alert(range.htmlText);
IE的範圍沒有任何屬性可以隨著範圍選區的變化而動態更新。不過,parentElement()方法倒是與DOM的 commonAncestorContainer屬性類似
var ancestor = range.parentElement();
這樣得到的父元素始終都可以反映文本選區的父節點
二、複雜選擇
在IE中創建複雜範圍的方法,就是以特定的增量向四周移動範圍。為此,IE提供了4個方法:move()、moveStart()、moveEnd()和expand()。這些方法都接受兩個參數:移動單位和移動單位的數量。其中,移動單位是下列一種字元串值
"character":逐個字元地移動 "word":逐個單詞(一系列非空格字元)地移動 "sentence":逐個句子(一系列以句號、問號或嘆號結尾的字元)地移動 "textedit":移動到當前範圍選區的開始或結束位置
通過moveStart()方法可以移動範圍的起點,通過moveEnd()方法可以移動範圍的終點,移動的幅度由單位數量指定,如下所示
range.moveStart("word", 2);//起點移動2個單詞 range.moveEnd("character", 1);//終點移動1個字元
使用expand()方法可以將範圍規範化。換句話說,expand()方法的作用是將任何部分選擇的文本全部選中。例如,當前選擇的是一個單詞中間的兩個字元,調用expand("word")可以將整個單詞都包含在範圍之內
而move()方法則首先會摺疊當前範圍(讓起點和終點相等),然後再將範圍移動指定的單位數量,如下所示
range.move("character", 5);//移動5個字元
調用move()之後,範圍的起點和終點相同,因此必須再使用moveStart()或moveEnd()創建新的選區
三、操作範圍內容
在IE中操作範圍中的內容可以使用text屬性或pasteHTML()方法。如前所述,通過text屬性可以取得範圍中的內容文本;但是,也可以通過這個屬性設置範圍中的內容文本。來看一個例子
var range = document.body.createTextRange(); range.findText("Hello"); range.text = "Howdy";
如果仍以前面的Hello World代碼為例,執行以上代碼後的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>");
執行這些代碼後,會得到如下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屬性讓我們知道範圍是否已經摺疊完畢。為此,必須使用boundingWidth屬性,該屬性返回範圍的寬度(以像素為單位)。如果boundingwidth屬性等於0,就說明範圍已經摺疊了
var isCollapsed = (range.boundingWidth == 0);
此外,還有boundingHeight、boundingLeft和boundingTop等屬性,雖然它們都不像boundingWidth那麼有用,但也可以提供一些有關範圍位置的信息
五、比較IE範圍
【compareEndPoints()】
IE中的compareEndPoints()方法與DOM範圍的compareBoundaryPoints()方法類似。這個方法接受兩個參數:比較的類型和要比較的範圍。比較類型的取值範圍是下列幾個字元串值:"StartToStart"、"StartToEnd"、"EndToEnd"和"EndToStart"。這幾種比較類型與比較DOM範圍時使用的幾個值是相同的
同樣與DOM類似的是,compareEndPoints()方法也會按照相同的規則返回值,即如果第一個範圍的邊界位於第二個範圍的邊界前面,返回-1;如果二者邊界相同,返回0;如果第一個範圍的邊界位於第二個範圍的邊界後面,返回1。仍以前面的Hello World代碼為例,下列代碼將創建兩個範圍,一個選擇"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
這個例子使用了與前面相同的範圍來示範這兩個方法。由於這兩個範圍的終點不同,所以它們不相等,調用isEqual返回false。由於range2實際位於rangel內部,它的終點位於後者的終點之前、起點之後,所以range2被包含在rangel內部,調用inRange()返回true
六、複製IE範圍
在IE中使用duplicate()方法可以複製文本範圍,結果會創建原範圍的一個副本,如下所示
var newRange = range.duplicate();
新創建的範圍會帶有與原範圍完全相同的屬性