检测到 :focus-within 失去焦点的事件侦听器

Dan*_*l T 6 javascript dom-events

我一直在尝试检测是否:focus-within掉课了。我尝试使用 addEventListener 来检测“click”、“auxclick”、“blur”、“mouseup”之外的点击。但我不知道如何检测实际文档之外的点击。例如,点击URL输入。我该如何解决?

Dan*_*rzo 9

要检测 DOM 元素是否丢失:focus-within,可以使用focusout如下事件:

containerElement.addEventListener('focusout', function(e) {
    if (e.currentTarget.contains(e.relatedTarget)) {
        /* Focus will still be within the container */
    } else {
        /* Focus will leave the container */
    }
});
Run Code Online (Sandbox Code Playgroud)

当页面完全失去焦点(访问 URL、切换选项卡等)时,e.relatedTarget不存在,因此代码可以正常工作。如果你想在页面失去焦点时忽略document.hasFocus(),可以使用检查:

containerElement.addEventListener('focusout', function(e) {
    /*
        If the document has lost focus,
        skip the containment check 
        and keep the element visible.
     */
    if (!document.hasFocus()) {
        return;
    }
    if (!e.currentTarget.contains(e.relatedTarget)) {
        hideSelf();
    }
});
Run Code Online (Sandbox Code Playgroud)

...但是当焦点返回页面时你必须做出反应所以完整的(呃)解决方案看起来像这样:

containerElement.addEventListener('focusout', function(e) {
    const self = e.currentTarget;
    /*
        If the document has lost focus,
        don't hide the container just yet,
        wait until the focus is returned.
     */
    if (!document.hasFocus()) {
        window.addEventListener('focus', function focusReturn() {
            /* 
                We want the listener to be triggered just once,
                so we have it remove itself from the `focus` event.
            */
            window.removeEventListener('focus', focusReturn);

            /*
                Test whether the active element 
                is within our container.
             */
            if (!self.contains(document.activeElement)) {
                hideSelf();
            }
        });
        return;
    }
    if (!self.contains(e.relatedTarget)) {
        hideSelf();
    }
});
Run Code Online (Sandbox Code Playgroud)