
Введение в браузерные события


Событие – это сигнал от браузера о том, что что-то произошло.

Список самых часто используемых событий

События мыши:
- click – происходит, когда кликнули на элемент левой кнопкой мыши
- contextmenu – происходит, когда кликнули на элемент правой кнопкой мыши
- mouseover – возникает, когда на элемент наводится мышь
- mouseout - возникает, когда ушла мышь
- mousedown и mouseup – когда кнопку мыши нажали или отжали
- mousemove – при движении мыши
Свойства объекта события

<input type="button" value="Нажми меня" id="elem">
<script>
elem.onclick = function(event) {
// вывести тип события, элемент и координаты клика
alert(event.type + " на " + event.currentTarget);
alert(event.clientX + ":" + event.clientY);
}
</script>event.type - Тип события, в данном случае click
event.target - Элемент, на котором произошел click
event.relatedTarget - Элемент с которого пришли
event.currentTarget - Элемент, на котором сработал обработчик. Значение – в точности такое же, как и у this, но бывают ситуации, когда обработчик является методом объекта и его this при помощи bind привязан к этому объекту, тогда мы можем использовать event.currentTarget.
event.clientX / event.clientY - Координаты курсора в момент клика (относительно окна)
event.keyCode - код нажатой кнопкию
Полное описание: Event Object

События на элементах управления:
- submit – посетитель отправил форму <form>
- focus – посетитель фокусируется на элементе, например нажимает на <input>
- blur – посетитель уводят фокус с элемента <input>
- change – посетитель сделал изменения в элементе, например в <textarea>

Клавиатурные события:
- keydown – когда посетитель нажимает клавишу
- keyup – когда посетитель отпускает клавишу
- keypress - когда посетитель нажал клавишу
События CSS:
- transitionend – когда CSS-анимация завершена.

События документа:
- DOMContentLoaded – когда HTML загружен и обработан, DOM документа полностью построен и доступен.
Если после стиля идёт скрипт, то этот скрипт обязан дождаться, пока стиль загрузится:
<link type="text/css" rel="stylesheet" href="style.css">
<script>
// сработает после загрузки style.css
</script>-
Побочный эффект – так как событие DOMContentLoaded будет ждать выполнения скрипта, то оно подождёт и загрузки стилей, которые идут перед <script>.
-
Автозаполнение - Это означает, что если на странице есть форма для ввода логина-пароля, то браузер введёт в неё запомненные значения только по DOMContentLoaded.

События документа load
Событие onload на window срабатывает, когда загружается вся страница, включая ресурсы на ней – стили, картинки, ифреймы и т.п.
Когда человек уходит со страницы или закрывает окно, на window срабатывает событие unload. В нём можно сделать что-то, не требующее ожидания, например, закрыть вспомогательные popup-окна, но отменить сам переход нельзя.
События документа beforeunload
События документа unload
Если посетитель инициировал переход на другую страницу или нажал «закрыть окно», то обработчик onbeforeunload может приостановить процесс и спросить подтверждение.

Также есть и много других событий:
Назначение обработчиков событий

Использование атрибута HTML

<input type="button" onclick="alert('Клик!')" value="Кнопка"/><!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script>
function sayClick() {
alert('Клик!');
}
</script>
</head>
<body>
<input type="button" onclick="sayClick()" value="Кнопка"/>
</body>
</html>Использование свойства DOM-объекта

<input id="elem" type="button" value="Нажми меня" />
<script>
elem.onclick = function() {
alert( 'Спасибо' );
};
</script>function sayThanks() {
alert( 'Спасибо!' );
}
elem.onclick = sayThanks;
elem.onclick = sayThanks();function sayThanks() {
alert( 'Спасибо!' );
}
<input type="button" id="button" onclick="sayThanks()" />
button.onclick = function() {
sayThanks(); // содержимое атрибута
};addEventListener и removeEventListener

elem.addEventListener(event, handler[, phase]);event - Имя события, например click
handler - Ссылка на функцию, которую надо поставить обработчиком.
phase - Необязательный аргумент, «фаза», на которой обработчик должен сработать.

