选择 API

W3C 工作草案

关于此文档的更多细节
此版本
https://w3org.cn/TR/2025/WD-selection-api-20250105/
最新发布版本
https://w3org.cn/TR/selection-api/
最新编辑草案
https://w3c.github.io/selection-api/
历史
https://w3org.cn/standards/history/selection-api/
提交历史
测试套件
https://wpt.fyi/results/selection/
编辑
(Apple Inc.)
反馈
GitHub w3c/selection-api (pull requests, new issue, open issues)

摘要

本文档是 Selection API 及与选区相关功能的规范初步草案。它取代了 HTML 规范中几个旧章节,以及旧版 DOM Range 规范中的选区部分。

本文档定义了用于选区的 API,允许用户和作者选择文档的一部分,或指定用于复制、粘贴及其他编辑操作的关注点。

本文档状态

本节描述本文档在发布时的状态。当前的 W3C 出版物列表以及本技术报告的最新修订版可在 https://w3org.cn/TR/ 的 W3C 技术报告索引 中找到。

此工作正在进行中。

本文档由 Web 编辑工作组 (Web Editing Working Group) 作为工作草案发布,采用 推荐标准轨道 (Recommendation track)

发布为工作草案并不意味着 W3C 及其成员的认可。

这是一份草案文档,可能会随时被其他文档更新、替换或废弃。将其作为非进行中工作引用是不恰当的。

本文档由在 W3C 专利政策下运作的小组编制。W3C 维护了一份与该小组可交付成果相关的专利披露公开列表;该页面还包含披露专利的说明。任何个人如果确实知悉某项其认为包含必要权利要求 (Essential Claim(s)) 的专利,必须按照 W3C 专利政策第 6 节披露相关信息。

本文档受 2023 年 11 月 3 日 W3C 流程文档 管辖。

1. 背景

本节是非规范性的。

IE9 和 Firefox 6.0a2 允许选区中包含任意范围,这遵循了本规范最初的描述。然而,这导致了一些作者、实现者和规范编写者都必须处理的麻烦的边界情况,且它们并无实际意义。Chrome 14 开发版和 Opera 11.11 对选区进行了积极的规范化,例如不允许选区位于空元素内等,但这也被认为是个坏主意,因为它剥夺了作者的灵活性。

因此,我将规范修改为一个折衷方案,它允许一定的简化,但不对作者施加太多限制。详见 讨论。基本上,它会在某些地方抛出异常,试图阻止选区包含一个非 Element 或 Text 节点的边界点的范围,或者一个不从属于 Document 的边界点。

但这导致 getRangeAt() 必须开始返回副本而非引用。此外,它容易在边界情况下出现奇怪的失败。或许最重要的是,当发生 DOM 变更时,可能会出现各种问题,例如如果边界节点的父节点被移除,且变更规则会将新的边界点置于非 Text/Element 节点内。最后,之前指定的行为具有符合两大主流实现的优势,而新行为则无人遵循。因此,我将其改了回来。

详见 bug 15470。IE9、Firefox 12.0a1、Chrome 17 开发版和 Opera Next 12.00 alpha 全部将范围初始化为 null。

2. 定义

每个具有 浏览上下文文档 都关联着一个唯一的 选区 (selection)

这是 HTML 规范的要求。IE9 和 Opera Next 12.00 alpha 似乎遵循了这一点,而 Firefox 12.0a1 和 Chrome 17 开发版似乎没有。参见 Mozilla bug, WebKit bug

此单一的 选区 必须被 文档 的所有内容共享(嵌套的 文档 除外),包括 文档 中的任何 编辑宿主 (editing hosts)

每个 选区 可关联一个单一的 范围 (range)。当没有 范围 关联到 选区 时,该选区是 空的 (empty)。选区必须初始为 空的

文档选区 是与该 文档 关联的单例对象,因此当调用 Document.open() 时,它会被替换为一个新对象。详见 bug 15470。IE9 和 Opera Next 12.00 alpha 允许用户通过在某处点击来将范围重置为 null;Firefox 12.0a1 和 Chrome 17 开发版则不允许。我们遵循 Gecko/WebKit 的做法,因为它降低了 getRangeAt(0) 抛出异常的几率。

一旦 选区 与给定的 范围 关联,除非本规范另有要求,否则它必须继续与该相同的 范围 保持关联。

