理解Range對象

1.理解Range對象

重新來學習下HTML5中的Range對象和Selection對象,最近在維護富文本編輯器,感覺這方面的知識點很有用,所以趁着週末多學習下~

什麼是Range對象?
在HTML5中,一個Range對象代表頁面上的一段連續區域。可以通過如下語句創建一個空的Range對象。如下代碼:

var range = document.createRange();

什麼是Selection對象?
在HTML5中,每一個瀏覽器窗口都有一個Selection對象,代表用戶鼠標在頁面中所選取的區域。可以通過如下代碼得到一個Selection對象:

var selection = window.getSelection();
或 
var selection = document.getSelection();

Selection對象與Range對象的區別是?
每一個Selection對象都有一個或多個Range對象,每一個Range對象代表用戶用鼠標所選取範圍內的一段連續區域。

Firefox 與 chrome,safari對Selection的區別?
在Firefox瀏覽器中,用戶可以通過按住 ctrl鍵來選取頁面上的多個區域,因此一個Selection對象可能有多個Range對象。
在chrome或safari瀏覽器中,用戶每次只能選取一段區域,所以一個Selection對象中只能有一個Range對象。

如何獲取Selection對象中的某個Range對象呢?
可以通過Selection對象的getRangeAt方法來獲取。代碼如下:

var range = document.getSelection().getRangeAt(rangeIndex);

rangeIndex 代表Range對象的序號,在chrome或safari中,用戶每次只能選取一段區域,因此該值只能爲0;

如何判斷用戶是否選取了內容?
可以通過Selection對象的 rangeCount 屬性來判斷;
\1. 用戶沒有按下鼠標該屬性值爲0;
\2. 用戶按下鼠標之後該屬性值爲1;
\3. 用戶用鼠標加ctrl鍵選取了一個或多個區域時,該屬性值代表用戶通過鼠標選取的區域的數量,當用戶取消該區域的選取之後,該屬性值爲1.
下面是一個demo;頁面上顯示一段文字和一個按鈕,當用戶單擊按鈕時彈出的提示框中顯示用戶用鼠標加ctrl鍵共選取了多少個區域及每一段區域中的內容。代碼如下:

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8">
      <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
      <title>標題</title>
    </head>
    <body>
      <h3>Selection對象與Range對象使用demo</h3>
      <input type="button" value="選中我然後點擊" onClick="rangeTest()" />
      <div id="showRange"></div>
      <script>
        function rangeTest() {
          var html,
            showRangeDiv=document.getElementById('showRange'),
            selection=document.getSelection();
          if(selection.rangeCount > 0) {
            html = "您選取了"+ selection.rangeCount + "段內容<br/>";
            for(var i = 0; i < selection.rangeCount; i++) {
              var range = selection.getRangeAt(i);
              html += "第"+ (i+1) + "段內容爲:" + range + "<br/>"; 
            }
            showRangeDiv.innerHTML = html;
          }
        }
      </script>
    </body>
  </html>

