Skip to content

FIX: use correct iframe selector and defer init until Docs is ready#17

Open
bennidhamma wants to merge 1 commit into
tirthd16:mainfrom
bennidhamma:fix/iframe-selector-and-timing
Open

FIX: use correct iframe selector and defer init until Docs is ready#17
bennidhamma wants to merge 1 commit into
tirthd16:mainfrom
bennidhamma:fix/iframe-selector-and-timing

Conversation

@bennidhamma
Copy link
Copy Markdown

Problem

The extension shows the NORMAL mode indicator but keystrokes are not intercepted — text inserts as if in insert mode.

Two bugs cause this:

  1. Wrong iframe: content.js used getElementsByTagName('iframe')[0], which returns the first iframe in DOM order. Google Docs has multiple iframes; the text event target is .docs-texteventtarget-iframe. The keydown listener was attached to the wrong element, so keystrokes were never intercepted. (page_script.js already used the correct selector — this brings content.js in line with it.)

  2. Timing race: Google Docs injects its iframes dynamically after document_idle. Even with the correct selector, the element may not exist when the content script runs. A MutationObserver now defers initialization until the target iframe appears. cursorTop (.kix-cursor-top) is fetched lazily for the same reason.

Changes

  • Replace getElementsByTagName('iframe')[0] with document.querySelector('.docs-texteventtarget-iframe')
  • Wrap initialization in a function; if the element isn't present yet, a MutationObserver retries until it is
  • Fetch cursorTop lazily in switchModeToNormal / switchModeToInsert with a null guard

Test plan

  • Load a Google Doc — NORMAL mode indicator appears and vim motions work immediately
  • Hard-refresh the doc — extension still initializes correctly
  • Press i to enter insert mode, type text, press Escape — returns to NORMAL and keystrokes are intercepted again

The extension was attaching the keydown listener to the wrong iframe —
getElementsByTagName('iframe')[0] returns the first iframe in DOM order,
which is not the text event target. page_script.js already used the correct
.docs-texteventtarget-iframe selector; content.js now matches it.

Additionally, Google Docs injects its iframes dynamically after document_idle,
so a MutationObserver is used to defer initialization until the target iframe
exists. cursorTop is also fetched lazily for the same reason.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant