Предотвратите запуск события blur, если какой-либо из его дочерних элементов получает фокус

У меня есть div на странице, которая показывает некоторую информацию о конкретной категории (изображение, имя и т. д.).

когда я нажимаю на изображение редактирования, он помещает категорию в режим редактирования, который позволяет мне обновлять имя. Как вы можете видеть из изображения ниже, он показывает, что" суп " в настоящее время находится в режиме редактирования, остальные находятся в обычном режиме просмотра. Все это работает, как и ожидалось, с кнопками отмены / сохранения, делая все правильно. (Я попытался добавить изображение, но не позволил мне, нужно больше любовь)

один раз в режиме редактирования, если я нажму где-нибудь еще на странице (вне div), ожидаемым результатом будет то, что категория супа вернется в режим просмотра. После какого-то события это также должно позволить мне спросить, хотят ли они сохранить изменения.

Итак, что я тогда решил сделать, это создать событие размытия на родительском div "супы". Это работает так, как ожидалось, если я нажимаю в любом месте страницы, однако, если я нажимаю на внутренний элемент div также вызывает запуск события размытия родителей, что приводит к возвращению категории в режим просмотра.

Итак, есть ли способ предотвратить Родительский div от запуска события размытия, если какой-либо из его детей получает фокус?

<div tabindex="-1" onblur="alert('outer')">
    <input type="text" value="Soup" />
</div>

Я просто написал код без компилятора, так что не уверен, если это даже работает, но с этим, надеюсь, вы поняли.

Я использую нокаут.js для обновления GUI на лету, но это не должно повлиять на этот ответ I не думал.

2 ответов


мне приходилось решать эту проблему раньше. Я не уверен, что это лучшее решение, но это то, что я использовал.

поскольку событие click срабатывает после размытия, нет (кросс-браузер, надежный) способ сказать, какой элемент получает фокус.

Mousedown, однако, срабатывает перед размытием. Это означает, что вы можете установить некоторый флаг в mousedown ваших дочерних элементов и опросить этот флаг в размытии вашего родителя.

рабочий пример: http://jsfiddle.net/L5Cts/

обратите внимание, что вам также придется обрабатывать keydown (и проверьте tab / shift-tab), если вы хотите также поймать размытия, вызванные клавиатурой.


Я не думаю, что есть какие-либо гарантию mousedown произойдет до событий фокуса во всех браузерах, поэтому лучшим способом справиться с этим может быть использование evt.relatedTarget. Для focusin мероприятия eventTarget свойство является ссылкой на элемент, который в настоящее время проигрыш фокус. Вы можете проверить, является ли этот элемент потомком родителя, а если нет, вы знаете, что фокус входит в родителя извне. Для focusout событие relatedTarget ссылка на элемент, который в настоящее время прием фокус. Используйте ту же логику, чтобы определить, полностью ли фокус покидает родителя:

const parent = document.getElementById('parent');

parent.addEventListener('focusin', e => {
    const enteringParent = !parent.contains(e.relatedTarget);

    if (enteringParent) {
        // do things in response to focus on any child of the parent or the parent itself
    }
});

parent.addEventListener('focusout', e => {
    const leavingParent = !parent.contains(e.relatedTarget);

    if (leavingParent) {
        // do things in response to fully leaving the parent element and all of its children
    }
});