Прослушиватель событий, который обнаруживает, что: фокус-в пределах потерянного фокуса

#javascript #dom-events

#javascript #dom-события

Вопрос:

Я пытался определить, был ли :focus-within потерян класс. Я пытался обнаружить щелчок вне с помощью addEventListener для ‘click’, ‘auxclick’, ‘blur’, ‘mouseup’. Но я не могу понять, как обнаружить щелчок за пределами фактического документа. Например, нажмите на ввод URL. Как я могу это решить?

Комментарии:

1. Не могли бы вы объяснить более подробно, чтобы каждый мог легко понять вопрос и предоставить вам наилучшее решение по нему?

2. Нужное вам событие focusout и тест, который вы хотите выполнить, когда произойдет событие event.target.matches(':focus-within') . Действия, которые на самом деле не удаляют фокус (как вы описываете), не могут быть прослушаны.

Ответ №1:

Чтобы определить, был ли потерян элемент 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 */
    }
});
 

Когда фокус полностью теряется страницей (посещение 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();
    }
});
 

… но тогда вы должны реагировать, когда фокус возвращается на страницу, поэтому полное (er) решение выглядит примерно так:

 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();
    }
});