Focus an element within a ShadowDOM

Viewed 1483

I have a modal dialog created within a Shadow DOM and injected (using violentmonkey) into a page during document load. This dialog contains a simple form. The idea is to prompt the user for input.

When the dialog is created, it has focus. Elements can be tabbed, and I can hook key/mouse events. The problem arises when the window load event is triggered. Focus returns to the main body (verified by issuing document.activeElement in the console and by hooking focusin/out for both body and the shodowroot). I can hook the focusin event, but so far nothing I have tried will return focus to my dialog.

A cut down version of the dialog:

<div id="twifty-translate-dialogue" style="">
  #shadow-root (open)
  <div class="outer" style="z-index: 2147483647; pointer-events: none;">
    <div class="container">
      <div id="header" class="">
      </div>
      <div id="languages" class="">
      </div>
      <div class="buttons">
        <button id="translate" class="button-translate" type="button">Translate</button>
        <button id="cancel" class="button-cancel" type="button">Cancel</button>
      </div>
    </div>
  </div>

I would expect the following to work:

window.onload = () => {
  document.getElementById("twifty-translate-dialogue").shadowRoot.getElementById("translate").focus()
}

From what I've read, there should be two active elements. The #twifty-translate-dialogue and the shadow DOMs #translate. But:

document.activeElement
> <body>
document.getElementById("twifty-translate-dialogue").shadowRoot.getElementById("translate").focus()
document.activeElement
> #twifty-translate-dialogue
document.getElementById("twifty-translate-dialogue").shadowRoot.activeElement
> null

How can I restore focus?

Update: A workaround:

window.onload = () => {
  window.setTimeout(() => {
    this.shadow.getElementById("translate").focus()
  }, 1)
}

I'm guessing that the focus changes after the onload event, meaning that trying to set the focus in the handler will have no effect. By using a timeout, I've scheduled the focus call for after the completion of onload.

Is this a bug or standard behaviour? Is there a prefered way of setting the focus?

0 Answers
Related