The original IME API was written with APIs in this document, but for
the standardization process to proceed smoothly, we extract what we agree
on as a “main” part first to
make it a public standard faster.
This document includes all the APIs including what is already included
in the main part, but the editor is planning to make this diff-only
(i.e. all interfaces will be partial).
The content of this document may (or may not) be merged into the main
API spec in the future.
This specification defines an “IME API” that provides Web applications with scripted access to an IME (input-method editor) associated with a hosting user agent. This IME API includes:
This API is designed to be used in conjunction with DOM events [[DOM-LEVEL-3-EVENTS]].
This document is a proposal that is being made available for public review in order to solicit feedback, particularly from implementors, with a goal of potential cross-browser implementation and standardization.
Even though existing Web-platform APIs allow developers to implement very complicated Web applications, such as visual chat applications or WYSIWYG presentation editors, developers have difficulties when implementing Web applications that involve input-method editors. To mitigate the difficulties, the DOM Level 3 Events specification[[DOM-LEVEL-3-EVENTS]] introduces composition events to retrieve composition text while it is being composed in an associated IME.
However, Web applications can still run into difficulties when
they want text input on non-editable elements such as the
<div>
element without contenteditable
attribute being set to true
, or interact with IMEs;
those difficulties include
the fact that a Web application cannot do the following:
To solve these IME-related problems, this specification introduces an IME API that allows Web applications to interact with the IME. This specification introduces interfaces for compositions, so Web applications can read detailed composition data. A CompositionEvent object provides a reference to an ongoing IME composition, so Web applications can retrieve the composition text and its attributes. In addition, this API also gives Web applications the ability to give a hint as to where to position a composition window.
There are also proposed standards related to IME:
Please also refer to the separate use cases for Input Method Editor API document for more information about possible use cases.
Consider the following examples.
This example is a simple web search page which gives a user search query suggestions while the user is doing composition. This example code hides the suggestion box when IME candidate window may overlap with it.
<!DOCTYPE html> <html> <head> <style type="text/css"> #search0 { max-width: 400px; } #input0 { width: 100%; } #suggest0 { width: 100%; list-style: none; margin: 0; padding: 0; border-style: solid; border-width: 1px; border-color: #000; } </style> <script language="javascript" type="text/javascript"> function init() { var node = document.getElementById('input0'); // This code only handles the compositionupdate event for brevity of the // example, but of course other input field changes should also be handled. node.addEventListener('compositionupdate', onCompositionUpdate, false); // Register handlers for candidate window appearance change. var ctx = node.inputMethodContext; ctx.addEventListener('candidatewindowshow', onCandidateWindowShow, false); ctx.addEventListener('candidatewindowhide', onCandidateWindowHide, false); } // Sends an XHR request to get search suggestions. // Upon receiving the result, expandSuggest() is called back. function getSuggests(query) { // For brevity, implementation of this function is omitted. } function expandSuggest(candidates) { // Callback after getting search suggestions. var suggest = document.getElementById('suggest0'); var i; // Clear old suggestions. for (i = 0; i < suggest.childNodes.length; i++) { suggest.removeChild(suggest.childNodes[0]); } // Render new suggeston list. for (i = 0; i < candidates.length; i++) { suggest.appendChild(document.createElement('li')); suggest.childNodes[i].textContent = candidates[i]; } } function onCompositionUpdate(event) { var query = document.getElementById('input0').value; getSuggests(query); } // Hides suggest window once IME candidate window is shown. function onCandidateWindowShow(event) { var suggest = document.getElementById('suggest0'); suggest.style.display = 'none'; } // Unhides suggest window once IME candidate window is closed. function onCandidateWindowHide(event) { var suggest = document.getElementById('suggest0'); suggest.style.display = ''; } </script> </head> <body> <div id="search0"> <input type="text" id="input0" placeholder="search here"> <ul id="suggest0"></ul> </div> </body> </html>
This example shows the source which draws composition text in its own style.
For the usage of compositionupdate event, see also the note in Drawing Composition Text section.
<!DOCTYPE html> <html> <head> <style> .clause { margin-right: 2px; border-style: solid; border-width: 0px 0px 1px 0px; border-color: #333333; } .selected { border-width: 0px 0px 2px 0px; border-color: #000000; } </style> <script language="javascript" type="text/javascript"> // compositionupdate event handler function onCompositionUpdate(event) { var target = event.target; // Remove all children. while (target.childNodes.length < 0) { edit.removeChild(edit.childNodes[0]); } // Get the IME context. var ctx = target.inputMethodContext; // Create clause spans. var text = event.data; var segments = event.getSegments(); for (i = 0; i < segments.length; i++) { var span = document.createElement('span'); span.classList.add('clause'); var selected = false; if (segments[i] == event.activeSegmentStart) { selected = true; span.classList.add('selected'); } var end = text.length; if (i < segments.length - 1) { end = segments[i + 1]; } span.textContent = text.substring(segments[i], end); target.appendChild(span); if (selected) { ctx.setCaretRectangle(document.body, rect.left, rect.top, rect.width, rect.height); } } // Prevent the browser from drawing composition text. event.preventDefault(); } function init() { var composition = document.getElementById('composition'); composition.enableEditingEvents(); composition.focus(); composition.addEventHandler('compositionupdate', onCompositionUpdate, false); } </script> </head> <body onload="init();"> <div id="composition"></div> </body> </html>
See the main document.
More to be written.
To be written.
Authors can get an object which implements the
InputMethodContext
interface on an editable or
focusable
element, which can get keyboard input first
(i.e. a “target” element).
.
If this property is accessed
on non-editable, non-focusable element, a user agent SHOULD
return a context for the innermost editable or focusable element
to the element. In this case, the target
property
in the InputMethodContext
interface points to the target element.
If all ancestors of an element are neither editable nor focusable,
this property returns null
.
To control the IME attached to an element, it is a good idea to add this property to the HTMLElement interface.
Returns an InputMethodContext interface associated with this element.
To change the behavior of the IME associated with an
element, authors MUST first obtain an InputMethodContext
interface from the inputMethodContext
property of
the HTMLElement interface.
The returned InputMethodContext interface MAY not be directly
associated to the element. An interface MAY be shared
among elements under an innermost editable or focusable element.
In that case, target
property in the
InputMethodContext interface points to the element which owns
the interface.
This interface represents an ongoing IME composition, by extending CompositionEvent interface definedin [[DOM-LEVEL-3-EVENTS]]. It provides attributes representing the text being composed by an IME and its associated information.
Represents the 0-based index to the first character of the active segment in the current composition text.
An author can assume that
activeSegmentStart
and activeSegmentEnd
boundary fit in with any of segments
, and
that activeSegmentStart
is equal or less than
activeSegmentEnd
.
Represents the 0-based index to the next position of the last character of the active segment in the current composition text. If there is no active segment, activeSegmentStart and activeSegmentEnd MUST be the same value and they indicate the position of the caret.
For example, if “DEF” is selected in composition
text “abcDEFghi”, activeSegmentStart
is 3
and activeSegmentEnd
is 6.
If the caret is between “B” and “C”
in composition text “ABCD”, both
actieSegmentStart
and activeSegmentEnd
are 2.
This can be used to render compostion text as segmented clauses, but how to visualize them are not specified here. It is recommended to follow the platform standard way to visualize the segmentation (e.g. using underline or reverse background etc.).
The way the platform standard renders composition text might be customized by a user (e.g. for accessibility). CSS property to indicate the current default style to render the composition is desired.
This event should be fired immediately after the IME candidate window is set to appear, which means immediately after the position information for the candidate window has been identified.
Common things among oncandidatewindowshow/update/hide events:
This events should be fired after either:
In either case, the event should be fired after the new size/location of the candidate window is known by the user agent.
More clarification should be written on how IME locale should be described using BCP-47.
Represents the element associated with the InputMethodContext object.
Once a target element gets deleted or modified not to accept
any input, any access to the
InputMethodContext
interface through the object has no effect. Any method calls
will just return, accesses to composition
and
target
will return null, and accesses to
locale
will return the empty string.
Represents the starting offset of the composition relative to
the target if a composition is occurring, or 0 if there is no
composition in progress. For composition occurring on an
<input>
or <textarea>
element, the
compositionStartOffset
is the starting offset of
the composition within the target's value
string.
For compositions occurring on an element with the
contentEditable
flag set, then this is the starting offset relative to the
target's textContent
property (textContent is a
linear view of all the text under an element).
Represents the ending offset of the composition,
in a similar way to compositionStartOffset
.
An web application may use this information to explicitly control the position for its own input-related UI elements, such as search suggestions.
Note: client coordinates are in document pixels and have origin at the upper-left corner of the client area.
Finishes the ongoing composition of the hosting user agent.
When a Web application calls this function, a user agent sends a compositionend event and a textInput event as a user types an ‘Accept’ key as written in “Input Method Editors” section the DOM Level 3 Events specification [[!DOM-LEVEL-3-EVENTS]].
This may cause the race condition when a script calls confirmComposition while system IME gets accept key in the same time, a user agent may confirm the ongoing composition twice. Instead, introducing cancelComposition() is proposed and when a script needs the behavior of confirmComposition(), it can commit the current composition and then call cancelComposition().
Notifies the rectangle of composition text to a user agent. When a user agent renders a candidate window or a composition window, it uses this rectangle to draw windows next to the composition or prevent these windows from being rendered on this rectangle.
If a Web application wants to render composition text itself,
it has to tell a user agent where the composition text will be
located whenever it gets compositionstart
event
or compositionend
event.
On Windows, this rectangle is used as a parameter for ImmSetCandidateWindow(). On Mac, this rectangle is sent when it calls [firstRectForCharacterRange:]. On Linux (GTK), this rectangle is used as a parameter for gtk_im_context_set_cursor_location().
These set values apply only to the current
composition session (i.e. until compositionend
event is sent).
A user agent MAY need to convert these coordinates to the screen coordinates when it shows a candidate window.
Causes the target element of this context to get editing
events (e.g. input
,
compositionupdate
) delivered when the element
is focused.
If this method is called on a editable element (
<input>
, <textarea>
,
contenteditable=true
), it has no effect.
Causes the target element of this context to turn off
receiving editing events (e.g. input
,
compositionupdate
) after
enableEditingEvents()
is called.
If this method is called on a editable element (
<input>
, <textarea>
,
contenteditable=true
), it has no effect.
This specification provides an interface for developing IME-aware Web applications.
This section describes practices for some use-cases.
Once a InputMethodContext interface is obtained,
it should be valid for the lifetime of its target
element's lifetime, as long as the element is editable or focusable.
Once the target gets disabled,
authors MAY NOT access an IME through the interface even after the
target gets enabled again. Once the target is deleted,
any access to the interface is void.
Any access to the InputMethodContext interface makes sense mostly when the target element has focus. In other words, it makes little sense if you access the interface when the target element doesn't have focus.
As of this writing, the order of
compositionupdate
event and DOM update is being
discussed
(see Bug 18931)
and if compositionupdate
event happens after
DOM modification, this section has to be rewritten using
beforeInput
event, which is also being discussed.
Example 2 code should be updated as well.
If a Web application wants to draw composition text by itself,
it SHOULD handle the compositionupdate
event
to get notified from the IME that the composition text has been
changed, and then
use the interface described in this document to retrieve
composition and let the IME know
where the composition text is drawn by calling
setCaretRectangle()
method.
If setCaretRectangle()
is not called, IME will not have
information about where to show IME UIs, and it may show UIs at
an obtrusive position. To avoid this situation, a user agent may
set some decent default position in the vicinity of the focused
input field.
When a Web application draws composition text, it MUST call
preventDefault()
in compositionupdate
handler so that the user agent will not draw the text.
When a Web application wants to handle DOM level3 composition events
on a non-<input>
, <textarea>
,
or contenteditable
node,
it MUST call enableEditingEvents()
method beforehand
and focus it to get composition events.
The following diagram shows the flow of events among the keyboard, the IME, the user agent, and the Web application when a user types ‘kyouha’ to convert to ‘今日は’.