系列文章快速阅读:
富文本编辑器开发系列-1-基础概念
富文本编辑器开发系列2-document.execCommand 的API
富文本编辑器开发系列3-selection
富文本编辑器开发系列4——Range对象
富文本编辑器开发系列5——浏览器Selection API
探究
富文本编辑器开发系列6——Range API
探究
富文本编辑器开发系列7——textRange对象详解
富文本编辑器开发系列8——常用DOM API
原生API编写简单富文本编辑器001
原生API编写简单富文本编辑器002
原生API编写简单富文本编辑器003
原生API编写简单富文本编辑器004
原生API编写简单富文本编辑器005
文章目录
- 1. Selection 基本属性
- 2. Selection 选区API
- `getRangeAt(index)` 获取拖蓝区域
- `collapse(parentNode, offset)` 将当前选区闭合到指定节点的指定位置
- `extend(node, offset)` 将选区焦点移动到特定位置。
- `modify(alter, direction, tranularity)` 修改选区
- `collapseToStart()` 取消当前选区,并把光标定位在原选区的最开始处
- `collapseToEnd()` 取消当前选区,并把光标定位在原选区的结束位置
- `selectAllChildren(parentNode)` 把指定元素所有子元素设为选中区域(不包含该元素本身),并取消之前选中区域
- `addRange(range)` 将一个拖蓝区域加入选区当中
- `removeRange(range)` 从选区中移除一个拖蓝区域
- `removeAllRanges()` 从当前选区中移除所有的拖蓝区区域
- `deleteFromDocument()` 从页面中删除选区中的内容
- `toString()` 返回代表当前selection对象的字符串,例如当前选择的文本文字
- `containsNode(aNode,aPartlyContained)` 判断指定节点是否包含在当前选区内
1. Selection 基本属性
我们先上示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Selection API</title>
</head>
<body>
<div id="box">
<div onclick="showInfo()">
<p>这里是一段普通的 <span>文字</span></p>
<p>这里是另一段普通的 <span>文字</span></p>
</div>
</div>
</body>
<script>
function showInfo() {
var sel = window.getSelection();
console.log(sel.toString());
}
</script>
</html>
我们在本地运行起这个示例页面,并且在控制台中的source
面板里,在console
语句一行打上断点,从右向左选中第二行文字的一部分,然后看看当前的selection
是什么样的:
![](https://gitee.com/hjb2722404/tuchuang/raw/master/img/20201210152935.png)
在这里,可以看到当前Selection
的所有属性:
anchorNode
: 锚点,返回该选区起点所在的节点,这里的值是文字
所在的文本节点,因为我们是从右向左拖动选择的,所以起点是该节点而不是这里是另一段普通的
所在的文本节点anchorOffset
: 锚点偏移量,表示的是选区起点在其所在节点中的位置偏移量,如果起点节点是文本节点,name返回的就是从该文字节点的第一个字开始,到被选中的第一个字之间的字数;如果起点节点是一个元素,则返回的就是在选区第一个节点之前的同级节点总数(这些节点都是起点节点的子节点)。这里我们的节点是文字节点,所以返回的是开始的文
字在文字
这个文本节点中偏移量。focusNode
: 该选区终点所在的节点, 这里就是这是一段普通的
这部分文字所在的文字节点focusOffset
: 与anchorOffset
类型,这里是文本节点,并且选中内容在该节点开头,所以偏移量为0isCollapsed
: 是否闭合,此处开始节点和结束节点,开始偏移量与结束偏移量皆不相同,所以为false
.rangeCount
: 包含的拖蓝区域数量,除了firfox
外,其它浏览器默认都只有一个type
: 类型,这里的值是Range
,代表当前是一个拖蓝区域
我们修改一下内容:
<p>这里是另一段普通的 <span>文字内容啊</span></p>
然后还是从右向左拖动选择,但选择范围改变一下:
然后再看当前的偏移量:
印证了我们上面的说明。还要注意一点,对于开始节点来说,这里的偏移量是3,意味着选区的开始位置前面有3个字符,即选区是从第4个字符开始的,而对于结束节点,偏移量是4,说明选区结束位置是在该文本节点的第4个字之后。
2. Selection 选区API
getRangeAt(index)
获取拖蓝区域
我们在js
部分增加两行代码:
var range = sel.getRangeAt(0);
console.log(range);
还是和上面一样的操作,然后还是在console
语句处断点:
可以看到,成功获取到了当前的拖蓝对象,而我们在具体的网页编辑器功能开发中,通常用的最多的也是这个拖蓝对象,它的几个关键属性:
collapsed
: 描述拖蓝是否闭合,如果我们只是在区域中某个文字后面点击鼠标,并不拖动选中文字,此时选区和拖蓝的开始节点与结束节点是同一个节点,偏移量也都相同,那么我们就说此时选区和拖蓝都是闭合的。startContainer
: 拖蓝的开始节点。拖蓝与选区不同,拖蓝的开始节点与选中时拖动方向无关。所以此例中的开始节点就是另一段普通的
所在的文本节点。startOffset
:开始节点偏移量,这里是3,同样意味着拖蓝的开始位置在开始节点(文本节点)第3个字符之后。endContainer
:拖蓝的结束节点。endOffest
:结束节点偏移量,这里是4,意味着拖蓝的结束位置在结束节点(文本节点)的第4个字符之后
collapse(parentNode, offset)
将当前选区闭合到指定节点的指定位置
我们继续在js
部分增加代码:
sel.collapse(document.getElementById('box'), 0);
然后还是按照上面的方法操作,这次不再断点。
我们发现,选中内容后点击选区,拖蓝消失了,其实就是选区闭合了,因为现在的页面内容还不是可编辑区域,所以闭合后没有看到有任何光标标识拖蓝闭合的位置。
我们改造下代码:
<div id="box" contenteditable>
<div onclick="showInfo()">
<p id="first">这里是一段普通的 <span>文字</span>内容</p>
<p id="second">这里是另一段普通的 <span>文字内容啊</span></p>
</div>
</div>
//...
<script>
function showInfo() {
var sel = window.getSelection();
var range = sel.getRangeAt(0);
sel.collapse(document.getElementById('first'), 2);
}
</script>
此时,按照上文的操作完成后,如下:
根据光标位置可知,选区闭合到了ID
为first
的p
元素的第二个节点(<span>文字</span>
)之后
extend(node, offset)
将选区焦点移动到特定位置。
此时,从选区中原来拖蓝的结束节点(即使是闭合拖蓝也一样)到指定的位置之间将形成新的拖蓝,原拖蓝将消失。
我们改造下js
代码:
var sel = window.getSelection();
var range = sel.getRangeAt(0);
sel.extend(document.getElementById('first'), 1);
仍旧按照上文中的操作,从右向左拖动选中另一段普通的 文字内容
, 触发脚本后结果如下:
modify(alter, direction, tranularity)
修改选区
-
alter
:操作类型,有两个可取值:move
: 移动光标位置extend
: 扩展选区范围
-
direction
: 移动或扩展方向,有四个可取值forward
: 文本前进方向backward
: 文本后退方向left
: 向左right
: 向右
-
tranularity
: 颗粒度,按照什么为单位进行移动或扩展 -
character
: 每次移动或扩展一个字符的位置word
:每次移动或扩展一个单词的位置,英文状态下比较明显,中文状态下有时一个字就是一个单词(例如是
),有时一个词语是一个单词(例如普通
),不确定。sentence
:每次移动或扩展一个句子的位置,以句号为分界(中英文句号皆可)。line
: 每次移动或扩展一行的位置,如果原开始位置在某行的第N个字符后,那移动或扩展后的位置就是上(下)一行的第N个字符后,如果上(下)一行字符总数小于N,则移动或扩展到行首(尾)。paragraph
: 每次移动或者扩展一个段落。偏移位置规则同上。lineboundary
: 移动或扩展到行首或行尾(根据方向)。sentenceboundary
: 移动或扩展到句首或句尾。paragraphboundary
: 移动或扩展到段首或段尾。documentboundary
: 移动或扩展到文档开头或结尾。
示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Selection API</title>
</head>
<body>
<div id="box" contenteditable>
<div onclick="showInfo()">
<p id="first">这里是一段普通的 <span>文字</span>内容</p>
<p id="second">这里是另一段普通的 <span id="third">文字内容啊</span></p>
<p>这是一段带有英文的句子: this is a line with english</p>
<p>这是一段带有英文的多行句子: this is a line with english。这是一段带有英文的多行句子: this is a line with english.这是一段带有英文的多行句子: this is a line with english,这是一段带有英文的多行句子: this is a line with english。这是一段带有英文的多行句子: this is a line with english。这是一段带有英文的多行句子: this is a line with english。这是一段带有英文的多行句子: this is a line with english,这是一段带有英文的多行句子: this is a line with english。</p>
</div>
</div>
</body>
<script>
function showInfo() {
var sel = window.getSelection();
var range = sel.getRangeAt(0);
sel.modify('move','backward', 'character');
// sel.modify('extend','backward', 'character');
// sel.modify('extend','forward', 'character');
// sel.modify('extend','backward', 'word');
// sel.modify('extend','backward', 'sentence');
// sel.modify('extend','backward', 'line');
// sel.modify('extend','backward', 'paragraph');
// sel.modify('extend','backward', 'lineboundary');
// sel.modify('extend','backward', 'sentenceboundary');
// sel.modify('extend','backward', 'paragraphboundary');
// sel.modify('extend','backward', 'documentboundary');
}
</script>
</html>
可以直接将此代码复制到本地运行,并通过开放关闭js
中不同的注释来查看不同参数下操作的差别。
collapseToStart()
取消当前选区,并把光标定位在原选区的最开始处
collapseToEnd()
取消当前选区,并把光标定位在原选区的结束位置
selectAllChildren(parentNode)
把指定元素所有子元素设为选中区域(不包含该元素本身),并取消之前选中区域
addRange(range)
将一个拖蓝区域加入选区当中
removeRange(range)
从选区中移除一个拖蓝区域
由于大多数浏览器一个选区都只能拖动出一个拖蓝区域,所以执行此操作后,用户选中的拖蓝区域将消失,且光标将消失。(注:并不会删除拖蓝区域中的内容)
removeAllRanges()
从当前选区中移除所有的拖蓝区区域
参看addRange
在线代码示例中的用法
deleteFromDocument()
从页面中删除选区中的内容
toString()
返回代表当前selection对象的字符串,例如当前选择的文本文字
containsNode(aNode,aPartlyContained)
判断指定节点是否包含在当前选区内
aNode
: 用于判断是否包含在选区中的那个节点aPartlyContained
: 当此参数为true
时,即使选区只包含指定节点的一部分内容,该方法也将返回true
,当此参数为false
时,只有选区完全包含指定节点时,才返回true
。