Handling composition
This fiddle shows how one could handle composition events on a contenteditable element
by lddubeau
HTML
<p id="edit" contenteditable="true">1234</p>
<p id="log"></p>
<p id="composing"></p>
<input id="field"></input>
CSS
#field {
position: fixed;
z-index: -1;
height: 0px;
width: 0px;
outline: none;
}
#field:focus {
outline: none;
}
#edit {
background-color: white;
}
}
JavaScript
//
// The method used here is to redirect keyboard events to a hidden
// field. This field is invisible because #edit has a background color.
// Turn that color off to see the field. The event handlers on the
// field then motify the contenteditable element which is supposed to // be edited. The composition events are handled so that the edited
// text shows the state of composition as it happens.
//
// It is important that the field be moved to the caret position so
// that it shows a possible list of choice. Like when chinese is input
// for instance.
$(function () {
var $edit = $("#edit");
var edit = $edit[0];
var $log = $("#log");
var $field = $("#field");
var caret = 0;
var caret_html = "<span>_</span>";
var $composing = $("#composing");
var composing = false;
var composition_data = "";
var composition_data_start = 0;
function moveCaret() {
$edit.children("span").remove();
var text = edit.innerHTML;
if (composing) {
text = text.slice(0, composition_data_start) + composition_data + text.slice(composition_data_start);
}
edit.innerHTML = text.slice(0, caret) + caret_html + text.slice(caret);
var $span = $edit.children("span");
var pos = $span.offset();
$field.css("top", pos.top);
$field.css("left", pos.left);
}
moveCaret();
function removeCompositionData() {
if (!composing) return;
$edit.children("span").remove();
var text = edit.innerHTML;
edit.innerHTML = text.slice(0, composition_data_start) + text.slice(composition_data_start + composition_data.length);
}
$field.on("compositionstart", function (ev) {
composing = true;
composition_data = ev.originalEvent.data;
composition_data_start = caret;
caret = composition_data_start + composition_data.length;
moveCaret();
});
$field.on("compositionupdate", function (ev) {
...