При взаимодействии пользователя с приложением, окном и 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>