range 標準化之擷取

來源:互聯網
上載者:User

w3c range

range 用來表示使用者的選擇地區,這塊選擇地區由兩個邊界位置界定,而位置則由其容器以及位移量構成,稱作 container 與 offset .如下是一個簡單的位置樣本:
複製代碼 代碼如下:
<p><span>文字</span>^<span>文字</span></p>


其中 ^ 表示一個位置,則 container 為父節點 p,offset即為相對於父節點的位移量為1。需要注意的是當container為元素節點時,其位移量單元為節點,即從容器的第一個子節點到當前位置處所經曆的子節點數。

相應的,container也可以是文位元組點,這時container 為 textnode ,而offset則為從該textnode到當前位置所經曆的 utf-16 字元個數(意味著,中文和英文計數一樣,不是位元組計數)。如
複製代碼 代碼如下:
<p><span>文字</span><span>01234^567</span></p>

上例中 container 為 "01234567" 這個文位元組點,而offset 則是從該文位元組點第一個字元到當前位置所經曆的字元個數即5.
ie range

簡要介紹一下,具體請查閱 msdn

ie range 沒有清晰的容器與位移量的概念,但是基本思想和 w3c range 一樣,具備同等的表達能力,分為 textrange 與 controlrange,包含一系列的方法。

textrange 不是從字面意義上的單純文字,而是表示使用者的選擇地區內容(可用其htmlText擷取完整內容),其操作方式大多是以文字為單元而不是 dom 樹節點。

controlrange 字面意思表示擷取選擇 控制項 ,實際是有些元素(div,img,object...)處於可編輯狀態時,經單擊可將整個元素選中。

ie 標準化之擷取

從上面介紹可見,w3c 的range更規範,更清晰,其 container 與 offset 的概念更直觀,當我們需要對range關聯dom節點進行操作時,無疑 container ,offset是必不可少的,而 ie range 則沒有顯示的提供擷取這兩個關鍵變數的方法, 前面說過 ie range 其實具備 w3c range 等價的功能,那麼就可以結合其提供的一系列方法推匯出這兩個變數。

範圍對象擷取:
範圍對象有兩種擷取方式:

1.從當前選擇地區獲得 range ,可調用
複製代碼 代碼如下:
document.selection.createRange()

方法根據目前選擇,返回 TextRange 或 ControlRange 執行個體。

2.從元素建立 range ,可調用
複製代碼 代碼如下:
oControlRange = object.createControlRange()

Js代碼
oTextRange = object.createTextRange()

前一種 之能在 body,element上調用,而後一種 可在大多數元素上調用。調用後則該範圍完全覆蓋調用元素。相當於 moveToElementText 。

textrange 標準化:

首先介紹下用到的幾個方法:

collapse :根據參數將結束位置重合到開始位置(true)或開始位置重合到結束位置(false)。

parentElement :擷取包圍選擇地區的元素節點,如下例調用後得到span節點。
複製代碼 代碼如下:
<span>文^字</span>

moveToElementText (Node a) :將選擇地區變更為 a ,起始位置為 a 的前後,如作用到如下 span 節點後:
複製代碼 代碼如下:
^<span>文字</span>^

range1.compareEndPoints('XxToYy',range2) :xx,yy 可以為 Start 或 End,取 range1 的 xx 位置和 range2 的 yy 位置比較,根據前後順序返回-1,1,0表示重合。

range1.setEndPoint("XxToYy",range2) :xx,yy 可以為 Start 或 End,將range1的xx位置設為range2的yy位置。

轉化:

有了上面的5個方法就可以開始我們的標準化第一步:擷取位置,首先給出操作例子:

 


(綠塊表示文位元組點,注意:正常手工編寫頁面情況下不會出現兩個相鄰的文位元組點,這裡使用 splitText 強制分離 )


當我們將選擇地區collapse後,可能有上述四個位置:1,2,3,4,其中 1,4 相鄰元素節點最簡單:


1,4位置 標準化:


1.根據 parentElement 得到包含位置的節點 p ,即為該位置的container

2.對container的所有元素子節點,一一驗證是否和已知位置相鄰,驗證方法即為:通過 moveToElementText 建立range包圍子節點,再通過 compareEndPoints 比較是否建立 range 的前後位置是否和當前位置重合:

複製代碼 代碼如下:
range = range.duplicate();
range.collapse(start);
var parent = range.parentElement(),
siblings = parent.childNodes;
for (var i = 0; i < siblings.length; i++) {
var child = siblings[i];
if (child.nodeType == 1) {
var tr = range.duplicate();
tr.moveToElementText(child);
//子項目節點開始位置比較
var comparisonStart = tr.compareEndPoints('StartToStart', range),
//子項目節點結束位置比較
comparisonEnd = tr.compareEndPoints('EndToStart', range);
//開頭已經在當前位置後面,沒必要繼續比了
if (comparisonStart > 0) break;
else if (!comparisonStart || comparisonEnd == 1 && comparisonStart == -1) return {
container: parent,
offset: i
};
else if (!comparisonEnd) return {
container: parent,
offset: i + 1
};
}
}

2,3位置 標準化:
2 表示位置在兩個文位元組點之間,container為 p ,由於moveToElementText 無法作用文位元組點,則只能另想他法。
3 表示位置處於文本節點中間,此時 container 為文本節點,而 offset 則要數字元數了。
1.當到達 1 位置時,停止。
2.建立range ra,開始位置為 1,結束位置為2或3,取得 ra的所有字元數 ra_textlength,對從位置1開始往右的每個文位元組點,從 ra_textlength 中減去其長度(data.length),當 ra_textlength 為0時,代表當前位置為2,而當前經過的文位元組點數目即為offset。
當 ra_textlength 為負數時,表示當前位置為3, 當前的文位元組點即為位置3 的container,ra_textlength 的上一個值則是offset。
樣本:
複製代碼 代碼如下:
<p id="test"><strong>粗體</strong>普通|文字<i>斜體</i></p>
<script>
document.getElementById("test").childNodes[1].splitText(2);
</script>

標準化 demo

 

 

controlrange 標準化

 

controlrange 就很簡單了,由 item(index) 方法得到選擇元素,結合其parentNode 就可以得到標準化表示了。

 


PS : 關於輸入框的範圍讀取


由於規範規定輸入框的選擇地區和頁面選擇地區是分離的,輸入框的選擇地區有不同的擷取方式 (IE 基本相同)。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.