例如,如果 DOM 以某种改变范围边界点的方式发生变化,或者脚本修改了范围的边界点,则同一个范围对象必须继续与选区关联。然而,如果用户更改了选区或脚本调用了 addRange(),则根据本规范其他部分的要求,选区必须与一个新的范围对象关联。

如果 选区范围 不为 null 且已 折叠 (collapsed),则插入符位置必须位于该 范围边界点。当 选区折叠 时,本规范不定义插入符位置;用户代理应遵循平台惯例,决定插入符位于 选区 的开头、结尾还是其他位置。

每个 选区 都有一个 方向 (direction)向前 (forwards)向后 (backwards)无方向 (directionless)。如果用户通过首先指示 范围 的一个 边界点,然后再指示另一个(例如点击一点并拖动到另一点)来创建 选区,且第一个指示的 边界点 在第二个 之后,则相应的 选区 最初必须是 向后 的。如果第一个指示的 边界点 在第二个 之前,则相应的 选区 最初必须是 向前 的。否则,它必须是 无方向 的。

选区范围 被脚本变更时(例如通过 selectNode(node)),必须保留 选区方向

每个 选区 都有一个 锚点 (anchor) 和一个 焦点 (focus)。如果 选区范围 为 null,则其 锚点焦点 均为 null。如果 选区范围 不为 null 且其 方向向前,则其 锚点范围开始,其 焦点结束。否则,其 焦点开始,其 锚点结束

选区锚点焦点 不一定在 文档树 中。它们可能位于同一个 文档阴影树 (shadow tree) 中。

每个 文档input 元素和 textarea 元素都有一个布尔值 has scheduled selectionchange event (已调度 selectionchange 事件),初始为 false。

3. 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;
  readonly attribute DOMString direction;
  Range getRangeAt(unsigned long index);
  undefined addRange(Range range);
  undefined removeRange(Range range);
  undefined removeAllRanges();
  undefined empty();
  sequence<StaticRange> getComposedRanges(optional GetComposedRangesOptions options = {});
  undefined collapse(Node? node, optional unsigned long offset = 0);
  undefined setPosition(Node? node, optional unsigned long offset = 0);
  undefined collapseToStart();
  undefined collapseToEnd();
  undefined extend(Node node, optional unsigned long offset = 0);
  undefined setBaseAndExtent(Node anchorNode, unsigned long anchorOffset, Node focusNode, unsigned long focusOffset);
  undefined selectAllChildren(Node node);
  undefined modify(optional DOMString alter, optional DOMString direction, optional DOMString granularity);
  [CEReactions] undefined deleteFromDocument();
  boolean containsNode(Node node, optional boolean allowPartialContainment = false);
  stringifier;
};

dictionary GetComposedRangesOptions {
  sequence<ShadowRoot> shadowRoots = [];
};
anchorNode

该属性必须返回 此对象锚点 节点;如果 锚点 为 null,或者 锚点 不在 文档树 中,则返回 null

anchorOffset

该属性必须返回 此对象锚点 偏移量;如果 锚点 为 null,或者 锚点 不在 文档树 中,则返回 0

focusNode

该属性必须返回 此对象焦点 节点;如果 焦点 为 null,或者 焦点 不在 文档树 中,则返回 null

focusOffset

该属性必须返回 此对象焦点 偏移量;如果 焦点 为 null,或者 焦点 不在 文档树 中,则返回 0

isCollapsed

当且仅当 锚点焦点 相同(包括两者均为 null 的情况)时,该属性必须返回 true。否则必须返回 false。

rangeCount

如果 此对象,或者 焦点锚点 不在 文档树 中,该属性必须返回 0,否则必须返回 1

type

如果 此对象,或者 焦点锚点 不在 文档树 中,该属性必须返回 "None";如果 此对象范围折叠,则返回 "Caret";否则返回 "Range"

direction

如果 此对象 或此选区为 无方向,该属性必须返回 "none";如果此选区的方向为 向前,则返回 "forward";如果方向为 向后,则返回 "backward"

getRangeAt() 方法

如果 index 不为 0,或者 此对象,或者 焦点锚点 不在 文档树 中,该方法必须抛出 IndexSizeError 异常。否则,它必须返回对 此对象范围 的引用(而非副本)。

因此,如果在此期间没有移除 此对象 的范围,该方法的后续调用将返回相同的 范围 对象。特别地,如果 选区 不为 ,则 getSelection().getRangeAt(0) === getSelection().getRangeAt(0) 的求值结果为 true