function handler() {
alert( 'Спасибо!' );
}
elem.addEventListener("click", handler);
// ....
elem.removeEventListener("click", handler);Примеры
<input id="elem" type="button" value="Нажми меня"/>
<script>
function handler1() {
alert('Спасибо!');
};
function handler2() {
alert('Спасибо ещё раз!');
}
elem.onclick = function() { alert("Привет"); };
elem.addEventListener("click", handler1); // Спасибо!
elem.addEventListener("click", handler2); // Спасибо ещё раз!
</script>
function handler() {
alert( 'Спасибо!' );
}
button.attachEvent("onclick", handler) // Назначение обработчика
// ....
button.detachEvent("onclick", handler) // Удаление обработчикаОтличия IE8-

У обработчиков, назначенных с attachEvent, нет this
<meta charset="utf-8">
<style>
button {
transition: width 1s;
width: 100px;
}
.wide { width: 300px; }
</style>
<button id="elem" onclick="this.classList.toggle('wide');">Нажми меня</button>
<script>
// addEventListener работает всегда, а DOM-свойство – нет
elem.ontransitionend = function() {
alert( "ontransitionend" ); // не сработает
};
elem.addEventListener("transitionend", function() {
alert( "addEventListener" ); // сработает по окончании анимации
});
</script>
Разница
| addEventListener | onclick |
|---|---|
| Некоторые события можно назначить только через addEventListener. | Обработчик, назначенный через onclick, проще удалить или заменить. |
| Метод addEventListener позволяет назначить много обработчиков на одно событие. |
Метод onclick кросс-браузерный. |
Порядок обработки событий


<textarea rows="8" cols="40" id="area">Кликни меня</textarea>
<script>
area.onmousedown = function() { this.value += "mousedown\n"; this.scrollTop = this.scrollHeight; };
area.onmouseup = function() { this.value += "mouseup\n"; this.scrollTop = this.scrollHeight; };
area.onclick = function() { this.value += "click\n"; this.scrollTop = this.scrollHeight; };
</script>Таким образом, при нажатии кнопки мыши в очередь попадёт событие mousedown, а при отпускании – сразу два события: mouseup и click. Браузер обработает их строго одно за другим: mousedown →mouseup → click.
Очередь событий

<input type="button" id="button" value="Нажми меня">
<input type="text" id="text" size="60">
<script>
button.onclick = function() {
text.value += ' ->в onclick ';
text.focus(); // вызов инициирует событие onfocus
text.value += ' из onclick-> ';
};
text.onfocus = function() {
text.value += ' !focus! ';
};
</script>Вложенные (синхронные) события

<input type="button" id="button" value="Нажми меня">
<input type="text" id="text" size="60">
<script>
button.onclick = function() {
text.value += ' ->в onclick ';
setTimeout(function() {
text.focus(); // сработает после onclick
}, 0);
text.value += ' из onclick-> ';
};
text.onfocus = function() {
text.value += ' !focus! ';
};
</script>Вложенные (асинхронные) события
Всплытие и перехват

Всплытие

<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>

Отличия this от event.currentTarget

var form = document.querySelector('form');
form.onclick = function(event) {
event.target.style.backgroundColor = 'yellow';
alert("target = " + event.target.tagName + ", this=" + this.tagName);
event.target.style.backgroundColor = '';
};- event.target – это исходный элемент, на котором произошло событие, в процессе всплытия он неизменен.
- this, event.currentTarget – это элемент, до которого дошло всплытие и на котором выполняется обработчик.
- this - Может быть переопределен.
Прекращение всплытия

<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p id="paragraph" onclick="event.stopPropagation()">P</p>
</div>
</form>event.stopImmediatePropagation()

<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p id="paragraph">P</p>
</div>
</form>
<script>
paragraph.addEventListener('mousedown', function (e) {alert(1);});
paragraph.addEventListener('mousedown', function (e) {
// (1) Ппредотвращает всплытие!
// (2) Останавливает обработку событий на текущем элементе. (+)
e.stopImmediatePropagation(); //
alert(2);
});
paragraph.addEventListener('mousedown', function (e) {alert(3);});
</script>Не прекращайте всплытие без необходимости!

