Copyright © 2016 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
This specification defines additions to events for text and related input to allow for the monitoring and manipulation of default browser behavior in the context of text editor applications and other applications that deal with text input and text formatting. This specification builds on the UI events spec [UI-EVENTS]
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
The group expects to produce another working draft by October 31st, 2016. The test suite and implementation reports for the Input Events specification are still work in progress.
This document was published by the Web Platform Working Group as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-editing-tf@w3.org (subscribe, archives). All comments are welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 1 September 2015 W3C Process Document.
This document describes editing related additions to 2 events - Input and beforeinput which are described in the UI events spec [UI-EVENTS]. The goal of these events is to allow authors to understand and/or override default edit behavior both before and after editing occurs.
DataTransfer
This section is not normative.
A kill buffer is a in-memory store of richtext content that is separate from the clipboard which allows for the temporal storage of content that was deleted using specific deletion commands. The user can replace the current selection with the content held in the kill buffer by indicating an intention to yank the kill buffer.This section is not normative.
Creating a webbased texteditor requires a considerable amount of JavaScript on top of the browser code, among other things because:
This spec seeks to alleviate the problem by providing a simple way for web developers to both override browser handling of all user input related to text editing through the beforeinput event, and to monitor what browsers have changed in the DOM due to user input trough the input event.
This section is not normative.
Input events are sent before (beforeinput event) and after (input event) a user attempts to edit the markup. This includes characters, deletions, and other related edits.
The main part of the InputEvent is defined in [UI-EVENTS]
[Constructor(DOMString typeArg, optional InputEventInit inputEventInitDict)]
partial interface InputEvent {
readonly attribute DOMString inputType
;
readonly attribute DataTransfer
? dataTransfer
;
sequence<StaticRange> getTargetRanges();
};
This section is not normative.
The following table provides a summary of when the data
and dataTransfer
attributes contain contents and when they are null as well as when the getTargetRanges()
method returns an empty or non-empty Array, based on the inputType.
Editing host | inputType | data | dataTransfer | getTargetRanges() |
---|---|---|---|---|
Contenteditable |
"insertText" , "insertCompositionText" , "insertFromComposition"
|
Yes | null | Non-empty Array |
Contenteditable |
"insertFromPaste" ,
"insertFromDrop" , "insertReplacementText" ,
"insertFromYank"
|
null | Yes | Non-empty Array |
<textarea> , <input type="text"> |
"insertText" , "insertFromPaste" ,
"insertFromDrop" , "insertReplacementText" ,
"insertFromYank"
|
Yes | null | Empty Array |
All |
"historyUndo" , "historyRedo"
|
null | null | Empty Array |
Contenteditable | All Remaining | null | null | Non-empty Array |
<textarea> , <input type="text"> |
All Remaining | null | null | Empty Array |
inputType
holds the type of input. Allowed values are the following: "insertText"
, "insertReplacementText"
,
"insertLineBreak"
, "insertParagraph"
,
"insertOrderedList"
, "insertUnorderedList"
,
"insertHorizontalRule"
, "insertFromYank"
,
"insertFromDrop"
, "insertFromPaste"
,
"insertCompositionText"
, "insertFromComposition"
,
"deleteWordForward"
, "deleteWordBackward"
,
"deleteSoftLineForward"
, "deleteSoftLineBackward"
,
"deleteEntireSoftLine"
,
"deleteHardLineForward"
, "deleteHardLineBackward"
,
"deleteCompositionText"
, "deleteByComposition"
,
"deleteByDrag"
, "deleteByCut"
,
"deleteContent"
,
"deleteContentBackward"
, "deleteContentForward"
,
"historyUndo"
, "historyRedo"
,
"insertTranspose"
,
"formatBold"
, "formatItalic"
, "formatUnderline"
,
"formatStrikeThrough"
, "formatSuperscript"
,
"formatSubscript"
, "formatJustifyCenter"
, "formatJustifyRight"
,
"formatJustifyLeft"
, "formatIndent"
, "formatOutdent"
,
"formatRemove"
. During initialization, the
user agent [UI-EVENTS] is responsible for populating this field as follows:
"insertText"
.
"insertReplacementText"
.
"insertLineBreak"
.
"insertParagraph"
.
"insertOrderedList"
.
"insertUnorderedList"
.
"insertHorizontalRule"
.
"insertFromYank"
.
"insertFromPaste"
.
"insertTranspose"
.
"insertCompositionText"
.
false
."insertFromComposition"
.
"deleteCompositionText"
.
false
."deleteByComposition"
.
"deleteWordBackward"
.
"deleteWordForward"
.
"deleteSoftLineBackward"
.
"deleteSoftLineForward"
.
"deleteEntireSoftLine"
.
"deleteHardlineBackward"
.
"deleteHardlineForward"
.
"deleteByDrag"
.
"deleteByCut"
.
"deleteContent"
.
"deleteContentBackward"
.
"deleteContentBackward"
will be used both when the user asks for text deletion within a text node, and when the user shows the intention to deletion of more complex elements or merge paragraphs if the caret is at the start of a text node. In some scripts, backward deletion within a text node with a collapsed selection will delete a code point rather than a grapheme. A grapheme can consist of several characters, where each character corresponds to a code point. The getTargetRanges()
method can be used to find out how many characters the browser will remove by default if deleting within a text node.
"deleteContentForward"
.
"deleteContentForward"
will be used both when the user asks for text deletion within a text node, and when the user shows the intention to deletion of more complex elements or merge paragraphs if the caret is at the end of a text node. In some scripts, forward deletion within a text node with a collapsed selection will delete a grapheme rather than a code point. A grapheme can consist of several characters, where each character corresponds to a code point. The getTargetRanges()
method can be used to find out how many characters the browser will remove by default if deleting within a text node.
"historyUndo"
.
"historyRedo"
.
"formatBold"
.
"formatItalic"
.
"formatUnderline"
.
"formatStrikeThrough"
.
"formatSuperscript"
.
"formatSubscript"
.
"formatJustifyCenter"
.
"formatJustifyRight"
.
"formatJustifyLeft"
.
"formatIndent"
.
"formatOutdent"
.
"formatRemove"
.
"insertFromDrop"
.
This section is not normative.
An IME composition causes several beforeinput events, not all of which can be canceled.
If the composition recomposes existing ranges of the DOM, by default the contents of the associated ranges will first be removed from the DOM.
The initial removal is preceded by a cancelable beforeinput event with the inputType
"deleteByComposition"
which is triggered before the IME composition takes place. Preventing the default action for this event will mean that the range will not be removed from the DOM by the user agent.
If the composition is starting with an empty composition string, this step is skipped .
If the composition recomposes an existing range of the DOM, a non-cancelable beforeinput event with the inputType "insertCompositionText"
is triggered with the data attribute set to the extracted contents of the range as they were at the time the beforeinput event of step 1 was triggered.
If the composition is starting with an empty composition string, this step is skipped .
During the composition process, which each DOM update of the composition string, a non-cancelable beforeinput event with the inputType "insertCompositionText"
is triggered with the data attribute set to the updated contents of the composition text.
When either the entire composition string is to be leave the composition string to become part of the DOM outside the composition string, or a part of it does while another part of the composition string continues to be composed in the IME, a non-cancelable beforeinput event with the inputType "deleteCompositionText"
is triggered. The default action for this event is that the entire composition string is removed from the DOM.
Thereafter, a cancelable beforeinput event with the inputType "inputFromComposition"
is triggered with the data attribute set to the part of the composition string that is to become part of the DOM outside the composition.
If only a part of the composition string was removed from the composition to become part of the DOM outside the composition, so that another part continues to be part of the composition, the process starts over from step 2.
data
holds information plaintext data that is to be added to the document.
"insertText"
, "insertCompositionText"
or "insertFromComposition"
, the value of data is to be the plain text string to be inserted."insertFromPaste"
, "insertFromDrop"
, "insertTranspose"
,
"insertReplacementText"
, or "insertFromYank"
the value of data is to be the plain text string to be inserted.dataTransfer
holds information about richtext and plaintext data that is to be taken from or added to the document in a DataTransfer
object if there is relevant data.
"insertFromPaste"
,
"insertFromDrop"
, "insertTranspose"
,
"insertReplacementText"
, or "insertFromYank"
the dataTransfer attribute is a prepopulated DataTransfer
object so that:
"text/html"
, whose kind is Plain Unicode string, and whose data is a HTML representation of the content that is in the clipboard, in the kill buffer, to be dropped or otherwise the content that is to be added. [HTML-LIVING]"text/plain"
, whose kind is Plain Unicode string, and whose data is a plain text representation of the content that is to be pasted, dropped or otherwise added. [HTML-LIVING]getTargetRanges()
returns an Array of
StaticRanges [STATIC-RANGE] associated with this event, unless the inputType is
"historyUndo"
or "historyRedo"
or the editing host is not a contenteditable element, in which case it returns an empty Array.
beforeinput
Type | beforeinput |
---|---|
Interface |
InputEvent
|
Sync / Async | Sync |
Bubbles | Yes |
Trusted Targets | Any Element with
contenteditable attribute enabled.
|
Default action [UI-EVENTS] | Varies: 'Update the DOM' for contentEditable=typing editing hosts for inputTypes "insertCompositionText" and "deleteCompositionText" . 'Update the DOM element' for contentEditable="true" editing hosts for all inputTypes. None otherwise. |
Context (trusted events) |
|
A user agent MUST dispatch [UI-EVENTS] this event when the user has attempted to input in a contenteditable element. It does not necessarily mean the user agent [ UI-EVENTS] will then update the DOM.
A user agent MUST NOT dispatch [UI-EVENTS] this event due to events that are not caused by attempted user input, such as system events.
input
Type | input |
---|---|
Interface |
InputEvent
|
Sync / Async | Sync |
Bubbles | Yes |
Trusted Targets | Any Element with
contenteditable attribute enabled.
|
Default action [UI-EVENTS] | None |
Context (trusted events) |
|
A user agent MUST dispatch [UI-EVENTS] this event immediately after the DOM has been updated due to a user expressed intention to change the document contents which the browser has handled.
Thanks to: Michael Aufreiter, Adrian Bateman, Oliver Buchtala, Robin Berjon, Enrica Casucci, Domenic Denicola, Olivier Forget, Aryeh Gregor, Marijn Haverbeke, Yoshifumi Inoue, Koji Ishii, Gary Kacmarcik, Frederico Caldeira Knabben, Takayoshi Kochi, Piotrek Koszuliński, Travis Leithead, Grisha Lyukshin, 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, and everyone in the Editing Taskforce for their input and feedback.