HTML中的Range对象

Range对象初次尝试

工作中遇到了非常奇葩的需求:要实现划选文字然后复制,且点击复制后还需要保持选中。
于是只好花时间研究了下Range对象。

什么是Range对象?

Range就是指HTML文档中任意一段内容,Range对象下有各种属性,记录了起始点和结束点等各种信息。
举个例子,你在网页上左键划下文字

1
aaaaaaa,bbbbbccccc

则Range对象被创建,内容可能是:

1
aaaaaaa,bbbbb</p><p>ccccc

这种跨标签的选择所有浏览器都会补全Range对象,并且你复制移动的Range对象的HTML文档一定也是可用的。

浏览器差异

在不同浏览器下共有三种Range对象:

  1. W3C Range:W3C标准下的Range对象;
  2. Mozilla Selection:现代浏览器下的Range对象
  3. Microsoft Text Range:基于字符串的ie浏览器下的Range对象 = =

主要工作就是要区分ie和其他浏览器。例如获取用户所划的内容:

1
2
3
4
5
if (window.getSelection) { //现代浏览器
var range = window.getSelection();
} else if (document.selection) { //IE浏览器
var range = document.selection.createRange();
}

读取range对象的内容

Mozilla Selection对象的格式虽然不是字符串,但可以直接当做字符串展示(没有标签)
ie的range对象需要读取他的text属性:

1
2
3
4
var selectedText = range;
if (range.text) {
selectedText = range.text;
}

从Selection对象创建Range对象

要完成需求点击复制后还保持文字选中状态就需要在点击导致Selection对象消失后重新让对应文字选中。
简单来说就是创建一个和Selection对象一样的Range对象:

1
2
3
4
5
6
7
8
9
10
11
var getRangeObject = function(selectionObject) {
if (selectionObject.getRangeAt)
return selectionObject.getRangeAt(0);//理想状态直接获取Range对象
else {
var range = document.createRange();
range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);
range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);
return range;
}
}
var rangeObject = getRangeObject(userSelection);

其中setStart和setEnd方法的两个参数为:

  1. range的起、止的Dom节点
  2. range的起、止的对应偏移量
    (如果range对象跨节点,则是对应节点的偏移量而不是总截取文字的偏移量)

总结

完成需求主要就用了range对象的获取,存储值并重新设置。成功实现了浏览器右键复制的功能= =
一下午的时间最主要的收获是想通了一个问题——为什么点击复制后原来选中的文字会不再被选中?
主要是当你点击到复制这两个字上又重新生成了新的range对象(起止相同,也就是没有选任何东西。。。)
这个原因也导致了不能复制正确的range对象,解决方法是用button标签然后改下css