[複製代碼](javascript:void(0)😉

查看效果

1-2 Range對象的屬性有哪些?
我們在頁面上創建的代碼如下:

var rangeObj = document.createRange();
console.log(rangeObj);

打印後看到有如下屬性:
collapsed: (Boolean) 用於判斷Range對象所代表的區域的開始點和結束點是否位於相同的位置,如果相同該屬性值爲true。
commonAncestorContainer: (node) 返回Range對象所代表的區域位於什麼節點之中。
endContainer: (node) 用於返回Range對象所代表的區域的終點位於什麼節點之中。
endOffset(int) 用於返回Range對象所代表區域的終點與包含該終點的節點起點之間的距離。
startContainer: (node) 用於返回Range對象所代表區域的起點位於什麼節點之中。
startOffset (int) 用於返回Range對象所代表的區域的起點與包含該起點節點的起點之間的距離。

2 Range對象的方法
2-1 理解使用 selectNode, selectNodeContents, 與 deleteContents方法
selectNode: Range對象的selectNode 方法用於將Range對象的起點指定爲某個節點的起點,將Range對象的終點指定爲該節點的終點。Range對象所代表的區域包含該節點。
使用方法如下:
rangeObj.selectNode(node);
demo舉例理解
假如頁面上有一個div,該div包含內容,如果使用 rangeObj.selectNode(“div”); 的含義是,選擇該div內的所有內容,包括該div標籤本身。

selectNodeContents: 該方法用於將Range對象的起點指定爲某個節點中的所有內容的起點,將Range對象的終點指定爲該節點所有內容的終點,也就是說使Range對象所代表的區域包含該節點的所有內容,但是不包括該節點標籤本身。

使用方法如下:
rangeObj.selectNodeContents(node);
demo舉例理解:
還是上面的div元素,該元素包含內容,如果使用 rangeObj.selectNodeContents(‘div’);的話,的含義是,選擇該div內的所有內容,但是不包括該div本身。

deleteContents: 該方法用於將Range對象中所包含的內容從頁面中刪除。
使用方法如下:
rangeObj.deleteContents();

下面是使用一個demo來理解上面的三個方法的具體含義,頁面中有一個div元素,一個刪除內容的按鈕,和一個刪除元素的按鈕,div元素中顯示一些文字,當用戶單擊 "刪除內容"按鈕時,會將div元素中的文字從頁面中刪除,單擊 “刪除元素” 按鈕時,會將整個div元素從頁面中刪除。

代碼如下:

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
     <html>
        <head>
          <meta charset="utf-8">
          <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
          <title>標題</title>
        </head>
        <body>
          <h3>Selection對象與Range對象使用demo</h3>
          <div id="div" style="background-color: #e0a0b0; width:300px; height: 50px;">aaaaadsadsdasadsbbgg</div>
          <button onclick="deleteRangeContents(true);">刪除內容</button>
          <button onclick="deleteRangeContents(false);">刪除元素</button>

          <script>
              function deleteRangeContents(flag) {
                var div = document.getElementById("div");
                var rangeObj = document.createRange();
                if (flag) {
                  rangeObj.selectNodeContents(div);
                } else {
                  rangeObj.selectNode(div);
                }
                rangeObj.deleteContents();
              }
          </script>
        </body>
    </html>

[複製代碼](javascript:void(0)😉

查看效果

2-2 理解使用 setStart方法,setEnd方法,setStartBefore方法,setStartAfter方法,setEndBefore方法與setEndAfter方法

setStart: 該方法用於將某個節點中的某個位置指定爲Range對象所代表區域的起點位置。使用方法如下:
rangeObj.setStart(node, num);
num的含義是:首先它是一個整型數值,有兩種含義取決於node節點;
\1. 當第一個參數node所代表的節點是一個內容爲一段文字的時候,那麼該參數值用於指定將第幾個文字結束位置作爲Range對象所代表區域的起點位置(num是從0開始)
\2. 當第一個參數node所代表的節點包括其他子節點時,該參數用於指定將第幾個子節點的結束位置作爲Range對象所代表區域的起點位置。

setEnd: 該方法用於將某個節點中的某處位置指定爲Range對象所代表區域的結束位置。使用方法如下:
rangeObj.setEnd(node, num);
num的含義: 首先是一個整型數值;
\1. 當第一個參數node所代表的節點是一個內容爲一段文字的時候,該參數指定將第幾個文字結束位置作爲Range對象所代表區域的結束位置。
\2. 當第一個參數node所代表的節點包括其他子節點時,該參數值用於指定將第幾個子節點的結束位置作爲Range對象所代表區域的結束位置。

下面是一個簡單的demo來理解上面的 setStart和setEnd方法的使用,頁面上有一個div元素和一個刪除文字的按鈕,div元素中有一些文字,當用戶點擊 刪除文字按鈕時,div元素中的第三個文字到第十個文字將被刪除。
代碼如下:

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
     <html>
        <head>
          <meta charset="utf-8">
          <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
          <title>標題</title>
        </head>
        <body>
          <div id="myDiv" style="color: red">這段文字中第三個文字到第十個文字將被刪除</div>
          <button onclick="deleteChar()">刪除文字</button>
          <script>
            function deleteChar() {
              var div = document.getElementById("myDiv");
              var textNode = div.firstChild;
              var rangeObj = document.createRange();
              rangeObj.setStart(textNode, 2);
              rangeObj.setEnd(textNode, 10);
              rangeObj.deleteContents();
            }
          </script>
        </body>
    </html>

[複製代碼](javascript:void(0)😉

查看效果

setStartBefore: 該方法用於將某個節點的起始位置指定爲Range對象所代表區域的起點位置。使用方法如下:
rangeObj.setStartBefore(node);

setStartAfter: 該方法用於將某個節點的終點位置指定爲Range對象所代表區域的起點位置。使用方法如下:
rangeObj.setStartAfter(node);

setEndBefore: 該方法用於將某個節點的起始位置指定爲Range對象所代表區域的終點位置,使用方法如下:
rangeObj.setEndBefore(node);

setEndAfter: 該方法用於將某個節點的終點位置指定爲Range對象所代表區域的終點位置。使用方法如下:
rangeObj.setEndAfter(node);

看上面的四個方法容易混淆,我們來做一個demo,使用一下 setStartBefore 和 setEndAfter方法。 頁面上有一個表格和一個按鈕,用戶單擊按鈕時,通過Range對象的setStartBefore 和 setEndAfter方法 使Range對象代表的區域包含表格的第一行,然後刪除該行。

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
        <title>標題</title>
      </head>
      <body>
        <table id="myTable" border="1" cellspacing="0" cellpadding="0">
          <tr>
            <td>第一行第一列</td>
            <td>第一行第二列</td>
          </tr>
          <tr>
            <td>第二行第一列</td>
            <td>第二行第二列</td>
          </tr>
        </table>
        <button onclick="deleteFirstRow()">刪除第一行</button>
        <script>
          function deleteFirstRow() {
            var myTable = document.getElementById('myTable');
            if (myTable.rows.length > 0) {
              var row = myTable.rows[0];
              var rangeObj = document.createRange();
              rangeObj.setStartBefore(row);
              rangeObj.setEndAfter(row);
              rangeObj.deleteContents();
            }
          }
        </script>
      </body>
    </html>

[複製代碼](javascript:void(0)😉

查看效果

2-3 理解使用 cloneRange方法,cloneContents方法,extractContents方法

cloneRange: 該方法用於對當前的Range對象進行復制,該方法返回複製的Range對象。使用方法如下:
var rangeClone = rangeObj.cloneRange();
下面可以看一個demo來理解一下,頁面上顯示一個 “克隆Range對象” 按鈕,用戶單擊該按鈕時,創建一個Range對象,該對象包含頁面中的所有內容,然後使用cloneRange方法複製Range對象,然後在彈窗顯示該Range對象中的內容。
代碼如下:

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
   <html>
      <head>
        <meta charset="utf-8">
        <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
        <title>標題</title>
      </head>
      <body>
        <button onclick="cloneRange()">克隆Range對象</button>
        <script>
          function cloneRange() {
            var rangeObj = document.createRange();
            rangeObj.selectNodeContents(document.body);
            var rangeClone = rangeObj.cloneRange();
            console.log(rangeClone);
            alert(rangeClone.toString());
          }
        </script>
      </body>
  </html>

[複製代碼](javascript:void(0)😉

查看效果

cloneContents: 該方法用於在頁面上追加一段HTML代碼,使用方法如下:
var docFragment = rangeObj.cloneContents();
該方法返回的是 一個 DocumentFragment對象,該對象爲一個容器元素,當需要追加,修改,刪除或查找頁面上的元素時,該方法非常有用。
下面是一個demo,頁面上顯示一個div元素,div元素中包含一些文字和一個按鈕,用戶點擊按鈕時將在該div元素底部克隆出相同的文字和按鈕。

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
   <html>
      <head>
        <meta charset="utf-8">
        <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
        <title>標題</title>
      </head>
      <body>
        <div id="div">
          <span>aaaaaa</span>
          <button onclick="cloneDivContent()">克隆</button>
        </div>
        <script>
          function cloneDivContent() {
            var div = document.getElementById('div');
            var rangeObj = document.createRange();
            rangeObj.selectNodeContents(div);
            var documentFragment = rangeObj.cloneContents();
            div.appendChild(documentFragment);
          }
        </script>
      </body>
  </html>

[複製代碼](javascript:void(0)😉

查看效果

extraContents: 該方法用於將Range對象所代表區域的HTML代碼克隆到一個 DocumentFragment中,然後從頁面中刪除這段HTML代碼;

使用方法如下:
var documentFragment = rangeObj.extraContents();

下面是一個demo, 頁面上有2個div元素和一個按鈕,其中第一個div元素包含一些文字,用戶單擊該按鈕時,把文字移動到第二個div中。

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
   <html>
      <head>
        <meta charset="utf-8">
        <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
        <title>標題</title>
      </head>
      <body>
        <div id="srcDiv" style="background-color: red; width: 300px; height:50px">adsddasdssdsdsdsads</div>
        <div id="distDiv" style="background-color: blue; width: 300px; height: 50px;"></div>
        <button onclick="moveContent()">移動元素內容</button>

        <script>
          function moveContent() {
            var srcDiv = document.getElementById('srcDiv');
            var distDiv = document.getElementById("distDiv");
            var rangeObj = document.createRange();
            rangeObj.selectNodeContents(srcDiv);
            var documentFragment = rangeObj.extractContents();
            distDiv.appendChild(documentFragment);
          }
        </script>
      </body>
  </html>

[複製代碼](javascript:void(0)😉

查看效果

2-4 insertNode方法
該方法用於將指定的節點插入到某個Range對象所代表的區域中,插入位置爲Range對象所代表區域的起點位置,如果該節點已經存在於頁面之中,那麼該節點
將被移動到Range對象所代表區域的起點處。
使用方法如下:
rangeObj.insertNode(node)

下面是一個demo,頁面中有一個div元素和一個按鈕,div元素有一些文字,在div元素中按下鼠標左鍵時,該按鈕將被移動到按下鼠標左鍵的位置。

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
   <html>
      <head>
        <meta charset="utf-8">
        <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
        <title>標題</title>
      </head>
      <body>
        <div onmouseup="moveButton()" style="width: 400px; background-color: red;">adssdasddsdasszczxccxzcx</div>
        <button id="button">按鈕</button>

        <script>
          function moveButton() {
            var button = document.getElementById("button");
            var selection = document.getSelection();
            if (selection.rangeCount > 0) {
              var range = selection.getRangeAt(0);
              range.insertNode(button);
            }
          }
        </script>
      </body>
  </html>

[複製代碼](javascript:void(0)😉

查看效果

2-5 理解collapse方法 和 detach方法
該方法用於將Range對象所代表的區域的終點移動到該區域的起點處,或將Range對象所代表的區域的起點移動到終點處,使Range對象所代表的區域內不包含任何內容。
使用方法如下:
RangeObj.collapse(toStart);
參數toStart,是一個Boolean型,如果爲false的話,表示將Range對象所代表的區域的起點移動到終點處,當爲true的話,表示將Range對象所代表的區域的終點移動到該區域的起點處。
下面是一個demo,可以來理解下 collapse方法的使用;
頁面上有一個div元素,裏面包含一些文字,一個 選擇元素的 按鈕,一個 取消選擇元素的按鈕,和一個 顯示Range內容的按鈕,用戶單擊 選擇元素 按鈕時該Range對象中將包含頁面中的div元素,然後單擊 顯示Range內容按鈕 就彈出 該div元素的內容,再單擊 取消選擇按鈕 將使用Range對象的collapse方法清空Range對象的內容。再次單擊 顯示Range內容,將顯示空字符串。
代碼如下:

[複製代碼](javascript:void(0)😉

<!DOCTYPE html>
       <html>
          <head>
            <meta charset="utf-8">
            <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
            <title>標題</title>
          </head>
          <body>
            <div id="div" style="background-color: red; width:300px; height: 50px;">元素中的內容</div>
            <button onclick="selectRangeContents()">選擇元素</button>
            <button onclick="unselect()">取消選擇</button>
            <button onclick="showRange()">顯示Range內容</button>
            <script>
              var rangeObj = document.createRange();
              function selectRangeContents() {
                var div = document.getElementById('div');
                rangeObj.selectNode(div);
              }
              function unselect() {
                rangeObj.collapse(false);
              } 
              function showRange() {
                alert(rangeObj.toString());
              }
            </script>
          </body>
      </html>

[複製代碼](javascript:void(0)😉

查看效果

detach方法: 該方法用於從瀏覽器中釋放Range對象,釋放之後將不能再訪問該Range對象,否則將拋出腳本錯誤,使用方法如下:
RangeObj.detach();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章