Here's how you can make it work without browser sniffing: When the keypress happens, bind a handler to the input
event on the textarea, and also set a 0-ms timeout.
If the browser accepted the pressed key for the textarea, the input
handler will run before the timeout (because the input
event fires synchronously). If that happens, you know the browser has handled the keypress correctly, and you can cancel the timeout.
Then, if the timeout fires, you know that the input
event hasn't fired and thus the character hasn't been added to the textarea, and you do it programmatically.
In both the event handler and the timeout handler, you unbind the event handler – it should run at most once (per key press).
var textarea = document.getElementById("input");
document.addEventListener("keypress", function (event) {
if (event.target === textarea) {
return;
}
var eventHandler = function () {
textarea.removeEventListener("input", eventHandler);
clearTimeout(timeoutId);
console.log("input event");
}
var timeoutHandler = function () {
var character = ("char" in event) ? event.char : String.fromCharCode(event.charCode);
textarea.value += character;
textarea.removeEventListener("input", eventHandler);
console.log("timeout fired");
}
timeoutId = setTimeout(timeoutHandler, 1);
textarea.addEventListener("input", eventHandler);
textarea.focus();
});
<textarea id="input"></textarea>
<p style="background: #ccc">
<b>Click here</b> to make sure the document is focused, but the textarea is not. Then press a key.
</p>
If you try the above snippet in Firefox, the console will say "timeout fired". In all other browsers it will say "input event". In either case, your pressed key is added to the textarea.
Some notes:
Technically, for consistent behavior you'd need to do more than just append the character to the end; you'd also have to look at things like cursor position and text selection. This may be overkill however.
If you need to support really old browsers, you might want to do a feature check for availability of the input
event.
If you have other code that relies on the textarea changing synchronously upon keypress, you'll probably have to make updates there.