输入事件 第 1 级

W3C 停止草案

有关本文件的更多详细信息
此版本:
https://www.w3.org/TR/2023/DISC-input-events-1-20230928/
最新发布版本:
https://www.w3.org/TR/input-events-1/
最新编辑草案:
https://w3c.github.io/input-events/
历史记录:
https://www.w3.org/standards/history/input-events-1/
提交历史
编辑:
(受邀专家)
前编辑:
(微软) (截至2015年2月23日)
反馈:
GitHub w3c/input-events (拉取请求新问题开放问题)
按级别发布的最新版本
第 1 级
第 2 级
按级别的最新编辑草案
第 1 级
第 2 级

摘要

本规范定义了文本及相关输入事件的补充,以便在文本编辑器应用程序和其他处理文本输入和文本格式的应用程序中监控和操作默认的浏览器行为。 本规范基于 UI 事件规范 [UI-EVENTS]。

本文档的状态

本节描述了本文档在发布时的状态。当前 W3C 发布的文档列表及该技术报告的最新版本可以在 W3C 技术报告索引中找到:https://www.w3.org/TR/。

输入事件第 1 级是输入事件的第一个版本 [INPUT-EVENTS]。

输入事件规范的 测试套件实现报告 仍在进行中。

本文档由 Web 编辑工作组 作为已停止草案发布,使用了 推荐标准流程

作为已停止草案发布并不意味着 W3C 及其成员对此的认可。

作为已停止草案发布意味着本文档不再有继续推进或维护的意图。因此,引用本文档仅适用于作为已放弃的工作。

本文档由一个在 W3C 专利政策 下运作的工作组制作。 W3C 维护着与该工作组相关交付物的 任何专利披露的公共列表, 该页面还包括专利披露的说明。任何知晓包含 必要声明的专利信息的个人, 必须按照 W3C 专利政策第 6 节 披露该信息。

本文档受 2023年6月12日 W3C流程文档 管辖。

1. 介绍

本文档描述了与编辑相关的两个事件的扩展 —— inputbeforeinput,它们在 UI 事件规范中有详细说明 [UI-EVENTS]。这些事件的目标是允许开发者在编辑发生前后理解和/或覆盖默认的编辑行为。

2. 定义

DataTransfer
DataTransfer 对象为某些输入类型包含富文本和纯文本数据。 [HTML]
表达意图
用户可以通过键盘、输入法、语音或类似方式 表达意图 来执行特定的编辑操作。具体的输入操作遵循平台特定的约定映射到意图。
kill buffer

此定义不是规范性的。

kill buffer 是一个内存中的富文本内容存储,与剪贴板分开,允许临时存储通过特定删除命令删除的内容。用户可以通过表达意图来用 kill buffer 中的内容替换当前选择,表达意图时会 yank kill buffer 的内容。
字符
字符 是一个 扩展字素簇。[UAX29]

3. 解决的问题

本节为非规范性。

创建基于网页的文本编辑器需要在浏览器代码之外编写大量的 JavaScript,原因包括:

  1. 浏览器对某些编辑操作的处理方式并不一致。
  2. 浏览器在处理某些编辑操作时往往会出现漏洞。
  3. 各个网站可能会有自己处理某些编辑操作的自定义偏好。
  4. 浏览器中的高级文本编辑功能开发并没有遵循 可扩展 Web 宣言 的原则,即这些功能的开发并不总是与 Web 开发者社区的需求协调进行。

本规范旨在通过提供一种简单的方法来缓解这一问题,允许 Web 开发者通过 beforeinput 事件覆盖浏览器对所有与文本编辑相关的用户输入的处理,并通过 input 事件监控浏览器因用户输入而在 DOM 中的更改。

4. 使用案例

本节为非规范性。

  1. 创建一个 JavaScript 文本编辑器,其中使用 <strong> 标签代替 <b> 标签来标记用户标记为加粗的文本,使用任何浏览器内置的方式加粗文本,而不需要访问所有现有的浏览器。
  2. 创建一个 JavaScript 文本编辑器,该编辑器在后台使用数据模型,并由 JavaScript 负责将编辑文本的更改渲染到 DOM。
  3. 创建一个 JavaScript 编辑器,该编辑器只允许富文本编辑的某个子集(例如:允许加粗,但不允许斜体)。
  4. 创建一个协作编辑器,JavaScript 用于根据用户意图渲染 DOM 中的更改,用户使用不同的浏览器以不同的方式表达特定的意图。
  5. 创建一个具有不同用户访问选项的 JavaScript 编辑器,其中一些用户只能添加或删除文本,另一些用户只能添加或删除某些类型的格式。

5. 输入事件类型

