html5支持ifrang吗,FireFox下的Selection对象已经W3C的Range对象详解,兼容IE的textRange的全选和插入功能。...

前面我们主要介绍了IE下的textRange方法,以及execCommand命令。今天我们介绍其他浏览器支持的范围区域对象:Selection,Range。

首先我们先列一下Selection对象的API,翻译的MDN下的Selection对象的介绍

selection 对象代表通过用户选中的文本或者现在的光标位置。为了修改或者查看获取selection对象,可以调用window.getSelection();

一个用户创建一个selection区域可能是从左到右.也可能是从右到左。anchor代表选区的开始位置,focus代表选区的结束位置。如果你真PC端通过鼠标创建的selection

选区,那么anchor代表鼠标按下的地方,focus代表鼠标松开的地方。anchor和focus不应该被开始和结束位置混淆。因为anchor可能在focus的前面或者后面,这取决于你选中的方向。

属性:

1,Selection.anchorNode-只读

返回选区的开始节点。

2,Selection.anchorOffset-只读

返回选区的位置在开始节点中的偏移位置的数值。如果开始节点是一个文本节点,数值代表开始节点前的字符数。如果开始节点是元素节点,数值代表开始节点中光标前面有多少子元素。

3,Selection.focusNode-只读

返回选区的结束节点。

4,Selection.focusOffset-只读

同2,

5,Selection.isCollapsed-只读

返回开始点和结束点是否是同一位置。

6,Selection.rangeCount-只读

返回选区范围的个数,但兼容处理大部分浏览器只支持一个选区。

方法:1,Selection.getRangeAt(index)

返回ranges中当前选中的range对象。

2,Selection.collapse(parentNode,offset)

将当前全区合并到一个点上。

3,Selection.extend(parentNode,offset)

移动选区的结束点到指定位置。

4,Selection.modify(alter,direction,granulary)

修改当前选区。此方法处于试验阶段,不建议使用。

5,Selection.collapseToStart()

合并选区中的第一个range对象到开始位置。

6,Selection.collapseToEnd()

合并选区中的最后一个range对象到结束位置。

7,Selection.selectAllChildren()

添加指定节点的所有子元素到选区中。

8,Selection.addRange(range)

添加range到选区中。

9,Selection.removeRange(range)

从选区中删除一个range对象。

10,Selection.removeAllRanges()

删除选区中的所有ranges对象。

11,Selection.deleteFromDocument()

从文档中删除选区的内容。

12,Selection.toString()

返回选区对象中当前的字符串,IE返回当前选中的text文本。

13,Selection.containsNode(aNode,true/false)

判断一个节点是不是selection选区的一部分。

我们下面实现一个获取用户选中文本内容的方法。因为前面已经介绍了textRange的方法,所以这里的示例都采用兼容代码。

....

获取选中文本

function getText(){

if(window.getSelection){

var selection=window.getSelection();

console.log(selection.toString());

}else{

var rg=document.selection.createRange();

console.log(rg.text);

}

}

注:这里解释一下IE的textRange,必须用document.selection.createRange(),不能用document.body.createTextRange();因为selection的createRange是在选区上创建的textRange,依据于用户选中内容,而body.createTextRange依据的是body,默认的是全选状态,这个你可以自己执行一下select()方法可以看到全选效果。你可以点击这里查看文内红字补充的两者的区别。

之前我们在“复制”功能中用selection.selectAllChildren(dom)方法实现过全选的功能,这里我们用selection的其他API再来实现一下全选功能。function selectAlls(){

var dom=document.getElementById("tt");

if(window.getSelection){

var selection=window.getSelection();

var startNode=dom,endNode=dom;

if(dom.childNodes.length>0){

startNode=dom.firstChild;

var tempNode=dom.lastChild;

while(tempNode.nodeType==1&&tempNode.childNodes.length>0){

tempNode=tempNode.lastChild;

console.log(tempNode);

}

endNode=tempNode;

}

selection.collapse(startNode,0);

selection.extend(endNode,endNode.length);

}else{

document.selection.clear();

var rg2=document.selection.createRange();

rg2.moveToElementText(dom);

rg2.select();

}

}

给此段代码实现了一个demo,什么都没有看到的直观。点击这里查看兼容的复制功能。

这段代码中我们使用了collapse和extend方法,两个方法的参数一样,第一个是要移动到的dom节点,第二个是偏移量,如果是dom节点,那么偏移量就是其子元素的个数,如果是textNode那么偏移量就是其字符数。collapse移动的是开始点,所以我们就移动到一个子元素的0偏移位置。不用遍历,即使子元素还有子节点那也是在开始位置。而通过extend方法移动的是focus结束点的位置。所以我们要通过while循环得到最内层的文本节点,默认也是在节点的开始位置,向后移动其字符个数。就能实现全选了。IE9+支持window.getSelection方法操作W3C的range对象,并且IE9+的浏览器的childNodes属性是包含文本节点的。

关于属性兼容性的介绍你可以查看这里。

下面我们列一下W3C的Range对象的API:翻译自MDN。

Range对象代表包含节点和部分文本节点的document文档片段。

Range对象可以通过Document.createRange()方法创建,也可以Selection.getRangeAt()方法或者Document.createRangeAtPoint()方法创建。