addRange() 方法

The method must follow these steps

  1. 如果 range 的边界点的 根节点 不是与 此对象 关联的 文档,则中止这些步骤。
  2. 如果 rangeCount 不为 0,则中止这些步骤。
  3. 通过强引用(而非通过制作副本)将 此对象 的范围设置为 range

由于 范围 是通过引用添加的,因此对 getRangeAt(0) 的后续调用将返回相同的对象,并且脚本在添加 范围 后对其所做的任何更改都必须反映在 选区 中,直到其他操作移除或替换 此对象范围。特别地,在运行以下代码后,选区 将包含 b 而不是 avar r = document.createRange(); r.selectNode(a); getSelection().addRange(r); r.selectNode(b);

在第 2 步,Chrome 58 和 Edge 25 不执行任何操作。Firefox 51 会产生一个多范围选区。至少它们保留了现有的 范围

在第 3 步,Chrome 58 和 Firefox 51 存储一个引用,如本文所述。Edge 25 存储一个副本。如果修改了 范围,Firefox 51 会更改其选区。

removeRange() 方法

如果 此对象范围range,该方法必须通过解除其 范围 的关联来使 此对象 变为 。否则,它必须抛出 NotFoundError

removeAllRanges() 方法

如果 此对象 有关联的 范围,该方法必须通过解除其 范围 的关联来使 此对象 变为

empty() 方法

该方法必须是 removeAllRanges() 的别名,并表现一致。

getComposedRanges() 方法
  1. 如果 此对象,则返回一个空数组。
  2. 否则,设 startNode 为与 此对象 关联的 范围开始节点,设 startOffset 为该 范围开始偏移量
  3. startNode节点startNode根节点阴影根节点 (shadow root),且 startNode根节点 不是 options["shadowRoots"] 中任一节点的 包含阴影的包含祖先 时,重复以下步骤:
    1. 设置 startOffsetstartNode根节点宿主 (host) 的索引。
    2. 设置 startNodestartNode根节点宿主父节点
  4. endNode 为与 此对象 关联的 范围结束节点,设 endOffset 为该 范围结束偏移量
  5. endNode节点endNode根节点阴影根节点,且 endNode根节点 不是 options["shadowRoots"] 中任一节点的 包含阴影的包含祖先 时,重复以下步骤:
    1. 设置 endOffsetendNode根节点宿主 的索引加 1。
    2. 设置 endNodeendNode根节点宿主父节点
  6. 返回一个包含新的 StaticRange 的数组,其 开始节点startNode开始偏移量startOffset结束节点endNode结束偏移量endOffset
collapse() 方法

The method must follow these steps

  1. 如果 node 为 null,此方法必须表现得与 removeAllRanges() 一致并中止这些步骤。
  2. 如果 nodeDocumentType,抛出 InvalidNodeTypeError 异常并中止这些步骤。
  3. 如果 offset 长度超过 node长度,该方法必须抛出 IndexSizeError 异常并中止这些步骤。
  4. 如果与 此对象 关联的 文档 不是 node包含阴影的包含祖先,则中止这些步骤。
  5. 否则,设 newRange 为一个新的 范围
  6. 设置 newRange开始结束 为 (node, offset)。
  7. 设置 此对象范围newRange
setPosition() 方法

该方法必须是 collapse() 的别名,并表现一致。

collapseToStart() 方法

如果 此对象,该方法必须抛出 InvalidStateError 异常。否则,它必须创建一个新的 范围设置开始结束 均为 此对象范围开始,然后将 此对象范围 设置为该新创建的 范围

对于 collapseToStart/End,IE9 会变更现有范围,而 Firefox 9.0a2 和 Chrome 15 开发版则将其替换为一个新范围。本规范遵循多数派,将其替换为新范围,使旧 Range 对象保持不变。

collapseToEnd() 方法

如果 此对象,该方法必须抛出 InvalidStateError 异常。否则,它必须创建一个新的 范围设置开始结束 均为 此对象范围结束,然后将 此对象范围 设置为该新创建的 范围

extend() 方法

