Рассмотренные на
предыдущем занятии элементы формы:
input, textarea, select
обладают
свойством фокусировки, то есть, когда мы кликаем по ним, они получают фокус и
мы можем изменять состояние этих элементов. Например, в такой странице:
<!DOCTYPE html>
<html>
<head>
<title>Уроки по JavaScript</title>
</head>
<body>
<form name="reg">
<p><input name="user" value="" />
<p><input name="sex" type="radio" checked />М
<input name="sex" type="radio" />Ж
<p>Город: <select name="city">
<option>Москва</option>
<option>Санкт-Петербург</option>
<option>Тверь</option>
</select>
<p>Согласие <input name="agree" type="checkbox" />
<p><textarea name="about" rows="10" cols="30">О себе</textarea>
<p><input type="submit" name="submit">
</form>
<script>
</script>
</body>
</html>
щелкая по формам
ввода, видим синюю подсветку элементов. Это как раз и есть визуальный признак
получения фокуса. Когда мы уходим с элемента, он теряет фокус. Так вот, при
получении или потери фокуса возникают события:
-
focus
– при получении фокуса;
-
blur
– при потере фокуса.
Давайте в этом
убедимся. Повесим на первый элемент ввода обработчики этих двух событий:
let frm = document.forms[0];
frm.user.onfocus = function(event) {
console.log("получение фокуса");
};
frm.user.onblur = function(event) {
console.log("потеря фокуса");
};
Теперь, щелкая
по элементу, появится сообщение «получение фокуса», то есть, сработало событие focus. А при переходе
к другому элементу появляется событие «потеря фокуса», то есть, сработало
событие blur.
Когда могут
понадобиться такие события? Например, для проверки корректности ввода данных в
поле ввода. Для простоты положим, что имя пользователя не должно содержать
символа #. Такую проверку можно сделать так:
frm.user.onblur = function(event) {
if(frm.user.value.includes('#'))
frm.user.classList.add('error');
else frm.user.classList.remove('error');
};
То есть, когда в
поле ввода содержится символ #, то оно принимает красный фон. Соответственно
стиль можно прописать так:
<style>
.error { background: #CC0000; }
</style>
А в обработчике
фокуса будем удалять этот класс, то есть, убирать красный фон:
frm.user.classList.remove('error');
Однако, обратите
внимание, стандарты HTML 5 и выше позволяют в полях ввода прописывать
атрибуты
required,
pattern
для
автоматической проверки корректности введенных данных. Так что скрипт следует
использовать, только если недостаточно встроенных способов валидации данных.
Также следует
иметь в виду, что события focus и blur не всплывают, то есть, мы не можем
перехватить их обработчиком элемента более высокого уровня в иерархии DOM-дерева.
Например, если поставить обработчик onfocus на форму:
frm.onfocus = function() {
console.log("form: focus");
}
то он никогда не
будет срабатывать. Однако, тут есть один нюанс: события focus и blur хоть и не
всплывают, но зато имеют фазу погружения и мы можем их перехватить на форме в
этот момент:
frm.addEventListener("focus", function() {
console.log("form: focus");
}, true);
Теперь, кликая
по элементам формы, мы будем видеть сообщения в консоли. Но, все же, если нам
нужно перехватывать события фокусировки, то лучше использовать для этого
специальные события:
focusin
и focusout
которые работают
также как и focus и blur, но всплывают. Обработчики этих событий можно
добавлять только через метод addEventListener, следующим образом:
frm.addEventListener("focusin", function() {
console.log("form: focusin");
});
Теперь событие
успешно перехватывается на этапе всплытия.
В JavaScript существуют
методы:
-
elem.focus()
– для установки фокуса на элемент;
-
elem.blur()
– для снятия фокуса с элемента.
Например, так:
и при обновлении
документа мы увидим фокусировку на теге textarea. Аналогично
работает второй метод. Но здесь есть несколько тонких моментов. Во-первых, эти
методы могут не работать в браузерах Firefox. Во-вторых,
бывают случаи, когда фокусировка с элемента будет сниматься автоматически.
Например, при появлении модальных окон, вызванных методами:
alert(), prompt(), confirm()
Так что
полагаться целиком на методы focus и blur не стоит и в практике
программирования ими стараются не пользоваться. Вместо этого лучше полагаться
на события focus и blur и реализовывать логику через их обработчики. Или же,
используя псевдокласс :focus, определять стили сфокусированного
элемента.
Работая с
событиями focus и blur, следует иметь в виду, что далеко не все элементы HTML-документа по
умолчанию поддерживают фокусировку. Например, элементы:
div,
p, table, span, img и т.п.
Добавим div на нашу
страницу:
<div id="block" style="height:50px; background: #777"></div>
И пропишем для
него два обработчика:
block.onfocus = function(event) {
console.log("focus");
};
block.onblur = function(event) {
console.log("blur");
};
Кликая по блоку div мы не увидим
никаких сообщений в консоли. Это, как раз, и говорит о том, что данный элемент
не имеет фокусировки. Но ее можно включить, если прописать вот такой атрибут:
tabindex="1"
Теперь, при
щелчке мыши по блоку div, будут срабатывать эти два события. Что
это за атрибут tabindex? Он указывает в какой
последовательности следует переключать фокусы между элементами, при нажатии на
клавишу Tab. Так что, если
мы какой-то элемент включаем в эту последовательность, то он должен обладать
фокусировкой. И браузеры ее включают, даже если, ранее элемент не обладал таким
свойством. Причем, это свойство можно установить и непосредственно в скрипте,
используя свойство tabIndex:
Обратите
внимание на его написание: здесь буква I заглавная.
У этого атрибута
(или же свойства) есть два специальных значения:
-
tabindex="0"
располагает элемент на уровне с другими элементами без атрибута tabindex, но
обладающих фокусировкой;
-
tabindex="-1"
позволяет фокусироваться на элементе только программно.
Ну и, наконец,
последнее. Для получения текущего элемента с фокусировкой, используется
свойство:
let active = document.activeElement;
console.log(active);
И в консоли мы
увидим элемент textarea, который имеет фокус на странице.