5

Working on a project where handling various languages (Japanese, Chinese etc.) as well as handling different language directions (right-to-left, left-to-right and the combinations of the two) is crucial part of our system. Because of that we have a custom implementation of input field to do things consistently across browser spectrum. One particularly challenging thing to replicate (via events from W3C specification) is to emulate IME composition together with Mac accent menu.

IME composition itself is fine. Handling IME composition languages via compositionstart, compositionupdate, compositionend events and non-IME languages via input event works well (using event.isComposing for separation between the two).

But incorporating the Mac accent menu gets wild quite quickly. The problem is the lifecycle of the accent menu doesn't trigger the events one would expect. E.g. the initial "Click & hold" that opens the accent menu triggers the following sequence:

  1. keydown, event.isComposing = false
  2. input, event.isComposing = false
  3. keydown, event.isComposing = false (X-times based on how long the key is held)
  4. keyup, event.isComposing = false

Thus, although Mac accent menu behaves (visually) the same way as IME composition for various languages, the event chain doesn't recognise that at all. Which forces the implementation to hack it by having keydown/keyup counter to manually recognise this "IME-composition-without-composition-events" state.

Everything going forward makes things even more complicated. E.g. navigating via arrows triggers compositionstart and compositionupdate events but selecting character via number just calls input event.

There have to be several people who implemented similar logic in the past for various browser based editors so any tips or experience is appreciated.

Martin Janíček
  • 444
  • 1
  • 6
  • 13

1 Answers1

1

You can check the inputType property of either the beforeinput or input event, to detect if you're still handling a composition event. In such a case you will receive "insertCompositionText" for each update (the first input of the non accented character would still be "insertText" though).

document.querySelector("input").oninput = (evt) => console.log(evt.data, evt.inputType);
<input>
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Thanks. It's helpful but doesn't solve it for me. There are basically two issues. (a) Is there any other way how to programatically detect Mac accent menu pops up other than having basically a "keydown"/"keyup" counter? And (b) is there any functional (or ideally recommended) event handling that handles IME composition together with Mac accent menu, especially given the fact that various browsers trigger slightly different event chain during IME composition. I'm Sorry, I'm aware it's rather hard to answer. – Martin Janíček Aug 07 '23 at 15:59
  • Btw: Do you think, it'd be helpful to separate those two into two different posts? – Martin Janíček Aug 07 '23 at 16:00
  • For b, `inputType === "insertCompositionText"` should do. For a, I'm not sure no. And yes, clarifying your question, maybe in two distinct ones would probably help. For instance, I'm not sure I understand why you need to "detect" the Mac accent menu. An other IME that would trigger similar events is the Android auto-complete keyboard, for as long as the user has a suggestion the IME will act as if it was composing a new input, allowing it to replace the content that has already been input. – Kaiido Aug 08 '23 at 02:32