The method must follow these steps

  1. 如果与 此对象 关联的 文档 不是 node包含阴影的包含祖先,则中止这些步骤。
  2. 如果 此对象,抛出 InvalidStateError 异常并中止这些步骤。
  3. oldAnchoroldFocus此对象锚点焦点,设 newFocus边界点 (node, offset)。
  4. newRange 为一个新的 范围
  5. 如果 node根节点此对象范围根节点 不相同,则将 newRange开始结束 设置newFocus
  6. 否则,如果 oldAnchornewFocus 之前 或相等,则 设置 newRange开始oldAnchor,然后将 结束 设置为 newFocus
  7. 否则,设置 newRange开始newFocus,然后将 结束 设置为 oldAnchor
  8. 设置 此对象范围newRange
  9. 如果 newFocusoldAnchor 之前,将 此对象方向 设置为 向后。否则,将其设置为 向前

约 2011 年 1 月逆向工程的结果。IE 不支持该方法,因此我依赖于 Firefox(2000 年前就实现了 extend())和 WebKit(2007 年实现)。我基本忽略了 Opera,因为 gsnedders 告诉我它的实现不兼容。Firefox 12.0a1 似乎会变更现有范围。IE9 不支持 extend(),且无法判断 Chrome 17 开发版或 Opera Next 12.00 alpha 是变更还是替换范围,因为 getRangeAt() 本身返回的就是副本。尽管如此,为了与 collapse() 保持一致,我在此违背了 Gecko 的做法。

setBaseAndExtent() 方法

The method must follow these steps

  1. 如果 anchorOffset 长度超过 anchorNode长度,或者 focusOffset 长度超过 focusNode长度,抛出 IndexSizeError 异常并中止这些步骤。
  2. 如果与 此对象 关联的 文档 不是 anchorNodefocusNode包含阴影的包含祖先,则中止这些步骤。
  3. anchor边界点 (anchorNode, anchorOffset),设 focus边界点 (focusNode, focusOffset)。
  4. newRange 为一个新的 范围
  5. 如果 anchorfocus 之前设置 newRange开始anchor,其 结束focus。否则,设置 它们分别为 focusanchor
  6. 设置 此对象范围newRange
  7. 如果 focusanchor 之前,将 此对象方向 设置为 向后。否则,将其设置为 向前
selectAllChildren() 方法

The method must follow these steps

  1. 如果 nodeDocumentType,抛出 InvalidNodeTypeError 异常并中止这些步骤。
  2. 如果 node根节点 不是与 此对象 关联的 文档,则中止这些步骤。
  3. newRange 为一个新的 范围childCountnode子节点 数量。
  4. 设置 newRange开始 为 (node, 0)。
  5. 设置 newRange结束 为 (node, childCount)。
  6. 设置 此对象范围newRange
  7. 设置 此对象方向向前

主要基于 Firefox 9.0a2。它有一个我没有重现的 bug,即如果将 Document 作为参数传递,结束偏移量会变成 1 而不是其子节点数量。它还会抛出 RangeException 而不是 DOMException,因为其实现早于两者的合并。

IE9 的表现类似,但有缺陷。如果节点是分离的或 display:none,它会抛出“未指定的错误”,显然在其他一些随机情况下也会这样。对于分离的注释(仅限注释!),它会抛出“无效参数”。最后,如果你传递给它一个注释,它似乎会选择整个注释,而不像对待文本节点那样。

Chrome 16 开发版的表现符合其 Selection 实现的预期。它拒绝选择任何不可见的内容,所以它几乎总是错误的。Opera 11.50 在我的所有测试中都什么也不做,一如既往。

新范围替换任何现有范围,而不变更它。这与 IE9 和 Firefox 12.0a1 一致。(Chrome 17 开发版和 Opera Next 12.00 alpha 无法测试,因为 getRangeAt() 返回的是副本。)

modify() 方法