还有一个Range()构造器可以创建Range对象。

属性:

1,Range.collapsed-只读

返回一个boolean值表示Range的开始和结束点是否在同一个位置。

2,Range.commonAncestorContainer-只读

返回包含startContainer(开始节点)和endContainer(结束节点)最内层的dom元素,相当于IE的range.parentElement对象。

3,Range.endContainer-只读

返回Range的结束节点。

4,Range.endOffset-只读

返回Range位置距离结束节点的偏移量。

5,Range.startContainer-只读

返回Range的开始节点。

6,Range.startOffset-只读

返回Range位置距离开始节点的偏移量。

构造方法:

Range()

返回一个以全局Document作为开始和结束的Range对象。

方法:

1,Range.setStart(startNode,startOffset)

设置Range的开始位置。

2,Range.setEnd(endNode,endOffset)

设置Range的结束位置。

3,Range.setStartBefore(refNode)

设置Range的开始位置在引用元素的前面。

4,Range.setStartAfter(refNode)

设置Range的开始位置在引用元素的后面。

5,Range.setEndBefore(refNode)

同上

6,Range.setEndAfter(refNode)

同上

7,Range.selectNode(refNode)

选中一个元素

8,Range.selectNodeContents(refNode)

选中元素的内容。

9,Range.collapse(true/false);

折叠Range的范围到一点,true为开始位置,false为结束位置,默认为false。

10,Range.cloneContents();

返回Range中的节点的一个DocumentFragment的文档片段对象。

11,Range.deleteContents();

从文档中删除Range对象的内容。

12,Range.extractContents();

把文档中的Range内容移动到DocumentFragment对象中并返回,相当于cloneContents和deleteContents的合并使用。

13,Range.insertNode(newNode);

在Range的开始位置插入一个元素。

14,Range.surroundContents(newNode);

在Range外层包围一个newNode元素,跟jquery的wrap方法相似。

15,Range.compareBoundaryPoints(how,sRange);

比较两个Range对象的范围,返回-1,0,1表示在前面,相等,在后面。

how的可选值为:Range.END_TO_END,Range.END_TO_START,Range.START_TO_END,Range.START_TO_START.

表示比较的方式,END_TO_END就是结束点和结束点比较,其他雷同。

16,Range.cloneRange();

返回Range对象的一个副本,跟IE下的range.duplicate()方法功能一样。

17,Range.detach()

释放Range对象,释放内存以提高性能,用了此方法,就不能再对Range进行其他的操作了。

18,Range.toString()

返回Range对象的文本内容。

19,Range.comparePoint(refNode,offset)

比较位置点和Range对象的关系,返回-1,0,1表示在之前,其内,其后。

20,Range.createContextualFragment(tagstring)

根据传入的字符串创建并返回一个DocumentFragment对象,字符串里面可以含有标签。

21,Range.intersectsNode(refNode)

比较引用元素是否和Range对象范围相交,返回boolean值。

22,Range.isPointInRange(refNode,offset)

判断给定点是否中Range范围内。

Range对象有兼容性问题,贴一张MDN的兼容性。

5eb87d70e93ffcecd34c53961d545c4c.png

下面我们利用Range对象的API实现一个插入hr横线的功能。插入横线

//判断一个元素及其父元素中是否是设计模式的元素。

function isInedit(pat){

var flag=false;

while(pat.nodeType!=9){

if(pat.nodeType==1){

var isedit=pat.getAttribute("contenteditable");

if(isedit){

flag=true;

break;

}

}

pat=pat.parentNode;

}

return flag;

}

}

function insertHR(){

var dom=document.getElementById("tt");

if(window.getSelection){

var selection=window.getSelection();

if(selection.rangeCount<=0){

return ;

}

var rng=selection.getRangeAt(0);

var pat=rng.commonAncestorContainer;

var flag=isInedit(pat);

if(!flag){

return;

}

rng.insertNode(document.createElement("hr"));

}else{

var rg=document.selection.createRange();

var pat=rg.parentElement();

var flag=isInedit(pat);

if(!flag){

return;

}

rg.pasteHTML("


");

}

代码看着不直观,来个DEMO,点击这里体验插入横线的功能。

上面这段代码我们用到了Range的commonAncestorContainer方法获取Range最近的父元素,然后要确定他在contenteditable元素内,之后通过insertNode来插入HR元素。代码很简短很好理解,事件要用mousedown的事件,用click事件的话,range对象早已转移到你点击的按钮上了。

注:再提一点,如果没有光标或选中时,getRangeAt会报错,所以要先判断rangeCount.如果用document.createRange()方法创建的对象操作是看不到效果的,一定记得要用Selection方法的addRange把创建的Range对象添加到selection对象中,才能在页面看到效果,此过程如同IE下的select()方法的调用。

结尾:连续介绍了几天textRange,Range,以及selection对象的api以及使用方法,写了几个demo来帮助大家理解。我们学习这些浏览器中最复杂的东西,不是为了要去实现一个富文本编辑器,富文本编辑器已经很多,还不停的造轮子,没有什么太大的价值了。但是我们掌握range后就可以去实现一些很玄的功能,比如一些论坛上的代码复制功能,等等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值