ํ์
On Android virtual keyboards, after selecting all text in a contenteditable element, typing a letter does not immediately start IME composition. The first letter is inserted as plain text, and IME composition only starts from second letter.
์ฌํ ์์
- Type text in contenteditable element (e.g., โใใใซใกใฏโ).
- Press Ctrl+A to select all text.
- Type first letter (e.g., โใโ).
๊ด์ฐฐ๋ ๋์
- First letter plain text: โใโ is inserted as plain text (not part of IME composition)
- Selection remains: The โSelect Allโ selection stays visible
- IME starts delayed: IME composition (candidate window) only appears after typing second letter
- Result: First letter appears as plain text, then IME composition replaces from second letter
์์ ๋์
- IME composition should start immediately when first letter is typed
- The entire selection should be replaced with IME composition
์ฐธ๊ณ ์ฌํญ ๋ฐ ๊ฐ๋ฅํ ํด๊ฒฐ ๋ฐฉํฅ
- Clear selection before typing: Remove selection before user starts new input
- Detect and handle first letter separately: Check if plain text is inserted before composition starts
- Use beforeinput event: Monitor
inputType = 'insertText'to detect plain text insertion - User education: Add UI hint to clear selection before starting new IME input
์ฝ๋ ์์
const editor = document.querySelector('div[contenteditable]');
let imeStarted = false;
let wasSelectAll = false;
// Detect select all
document.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.key === 'a') {
wasSelectAll = true;
}
});
// Track composition start
editor.addEventListener('compositionstart', () => {
imeStarted = true;
// Clear selection if it exists
const selection = window.getSelection();
if (selection.rangeCount > 0 && !selection.isCollapsed) {
selection.removeAllRanges();
}
});
// Distinguish plain text vs IME
editor.addEventListener('beforeinput', (e) => {
if (e.inputType === 'insertText' && !imeStarted && wasSelectAll) {
// Plain text was inserted before IME started
console.warn('Plain text inserted before IME started:', e.data);
}
});
editor.addEventListener('keydown', (e) => {
if (wasSelectAll) {
// First letter after select all detected
console.log('First letter after select all:', e.key);
// Optionally add cleanup logic
}
});