在用户尝试编辑标记时,输入事件会在操作之前(beforeinput 事件)和之后(input 事件)发送。这包括内容的插入和删除,以及格式更改。

输入事件会在作为编辑主机的元素上 调度 [UI-EVENTS],这些元素包括设置了 contenteditable 属性的元素、textarea 元素,以及允许文本输入的 input 元素。

5.1 接口 InputEvent

WebIDL

partial interface InputEvent {
       readonly attribute DataTransfer? dataTransfer;
       sequence<StaticRange> getTargetRanges();
    };
    
    partial dictionary InputEventInit {
       DataTransfer? dataTransfer = null;
       sequence<StaticRange> targetRanges = [];
    };

InputEventInputEventInit 对象定义于 [UI-EVENTS]。

inputTypedataTransfertargetRanges 属性会初始化 InputEventInit 对象的对应属性。

5.1.1 概述

本节是非规范性的。

下表总结了 datadataTransfer 属性在何时包含内容、何时为 null,以及 getTargetRanges() 方法何时返回空数组或非空数组,取决于 inputType。

编辑主机 inputType data dataTransfer getTargetRanges()
Contenteditable "insertText", "insertCompositionText", "formatSetBlockTextDirection", "formatSetInlineTextDirection", "formatBackColor", "formatFontColor", "formatFontName", "insertLink" null 非空数组
Contenteditable "insertFromPaste", "insertFromPasteAsQuotation", "insertFromDrop", "insertReplacementText", "insertFromYank" null 非空数组
<textarea>, <input type="text"> "insertText", "insertCompositionText", "insertFromPaste", "insertFromPasteAsQuotation", "insertFromDrop", "insertReplacementText", "insertFromYank", "formatSetBlockTextDirection", "formatSetInlineTextDirection", "formatBackColor", "formatFontColor", "formatFontName", "insertLink" null 空数组
全部 "historyUndo", "historyRedo" null null 空数组
Contenteditable 所有剩余 null null 非空数组
<textarea>, <input type="text"> 所有剩余 null null 空数组

5.1.2 属性

beforeinput 事件的可取消性取决于 inputType。

要选择的 inputType 取决于用户的 意图表达,编辑是否在 IME 组成期间发生,以及选择的状态。

本规范定义了 inputType 值,如下表中的 inputType 列所示。

inputType 用户的意图表达 IME 组成的一部分 beforeinput 可取消 选择状态
"insertText" 插入键入的纯文本 未定义 任何
"insertReplacementText" 通过拼写检查器、自动更正或类似方式替换现有文本 未定义 任何
"insertLineBreak" 插入换行符 未定义 任何
"insertParagraph" 插入段落分隔符 未定义 任何
"insertOrderedList" 插入有序列表 任何
"insertUnorderedList" 插入无序列表 任何
"insertHorizontalRule" 插入水平线 任何
"insertFromYank" 用存储在 kill buffer 中的内容替换当前选择 任何
"insertFromDrop" 通过拖放插入内容到 DOM 中 任何
"insertFromPaste" 粘贴 任何
"insertFromPasteAsQuotation" 以引用形式粘贴内容 任何
"insertTranspose" 互换最后输入的两个 字符 任何
"insertCompositionText" 替换当前的组成字符串 任何
"insertLink" 插入链接 任何
"deleteWordBackward" 删除光标位置前的一个单词 未定义 已折叠
"deleteWordForward" 删除光标位置后的一个单词 未定义 已折叠
"deleteSoftLineBackward" 从光标到最近的视觉换行符之间删除 未定义 已折叠
"deleteSoftLineForward" 从光标到最近的视觉换行符之后删除 未定义 已折叠
"deleteEntireSoftLine" 从光标位置前的视觉换行符到光标位置后的视觉换行符之间删除 未定义 已折叠
"deleteHardLineBackward" 从光标位置删除到块元素的开头或 br 元素之前 未定义 已折叠
"deleteHardLineForward" 从光标位置删除到块元素的末尾或 br 元素之后 未定义 已折叠
"deleteByDrag" 通过拖动从 DOM 中移除内容 任何
"deleteByCut" 作为剪切的一部分删除当前选择 任何
"deleteContent" 删除选择内容而不指定删除的方向,该意图未被其他 inputType 覆盖 未定义 未折叠
"deleteContentBackward" 删除光标位置前的内容,此意图未被其他 inputType 覆盖,或删除选择并在删除后将选择折叠到起点 未定义 任何
"deleteContentForward" 删除光标位置后的内容,此意图未被其他 inputType 覆盖,或删除选择并在删除后将选择折叠到终点 未定义 任何
"historyUndo" 撤销上一次编辑操作 任何
"historyRedo" 重做上次撤销的编辑操作 任何
"formatBold" 启用粗体文本 任何
"formatItalic" 启用斜体文本 任何
"formatUnderline" 启用下划线文本 任何
"formatStrikeThrough" 启用删除线文本 任何
"formatSuperscript" 启用上标文本 任何
"formatSubscript" 启用下标文本 任何
"formatJustifyFull" 使当前选区完全对齐 任何
"formatJustifyCenter" 使当前选区居中对齐 任何
"formatJustifyRight" 使当前选区右对齐 任何
"formatJustifyLeft" 使当前选区左对齐 任何
"formatIndent" 缩进当前选区 任何
"formatOutdent" 减少当前选区缩进 任何
"formatRemove" 移除当前选区的所有格式 任何
"formatSetBlockTextDirection" 设置文本块方向 任何
"formatSetInlineTextDirection" 设置内联文本方向 任何
"formatBackColor" 更改背景颜色 任何
"formatFontColor" 更改字体颜色 任何
"formatFontName" 更改字体名称 任何
注意
其他规范可能会扩展此定义。
注意
上述提到的inputTypes的存在并不意味着任何特定的实现都会支持所有这些。 但是,如果某个浏览器支持可能导致DOM更改的编辑操作,它必须 触发 [UI-EVENTS] 相应的beforeinputinput事件。
注意
如果选择已折叠,"deleteContentBackward"将用于用户请求在文本节点中删除文本时,以及在光标位于文本节点开头时用户意图删除更复杂的元素或合并段落。
注意
如果选择已折叠,"deleteContentForward"将用于用户请求在文本节点中删除文本时,以及在光标位于文本节点末尾时用户意图删除更复杂的元素或合并段落。
注意

