输入事件规范 第2级

W3C 工作草案

有关此文档的更多详细信息
此版本:
https://www.w3.org/TR/2025/WD-input-events-2-20250716/
最新发布版本:
https://www.w3.org/TR/input-events-2/
最新编辑草案:
https://w3c.github.io/input-events/
历史记录:
https://www.w3.org/standards/history/input-events-2/
提交历史
编辑:
(受邀专家)
前任编辑:
Ben Peters (微软) - 截至
反馈:
GitHub w3c/input-events (拉取请求新问题开放问题)
public-editing-tf@w3.org 主题行 [input-events-2] … 主题内容 … (存档)
按级别发布的最新版本
第2级
按级别发布的最新编辑草案
第2级

摘要

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

本文件的状态

本节描述了本文件在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准与草案索引中找到。

输入事件规范 第2级 取代了输入事件的第一个版本 [INPUT-EVENTS],并包含:

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

本文件由 Web 编辑工作组 作为工作草案发布,使用了推荐轨道

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

本文档为草案,可能随时被其他文档更新、替换或废弃。将本文件作为除“进行中工作”之外的引用是不合适的。

本文档由一组遵循 W3C 专利政策 的成员编写。 W3C 维护着一个 有关本小组成果的公开专利披露列表; 该页面还包括专利披露说明。任何个人若实际知晓某项专利并认为其包含 必要权利要求(Essential Claim(s)), 必须根据 W3C 专利政策第 6 节 披露相关信息。

本文件受 2023年11月3日 W3C 流程文件 的约束。

1. 简介

本文档描述了与编辑相关的两个事件的扩展 - inputbeforeinput,这些事件在 UI 事件规范中进行了描述 [UI-EVENTS]。这些事件的目的是允许开发者理解和/或覆盖编辑行为的默认处理,编辑操作在执行前或执行后。

2. 一致性

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

本文档中的关键词 MAYMUSTMUST NOT 应按照 BCP 14 [RFC2119] [RFC8174] 的说明进行解释,仅当这些词以如上所示全部大写形式出现时,才按上述定义解释。

3. 定义

表达意图
用户可以通过键盘、输入法(IME)、语音或类似方法表达执行特定编辑操作的意图。特定的输入操作根据平台特定的约定映射为意图。
杀死缓冲区

此定义为非规范性内容。

杀死缓冲区 是一个与剪贴板分开的内存存储区域,用于暂存通过特定删除命令删除的富文本内容。用户可以通过表达“提取杀死缓冲区”的意图,将杀死缓冲区中的内容替换当前选中的内容。

4. 解决的问题

本节为非规范性内容。

创建一个基于Web的文本编辑器需要在浏览器代码之上编写大量的JavaScript,部分原因是:

  1. 各个浏览器对编辑操作的处理方式不尽相同。
  2. 浏览器在处理某些编辑操作时通常存在问题。
  3. 各个网站可能对某些编辑操作有自定义的处理偏好。
  4. 浏览器在开发高级文本编辑功能时未完全遵循可扩展Web宣言中提出的原则,因为这些功能的开发未始终与Web开发者社区的需求相协调。

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

5. 使用案例

本节为非规范性内容。

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

6. 输入事件类型

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

输入事件会在作为 编辑主机(editing hosts) 的元素上分派,包括设置了 contenteditable 属性的元素、textarea 元素,以及允许文本输入的 input 元素。

6.1 接口 InputEvent

WebIDLpartial interface InputEvent {
   readonly attribute DataTransfer? dataTransfer;
   sequence<StaticRange> getTargetRanges();
};

partial dictionary InputEventInit {
   DataTransfer? dataTransfer = null;
   sequence<StaticRange> targetRanges = [];
};

inputTypedataTransfertargetRanges 这三个 InputEventInit 的属性用于初始化 InputEvent 对象的对应属性。

6.1.1 概览

本节为非规范性内容。

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

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

6.1.2 属性

