虽然我们会讲解用程序创建范围对象,但是我们把精力主要集中在如何将用户的选取范围转换成为W3C 范围或者微软的文档范围对象。
什么是范围
范围是指HTML文档中的任意一部分内容。一个范围的开始和结束点都可以是随意的,甚至是相同的(一个空范围)。最常见的范围就是用户选取的文本。当用户在页面上选取了一部分,你就可以他的选取部分转换为范围对象。然而,你也可以让程序自动选择范围。
让我们以下面的代码为例。假设用户选择了下面的文字:
1 | <h4 id= "entry1196" ><a<BR> href= "http://radar.oreilly.com/archives/2007/03/call_for_a_blog_1.html" <BR> class = "external" >Call for a Blogger 's Code of Conduct</a></h4><br><br><p>Tim O' Reilly<span style= "BACKGROUND-COLOR: #3366ff" ><span style= "COLOR: #000000" > calls for a Blogger Code of Conduct</span></span>. His proposals are:</p><br><br><ol><br> <li>Take responsibility not just for your own words, but for the<br> comments you allow on your blog.</li><br> <li>Label your tolerance level for abusive comments.</li><br> <li>Consider eliminating anonymous comments.</li><br></ol>
|
ログイン後にコピー
你可以将用户选择转换为一个包含用户选择范围的文本的范围对象(后面讲)。根据范围对象,你能找到开始和结束的范围点。如果你愿意你可以删除它拷贝它或者用其他文本代替,甚至用HTML代码来代替。
这是范围对象最简单的例子了,因为他只包含文本。下面我们来看一个复杂的例子:
1 | <h4 id= "entry1196" ><a<BR> href= "http://radar.oreilly.com/archives/2007/03/call_for_a_blog_1.html" <BR> class = "external" >Call for a Blogger 's Code of Conduct</a></h4><br><br><p>Tim O' Reilly <span style= "BACKGROUND-COLOR: #3366ff" ><span style= "COLOR: #000000" >calls for a Blogger Code of Conduct. His proposals are:</p><br><br><ol><br> <li>Take responsibility not just for your own words, but for the<br> comments you allow on your blog.</li><br> <li>Label</span></span> your tolerance level for abusive comments.</li><br> <li>Consider eliminating anonymous comments.</li><br></ol>
|
ログイン後にコピー
另外一个范围对象被创建了,而且还包含HTML。问题在于用户的选择范围跨越了几个元素。去掉其他的内容,就剩下:
1 | calls for a Blogger Code of Conduct. His proposals are:</p><br><br><ol><br> <li>Take responsibility not just for your own words, but for the<br> comments you allow on your blog.</li><br> <li>Label your toleran
|
ログイン後にコピー
这是一段不完整的HTML。幸好所有的浏览器都会转化一下:
1 | <b></b><p><b></b>calls for a Blogger Code of Conduct. His proposals are:</p><br><br><ol><br> <li>Take responsibility not just for your own words, but for the<br> comments you allow on your blog.</li><br> <li>Label your toleran<b></b></p>
|
ログイン後にコピー
正如你所看到的,浏览器会添加最少的元素让这段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 は Microsoft のメソッドを使用し、他のブラウザは Mozilla のメソッドを使用します。
var userSelection;
if (window.getSelection) {
userSelection = window.getSelection();
}
else if (document.selection) { / / Opera は最後に来る必要があります。
userSelection = document.selection.createRange();
}
Mozilla、Safari、および Opera では、userSelection が選択オブジェクトになりました。 、IE のテキスト範囲オブジェクトです。この区別は、コードの後半でも当てはまります。IE のテキスト範囲オブジェクトは、W3C の範囲オブジェクトや Mozilla の選択オブジェクトとは根本的に異なり、コードの各部分は他の部分によって補完される必要があります。
ブランチの順序に注意してください。Mozilla 選択は最初に来る必要があります。 Opera は両方をサポートしているため、window.getSelection() を使用してユーザーの選択内容を読み取ると、Opera は選択オブジェクトを作成しますが、document.selection を使用するとテキスト範囲オブジェクトも作成します。
Opera は Mozilla と W3C モードを非常によくサポートしていますが、IE のサポートには確かに欠陥があるため、検出のために window.getSelection を最初に置く必要があります。
userSelection の内容
userSelection は、Mozilla 選択オブジェクトと IE テキスト範囲オブジェクトの両方になります。これにより、すべてのメソッドとプロパティを使用できるようになります。
次に、Mozilla の選択オブジェクト userSelection は、ユーザーが選択したテキスト (HTML の代わりに) を保存します。次のように記述します:
alert(userSelection)
は次のことを行います:
はブロガーの行動規範を求めます: 自分の言葉だけでなく、ブログで許可するコメントにも責任を持ちます。必要に応じて自分の寛容なラベルを付けます。 Microsoft テキスト内 範囲オブジェクトで同じコンテンツを取得するには、以下を使用する必要があります。
var selectedText = userSelection;if (userSelection.text) selectedText = userSelection.text; これで、selectedText にはユーザーが選択したテキストが含まれます。 。この情報で十分だと思われる場合は、次の作業の準備を始めてください。
選択オブジェクトから範囲オブジェクトを作成する
多くの場合、処理したいのは、ユーザーの選択範囲を表す範囲オブジェクトです。 Microsoft モードでは、userSelection がテキスト範囲であるという条件がすでに満たされています。 W3C 準拠のブラウザでは、userSelection は単なる選択オブジェクトです。ここで、選択オブジェクトと同じ内容を持つ範囲オブジェクトを作成します。
次のように:
var rangeObject = getRangeObject(userSelection);
function getRangeObject(selectionObject) {
if (selectionObject.getRangeAt)
returnselectionObject.getRangeAt(0) { // Safari! var range = document.createRange();
range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);
範囲を返します。 }
}
理想情况下,我们通过选择对象的getRangeAt()来访问W3C范围对象。这个方法会在给定的位置返回一个范围对象:就像平常一样第一个范围对象的编号是0。(getRangeAt()已经设计好如果有多处选择的情况下怎么办。在那种情况下你的代码也很简单)
自从创建一个范围
不幸的是Safari1.3不支持getRangeAt()。因此我们需要创建一个跟用户选择一样的范围对象。这是一个很好的练习机会,可以让你知道如何创建自己的范围对象。
很明显的从创建一个对象开始:
1 | var range = document.createRange();
|
ログイン後にコピー
现在我们已经有了一个空对象。为了把他插入到文档里面去我们需要使用setStart()函数和setEnd()函数。
这两个方法需要两个参数:
1、在哪个DOM节点上开始或者结束的?
2、从哪个文本偏移上开始或者结束的?文本偏移就是指范围对象的第一个或者最后一个字符的位置。
让我们再来看一遍第二个例子:
1 | href= "http://radar.oreilly.com/archives/2007/03/call_for_a_blog_1.html" <br> class = "external" >Call for a Blogger 's Code of Conduct</a></h4><br><br><p>Tim O' Reilly <span style= "BACKGROUND-COLOR: #3366ff" ><span style= "COLOR: #000000" >calls for a Blogger Code of Conduct. His proposals are:</p><br><br><ol><br> <li>Take responsibility not just for your own words, but for the<br> comments you allow on your blog.</li><br> <li>Label </span></span>your tolerance level for abusive comments.</li><br> <li>Consider eliminating anonymous comments.</li><br></ol>
|
ログイン後にコピー
范围从
节点开始,并且文字偏移量是13,因为第14个字符已经是包含在范围里面的了(和通常一样,编号从0开始的)。
范围从
结束,偏移量是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
转载请保留以下信息
作者:北玉(tw:@rehawk)