此注释不是规范性的。

在某些平台的某些脚本中,带有折叠选择的文本节点内的向后删除操作会删除单个代码点 [INFRA],而不是整个字素簇 [UAX29]。 可以使用getTargetRanges()方法来查明浏览器在文本节点中默认会删除多少个代码点 [INFRA]。
注意

此注释不是规范性的。

在某些平台的某些脚本中,带有折叠选择的文本节点内的向前删除操作会删除整个字素簇 [UAX29],而不是单个代码点 [INFRA]。 可以使用getTargetRanges()方法来查明浏览器在文本节点中默认会删除多少个代码点 [INFRA]。

data 包含与要添加到文档中的内容相关的纯文本数据。

inputType 编辑主机 data
"insertText""insertCompositionText" 任何 要插入的纯文本字符串
"insertFromPaste", "insertFromPasteAsQuotation", "insertFromDrop", "insertTranspose", "insertReplacementText""insertFromYank" inputtextarea 要插入的纯文本字符串
"formatSetInlineTextDirection""formatSetBlockTextDirection" 任何 "ltr", "rtl", "auto""null"
"formatBackColor""formatFontColor" 任何 包含建议颜色的字符串,表示序列化的 CSS 组件值 [CSSOM]。
"formatFontName" 任何 建议的字体家族 CSS 属性值
"insertLink" 任何 建议链接的 URL
其余所有 任何 null

dataTransfer 保存了有关从文档中提取或添加到文档中的富文本和纯文本数据的信息, 如果存在相关数据,存储在DataTransfer 对象中。

inputType 编辑主机 dataTransfer
"insertFromPaste", "insertFromPasteAsQuotation", "insertFromDrop", "insertTranspose", "insertReplacementText""insertFromYank" contenteditable 一个预填充的 DataTransfer 对象,以便:
  1. DataTransfer 对象的拖动数据存储处于 只读模式。 [HTML]
  2. DataTransfer 对象的拖动数据存储项列表包含一个条目, 其中拖动数据项类型字符串"text/html",其类型纯 Unicode 字符串,其数据为将要粘贴、拖放或添加到内容中的 HTML 表示形式,或者来自kill buffer的数据。 [HTML]
  3. DataTransfer 对象的拖动数据存储项列表包含一个条目, 其中拖动数据项类型字符串"text/plain",其类型纯 Unicode 字符串,其数据为将要粘贴、拖放或添加到内容中的纯文本表示形式。 [HTML]
其余所有 任何 null

getTargetRanges() 返回一个 StaticRanges数组,如果事件未被取消,这些范围将受到影响。

5.1.3 方法

inputType 编辑主机 getTargetRanges()的响应
"historyUndo""historyRedo" 任何 空数组
其余所有 contenteditable 一个与事件相关的 StaticRanges [DOM]
其余所有 inputtextarea 空数组

