Case ce-0548-gettargetranges-empty-en · Scenario scenario-gettargetranges-empty

beforeinput.getTargetRanges() returns empty array with Samsung keyboard text prediction ON

OS: Android 10-14 Device: Mobile (Samsung Galaxy series) Any Browser: Chrome for Android 120+ Keyboard: Korean (IME) - Samsung Keyboard with Text Prediction ON Status: draft
getTargetRanges beforeinput samsung-keyboard text-prediction link android chrome

Phenomenon

On Android Chrome with Samsung keyboard text prediction enabled, typing text next to a link in a contenteditable element causes beforeinput event’s getTargetRanges() to return an empty array.

Reproduction example

  1. Open Chrome browser on an Android device (Samsung Galaxy series, etc.).
  2. Enable text prediction feature in Samsung keyboard.
  3. Prepare HTML with an anchor link inside a contenteditable element (e.g., <a href="https://example.com">Link text</a>).
  4. Position the cursor right next to (after) the anchor link.
  5. Type text (e.g., “Hello”).
  6. Check beforeinput.getTargetRanges() in the browser console.

Observed behavior

When typing text next to a link:

  1. beforeinput event:

    • e.getTargetRanges() returns [] (empty array)
    • Or e.getTargetRanges may be undefined
    • Cannot determine exact text insertion position
  2. Fallback required:

    • Must use window.getSelection() but it may be less accurate
    • window.getSelection() may include link element
  3. Result:

    • Difficult to determine exact insertion position
    • Text may be inserted at wrong location
    • Link structure may be corrupted

Expected behavior

  • getTargetRanges() should return an array of StaticRange objects indicating exact insertion position
  • Should provide valid range information, not empty array
  • Should return accurate position even when typing next to links

Impact

  • Cannot determine exact position: Without getTargetRanges(), cannot know exact insertion position
  • Inaccurate fallback: Must rely on window.getSelection() which is less accurate
  • Incorrect insertion position: Text may be inserted at wrong location
  • Link structure corruption: Text may be inserted into link instead of after it

Browser Comparison

  • Android Chrome + Samsung Keyboard (Text Prediction ON): This issue occurs
  • Android Chrome + Samsung Keyboard (Text Prediction OFF): Works normally
  • Android Chrome + Gboard: Works normally
  • Chrome 77: Known bug where getTargetRanges() always returned empty array

Notes and possible direction for workarounds

  • Check for empty array: Always check if getTargetRanges() returns empty array
  • window.getSelection() fallback: Use window.getSelection() when empty array
  • Normalize selection: Normalize selection when using fallback to exclude link
  • Store DOM state: Store DOM state when getTargetRanges() is unavailable for comparison

Code example

const editor = document.querySelector('div[contenteditable]');

editor.addEventListener('beforeinput', (e) => {
  const targetRanges = e.getTargetRanges?.() || [];
  
  if (targetRanges.length === 0) {
    // getTargetRanges() is empty array - use fallback
    const selection = window.getSelection();
    if (selection && selection.rangeCount > 0) {
      const range = selection.getRangeAt(0).cloneRange();
      
      // Normalize selection (exclude link)
      const normalized = normalizeRangeForLink(range);
      
      // Process with normalized range
      handleInputWithRange(normalized, e);
    }
  } else {
    // getTargetRanges() available
    const staticRange = targetRanges[0];
    // Convert StaticRange to Range for use
    const range = document.createRange();
    range.setStart(staticRange.startContainer, staticRange.startOffset);
    range.setEnd(staticRange.endContainer, staticRange.endOffset);
    
    handleInputWithRange(range, e);
  }
});

function normalizeRangeForLink(range) {
  let container = range.startContainer;
  if (container.nodeType === Node.TEXT_NODE) {
    container = container.parentElement;
  }
  
  const link = container.closest('a');
  if (link && range.startContainer === link) {
    // Adjust to position after link
    const normalized = document.createRange();
    try {
      normalized.setStartAfter(link);
      normalized.collapse(true);
      return normalized;
    } catch (e) {
      return range;
    }
  }
  
  return range;
}
Before
Cursor positioned after link
beforeinput event (Bug)
beforeinput: getTargetRanges() returns [] (empty array), cannot determine exact insertion position
vs
✅ Expected
Link text Hello
Expected: getTargetRanges() should return ranges indicating exact insertion position

Playground for this case

Use the reported environment as a reference and record what happens in your environment while interacting with the editable area.

Reported environment
OS: Android 10-14
Device: Mobile (Samsung Galaxy series) Any
Browser: Chrome for Android 120+
Keyboard: Korean (IME) - Samsung Keyboard with Text Prediction ON
Your environment
Sample HTML:
Event log
Use this log together with the case description when filing or updating an issue.
0 events
Interact with the editable area to see events here.

Comments & Discussion

Have questions, suggestions, or want to share your experience? Join the discussion below.