
Попытка отследить через JavaScript событие потеря фокуса формой может поначалу поставить новичков в затруднительное положение. На самом деле тут нет ничего сложного.
Создание формы
Допустим, у вас есть форма с несколькими элементами внутри, и вам требуется, например, запустить функцию в случае снятия с нее фокуса.
<form action="#!"> <label for="input1">Input 1</label> <input type="text" id="input1" value="Hello"> <label for="input2">Input 2</label> <input type="text" id="input2" value="world"> <label for="input3">Input 3</label> <input type="text" id="input3" value="!"> <button>Submit</button> </form>
Как же это сделать? Давайте попробуем разобраться.
Событие focusout
В нативном JavaScript есть такое событие, как focusout. И большинство новичков несомненно попробуют применить именно его.
const form = document.querySelector('form'); form.addEventListener('focusout', function (event) { // Здесь можно написать код, который должен будет выполняться при снятии фокуса с формы console.log('focus left!'); });
Но из-за принципа всплытия событий это не сработает при снятии фокуса с form. Оно будет работать всякий раз, когда один из элементов внутри формы теряет фокус. Если требуется отследить переход, например, от одного инпута к другому, то callback в addEventListener сработал бы.
Можно также попытаться использовать event.target, но и это не будет работать. Все дело в том, что событие запускает input, который теряет фокус, а не тот, который его получает.
Точно так же вы не сможете осуществить проверку и при помощи свойства document.activeElement. В этом случае событие срабатывает в каком-то странном промежуточном состоянии, когда текущий элемент потерял фокус, а новый его еще не получил.
form.addEventListener('focusout', function (event) { // Здесь можно написать код, который должен будет выполняться при снятии фокуса с формы console.log(event.target, document.activeElement); });
Как же быть в этом случае?
Он доступен только для событий focus и возвращает «вторичную цель». Она варьируется в зависимости от события. При применении focusin — это элемент, теряющий фокус, а при focusout — получающий его.
С помощью Event.relatedTarget и метода contains() мы можем отследить события потери фокуса при помощи JavaScript внутри формы.
// Здесь можно написать код, который должен будет выполняться при снятии фокуса с формы form.addEventListener('focusout', function (event) { // Если фокус все еще находится на форме, то ничего не происходит if (form.contains(event.relatedTarget)) return; // В противном случае в консоль выводится сообщение console.log('Фокус снят!'); });
Кроссбраузерность
Event.relatedTarget воспринимается всеми современными браузерами вплоть до IE9, как и contains(), но отличается тем, что применим только к DOM-элементам. Для других типов узлов, таких как текстовые (text nodes), он не доступен.