- Мы делаем меню. Оно обрабатывает клики на своих элементах и делает для них stopPropagation. Вроде бы, всё работает.
- Позже мы решили отслеживать все клики в окне, для какой-то своей функциональности, к примеру, для статистики – где вообще у нас кликают люди.
- Над областью, где клики убиваются stopPropagation, статистика работать не будет! Получилась «мёртвая зона».



standart DOM Events 3
var elems = document.querySelectorAll('form,div,p');
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", highlightThis, true);
elems[i].addEventListener("click", highlightThis, false);
}
function highlightThis() {
this.style.backgroundColor = 'yellow';
alert(this.tagName);
this.style.backgroundColor = '';
}Полный пример по ссылке:

Отличия IE8-
- event.currentTarget - Нет свойства. Если нужен, можно будет взять лишь из замыкания.
- Вместо event.target в IE8- используется event.srcElement
elem.onclick = function(event) {
event = event || window.event;
var target = event.target || event.srcElement;
// ... теперь у нас есть объект события и target
...
}event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);Для остановки всплытия используется код event.cancelBubble=true.
Делегирование событий

Пример


ul.onclick = function(event) {
var target = event.target;
// цикл двигается вверх от target к родителям до ul
while (target != this) {
if (target.tagName == 'LI') {
// нашли элемент, который нас интересует!
fn(target);
return;
}
target = target.parentNode;
}
}Приём проектирования "поведение"

Счётчик: <button data-counter>1</button>
Ещё счётчик: <button data-counter>2</button>
<script>
document.onclick = function (event) {
if (event.target.hasAttribute('data-counter')) {
event.target.innerHTML++;
}
};
</script><button data-toggle-id="subscribe-mail">
Показать форму подписки
</button>
<form id="subscribe-mail" hidden>
Ваша почта: <input type="email">
</form>
<script>
document.onclick = function(event) {
var target = event.target;
var id = target.getAttribute('data-toggle-id');
if (!id) return;
var elem = document.getElementById(id);
elem.hidden = !elem.hidden;
};
</script>Зачем использовать

- Экономит память: не нужно вешать много обработчиков.
- Меньше кода: не нужно ставить или снимать обработчики.
- Удобство изменений: можно массово добавлять или удалять элементы путём изменения innerHTML.
Действия браузера по умолчанию


- Клик по ссылке инициирует переход на новый URL.
- Нажатие на кнопку «отправить» в форме – отсылку ее на сервер.
- Двойной клик на тексте – инициирует его выделение.
- Клик по checkbox
- wheel - движение колёсика мыши инициирует прокрутку.
Например

Отмена действия браузера
<a href="/" onclick="return false">Нажми здесь</a>
<a href="/" onclick="event.preventDefault()">здесь</a>Особенности IE8-
event.preventDefault ? event.preventDefault() : (event.returnValue=false);Генерация событий на элементах

API / DOM 3 Events.

eventInterface – это тип события, например MouseEvent, FocusEvent, KeyboardEvent.
var event = document.createEvent(eventInterface);Аргументы:
- type – тип события, например "click".
- bubbles – всплывает ли событие.
- cancelable – можно ли отменить событие.
var event = document.createEvent("Event");
event.initEvent("hello", true, true);
elem.dispatchEvent(event)API / DOM 3 Events.

<h1 id="elem">Привет от скрипта!</h1>
<script>
document.addEventListener("hello", function(event) {
alert( "Привет" );
event.preventDefault();
}, false);
var event = document.createEvent("Event");
event.initEvent("hello", true, true);
if (elem.dispatchEvent(event) === false) {
alert( 'Событие было отменено preventDefault' );
}
</script>API / DOM 3 Events.

<h1 id="elem">Привет от скрипта!</h1>
<script>
document.addEventListener("hello", function(event) {
alert( "Привет" );
event.preventDefault();
}, false);
var event = document.createEvent("Event");
event.initEvent("hello", true, true);
if (elem.dispatchEvent(event) === false) {
alert( 'Событие было отменено preventDefault' );
}
</script>The end!

RD Events
By Sarhan Azizov
RD Events
- 440