quickadd icon indicating copy to clipboard operation
quickadd copied to clipboard

[BUG] press enter when using IME causes unwanted submit in modal input

Open reorx opened this issue 3 years ago • 0 comments

Describe the bug

When typing by input method editor (IME) in a modal input (e.g. triggered by a Capture command), if enter is hit, the text is submitted immediately.

To Reproduce Steps to reproduce the behavior:

  1. Run a Capture command
  2. Switch to an IME (most of them are CJK language)
  3. Type something
  4. Press enter, and the input is submitted immediately

Expected behavior The text in the IME is inserted, and the input does not submit.

Screenshots

https://user-images.githubusercontent.com/405972/167262040-526b1948-6ba8-4f40-a92f-938e35d8d3cf.mov

Here you can see I typed test in the IME, then I pressed enter, I intended to insert test in the input and continue typing, but the input was submitted.

Desktop (please complete the following information):

Obsidian version: v0.14.6
Installer version: v0.12.4
Operating system: Darwin Kernel Version 21.4.0: Mon Feb 21 20:36:53 PST 2022; root:xnu-8020.101.4~2/RELEASE_ARM64_T8101 21.4.0

Additional context

In CJK IME, when enter is hit, it means to insert the text without converting it to the CJK character, this is a common trick to insert English words without turning off the IME.

By listening to Element: compositionstart event - Web APIs | MDN, we can determine whether the enter key means to insert text or submit. Here's a snippet I used in my projects:

interface CompositionState {
	lock: boolean
}

export function lockInputMethodComposition(el: HTMLInputElement): CompositionState {
	const state: CompositionState = {
		lock: false,
	}
	el.addEventListener('compositionstart', () => {
		state.lock = true
	})
	el.addEventListener('compositionend', () => {
		state.lock = false
	})
	return state
}

const nameInputState = lockInputMethodComposition(nameInputEl)
nameInputEl.addEventListener('keydown', async (e) => {
	if (e.key === 'Enter' && !nameInputState.lock) {
		e.preventDefault()
		// do things like submit the input here
	}
})

Reference: dom events - What is JavaScript's CompositionEvent? Please give examples - Stack Overflow

reorx avatar May 07 '22 16:05 reorx