JavaScript DOM 学习第九章 选取范围的介绍


Posted in Javascript onFebruary 19, 2010

虽然我们会讲解用程序创建范围对象,但是我们把精力主要集中在如何将用户的选取范围转换成为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 responsibilitynot 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();

现在我们已经有了一个空对象。为了把他插入到文档里面去我们需要使用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

转载请保留以下信息
作者:北玉(tw:@rehawk)

Javascript 相关文章推荐
JavaScript学习笔记之获取当前目录的实现代码
Dec 14 Javascript
js切换光标示例代码
Oct 10 Javascript
js自动生成的元素与页面原有元素发生堆叠的解决方法
Oct 24 Javascript
原生JS实现平滑回到顶部组件
Mar 16 Javascript
JavaScript实现公历转农历功能示例
Feb 13 Javascript
react-redux中connect()方法详细解析
May 27 Javascript
Bootstrap Table 在指定列中添加下拉框控件并获取所选值
Jul 31 Javascript
Vue利用路由钩子token过期后跳转到登录页的实例
Oct 26 Javascript
浅谈TypeScript的类型保护机制
Feb 23 Javascript
解决vue无法侦听数组及对象属性的变化问题
Jul 17 Javascript
H5+css3+js搭建带验证码的登录页面
Oct 11 Javascript
element-ui 弹窗组件封装的步骤
Jan 22 Javascript
JavaScript DOM学习第八章 表单错误提示
Feb 19 #Javascript
JavaScript DOM 学习第七章 表单的扩展
Feb 19 #Javascript
JavaScript DOM学习第六章 表单实例
Feb 19 #Javascript
JavaScript DOM 学习第五章 表单简介
Feb 19 #Javascript
JavaScript DOM学习第四章 getElementByTagNames
Feb 19 #Javascript
JavaScript DOM 学习第三章 内容表格
Feb 19 #Javascript
JavaScript DOM 学习第二章 编辑文本
Feb 19 #Javascript
You might like
PHP 5.0 Pear安装方法
2006/12/06 PHP
PHP数组游标实现对数组的各种操作详解
2016/01/26 PHP
BOOM vs RR BO3 第二场2.13
2021/03/10 DOTA
google 搜索框添加关键字实现代码
2010/04/24 Javascript
最简单的js图片切换效果实现代码
2011/09/24 Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
2012/07/31 Javascript
JS自定义功能函数实现动态添加网址参数修改网址参数值
2013/08/02 Javascript
jquery如何实现锚点链接之间的平滑滚动
2013/12/02 Javascript
基于Flowplayer打造一款免费的WEB视频播放器附源码
2015/09/06 Javascript
HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
2015/11/25 Javascript
BootStrap 下拉菜单点击之后不会出现下拉菜单(下拉菜单不弹出)的解决方案
2016/12/14 Javascript
对存在JavaScript隐式类型转换的四种情况的总结(必看篇)
2017/08/31 Javascript
详解基于 Nuxt 的 Vue.js 服务端渲染实践
2017/10/24 Javascript
js实现复制功能(多种方法集合)
2018/01/06 Javascript
mpvue跳转页面及注意事项
2018/08/03 Javascript
vue服务端渲染页面缓存和组件缓存的实例详解
2018/09/18 Javascript
AJAX在JQuery中的应用详解
2019/01/30 jQuery
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
2019/03/28 Javascript
vue实现中部导航栏布局功能
2019/07/30 Javascript
JavaScript canvas基于数组生成柱状图代码实例
2020/03/06 Javascript
JavaScript仿京东秒杀倒计时
2020/03/17 Javascript
Windows下PyMongo下载及安装教程
2015/04/27 Python
Python格式化输出%s和%d
2018/05/07 Python
python实现简单日期工具类
2019/04/24 Python
学python安装的软件总结
2019/10/12 Python
利用Python计算KS的实例详解
2020/03/03 Python
python实现批量修改文件名
2020/03/23 Python
英国马莎百货官网:Marks & Spencer
2016/07/29 全球购物
英国床垫在线:Mattress Online
2016/12/07 全球购物
简述安装Slackware Linux系统的过程
2012/01/12 面试题
毕业生求职信范文
2014/06/29 职场文书
2014年教师节国旗下讲话稿
2014/09/10 职场文书
员工激励培训演讲稿
2014/09/16 职场文书
高中生国庆节演讲稿范文2014
2014/09/21 职场文书
2015年事业单位工作总结
2015/04/27 职场文书
opencv-python图像配准(匹配和叠加)的实现
2021/06/23 Python