本文是W3C Selection Api的阅读笔记。
一个文档可以带有一个全局共享的选段(selection)。一个选段可以关联有一个范围(range),如果范围为空,则选段为空。初始的时候选段都是为空。
如果选段范围为空,且范围是闭合的(collapsed),则光标就是在范围边界上。
选段可以有方法:前向(forwards)、后向(backwards),也可以没有方向(directionless)。前向意味着用户用光标选择范围的时候,开头位置在结束位置的前面;后向意味着开头位置在结束位置的后面。一般情况下,从左到右选是前向,反之后向。
选段有一个锚点(anchor)和一个焦点(focus)。如果选段范围为空,那么这两者都为空。否则的话,对于前向选择而言,开头为锚点,结尾为焦点;后向选择开头为焦点,结尾为锚点。
用户代理(浏览器)必须根据用户的行为来将选段设置成合适的结果。用户代理不能主动清楚选段(比如点击了不可编辑的区域)。
为什么要区分选段和范围,而不是将范围的属性直接纳入选段?我的思考是选段是document的属性,而范围是文档上层对象的属性。范围不属于文档,文档直接添加到范围的引用。范围可以通过
document.createRange()
创建
Selection接口
Selection的WebIDL描述:
[Exposed=Window]
interface Selection {
readonly attribute Node? anchorNode;
readonly attribute unsigned long anchorOffset;
readonly attribute Node? focusNode;
readonly attribute unsigned long focusOffset;
readonly attribute boolean isCollapsed;
readonly attribute unsigned long rangeCount;
readonly attribute DOMString type;
Range getRangeAt(unsigned long index);
void addRange(Range range);
void removeRange(Range range);
void removeAllRanges();
void empty();
void collapse(Node? node, optional unsigned long offset = 0);
void setPosition(Node? node, optional unsigned long offset = 0);
void collapseToStart();
void collapseToEnd();
void extend(Node node, optional unsigned long offset = 0);
void setBaseAndExtent(Node anchorNode, unsigned long anchorOffset, Node focusNode, unsigned long focusOffset);
void selectAllChildren(Node node);
[CEReactions]
void deleteFromDocument();
boolean containsNode(Node node, optional boolean allowPartialContainment = false);
stringifier DOMString ();
};
其中:
- anchorNode和anchorOffset定义了范围锚点的Boundary points
- focusNode和focusOffset定义了范围焦点的Boundary points
- isCollapsed用来说明范围是否闭合(锚点和焦点在一个位置,或者两者都为空)
- rangeCount,0表示无范围(可能是文档还没有关联上层对象),1表示有范围。
- type,文档还没有关联上层对象的时候为“none”,“Caret”表示选段范围闭合,其他情况下为“Range”
- getRangeAt(),返回选段范围,其参数index必须为0
- addRange(),添加文档的选段范围,必须在没有rangeCount为0的时候才可以
- removeRange(),删除范围,rangeCount变为0
- removeAllRanges(),删除所有范围
- empty,和removeAllRanges()等效
- collapse() ,闭合范围到参数指定到节点上
- setPosition() ,和collapse()等效
- collapseToStart() ,闭合到开始位置
- collapseToEnd(),闭合到结束位置
- extend(),扩展范围
- setBaseAndExtent(),双头扩展范围
- selectAllChildren() ,以某个节点的所有节点做范围
- deleteFromDocument() ,将范围之内的文档删除
- containsNode(),判断某节点是否在范围之内
对其他接口的扩展
partial interface Document {
Selection? getSelection();
};
partial interface Window {
Selection? getSelection();
};
partial interface mixin GlobalEventHandlers {
attribute EventHandler onselectstart;
attribute EventHandler onselectionchange;
};
document.getSelection()
返回当前选段window.getSelection()
返回当前选段- 增加selectstart事件和相应的处理器onselectstart
- 如果当前选段为空,或者选段为闭合状态,当用户代理准备更新选段的范围时,必须触发selectstart事件(可回溯并可以取消),事件目标设置在新范围的开始位置所在的节点。
- 如果selectstart被撤销时,用户代理不能修改既有选段。
- 当selection被设为空时,用户代理不需要触发此事件。
- 增加selectionchange事件和相应的处理器onselectionchange
- 当需要替换当前选段的范围时,用户代理必须放置一个selectionchange事件在事件队列中。
- 此事件目标是document,且不可回溯不可撤销
(完)