Подойдет ли событие blur чтобы понять что форма расфокусировалась
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Ограничения события blur для определения расфокусировки формы
Нет, стандартного события blur недостаточно, чтобы однозначно понять, что форма расфокусировалась полностью. Это связано с фундаментальным различием в поведении событий на уровне элементов и на уровне формы как целого.
Почему blur на отдельных полях не подходит
Событие blur срабатывает на отдельном элементе формы (input, textarea, select), когда он теряет фокус. Однако фокус может просто перейти на другой элемент внутри той же формы. В этом случае форма остаётся активной, но blur на предыдущем элементе всё равно произойдёт.
Пример проблемного сценария:
<form id="myForm">
<input type="text" id="name" placeholder="Имя">
<input type="email" id="email" placeholder="Email">
</form>
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
nameInput.addEventListener('blur', () => {
// Сработает при переходе с name на email,
// но форма при этом НЕ расфокусирована!
console.log('Поле name потеряло фокус');
});
Альтернативные и более надежные подходы
1. Использование события focusout с делегированием и проверкой relatedTarget
Событие focusout всплывает в отличие от blur, что позволяет использовать делегирование. Ключевая проверка — находился ли relatedTarget (элемент, получивший фокус) внутри формы.
const form = document.getElementById('myForm');
form.addEventListener('focusout', (event) => {
// Проверяем, находится ли новый элемент фокуса ВНЕ формы
const isStillInForm = form.contains(event.relatedTarget);
if (!isStillInForm) {
console.log('Форма полностью расфокусирована');
// Здесь можно выполнить валидацию, автосохранение и т.д.
}
});
2. Отслеживание события focusin на документе
Более универсальный подход — отслеживание всех изменений фокуса на уровне документа и проверка, находится ли текущий активный элемент внутри формы.
const form = document.getElementById('myForm');
let formHasFocus = false;
// Отслеживаем, когда фокус попадает в форму
form.addEventListener('focusin', () => {
formHasFocus = true;
});
// Отслеживаем все изменения фокуса в документе
document.addEventListener('focusin', (event) => {
const focusInsideForm = form.contains(event.target);
// Если форма имела фокус, но теперь фокус вне её
if (formHasFocus && !focusInsideForm) {
console.log('Форма расфокусирована');
formHasFocus = false;
// Выполняем необходимые действия
}
// Обновляем статус, если фокус вернулся в форму
if (focusInsideForm) {
formHasFocus = true;
}
});
3. Комбинация blur с флагом и setTimeout
Менее надежный, но иногда используемый подход для поддержки старых браузеров.
const form = document.getElementById('myForm');
let blurTimeout;
form.addEventListener('blur', (event) => {
// Используем setTimeout, чтобы дать время другому элементу получить фокус
blurTimeout = setTimeout(() => {
if (!form.contains(document.activeElement)) {
console.log('Форма расфокусирована');
}
}, 10);
}, true); // Используем capture phase для всплытия
form.addEventListener('focus', () => {
clearTimeout(blurTimeout);
}, true);
Практические рекомендации
- Для современных браузеров предпочтительнее использовать
focusout/focusinс проверкойrelatedTarget— это наиболее семантически правильный подход. - Для сложных сценариев (модальные окна, всплывающие подсказки) может потребоваться дополнительная логика для игнорирования временных потерь фокуса.
- Учитывайте доступность — некоторые вспомогательные технологии могут вызывать неожиданные последовательности событий фокуса.
- Тестируйте на мобильных устройствах — поведение фокуса на touch-устройствах может отличаться от десктопного.
Вывод
blur события отдельных элементов недостаточно для определения полной расфокусировки формы. Для этой задачи требуется более комплексный подход, отслеживающий перемещение фокуса за пределы всей формы-контейнера. Рекомендую использовать делегирование события focusout с анализом relatedTarget — это наиболее надежное и современное решение.