爲了讓開發人員更方便地控制頁面,DOM定義了「範圍」(range)接口。經過範圍能夠選擇文檔中的一個區域,而沒必要考慮節點的界限(選擇在後臺完成,對用戶是不可見的)。在常規的DOM操做不能更有效地修改文擋時,使用範圍每每能夠達到目的。本文將詳細介紹DOM範圍javascript
Document類型中定義了createRange()方法。在兼容DOM的瀏覽器中,這個方法屬於document對象。使用hasFeature()或者直接檢測該方法,均可以肯定瀏覽器是否支持範圍html
[注意]IE8-瀏覽器不支持java
var supportsRange = document.implementation.hasFeature("Range", "2.0");
var alsoSupportsRange =(typeof document.createRange == "function");
若是瀏覽器支持範圍,那麼就可使用createRange()來建立DOM範圍,以下所示node
var range = document.createRange();
與節點相似,新建立的範圍也直接與建立它的文檔關聯在一塊兒,不能用於其餘文檔。建立了範圍以後,接下來就可使用它在後臺選擇文檔中的特定部分。而建立範圍並設置了其位置以後,還能夠針對範圍的內容執行不少種操做,從而實現對底層DOM樹的更精細的控制瀏覽器
每一個範圍由一個Range類型的實例表示,這個實例擁有不少屬性和方法。下列屬性提供了當前範圍在文檔中的位置信息app
startContainer:包含範圍起點的節點(即選區中第一個節點的父節點)
startoffset:範圍在startContainer中起點的偏移量。若是startContainer是文本節點、註釋節點或CDATA節點,那麼startoffset就是範圍起點以前跳過的字符數量。不然,startoffset就是範圍中第一個子節點的索引
endContainer:包含範圍終點的節點(即選區中最後一個節點的父節點)
endOffset:範圍在endContainer中終點的偏移量(與startoffset遵循相同的取值規則)
commonAncestorContainer:startContainer和endContainer共同的祖先節點在文檔樹中位置最深的那個
在把範圍放到文檔中特定的位置時,這些屬性都會被賦值spa
要使用範圍來選擇文檔中的一部分,最簡單的方式就是使用selectNode()或selectNodeContents()。這兩個方法都接受一個參數,即一個DOM節點,而後使用該節點中的信息來填充範圍。其中,selectNode()方法選擇整個節點,包括其子節點;而selectNodeContents()方法則只選擇節點的子節點指針
<!DOCTYPE html> <html> <body> <p id="p1"><b>Hello</b> world!</p> </body> </html>
咱們可使用下列代碼來建立範圍code
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);
這裏建立的兩個範圍包含文檔中不一樣的部分:rang1包含<p>元素及其全部子元素,而rang2包含<b>元素、文本節點"Hello"和文本節點"world!"htm
在調用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()方法。這個方法接受一個參數,即環繞範圍內容的節點。在環繞範圍插入內容時,後臺會執行下列步驟
一、提取出範圍中的內容(相似執行extractContents())
二、將給定節點插入到文檔中原來範圍所在的位置上
三、將文檔片斷的內容添加到給定節點中
可使用這種技術來突出顯示網頁中的某些詞句,例以下列代碼
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;//解除引用
在使用範圍的最後再執行這兩個步驟是推薦的方式。一且分離範圍,就不能再恢復使用了
IE8-瀏覽器不支持DOM範圍。但支持一種相似的概念,即文本範圍(textrange)。文本範圍是IE專有的特性,其餘瀏覽器都不支持。顧名思義,文本範圍處理的主要是文本(不必定是DOM節點)。經過<body>、<button>、<input>和<textarea>等這幾個元素,能夠調用createTextRange()方法來建立文本範圍。如下是一個例子
var range = document.body.createTextRange();
像這樣經過document建立的範圍能夠在頁面中的任何地方使用(經過其餘元素建立的範圍則只能在相應的元素中使用)。與DOM範圍相似,使用IE文本範圍的方式也有不少種
1、簡單選擇
【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();
這樣獲得的父元素始終均可以反映文本選區的父節點
2、複雜選擇
在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()建立新的選區
3、操做範圍內容
在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
4、摺疊IE範圍
【collapse()】
IE爲範圍提供的collapse()方法與相應的DOM方法用法同樣:傳入true把範圍摺疊到起點,傳入false把範圍摺疊到終點。例如:
range.collapse(true); //摺疊到起點
惋惜的是,沒有對應的collapsed屬性讓咱們知道範圍是否已經摺疊完畢。爲此,必須使用boundingWidth屬性,該屬性返回範圍的寬度(以像素爲單位)。若是boundingwidth屬性等於0,就說明範圍已經摺疊了
var isCollapsed = (range.boundingWidth == 0);
此外,還有boundingHeight、boundingLeft和boundingTop等屬性,雖然它們都不像boundingWidth那麼有用,但也能夠提供一些有關範圍位置的信息
5、比較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
6、複製IE範圍
在IE中使用duplicate()方法能夠複製文本範圍,結果會建立原範圍的一個副本,以下所示
var newRange = range.duplicate();
新建立的範圍會帶有與原範圍徹底相同的屬性