The method must follow these steps

  1. 如果 alter 与 "extend" 或 "move" 不符合 ASCII 大小写不敏感 匹配,则中止这些步骤。
  2. 如果 direction 与 "forward"、"backward"、"left" 或 "right" 不符合 ASCII 大小写不敏感 匹配,则中止这些步骤。
  3. 如果 granularity 与 "character"、"word"、"sentence"、"line"、"paragraph"、"lineboundary"、"sentenceboundary"、"paragraphboundary"、"documentboundary" 不符合 ASCII 大小写不敏感 匹配,则中止这些步骤。
  4. 如果 此对象选区 为空,则中止这些步骤。
  5. effectiveDirection向后
  6. 如果 direction 与 "forward" 符合 ASCII 大小写不敏感 匹配,设置 effectiveDirection向前
  7. 如果 direction 与 "right" 符合 ASCII 大小写不敏感 匹配,且 此对象选区焦点内联基准方向ltr,设置 effectiveDirection向前
  8. 如果 direction 与 "left" 符合 ASCII 大小写不敏感 匹配,且 此对象选区焦点内联基准方向rtl,设置 effectiveDirection向前
  9. 设置 此对象选区方向effectiveDirection
  10. 如果 alter 与 "extend" 符合 ASCII 大小写不敏感 匹配,则将 此对象选区焦点 设置为用户请求按 granularity 扩展选区时的位置。
  11. 否则,将 此对象选区焦点锚点 设置为用户请求按 granularity 移动选区时的位置。

我们需要更精确地定义按每种颗粒度扩展或移动选区的含义。

deleteFromDocument() 方法

如果 此对象 不为 ,且 焦点锚点 均在 文档树 中,该方法必须在 此对象范围 上调用 deleteContents()。否则该方法必须不执行任何操作。

这是唯一一个实际变更范围而不是替换它的方法。这与 IE9 和 Firefox 12.0a1 一致。(Chrome 17 开发版和 Opera Next 12.00 alpha 无法测试,因为 getRangeAt() 返回的是副本。)

containsNode() 方法

如果 此对象,或者 node根节点 不是与 此对象 关联的文档,该方法必须返回 false

否则,如果 allowPartialContainmentfalse,当且仅当其 范围开始node 内的第一个 边界点 之前或在视觉上等效,范围结束node 内的最后一个 边界点 之后或在视觉上等效时,该方法必须返回 true

如果 allowPartialContainmenttrue,当且仅当其 范围开始node 内的最后一个 边界点 之前或在视觉上等效,范围结束node 内的第一个 边界点 之后或在视觉上等效时,该方法必须返回 true

stringifier

字符串化必须返回字符串,如果 此对象 关联有 范围,该字符串是渲染文本的拼接。

如果选区位于 textareainput 元素内,它必须返回其值中选定的子字符串。

另请参见 Gecko 的 nsISelection.idl。本规范尚未包含其中的所有内容,特别是 selectionLanguageChange() 和 containsNode() 缺失。它们缺失是因为我无法找到如何用范围 (Ranges) 来定义它们。

最初,Selection 接口是 Netscape 的一项功能。最初的实现被带到了 Gecko (Firefox) 中,该功能后来由其他浏览器引擎独立实现。Netscape 实现总是允许在单个选区中有多个范围,例如这样用户可以选择表格的一列。然而,多范围选区被证明是一个 Web 开发人员不了解的棘手边界情况,甚至 Gecko 开发人员也很少能正确处理。其他浏览器引擎从未实现该功能,而是以各种不兼容的方式将选区限制为单一范围。

本规范遵循非 Gecko 引擎,将选区限制为最多一个范围,但 API 最初仍是为具有任意数量范围的选区设计的。这解释了诸如 removeRange()removeAllRanges() 共存,以及一个接收必须始终为零的整数参数的 getRangeAt() 方法等奇怪现象。

Selection 接口的所有成员都是根据对对象表示的 范围 对象(如果有)的操作来定义的。这些操作可能会像 Range 接口定义的那样抛出异常;因此,这可能导致 Selection 接口的成员除了上面明确指出的异常外,也会抛出异常。

4. 对其他接口的扩展

本规范扩展了几个接口,为本规范定义的接口提供了入口点。

4.1 Document 接口的扩展

Document 接口定义于 [HTML]。

WebIDLpartial interface Document {
  Selection? getSelection();
};
getSelection() 方法

如果 此对象 有关联的 浏览上下文,该方法必须返回与 此对象 关联的 选区,否则返回 null

4.2 Window 接口的扩展

Window 接口定义于 [HTML]。

WebIDLpartial interface Window {
  Selection? getSelection();
};
getSelection() 方法

该方法必须在 此对象Window.document 属性上调用 getSelection() 并返回结果。

4.3 GlobalEventHandlers 接口的扩展

GlobalEventHandlers 接口定义于 [HTML]。

WebIDLpartial interface mixin GlobalEventHandlers {
  attribute EventHandler onselectstart;
  attribute EventHandler onselectionchange;
};
onselectstart