返回除非 inputType 为 "historyUndo""historyRedo",或者编辑主机不是 contenteditable 元素,在这种情况下返回空数组。

5.2 事件定义

beforeinput
类型 beforeinput
接口 InputEvent
同步 / 异步 同步
冒泡
可信目标 启用了 contenteditable 属性的任何 Element
默认操作 [UI-EVENTS] 视情况而定: 对于 inputType "insertCompositionText" 的 contentEditable=typing 编辑主机,更新DOM; 对于所有 inputTypes 的 contentEditable="true" 编辑主机,更新 DOM 元素。 否则无操作。
上下文
(可信事件)

当用户尝试在 contenteditable 元素中输入时,用户代理 MUST 派发 [UI-EVENTS] 此事件。 这并不一定意味着 用户代理 [UI-EVENTS] 会随后更新 DOM。

由于非用户输入引起的事件(例如系统事件),用户代理 MUST NOT 派发 [UI-EVENTS] 此事件。

input
类型 input
接口 InputEvent
同步 / 异步 同步
冒泡
可信目标 启用了 contenteditable 属性的任何 Element
默认操作 [UI-EVENTS]
上下文
(可信事件)
  • InputEvent.data: 包含添加到元素中的数据的字符串,如果不适用,则 MAY 为 null。
  • InputEvent.dataTransfer: 添加或从元素中删除的富文本数据,如果不适用,则 MAY 为 null。

当用户表达更改文档内容的意图并且浏览器已处理时,用户代理 [UI-EVENTS] MUST 立即 派发 [UI-EVENTS] 此事件。

6. 隐私和安全考虑

本节不具规范性。

除了现有事件(如 keydownkeypress [UI-EVENTS] 事件)已经可用的 指纹识别 [fingerprinting-guidance] 技术之外,此功能没有已知的安全或隐私影响。

如果该功能替代了现有的事件,它可能 导致可用的 指纹识别 [fingerprinting-guidance] 技术减少,因为用户的意图被记录,而不是他们使用的硬件类型来 表达 这种意图。

7. 致谢

感谢: Michael Aufreiter, Adrian Bateman, Oliver Buchtala, Robin Berjon, Enrica Casucci, Bo Cupp, Domenic Denicola, Emil Eklund, Olivier Forget, Aryeh Gregor, Marijn Haverbeke, Yoshifumi Inoue, Koji Ishii, Gary Kacmarcik, Ian Kilpatrick, Frederico Caldeira Knabben, Takayoshi Kochi, Piotrek Koszuliński, Travis Leithead, Grisha Lyukshin, Miles Maxfield, Chaals McCathie Nevile, Masayuki Nakano, Ryosuke Niwa, Julie Parent, Ben Peters, Florian Rivoal, Morgan Smith, Hallvord R. M. Steen, Johan Sörlin, Cristian Talau, Dave Tapuska, Ojan Vafai, Léonie Watson, Xiaoqian Wu, Chong Zhang, Joanmarie, 以及所有参与编辑任务组的成员们,感谢你们的贡献和反馈。

A. 参考资料

A.1 参考性引用资料

[CSSOM]
CSS Object Model (CSSOM). Daniel Glazman; Emilio Cobos Álvarez. W3C. 2021 年 8 月 26 日. W3C 工作草案. URL: https://www.w3.org/TR/cssom-1/
[DOM]
DOM 标准. Anne van Kesteren. WHATWG. 现行标准. URL: https://dom.spec.whatwg.org/
[fingerprinting-guidance]
减轻 Web 规范中的浏览器指纹识别. Nick Doty. W3C. 2019 年 3 月 28 日. W3C 工作组说明. URL: https://www.w3.org/TR/fingerprinting-guidance/
[HTML]
HTML 标准. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 现行标准. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Infra 标准. Anne van Kesteren; Domenic Denicola. WHATWG. 现行标准. URL: https://infra.spec.whatwg.org/
[INPUT-EVENTS]
输入事件级别 1. Johannes Wilm; Ben Peters. W3C. 2019 年 5 月 30 日. W3C 工作草案. URL: https://www.w3.org/TR/input-events-1/
[UAX29]
Unicode 文本分割. Josh Hadley. Unicode 联盟. 2023 年 8 月 16 日. Unicode 标准附录 #29. URL: https://www.unicode.org/reports/tr29/tr29-43.html
[UI-EVENTS]
UI 事件. Gary Kacmarcik; Travis Leithead. W3C. 2023 年 9 月 15 日. W3C 工作草案. URL: https://www.w3.org/TR/uievents/
[WEBIDL]
Web IDL 标准. Edgar Chen; Timothy Gu. WHATWG. 现行标准. URL: https://webidl.spec.whatwg.org/