javascriptime

Detect whether Japanese IME is active in input box in Javascript


Is there a way to detect whether a Japanese (or other language) input method editor is active when a user is typing into an input box in Javascript? I have an input box which responds to the enter key to submit a form, but while testing with a Japanese IME I realized that the user might press enter to confirm an autocomplete candidate, which still triggers my own code.

Essentially, while typing autocomplete suggestions appear, and I'd only like the enter key to trigger a form submission when the IME has completely finished its work. I do see https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionend_event, which looks like I could use compositionstart and compositionend events to set a boolean, and then check the boolean when the user hits enter; I'm just curious if there's a way to directly query whether the IME is active, as I'm slightly worried that handling the state manually might turn out to be brittle if it's possible for things to become out of sync.

EDIT: So I have found https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/isComposing, which can be used to check if the keypress event is fired within the context of the IME, but the last Enter which causes the compositionend event to fire doesn't have isComposing set, so setting a boolean has been the only thing I've found that works. However, there is a race condition, where depending on whether the keypress or compositionend event handler goes first the code may still erroneously cause the enter which causes the IME to exit to trigger the input submission. The only way around this I've found was to introduce an asyncronous delay in the onCompositionEnd event handler, to ensure that it always goes last.

That way, when hitting Enter in the IME, the isIME boolean is true, and the keypress event finishes first, checking the isIME boolean and finishing without submitting the answer, then the onCompositionEnd finishes and sets the isIME boolean to false. The non-determinism isn't great, but this seems to be working.


Solution

  • I have an input box which responds to the enter key to submit a form

    Just don't do that. Put your <input> element inside the <form>, and have your code respond to the form's submit event instead of specific key events. Pressing enter in a normal input will already select an autocomplete candidate or submit the form - but not both - by default.