beforeinput事件是否可取消取决于inputType。

inputType的选择取决于用户的意图表达,编辑是否在IME组合过程中进行,以及选择的状态。

本规范将inputType值定义为下表中的inputType列中的值。

inputType 用户的意图表达 IME组合的一部分 beforeinput是否可取消 选择的状态
"insertText" 插入键入的纯文本 任何
"insertReplacementText" 通过拼写检查器、自动更正、书写建议或类似方式插入或替换现有内容 任何
"insertLineBreak" 插入换行符 任何
"insertParagraph" 插入段落符 任何
"insertOrderedList" 插入编号列表 任何
"insertUnorderedList" 插入项目符号列表 任何
"insertHorizontalRule" 插入水平线 任何
"insertFromYank" 用存储在kill buffer中的内容替换当前选择 任何
"insertFromDrop" 通过拖放插入内容 任何
"insertFromPaste" 从剪贴板粘贴内容或从客户端提供的图像库粘贴图像 任何
"insertFromPasteAsQuotation" 作为引用从剪贴板粘贴内容 任何
"insertTranspose" 调换最后输入的两个字素簇(grapheme cluster)的顺序。 任何
"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 发生变化的编辑操作,则它 MUST 分派 相应的 beforeinputinput 事件。
注意
如果选择被折叠,"deleteContentBackward"将用于用户请求在文本节点内删除文本时,以及当用户表示删除更复杂的元素或在光标位于文本节点开头时合并段落时。
注意
如果选择被折叠,"deleteContentForward"将用于用户请求在文本节点内删除文本时,以及当用户表示删除更复杂的元素或在光标位于文本节点末尾时合并段落时。

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 对象的 拖拽数据存储(drag data store)处于 只读模式。[HTML]
  2. 如果粘贴内容为文件,则 DataTransfer 对象的 拖拽数据存储项目列表(drag data store item list) 包含一个条目,其 数据项类型字符串(drag data item type string) 为文件的 MIME 类型类型(kind)File,其数据为与粘贴文件对应的 File 对象。[HTML]
  3. DataTransfer 对象的 拖拽数据存储项目列表(drag data store item list)包含一个条目,其 数据项类型字符串"text/html"类型纯 Unicode 字符串(Plain Unicode string),其数据为剪贴板或kill buffer中内容的 HTML 表示,或将被插入的内容的 HTML 表示。[HTML]
  4. DataTransfer 对象的 拖拽数据存储项目列表包含一个条目,其 数据项类型字符串"text/plain"类型纯 Unicode 字符串,其数据为将要粘贴、拖拽或添加的内容的纯文本表示。[HTML]
  5. 如果要粘贴的内容为链接,则 DataTransfer 对象的 拖拽数据存储项目列表包含一个条目,其 数据项类型字符串"text/uri-list"类型纯 Unicode 字符串,其数据为将被插入或添加的链接的纯文本表示。[HTML]
所有其他 任意 null

getTargetRanges() 返回一个 StaticRange 数组,表示如果事件未被取消,将要被修改的内容。返回的 StaticRange MUST 仅覆盖浏览器通常会替换的 码点(code points),即使它们只是 字素簇(grapheme cluster) 的一部分。

注意

本注释不具规范性。

根据不同的书写系统和平台,在文本节点中使用折叠选区向前或向后删除时,可能会影响一个或多个码点,或整个字素簇(grapheme cluster)。例如,在包含“café”的文本节点中向后删除,可能会删除重音符号,也可能会直接删除整个“é”字符,这取决于书写系统和平台。

6.1.3 方法

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

返回值,除非 inputType 为 "historyUndo""historyRedo",或 编辑主机(editing host) 不是 contenteditable 元素,此时将返回一个空数组。

6.2 事件定义

beforeinput
类型 beforeinput
接口 InputEvent
同步 / 异步 同步
冒泡
受信目标 任何作为 Element编辑主机(editing host)
默认操作 [UI-EVENTS]
上下文
(受信事件)

用户代理(user agent) MUST 在用户尝试在 contenteditable 元素中输入时 分派 此事件。这并不一定意味着 用户代理会随即更新 DOM。

用户代理 MUST NOT 因非用户输入尝试引发的事件(如系统事件)而 分派 此事件。

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

用户代理(user agent) MUST 应在由于用户明确意图更改文档内容且浏览器已处理该操作后、DOM 被更新后立即 分派此事件。如果浏览器未进行任何 DOM 更改,无论是因为编辑主机为 EditContext 编辑主机(其不会自动更改 DOM),还是因为 用户代理认定无需更改 DOM,则用户代理 MUST NOT 分���此事件。

7. 输入事件在合成期间的顺序

合成的开始通过调度 compositionstart 事件标记。

在合成会话期间,每当文本合成系统更新其活动文本段落时,都会调度 compositionupdate 事件。

在每个 compositionupdate 事件之后,会调度一对 beforeinputinput 事件。 beforeinputinput 事件:

活动文本段落的 DOM 内容在调度 beforeinput 事件后,input 事件之前更新。

合成会话的结束通过调度 compositionend 事件标记。

8. 使用 "insertFromPaste" 时的事件顺序

当调度 "insertFromPaste" beforeinput 事件时,它 必须 之前已经调度了 paste 事件。[CLIPBOARD-APIS]

9. 隐私和安全考虑

本节不是规范性的。

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

如果此功能替换现有事件,它 可能 导致可用的 指纹识别 技术减少,因为记录的是用户的意图,而不是他们使用的特定硬件类型来 表达 这个意图。

10. 致谢

感谢: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 规范性引用

[CLIPBOARD-APIS]
Clipboard API and events。Gary Kacmarcik;Anupam Snigdha。W3C。2025年5月16日。W3C 工作草案。URL:https://www.w3.org/TR/clipboard-apis/
[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 Standard。Anne van Kesteren。WHATWG。Living Standard。URL:https://dom.spec.whatwg.org/
[FileAPI]
File API。Marijn Kruisselbrink。W3C。2024年12月4日。W3C 工作草案。URL:https://www.w3.org/TR/FileAPI/
[fingerprinting-guidance]
Mitigating Browser Fingerprinting in Web Specifications。Nick Doty;Tom Ritter。W3C。2025年3月21日。W3C 工作组备忘。URL:https://www.w3.org/TR/fingerprinting-guidance/
[HTML]
HTML Standard。Anne van Kesteren;Domenic Denicola;Dominic Farolino;Ian Hickson;Philip Jägenstedt;Simon Pieters。WHATWG。Living Standard。URL:https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard。Anne van Kesteren;Domenic Denicola。WHATWG。Living Standard。URL:https://infra.spec.whatwg.org/
[mimesniff]
MIME Sniffing Standard。Gordon P. Hemsley。WHATWG。Living Standard。URL:https://mimesniff.spec.whatwg.org/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels。S. Bradner。IETF。1997年3月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words。B. Leiba。IETF。2017年5月。最佳当前实践。URL:https://www.rfc-editor.org/rfc/rfc8174
[UI-EVENTS]
UI Events。Gary Kacmarcik;Travis Leithead。W3C。2024年9月7日。W3C 工作草案。URL:https://www.w3.org/TR/uievents/
[WEBIDL]
Web IDL Standard。Edgar Chen;Timothy Gu。WHATWG。Living Standard。URL:https://webidl.spec.whatwg.org/

A.2 参考性引用

[i18n-glossary]
国际化术语表(Internationalization Glossary)。Richard Ishida;Addison Phillips。W3C。2024年10月17日。W3C 工作组备忘。URL:https://www.w3.org/TR/i18n-glossary/
[INPUT-EVENTS]
输入事件第1级(Input Events Level 1)。Johannes Wilm。W3C。2023年9月28日。W3C 工作草案。URL:https://www.w3.org/TR/input-events-1/