Copyright © 2021 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/.
Input Events Level 2 replaces the first version of Input Events [ INPUT-EVENTS ] and includes:
The test suite and implementation reports for the Input Events specification are still work in progress.
This document was published by the Web Editing Working Group as an Editor's Draft.
GitHub Issues are preferred for discussion of this specification. Alternatively, you can send comments to our mailing list. Please send them to public-editing-tf@w3.org ( subscribe , archives ).
Publication as an Editor's 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 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 15 September 2020 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.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , and MUST NOT in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
This definition 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 through 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 insertion and deletion of content, and formatting changes.
Input
events
are
dispatched
[
UI-EVENTS
]
on
elements
that
act
as
editing
hosts
,
including
elements
with
the
contenteditable
attribute
set,
textarea
elements,
and
input
elements
that
permit
text
input.
WebIDLpartial interface InputEvent
{
readonly attribute DataTransfer? dataTransfer
;
sequence<StaticRange> getTargetRanges
();
};
partial dictionary InputEventInit
{
DataTransfer? dataTransfer
= null;
sequence<StaticRange> targetRanges
= [];
};
The
InputEvent
and
InputEventInit
objects
are
defined
in
[
UI-EVENTS
].
The
attributes
inputType
,
dataTransfer
and
targetRanges
of
InputEventInit
initialize
the
corresponding
attributes
of
the
InputEvent
object.
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"
,
"formatSetBlockTextDirection"
,
"formatSetInlineTextDirection"
,
"formatBackColor"
,
"formatFontColor"
,
"formatFontName"
,
"insertLink"
|
Yes | null | Non-empty Array |
Contenteditable |
"insertFromPaste"
,
"insertFromPasteAsQuotation"
,
"insertFromDrop"
,
"insertReplacementText"
,
"insertFromYank"
|
null | Yes | Non-empty Array |
<textarea>
,
<input
type="text">
|
"insertText"
,
"insertCompositionText"
,
"insertFromComposition"
,
"insertFromPaste"
,
"insertFromPasteAsQuotation"
,
"insertFromDrop"
,
"insertReplacementText"
,
"insertFromYank"
,
"formatSetBlockTextDirection"
,
"formatSetInlineTextDirection"
,
"formatBackColor"
,
"formatFontColor"
,
"formatFontName"
,
"insertLink"
|
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 |
The cancelability of the beforeinput event depends on the inputType.
The inputType to be picked depends on the user's expression of intention , whether or not the editing takes place during an IME composition and the state of the selection.
This specification defines the inputType values as the values in the inputType column of the following table.
inputType | User's expression of intention | Part of IME composition | beforeinput cancelable | State of selection |
---|---|---|---|---|
"insertText"
|
insert typed plain text | No | Yes | Any |
"insertReplacementText"
|
replace existing text by means of a spell checker, auto-correct or similar | No | Yes | Any |
"insertLineBreak"
|
insert a line break | No | Yes | Any |
"insertParagraph"
|
insert a paragraph break | No | Yes | Any |
"insertOrderedList"
|
insert a numbered list | No | Yes | Any |
"insertUnorderedList"
|
insert a bulleted list | No | Yes | Any |
"insertHorizontalRule"
|
insert a horizontal rule | No | Yes | Any |
"insertFromYank"
|
replace the current selection with content stored in a kill buffer | No | Yes | Any |
"insertFromDrop"
|
insert content by means of drop | No | Yes | Any |
"insertFromPaste"
|
paste content from clipboard or paste image from client provided image library | No | Yes | Any |
"insertFromPasteAsQuotation"
|
paste content from the clipboard as a quotation | No | Yes | Any |
"insertTranspose"
|
transpose the last two characters that were entered | No | Yes | Any |
"insertCompositionText"
|
replace the current composition string | Yes | No | Any |
"insertFromComposition"
|
insert a finalized composed string that will not form part of the next composition string | Yes | Yes | Any |
"insertLink"
|
insert a link | No | Yes | Any |
"deleteByComposition"
|
remove a part of the DOM in order to recompose this part using IME | Yes | Yes | Any |
"deleteCompositionText"
|
delete the current composition string before commiting a finalized string to the DOM | Yes | No | Any |
"deleteWordBackward"
|
delete a word directly before the caret position | No | Yes | Collapsed |
"deleteWordForward"
|
delete a word directly after the caret position | No | Yes | Collapsed |
"deleteSoftLineBackward"
|
delete from the caret to the nearest visual line break before the caret position | No | Yes | Collapsed |
"deleteSoftLineForward"
|
delete from the caret to the nearest visual line break after the caret position | No | Yes | Collapsed |
"deleteEntireSoftLine"
|
delete from to the nearest visual line break before the caret position to the nearest visual line break after the caret position | No | Yes | Collapsed |
"deleteHardLineBackward"
|
delete
from
the
caret
to
the
nearest
beginning
of
a
block
element
or
br
element
before
the
caret
position
|
No | Yes | Collapsed |
"deleteHardLineForward"
|
delete
from
the
caret
to
the
nearest
end
of
a
block
element
or
br
element
after
the
caret
position
|
No | Yes | Collapsed |
"deleteByDrag"
|
remove content from the DOM by means of drag | No | Yes | Any |
"deleteByCut"
|
remove the current selection as part of a cut | No | Yes | Any |
"deleteContent"
|
delete the selection without specifying the direction of the deletion and this intention is not covered by another inputType | No | Yes | Non-collapsed |
"deleteContentBackward"
|
delete the content directly before the caret position and this intention is not covered by another inputType or delete the selection with the selection collapsing to its start after the deletion | No | Yes | Any |
"deleteContentForward"
|
delete the content directly after the caret position and this intention is not covered by another inputType or delete the selection with the selection collapsing to its end after the deletion | No | Yes | Any |
"historyUndo"
|
undo the last editing action | No | Yes | Any |
"historyRedo"
|
to redo the last undone editing action | No | Yes | Any |
"formatBold"
|
initiate bold text | No | Yes | Any |
"formatItalic"
|
initiate italic text | No | Yes | Any |
"formatUnderline"
|
initiate underline text | No | Yes | Any |
"formatStrikeThrough"
|
initiate stricken through text | No | Yes | Any |
"formatSuperscript"
|
initiate superscript text | No | Yes | Any |
"formatSubscript"
|
initiate subscript text | No | Yes | Any |
"formatJustifyFull"
|
make the current selection fully justified | No | Yes | Any |
"formatJustifyCenter"
|
center align the current selection | No | Yes | Any |
"formatJustifyRight"
|
right align the current selection | No | Yes | Any |
"formatJustifyLeft"
|
left align the current selection | No | Yes | Any |
"formatIndent"
|
indent the current selection | No | Yes | Any |
"formatOutdent"
|
outdent the current selection | No | Yes | Any |
"formatRemove"
|
remove all formatting from the current selection | No | Yes | Any |
"formatSetBlockTextDirection"
|
set the text block direction | No | Yes | Any |
"formatSetInlineTextDirection"
|
set the text inline direction | No | Yes | Any |
"formatBackColor"
|
change the background color | No | Yes | Any |
"formatFontColor"
|
change the font color | No | Yes | Any |
"formatFontName"
|
change the font-family | No | Yes | Any |
This note is not normative.
When an
"insertFromPaste"
beforeinput
event
is
dispatched,
it
should
be
preceded
by
a
paste
[
CLIPBOARD-APIS
]
event.
"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.
"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.
This note is not normative.
In some scripts on some platforms, backward deletion within a text node with a collapsed selection will delete a single code point [ INFRA ] rather than a entire grapheme cluster [ UAX29 ]. The
getTargetRanges()
method
can
be
used
to
find
out
how
many
code
points
[
INFRA
]
the
browser
will
remove
by
default
if
deleting
within
a
text
node.
This note is not normative.
In some scripts on some platforms, forward deletion within a text node with a collapsed selection will delete an entire grapheme cluster [ UAX29 ] rather than a single code point [ INFRA ]. The
getTargetRanges()
method
can
be
used
to
find
out
how
many
code
points
[
INFRA
]
the
browser
will
remove
by
default
if
deleting
within
a
text
node.
data
holds
information
plaintext
data
related
to
what
is
to
be
added
to
the
document.
inputType | Editing host | data |
---|---|---|
"insertText"
,
"insertCompositionText"
or
"insertFromComposition"
|
Any | the plain text string to be inserted |
"insertFromPaste"
,
"insertFromPasteAsQuotation"
,
"insertFromDrop"
,
"insertTranspose"
,
"insertReplacementText"
or
"insertFromYank"
|
input
or
textarea
|
the plain text string to be inserted |
"formatSetInlineTextDirection"
or
"formatSetBlockTextDirection"
|
Any |
"ltr"
,
"rtl"
,
"auto"
or
"null"
|
"formatBackColor"
or
"formatFontColor"
|
Any | a string containing a serialized CSS component value [ CSSOM ] of the proposed color |
"formatFontName"
|
Any | the proposed value of the font-family CSS property |
"insertLink"
|
Any | the url of the proposed link |
All remaining | Any | null |
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.
inputType | Editing host | dataTransfer |
---|---|---|
"insertFromPaste"
,
"insertFromPasteAsQuotation"
,
"insertFromDrop"
,
"insertTranspose"
,
"insertReplacementText"
or
"insertFromYank"
|
contenteditable
|
A
prepopulated
DataTransfer
object
so
that:
|
All remaining | Any | null |
getTargetRanges()
returns
an
arrays
StaticRanges
that
will
be
affected
by
the
event
if
it
is
not
cancelled.
inputType | Editing host |
Response
of
getTargetRanges()
|
---|---|---|
"historyUndo"
or
"historyRedo"
|
Any | empty Array |
All remaining |
contenteditable
|
an Array of StaticRanges [ DOM ] associated with event |
All remaining |
input
or
textarea
|
an empty Array |
returns
,
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 [ UI-EVENTS ] 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.
An IME composition causes several beforeinput events, not all of which can be canceled.
If the composition is starting with an empty initial composition string (i.e. the composition is not recomposing an existing range of the DOM), this step is skipped.
"deleteByComposition"
is
dispatched
[
UI-EVENTS
].
"deleteByComposition"
is
dispatched
[
UI-EVENTS
].
This note is not normative.
The default action for this beforeinput event is the removal of the targetRanges from the DOM (i.e. the initial composition string will be removed from the DOM).
The beforeinput event can be canceled. Canceling the event will prevent the browser from removing the initial composition string from the DOM. Canceling or handling the event will not prevent the composition from taking place or influence the contents of the initial composition string.
A
compositionstart
event
is
dispatched.
[
UI-EVENTS
].
If the composition has an empty initial composition string, this step is skipped.
"insertCompositionText"
is
dispatched
[
UI-EVENTS
]
with
the
data
attribute
set
to
the
initial
composition
string.
"insertCompositionText"
is
dispatched
[
UI-EVENTS
]
This note is not normative.
Notice that the beforeinput event cannot be canceled.
With each DOM update of the composition string:
"insertCompositionText"
is
dispatched
[
UI-EVENTS
]
with
the
data
attribute
set
to
the
updated
contents
of
the
composition
text.
compositionupdate
event
is
dispatched.
[
UI-EVENTS
].
"insertCompositionText"
is
dispatched
[
UI-EVENTS
].
This step is repeated as long as no text is to be committed to the DOM (i.e. is made to be part of the DOM outside the range controlled by the composition).
When a part or the entire composition string is to be committed to the DOM:
"deleteCompositionText"
is
dispatched
[
UI-EVENTS
].
"insertFromComposition"
is
dispatched
[
UI-EVENTS
]
with
the
data
attribute
set
to
the
part
of
the
final
composition
string
that
is
to
be
committed
to
the
DOM.
"insertFromComposition"
has
been
canceled,
the
DOM
is
updated
with
the
part
of
the
composition
string
that
is
to
be
committed
to
the
DOM
inserted
at
the
start
of
the
selection.
compositionend
event
is
dispatched.
[
UI-EVENTS
].
"insertFromComposition"
has
been
canceled,
a
input
event
with
the
inputType
"insertFromComposition"
is
dispatched
If only a part of the composition string was committed to the DOM, while another part is not yet to be committed, the process starts over from step 3 with the non-committed part of the final composition string as the new initial composition string.
This note is not normative.
Note
that
while
every
composition
only
has
one
compositionstart
event,
it
may
have
several
compositionend
events.
This section is not normative.
There
are
no
known
security
or
privacy
impacts
of
this
feature
beyond
fingerprinting
[
fingerprinting-guidance
]
techniques
that
already
are
available
through
existing
events,
such
as
the
keydown
and
keypress
[
UI-EVENTS
]
events.
If this feature replaces existing events, it MAY lead to a decline in available fingerprinting [ fingerprinting-guidance ] techniques, as users' intentions are recorded, and not the particular type of hardware they used to express this intention.
Thanks to: 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, and everyone in the Editing Taskforce for their input and feedback.
Referenced in:
Referenced in:
Referenced in: