文章目錄
這一章會對範圍對象做一些介紹。使用這個對象你能選取HTML文檔中的任何部分然後根據選取資訊作一些事情。最常見的範圍對象是由使用者選擇的。
雖然我們會講解用程式建立範圍對象,但是我們把精力主要集中在如何將使用者的選取範圍轉換成為W3C 範圍或者微軟的文檔範圍對象。
什麼是範圍
範圍是指HTML文檔中的任意一部分內容。一個範圍的開始和結束點都可以是隨意的,甚至是相同的(一個空範圍)。最常見的範圍就是使用者選取的文本。當使用者在頁面上選取了一部分,你就可以他的選取部分轉換為範圍對象。然而,你也可以讓程式自動選擇範圍。
讓我們以下面的代碼為例。假設使用者選擇了下面的文字:
<h4 id="entry1196"><a
href="http://radar.oreilly.com/archives/2007/03/call_for_a_blog_1.html"
class="external">Call for a Blogger's Code of Conduct</a></h4>
<p>Tim O'Reilly calls for a Blogger Code of Conduct. His proposals are:</p>
<ol>
<li>Take responsibility not just for your own words, but for the
comments you allow on your blog.</li>
<li>Label your tolerance level for abusive comments.</li>
<li>Consider eliminating anonymous comments.</li>
</ol>
你可以將使用者選擇轉換為一個包含使用者選擇範圍的文本的範圍對象(後面講)。根據範圍對象,你能找到開始和結束的範圍點。如果你願意你可以刪除它拷貝它或者用其他文本代替,甚至用HTML代碼來代替。
這是範圍對象最簡單的例子了,因為他只包含文本。下面我們來看一個複雜的例子:
<h4 id="entry1196"><a
href="http://radar.oreilly.com/archives/2007/03/call_for_a_blog_1.html"
class="external">Call for a Blogger's Code of Conduct</a></h4>
<p>Tim O'Reilly calls for a Blogger Code of Conduct. His proposals are:</p>
<ol>
<li>Take responsibility not just for your own words, but for the
comments you allow on your blog.</li>
<li>Label your tolerance level for abusive comments.</li>
<li>Consider eliminating anonymous comments.</li>
</ol>
另外一個範圍對象被建立了,而且還包含HTML。問題在於使用者的選擇範圍跨越了幾個元素。去掉其他的內容,就剩下:
calls for a Blogger Code of Conduct. His proposals are:</p>
<ol>
<li>Take responsibility not just for your own words, but for the
comments you allow on your blog.</li>
<li>Label your toleran
這是一段不完整的HTML。幸好所有的瀏覽器都會轉化一下:
<p>calls for a Blogger Code of Conduct. His proposals are:</p>
<ol>
<li>Take responsibility not just for your own words, but for the
comments you allow on your blog.</li>
<li>Label your toleran</li></ol>
正如你所看到的,瀏覽器會添加最少的元素讓這段HTML完整,如果你複製的話,那麼這些添加的東西也會被複製。
瀏覽器安全色性一覽
在我們繼續之前,有必要看看瀏覽器的相容性。主要問題在於這裡有不下3個範圍對象的類型,你必須都有所瞭解才行。
Module |
Explorer 6/7 |
Firefox 2 |
Safari 1.3 |
Opera 9 |
W3C Range |
no |
yes |
yes |
yes |
Mozilla Selection |
no |
yes |
incomplete |
yes |
Microsoft Text Range |
yes |
no |
no |
incomplete |
訪問使用者選區
要處理使用者的選擇就必須先訪問到使用者的選區。這會立馬又一個代碼分支:IE使用微軟的方法,其他瀏覽器使用Mozilla的方法:
var userSelection;if (window.getSelection) {userSelection = window.getSelection();}else if (document.selection) { // should come last; Opera!userSelection = document.selection.createRange();}
在Mozilla,Safari,Opera裡面現在userSelection是一個選擇對象(selection object),在IE中是一個文本範圍對象(text range object)。這個區別在後面的代碼中依然有效:IE的文本範圍對象和W3C的範圍對象以及Mozilla的選擇對象有根本的不同,每一部分的代碼都需要另一部分的補充。
要注意分支的順序:Mozilla Selection一定要在前。因為Opera兩種都支援,如果你用window.getSelection()讀取使用者的選區,Opera就會建立一個選擇對象,可是你用document.selection的時候他也會建立一個文本範圍對象。
雖然Opera支援Mozilla和W3C模式很不錯,但是支援IE確是有毛病,這樣就不得不把window.getSelection放在前面檢測。
userSelection的內容現在userSelection既是一個Mozilla的選擇對象又是IE的文本範圍對象。這樣他就可以使用所有的方法和屬性了。
然後,Mozilla的選擇對象userSelection裡面儲存的使用者選擇的文本(而不是HTML)。這樣寫:
alert(userSelection)
就會產生:
calls for a Blogger Code of Conduct. His proposals are: Take responsibility
not just for your own words, but for the comments you allow on your blog.
Label your toleran
如果想在微軟的文本範圍對象中得到相同的內容你就要使用:
var selectedText = userSelection;
if (userSelection.text)
selectedText = userSelection.text;
現在selectedText就包含了使用者選擇的文本。如果你覺得這樣的資訊足夠的話,那麼就開始準備後面的工作吧。
從選擇對象建立範圍對象很多時候,你想處理的是代表使用者選擇範圍的範圍對象(range object)。在微軟模式中條件已經具備:userSelection就是一個文本範圍。在相容W3C的瀏覽器中userSelection依然只是一個選擇對象,是時候建立一個與選擇對象內容相同的範圍對象了。
按照下面這樣:
var rangeObject = getRangeObject(userSelection);function getRangeObject(selectionObject) {if (selectionObject.getRangeAt)return selectionObject.getRangeAt(0);else { // Safari!var range = document.createRange();range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);return range;}}
理想情況下,我們通過選擇對象的getRangeAt()來訪問W3C範圍對象。這個方法會在給定的位置返回一個範圍對象:就像平常一樣第一個範圍對象的編號是0。(getRangeAt()已經設計好如果有多處選擇的情況下怎麼辦。在那種情況下你的代碼也很簡單)
自從建立一個範圍不幸的是Safari1.3不支援getRangeAt()。因此我們需要建立一個跟使用者選擇一樣的範圍對象。這是一個很好的練習機會,可以讓你知道如何建立自己的範圍對象。
很明顯的從建立一個對象開始:
var range = document.createRange();
現在我們已經有了一個Null 物件。為了把他插入到文檔裡面去我們需要使用setStart()函數和setEnd()函數。
這兩個方法需要兩個參數:
1、在哪個DOM節點上開始或者結束的?
2、從哪個文本位移上開始或者結束的?文本位移就是指範圍對象的第一個或者最後一個字元的位置。
讓我們再來看一遍第二個例子:
href="http://radar.oreilly.com/archives/2007/03/call_for_a_blog_1.html"
class="external">Call for a Blogger's Code of Conduct</a></h4>
<p>Tim O'Reilly calls for a Blogger Code of Conduct. His proposals are:</p>
<ol>
<li>Take responsibility not just for your own words, but for the
comments you allow on your blog.</li>
<li>Label your tolerance level for abusive comments.</li>
<li>Consider eliminating anonymous comments.</li>
</ol>
範圍從<p>節點開始,並且文字位移量是13,因為第14個字元已經是包含在範圍裡面的了(和通常一樣,編號從0開始的)。
範圍從<li>結束,位移量是17,因為第18個字元時範圍內的最後一個字元了。
如何建立這個範圍對象:
var startPar = [the p node];var endLi = [the second li node];range.setStart(startPar,13);range.setEnd(endLi,17);
(注意現在建立的範圍對使用者不可見,只在瀏覽器的內部)
現在我們已經建立了一個範圍,我們也可以讀出他的開始和結束點。startContainer和startOffset決定了範圍的開始位置,同樣的endContainer和endOffset決定了結束位置。
讀取選區的開始和結束位置不幸的是,你並不知道使用者選擇了頁面哪個部分。所以你需要先讀出使用者選擇的開始和結束的位置:這個必須在選擇對象(selection object)裡面完成,因為這時候還沒有範圍對象(range object)。
我們剛剛看到每一個範圍對象都有標明他開始和結束位置的四個屬性。選擇對象也有相似的。當然是另外的名字:anchorNode/anchorOffset代表開始位置,focusNode/focusOffset代表結束位置。
所以讀出了選擇對象的開始和結束位置之後我們就能建立範圍對象了:
range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);
待續現在我們有了範圍對象和微軟的文本範圍對象。以後我們會講解如何使用它們,並且解決不相容的問題。
翻譯地址:http://www.quirksmode.org/dom/range_intro.html