При взаимодействии пользователя с приложением, окном и Web-страницей происходят события. События — это своего рода извещения системы о том, что пользователь выполнил какое-либо действие или внутри самой системы возникло некоторое условие. События возникают при щелчке на элементе, перемещении мыши, нажатии клавиши на клавиатуре, изменении размеров окна, окончании загрузки Web-страницы и т. д.
В предыдущих главах мы уже рассмотрели события объекта приложения, а также события окна. В этой главе мы рассмотрим события, которые генерируется при работе с Web-страницей.
Назначить обработчик события можно несколькими способами. Первый способ заключается в добавлении к тегам параметров с названиями событий. В качестве значений параметров указывается выражение или вызов функции. Пример назначения обработчика нажатия кнопки:
<input type="button" value="Кнопка 1" onclick="handler1()">При нажатии кнопки будет вызвана функция handler1().
Второй способ подразумевает использование свойств элементов. Причем тут возможны два варианта: с помощью анонимной функции или ссылки на функцию:
document.getElementById('btn2').onclick = function() {
console.log('Нажата кнопка 2');
};
document.getElementById('btn3').onclick = handler2;Чтобы получить доступ к свойствам элемента нужно вначале получить ссылку на сам элемент с помощью метода getElementById() объекта document. В качестве значения метод принимает строку с идентификатором элемента. Далее указывается название события, которое совпадает и названием параметра тега. После оператора = задается анонимная функция или ссылка на функцию. Обратите внимание, при указании ссылки название функции указывается без круглых скобок. Если круглые скобки указать, то функция будет вызвана и результат ее работы станет значением свойства.
Первые два способа позволяют назначить только один обработчик. Попытка присвоить другое значение свойству приведет к удалению имеющегося обработчика. Третий способ лишен этого недостатка. Назначить обработчик события позволяет метод addEventListener(). Формат метода:
addEventListener(<Событие>, <Ссылка на функцию>[, <Фаза>]);В параметре <Событие> указывается название события в виде строки без префикса on, например, click вместо onclick. Ссылка на функцию-обработчик указывается во втором параметре. В эту функцию в качестве параметра передается ссылка на объект event, а внутри функции через ключевое слово this доступна ссылка на текущий элемент. В параметре <Фаза> значение false используется в большинстве случаев. Учитывая, что это значение по умолчанию в Electron, следовательно параметр можно не указывать.
Пример назначения обработчиков различными способами приведен в листинге 7.1.
Листинг 7.1. Назначение обработчиков событий
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Назначение обработчиков событий</title>
</head>
<body>
<input type="button" value="Кнопка 1" onclick="handler1()">
<input type="button" value="Кнопка 2" id="btn2">
<input type="button" value="Кнопка 3" id="btn3">
<input type="button" value="Кнопка 4" id="btn4">
<script>
function handler1() {
console.log('Нажата кнопка 1');
}
function handler2() {
console.log('Нажата кнопка 3');
}
function handler3(e) {
console.log('Нажата кнопка 4. handler3()');
}
function handler4(e) {
console.log('Нажата кнопка 4. handler4()');
}
document.getElementById('btn2').onclick = function() {
console.log('Нажата кнопка 2');
};
// Название функции указывается без круглых скобок
document.getElementById('btn3').onclick = handler2;
// Можно назначить сразу несколько обработчиков
let btn4 = document.getElementById('btn4');
btn4.addEventListener('click', handler3);
btn4.addEventListener('click', handler4);
</script>
</body>
</html>Если обработчик назначался через параметр тега или свойство, то для удаления обработчика нужно присвоить свойству значение null, пустую строку или пустую анонимную функцию:
document.getElementById('btn2').onclick = function() {};Если обработчик назначался через метод addEventListener(), то удалить его можно с помощью метода removeEventListener(). Формат метода:
removeEventListener(<Событие>, <Ссылка на функцию>[, <Фаза>]);Обратите внимание, нужно обязательно иметь ссылку на обработчик, назначенный с помощью метода addEventListener(). Если при назначении обработчика использовалась анонимная функция, то удалить обработчик будет нельзя. Пример:
document.getElementById('btn4').removeEventListener('click', handler3);При назначении обработчика с помощью свойства или метода addEventListener() внутри обработчика будет доступна ссылка на текущий элемент через указатель this. С помощью этого указателя можно получить доступ к свойствам элемента. Если обработчик назначается через параметр тега, то указатель нужно передать в качестве параметра. Получим текст на кнопке при ее нажатии (листинг 7.2).
Листинг 7.2. Указатель this
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Указатель this</title>
</head>
<body>
<input type="button" value="Кнопка 1" onclick="handler1(this)">
<input type="button" value="Кнопка 2" id="btn2">
<input type="button" value="Кнопка 3" id="btn3">
<script>
function handler1(elem) {
console.log('Нажата кнопка ' + elem.value);
}
function handler2(event) {
console.log('Нажата кнопка ' + this.value);
}
document.getElementById('btn2').onclick = function(event) {
console.log('Нажата кнопка ' + this.value);
};
let btn3 = document.getElementById('btn3');
btn3.addEventListener('click', handler2);
</script>
</body>
</html>Объект event позволяет получить детальную информацию о произошедшем событии и выполнить необходимые действия. Объект event доступен только в обработчиках событий. При наступлении следующего события все предыдущие значения свойств сбрасываются.
При назначении обработчика с помощью метода addEventListener() или свойства объект event будет доступен через первый параметр. Если обработчик назначается через параметр тега, то объект нужно передать в обработчик в качестве параметра.
Объект event имеет следующие основные свойства:
type — строка, содержащая тип события. Возвращается в нижнем регистре и без префикса on. Например, при событии onclick свойство type равно click;target — ссылка на элемент, который является источником события;currentTarget — возвращает ссылку на элемент, в котором обрабатывается событие. Ссылается на тот же элемент, что и ключевое слово this внутри обработчика события. Значение свойства currentTarget может не совпадать со значением свойства target;timeStamp — время возникновения события в миллисекундах.Благодаря объекту event мы можем назначить один обработчик сразу для нескольких элементов и даже для нескольких типов событий. В листинге 7.3 приведен пример обработки нажатия кнопок внутри одного обработчика.
Листинг 7.3. Объект event
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Объект event</title>
</head>
<body>
<input type="button" value="Кнопка 1" onclick="handler(event)">
<input type="button" value="Кнопка 2" id="btn2">
<input type="button" value="Кнопка 3" id="btn3">
<script>
function handler(event) {
console.log(event.type);
console.log(event.target.value);
console.log(event.currentTarget.value);
console.log(event.timeStamp);
}
document.getElementById('btn2').onclick = handler;
let btn3 = document.getElementById('btn3');
btn3.addEventListener('click', handler);
</script>
</body>
</html>Для многих событий назначены действия по умолчанию, т. е. действия, которые Web-браузер выполняет в ответ на возникшие в документе события. Например, при щелчке на гиперссылке действием по умолчанию будет переход по указанному URL-адресу, нажатие кнопки Отправить приводит к отправке данных формы и т. д.
Иногда действия по умолчанию необходимо прервать. Для этого используются следующие свойства и методы объекта event:
cancelable — содержит true, если действие по умолчанию может быть отменено, и false — в противном случае;preventDefault() — отменяет действие по умолчанию, если его можно отменить;defaultPrevented — содержит true, если действие по умолчанию для текущего события было отменено в этом или предыдущем обработчике, и false — в противном случае.Для отмены действия по умолчанию можно также внутри обработчика вернуть значение false.
В листинге 7.4 приведен пример прерывания перехода по гиперссылке.
Листинг 7.4. Прерывание действий по умолчанию
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Прерывание действий по умолчанию</title>
<script>
function handler(e) {
e.preventDefault();
alert('Перехода по ссылке не будет!');
}
</script>
</head>
<body>
<p>
<a href="file.html"
onclick="alert('Перехода по ссылке не будет!'); return false;">
Нажмите для перехода по ссылке</a><br><br>
<a href="file.html" onclick="handler(event);">
Нажмите для перехода по ссылке</a>
</p>
</body>
</html>В этом примере рассмотрены два способа прерывания действия по умолчанию. В первой ссылке прерывание действия по умолчанию осуществляется возвратом значения false. Во второй ссылке с помощью свойств и методов объекта объекта event.
Что же такое "всплывание" событий? Давайте рассмотрим следующий пример (листинг 7.5).
Листинг 7.5. Всплывание событий
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Всплывание событий</title>
<script>
function showMsg(msg) {
let div1 = document.getElementById('div1');
div1.innerHTML += msg + '<br>';
}
</script>
</head>
<body onclick="showMsg('Событие onclick - Документ')">
<p onclick="showMsg('Событие onclick - Абзац')">
Щелкните мышью
<span style="color: red"
onclick="showMsg('Событие onclick - SPAN')">
здесь</span>
</p>
<div id="div1"></div>
</body>
</html>В этом примере мы написали обработчики события onclick для трех элементов страницы — тела документа, абзаца и тега <span>. Попробуем щелкнуть левой кнопкой мыши на слове "здесь". В итоге вместо одного события onclick мы получим целую последовательность событий:
Событие onclick - SPAN
Событие onclick - Абзац
Событие onclick - ДокументИными словами, событие onclick последовательно передается элементу-родителю. Для тега <span> элементом-родителем является абзац. А для абзаца элементом-родителем является само тело документа. Такое прохождение событий называется всплыванием событий.
Управлять всплыванием события позволяют следующие свойства и методы объекта event:
bubbles — содержит true, если текущее событие может всплывать, и false — в противном случае;stopPropagation() — прерывает всплывание события.Продемонстрируем прерывание всплывания события на примере (листинг 7.6).
Листинг 7.6. Прерывание всплывания события
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Прерывание всплывания события</title>
<script>
function showMsg(e, msg) {
let div1 = document.getElementById('div1');
div1.innerHTML += msg + '<br>';
e.stopPropagation();
}
</script>
</head>
<body onclick="showMsg(event, 'Событие onclick - Документ')">
<p onclick="showMsg(event, 'Событие onclick - Абзац')">
Щелкните мышью
<span style="color: red"
onclick="showMsg(event, 'Событие onclick - SPAN')">
здесь</span>
</p>
<div id="div1"></div>
</body>
</html>Попробуем теперь щелкнуть левой кнопкой мыши на слове "здесь". В итоге вместо трех событий мы получим только одно:
Событие onclick - SPANПеречислим основные события документа:
DOMContentLoaded — структура документа сформирована. Внутри обработчика этого события можно обращаться к элементам из скрипта и назначать обработчики событий для элементов страницы:window.addEventListener('DOMContentLoaded', () => {
// Здесь назначаем обработчики событий для элементов
});onload — после полной загрузки Web-страницы. Внутри обработчика этого события можно обращаться ко всем элементам из скрипта и назначать обработчики событий для элементов страницы:window.onload = function() {
// Здесь назначаем обработчики событий для элементов
};onscroll — при прокручивании содержимого элемента страницы, документа, окна или фрейма;onresize — при изменении размеров окна;onbeforeunload — перед выгрузкой документа;onunload — непосредственно перед выгрузкой документа. Генерируется после события onbeforeunload.Пример обработки событий документа приведен в листинге 7.7.
Листинг 7.7. События документа
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>События документа</title>
<script>
function showMsg(event, msg) {
let div1 = document.getElementById('div1');
div1.innerHTML += msg + '<br>';
console.log(event);
}
window.addEventListener('DOMContentLoaded', (e) => {
showMsg(e, 'Событие DOMContentLoaded');
});
</script>
</head>
<body onload="showMsg(event, 'Событие onload')"
onscroll="showMsg(event, 'Событие onscroll')"
onresize="showMsg(event, 'Событие onresize')">
<div id="div1"></div>
<div style="height: 600px"></div>
</body>
</html>Перечислим основные события мыши:
onmousedown — при нажатии кнопки мыши на элементе Web-страницы или самой странице;onmouseup — при отпускании ранее нажатой кнопки мыши;onclick — при щелчке мыши на элементе или на Web-странице;ondblclick — при двойном щелчке мыши;onmousemove — при любом перемещении мыши;onmouseover — при наведении курсора мыши на элемент;onmouseout — при выведении курсора мыши с элемента;onselect — при выделении элемента;oncontextmenu — при нажатии правой кнопки мыши для вывода контекстного меню;onwheel — при вращении колесика мыши.События возникают последовательно, например, последовательность событий при нажатии кнопки мыши на элементе страницы будет такой:
onmousedown
onmouseup
onclickПри двойном нажатии последовательность будет такой:
onmousedown
onmouseup
onclick
ondblclickЭто значит, что событие ondblclick возникает после события onclick.
Продемонстрируем обработку событий мыши на примере (листинг 7.8).
Листинг 7.8. События мыши
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>События мыши</title>
<script>
function showMsg(event, msg) {
let div1 = document.getElementById('div1');
div1.innerHTML += msg + '<br>';
console.log(event);
}
</script>
</head>
<body onmousedown="showMsg(event, 'Событие onmousedown')"
onmouseup="showMsg(event, 'Событие onmouseup')"
onclick="showMsg(event, 'Событие onclick')"
ondblclick="showMsg(event, 'Событие ondblclick')"
oncontextmenu="showMsg(event, 'Событие oncontextmenu')"
onwheel="showMsg(event, 'Событие onwheel')">
<p onmouseover="showMsg(event, 'Событие onmouseover')"
onmouseout="showMsg(event, 'Событие onmouseout')">
Щелкните мышью в любом месте страницы
</p>
<div id="div1"></div>
<div style="height: 600px"></div>
</body>
</html>Получить информацию о событии позволяют следующие свойства:
clientX и clientY — координаты события (по осям X и Y) в клиентских координатах;pageX и pageY — координаты события (по осям X и Y) относительно левого верхнего угла страницы;offsetX и offsetY — координаты события (по осям X и Y) относительно контейнера;button — число, указывающее нажатую кнопку мыши. Может принимать следующие значения:0 — нажата левая кнопка мыши;1 — нажата средняя кнопка;2 — нажата правая кнопка мыши;relatedTarget — для события onmouseover содержит ссылку на элемент, с которого переместился курсор мыши. Для события onmouseout содержит ссылку на элемент, на который пользователь перемещает курсор мыши;detail — для событий onclick, onmousedown и onmouseup возвращает количество выполненных щелчков мышью.deltaX, deltaY и deltaZ — позволяют определить направление вращения колесика мыши при событии onwheel.Перечислим события клавиатуры:
onkeydown — при нажатии клавиши на клавиатуре;onkeypress — аналогично событию onkeydown, но генерируется только для символьных клавиш;onkeyup — при отпускании ранее нажатой клавиши клавиатуры.При нажатии клавиши на клавиатуре последовательность будет такой:
onkeydown
onkeypress
onkeyupПродемонстрируем обработку событий клавиатуры на примере (листинг 7.9).
Листинг 7.9. События клавиатуры
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>События клавиатуры</title>
<script>
function showMsg(event, msg) {
let div1 = document.getElementById('div1');
div1.innerHTML += msg + '<br>';
console.log(event);
}
</script>
</head>
<body onkeydown="showMsg(event, 'Событие onkeydown')"
onkeypress="showMsg(event, 'Событие onkeypress')"
onkeyup="showMsg(event, 'Событие onkeyup')">
<p>Нажмите клавишу на клавиатуре</p>
<div id="div1"></div>
</body>
</html>Получить информацию о событии позволяют следующие свойства:
key — строка с буквой или описанием клавиши (например, "ArrowDown");keyCode и which — код нажатой клавиши;location — позволяет определить на какой клавиатуре была нажата клавиша:0 — на обычной клавиатуре;1 — функциональная клавиша, например, <Ctrl>, нажата слева;2 — функциональная клавиша, например, <Ctrl>, нажата справа;3 — на цифровой клавиатуре;repeat — true, если клавиша удерживается нажатой;shiftKey — true, если была нажата клавиша <Shift>;ctrlKey — true, если была нажата клавиша <Ctrl>;altKey — true, если была нажата клавиша <Alt>;metaKey — true, если была нажата клавиша <Meta>.Перечислим основные события формы:
onsubmit — при отправке данных формы;onreset — при очистке формы;onfocus — при получении фокуса элементом формы;onchange — при изменении данных в текстовом поле и перемещении фокуса на другой элемент формы либо при отправке данных формы (наступает перед событием onblur);onblur — при потере фокуса элементом формы;oninput — периодически возникает в процессе ввода данных в поле ввода или в область редактирования;oninvalid — возникает, например, если не заполнено обязательное поле.Продемонстрируем обработку событий формы на примере (листинг 7.10).
Листинг 7.10. События формы
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>События формы</title>
<script>
function showMsg(event, msg) {
let div1 = document.getElementById('div1');
div1.innerHTML += msg + '<br>';
console.log(event);
}
</script>
</head>
<body>
<form action="#" method="GET"
onsubmit="showMsg(event, 'Событие onsubmit'); return false"
onreset="showMsg(event, 'Событие onreset')">
<div>
Логин:<br>
<input type="text" name="login"
onfocus="showMsg(event, 'Событие onfocus')"
onblur="showMsg(event, 'Событие onblur')"
onchange="showMsg(event, 'Событие onchange')"
oninput="showMsg(event, 'Событие oninput')"><br>
E-mail:<br>
<input type="text" name="email" required
oninvalid="showMsg(event, 'Событие oninvalid')"><br>
Описание:<br>
<textarea name="descr" rows="10" cols="15"></textarea><br>
<input type="reset" value="Очистить">
<input type="submit" value="Отправить">
</div>
</form>
<div id="div1"></div>
</body>
</html>