该属性必须是所有 HTML 元素Document 对象和 Window 对象支持的 selectstart 事件的 事件处理程序 IDL 属性

onselectionchange

该属性必须是所有 HTML 元素Document 对象和 Window 对象支持的 selectionchange 事件的 事件处理程序 IDL 属性

5. 响应 DOM 变更

当用户代理要对 CharacterData 替换数据截取子字符串 时,用户代理必须就像其为 动态范围 (live range) 一样,更新与该 CharacterData节点文档选区 关联的 范围

当用户代理要拆分 Text 节点 时,用户代理必须就像其为 动态范围 一样,更新与该 Text节点文档选区 关联的 范围

当用户代理要运行 normalize() 方法的步骤时,用户代理必须就像其为 动态范围 一样,更新与 此对象节点文档选区 关联的 范围

当用户代理要 移除插入 节点 时,用户代理必须就像其为 动态范围 一样,更新与该 节点节点文档选区 关联的 范围

6. 用户交互

用户代理应允许用户更改与 活动文档 关联的 选区。如果用户对 选区 进行任何修改,用户代理必须创建一个具有合适 开始结束 的新 范围,并使 选区 与此新 范围 关联(而非修改现有 范围),且如果 开始结束 之前或相等,则将 选区方向 更新为 向前;如果 结束开始 之前,则更新为 向后;或者如果由于平台惯例无法对 开始结束 进行排序,则更新为 无方向

用户代理在响应任何用户操作(例如点击非可编辑区域)时,不得使之前非 选区

详见 bug 15470。IE9 和 Opera Next 12.00 alpha 允许用户通过在某处点击来将范围重置为 null;Firefox 12.0a1 和 Chrome 17 开发版则不允许。我遵循 Gecko/WebKit 的做法,因为它降低了 getRangeAt(0) 抛出异常的几率。

6.1 selectstart 事件

当用户代理准备响应用户发起的动作而将新范围 newRange选区 关联时,如果 选区 之前是 空的 或之前关联的范围已 折叠,则用户代理必须在更改选区之前,在与 newRange开始边界点 关联的 节点触发一个名为 selectstart 的冒泡且可取消的事件。

如果事件被取消,用户代理不得更改 选区

当用户代理将 选区 设置为 时,不得 触发事件

6.2 selectionchange 事件

选区 与其 范围 解除关联、与新 范围 关联,或关联的 范围边界点 被用户或内容脚本修改时,用户代理必须在 文档调度 selectionchange 事件

inputtextarea 元素提供文本选区且其选区发生变化(范围或 方向 变化)时,用户代理必须在该元素上 调度 selectionchange 事件

6.2.1 调度 selectionchange 事件

要在节点 target调度 selectionchange 事件 (schedule a selectionchange event),请运行以下步骤:

  1. 如果 targethas scheduled selectionchange event 为 true,中止这些步骤。
  2. 用户交互任务源排队一个任务,以便在 target触发 selectionchange 事件

6.2.2 触发 selectionchange 事件

要在节点 target触发 selectionchange 事件 (fire a selectionchange event),请运行以下步骤:

  1. targethas scheduled selectionchange event 设置为 false。
  2. 如果 target 是一个元素,则在 target触发一个名为 selectionchange 的冒泡且不可取消的事件。
  3. 否则,如果 target 是文档,则在 target触发一个名为 selectionchange 的非冒泡且不可取消的事件。

7. 一致性

除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。本规范中的其他所有内容均为规范性内容。

本规范定义了适用于单一产品的符合性准则:实现本规范所含接口的 用户代理 (user agent)

8. 安全与隐私考量

目前没有针对本标准的已知安全考量。

为了减轻暴露用户使用辅助技术带来的潜在隐私风险,例如,当用户选择修改文档的 选区 时,用户代理 可以选择模拟通常与 selectstartselectionchange 事件相关的鼠标和键盘事件。

A. 致谢

非常感谢:

B. 参考资料

B.1 规范性参考资料

[css-writing-modes-4]
CSS 书写模式第 4 版。Elika Etemad; Koji Ishii。W3C。2019 年 7 月 30 日。W3C 候选推荐标准。URL: https://w3org.cn/TR/css-writing-modes-4/
[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
HTML 标准. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 活标准. URL: https://html.whatwg.cn/multipage/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[url]
URL 标准. Anne van Kesteren. WHATWG. 活标准. URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/