博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编辑器开发之 Range 范围对象的学习
阅读量:6049 次
发布时间:2019-06-20

本文共 3971 字,大约阅读时间需要 13 分钟。

写在前面:

网上有各种富文本编辑器,微博分享等操作,这些功能非常实用,他们就是使用 range,selection 对象来实现的,这两个对象偏冷门,不涉及编辑器一般用不到,range 对象是对选区的操作,选区是鼠标在页面上按下,然后拖动选择的内容,range 对象就是对这个选区的操作;selection 是当前活动区的操作对象,selection 对象下面可以有多个 range 对象;这篇文章写的是标准的 selection和 range,小于 IE 9 的旧版本不在讨论范围内;

先来看一下 W3C 文档上的 range 对象的基本属性:

collapsed:返回一个用于判断 Range 起始位置和终止位置是否相同的布尔值。

commonAncestorContainer:返回包含 startContainer 和 endContainer 的最深的节点。

endContainer:返回包含 Range 终点的节点。

endOffset:返回 endContainer 中表示Range终点位置的数字。

startContainer:返回包含 Range 开始的节点。

startOffset:返回 startContainer 中表示 Range 起始位置的数字。

注意:range 的这些属性都是只读的,看下面这张图,就明白这些属性是怎么回事了:

collapsed 为 flase,说明起始点和终点不在同一个位置,startOffset 是从0开始的,d 的索引是2,表示鼠标按下的位置,也就是 div 元素的字符开始算的,endOffset 是 4,是从 span 标签开始算的,i 字符在 span 标签立面的索引是4;

注意,他们总是从包裹字符的节点的开始字符计算的;

再来看下 range 的方法和解释:

setStart(node, index):设置 Range 的起点。

setEnd(node, index):设置 Range 的终点。
setStartBefore(node):以其它节点( Node)为基准,设置 Range 的起点。
setStartAfter():以其它节点为基准,设置 Range 的始点。
setEndBefore():以其它节点为基准,设置 Range 的终点。
setEndAfter():以其它节点为基准,设置 Range 的终点。
selectNode():设定一个包含节点和节点内容的 Range。
selectNodeContents():设定一个包含某个节点内容的 Range。
collapse():向指定端点折叠该 Range。

这个解释看了之后一脸蒙圈,我的感受是讲的不清楚,还是上图,加上我们的理解更直观:

setStart setEnd 方法:

JS 操作:

1 // 创建新的 range 对象,设置 setStart setEnd 2   function setStartEnd() { 3     var box = document.getElementById('box'); 4     if (document.createRange) { 5       var range = document.createRange(); 6       var start = box.querySelector('span').firstChild; 7       var end = box.querySelector('p').firstChild; 8  9       range.setStart(start, 2); // p 标签的第 2 个字符10       range.setEnd(end, 3); // span 标签的 第 3 个字符11       console.log(range.cloneContents()); // 打印 range 的内容12       console.log(range); // 打印 range13     }14   }

选区的内容和打印 range 的结果:

这个例子可以看出来,startOffset 的位置在第一个 span 标签的 g 字符前面,endOffset 的位置在 p 标签的 p 字符前面;

需要注意的是,如果是跨标签的选区,没有匹配到结束标签时,会折叠选区,把起点的位置设置为结束点的位置;

看下这个例子,把开始节点设置为 p 标签,结束节点为 span 标签,从后面向前面选择:

var start = box.querySelector('p').firstChild; // 开始节点是 pvar end = box.querySelector('span').firstChild; // 结束节点是 span

打印出来的结果:

仔细检查会发现 collapsed: true,并且 startContainer 和 endContainer 是同一个元素,这说明这个 range 选区折叠了,所以操作的时候需要注意;

setStartBefore setEndBefore 方法:

JS 操作:

var box = document.getElementById('box');    if (document.createRange) {      var range = document.createRange();      var spans = box.querySelectorAll('span');      var refStart = spans[0].firstChild;      var refEnd = spans[1].firstChild;      range.setStartBefore(refStart); // 设置 p 节点的开始位置为 range 的起点      range.setEndBefore(refEnd); // 设置 span 节点的开始位置为 range 的终点      console.log(range.cloneContents());      console.log(range);    }

这两个方法的作用是以参考节点的开始位置作为参考,来设置 range 的起点和结束点;

setStartAfter,setEndAfter 方法:

JS:

var box = document.getElementById('box');    if (document.createRange) {      var range = document.createRange();      var spans = box.querySelectorAll('span');      var refStart = spans[0].firstChild;      var refEnd = spans[1].firstChild;      range.setStartAfter(refStart); // 设置 p 节点的结束位置为 range 的起点      range.setEndAfter(refEnd); // 设置 span 节点的结束位置为 range 的终点      console.log(range.cloneContents());      console.log(range);    }

这两个方法的作用是以参考节点的结束位置作为参考,来设置 range 的起点和结束点;

selectNode 方法:

JS:

var box = document.getElementById('box');    if (document.createRange) {      var range = document.createRange();      var span = box.querySelector('span').firstChild;      range.selectNode(span);      console.log(range.cloneContents());      console.log(range);    }

selectNode 方法的操作就是 range 选择整个节点的,默认 startOffset 是 0,endOffset 是1;

 selectNodeContents 方法:

这个方法和 selectNode 很类似,区别是会默认把结束点的位置移到最后;

var box = document.getElementById('box');    if (document.createRange) {      var range = document.createRange();      var span = box.querySelector('span').firstChild;      range.selectNodeContents(span);      console.log(range.cloneContents());      console.log(range);    }

collapse 方法是设置折叠选区的,开始位置和结束位置相同,这么解释就清楚多了,作用是多用来设置光标的;

下一篇看一下 selection 对象的基本属性和用法;

转载于:https://www.cnblogs.com/zhangmao/p/10739236.html

你可能感兴趣的文章
智能时代,深度学习和大数据成了密不可分的一对儿
查看>>
Rays Power Infra将在印度建立100MW光伏项目
查看>>
QTP安装问题小记
查看>>
对话阿里云AI 科学家闵万里:1984年人工智能低潮是否会重演?
查看>>
Intellij IDEA 添加jar包的三种方式
查看>>
十分钟入门RocketMQ
查看>>
年计划,技术儿告诉你怎么做?
查看>>
通过ODBC连接PostgreSQL和Greenplum
查看>>
2015.08.19结构体
查看>>
Nodejs测试:从0到90(理论篇)
查看>>
Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能
查看>>
windows7下制作苹果mac os x 10.10Yosemiteu盘启动盘
查看>>
Appium移动自动化测试(四)--one demo
查看>>
这是就是联想?2年4次因同一问题返售后,售后找不到确切原因。。。。。
查看>>
10、spss做最优尺度分析
查看>>
OCMaskedTextField
查看>>
Linux命令学习总结:reboot命令
查看>>
【Oracle】使用hanganalyze 命令分析数据库hang【转】
查看>>
Python 应用剖析工具介绍
查看>>
JSP标准标签库
查看>>