javascripthtmldomdom-events

document.activeElement not displaying focused elements within shadow root


document.activeElement is neat, but when using it on a site that uses shadow root - I get the outer container. How can I get the active element within nested shadow roots?

Do I need to crawl through elements that have shadowRoot and add eventListeners on each level?

Example that shows the issue:

window.addEventListener('focus', e => {
    if (e.target instanceof Window) return;
  
  console.log({target: e.target, activeElement: document.activeElement})
}, true)
  <input placeholder="level 1" />

  <div id="div2">

    <template shadowrootmode="open">
      <input placeholder="level 2" />

      <div id="div3">
        <template shadowrootmode="open">
          <input placeholder="level 3" />

          <div id="div4">
            <template shadowrootmode="open">
              <input placeholder="level 4" />
            </template>
          </div>
        </template>
      </div>

    </template>
  </div>


Solution

  • I figured out that you don't need to attach any more eventListeners. document.activeElement will point to one element and then you check if that element has shadowRoot. If it does you grab the .activeElement of that, and keep checking for shadowRoot.

    document.activeElement.shadowRoot.activeElement.shadowRoot... etc