简体   繁体   中英

Firefox issue when focusing textarea element in keypress event handler

The following snippet works great in chrome/edge/safari. In Firefox the textarea gets focused, but the pressed character isn't being added to the textarea - the first character will be always missing.

 document.addEventListener('keypress', (event) => { document.querySelector('#input').focus(); }); 
 <textarea id="input"></textarea> 

How can I make this behave consistently across all browsers?

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.

While this code will not work if any other browsers share the same behavior as Firefox, the following code will add any key input, given that it is a character whose string length is 1, when the code is run on Firefox :

 var mozFocused = false; document.addEventListener('keypress', (event) => { document.querySelector('#input').focus(); var isFirefox = typeof InstallTrigger !== 'undefined'; if (isFirefox && !mozFocused && event.key.length === 1) { mozFocused = true; document.querySelector('#input').value += event.key; } }); document.querySelector('#input').addEventListener('blur', (event) => { mozFocused = false; }); 
 <textarea id="input"></textarea> 

Again, note that this does not guarantee it to work across all browsers, as this was a fix for Firefox specifically, but, if you see the same behavior occurring in other browsers, I used the answer from this SO post to detect the current browser the client is using (assuming it is in the list of the browsers that this post discusses): How to detect Safari, Chrome, IE, Firefox and Opera browser?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM