таймер. Події
Фронтенд розробка JavaScript. -> Події
Події
Всередині комп’ютера постійно відбуваються події, які можуть виходити від самого користувача (натискання на клавіатуру), так і від програм.
Завдання комп’ютера (операційної системи) - якнайшвидше реагувати такі події і запускати відповідні їм програми (обробники).
У ОС такі події називаються перериваннями, у js – подіями.
Як правило, обробники подій — це окремі функції.
Робота системи подій пов’язані з поняттям повідомлень.
Повідомлення - це інформація про те, що в системі відбулася якась подія.
Операційна система має свій набір стандартних повідомлень, наприклад рух миші або натискання її клавіш, перемикання між вікнами, зміна їх розмірів чи положення, натискання кнопок клавіатури і т.д. Прикладні програми можуть створювати інші (Додаткові) повідомлення.
Наприклад, браузери доповнюють системні повідомлення власним набором, необхідно саме для веб-сторінок.
Обробка повідомлення, прийняття рішення про його тип, аналіз додаткових даних називається подією.
Всі повідомлення надходять до черги повідомлень, цю чергу обслуговує спеціальний програмний цикл - цикл подій (життєвий цикл).
Який у циклі вибирає повідомлення, обробляє певне повідомлення (тоді і виникає подія) та запускає його обробник.
Якщо для події обробника немає, таке повідомлення просто ігнорується та видаляється з черги.
У JavaScript прийнято звертатися до соб- тий за їх іменами (в операційній системі - за кодами).
Як узагальнення події можна умовно розділити на кілька груп:
-
Події інтерфейсу користувача;
-
події життєвого циклу;
-
індивідуальні події.
Події інтерфейсу користувача виникають за рахунок активності користувача веб-сторінки.
Події життєвого циклу надсилаються елементам при їх створенні, завантаженні, у тому числі помилках завантаження, при отриманні системних повідомлень, переході до online або offline режим, запуск анімації тощо
Індивідуальні події характерні лише для певних об’єктів та для об’єктів іншого типу не використовуються. Прикладом може бути подія “pause”, що виникає при зупинці відтворення (паузі) медіа-контенту. Очевидно, що ця подія стосується лише медіа-контейнерів.
Обробка подій у сценаріях
Для всіх стандартних подій елементи сторінки передбачені обробники. Традиційно їхні імена формуються з префіксу on та імені події. Наприклад, обробник події клацання миші «click» буде мати назва “onclick”.
Існує кілька способів визначити тіло для оброблювача подій.
-
Вказати його як HTML-атрибут під час оголошення елемента
-
Визначити обробник події у скриптовій частині коду.
При цьому з ідентифікатора створюється однойменний об’єкт.
-
Задати обробник події для елемента - це застосувати спеціальний метод addEventListener.
Зверніть увагу, у цьому У разі передається ім’я події «click» (без префікса «on», використовуваного імені обробника).
Об’єкт event та його властивості
При обробці події часто буває потрібна додаткова інформація, пов’язана з виникненням самої події.
При обробці системного повідомлення та створення програмної події браузер формує спеціальний об’єкт “event”, в якому збираються всі дані про подію.
Інформація в об’єкті «event» залежить від типу події, яке обробляється.
Її можна розділити на ту, яка притаманна всім подіям, наприклад об’єкт target, в якому знаходиться цільовий об’єкт події. І інформацію, властиву конкретній події, наприклад дані про кнопку клавіатури, або координати вказівника миші.
Приклад обробки події.
<body onclick = "out.innerText = 'Click detected over: ' + event.target.nodeName">
Т.к. ми помістили обробник в тег body, він буде спрацьовувати при натисканні на будь-який елемент на сторінці.
Таким чином подія “спливає” нагору. Але об’єкт target міститиме той елемент, на якому клацнули.
Як виглядає об’єкт події у консолі.
Деякі стандартизовані значення.
- screenX, screenY -координати щодо клієнтської частини вікна браузера
Також у події присутні координати елемента щодо батька.
Подія передається у функцію-обробник як параметр.
element.onclick = function(e){...}
Зазвичай подію називають e або evt
Управління стилями елементів веб-сторінки
Здійснюється встановленням властивості style об’єкта.
function moveStranger(e){
stranger.style.left=e.pageX+'px';
stranger.style.top =e.pageY+'px';
}
Можна через індекс масиву.
element.style["left"]
У цьому т.к. - це знак віднімання та element.style.background-сolor неприпустимий, то використовується верблюжа нотація
element.style["background-color"] = element.style.backgroundColor
Рух мишкою.
Відмінність подій mouseenter від mouseover.
Різниця між цими подіями полягає в тому, що події «mouseenter» та «mouseleave» отримує тільки «найвищий» елемент, тоді як інша пара подій “mouseover” і “mouseout” передається всім елементам, що знаходяться під курсором миші.
Цей ефект називається спливанням подій (англ. bubbling чи propagation).
Припустимо є 2 вкладені блоки
Подія “onmouseover” приходить двічі - спочатку від блоку “d2”, потім від “d1”.
Для управління процесом спливання у подій призначений метод “stopPropagation”.
div1.addEventListener("click",function(e){
console.log('Click on div1');
e.stopPropagation()
})
Пример реализации функции Drug and Drop.
<style>
body{
position: relative;
}
#div1 {
background-color: tomato;
border: 1px solid red;
border-radius: 50%;
height: 100px;
width: 100px;
position: absolute;
}
</style>
<div id="div1"></div>
<script>
var isDrag = false;
div1.addEventListener("mousedown",
function(){ isDrag = true }
)
document.addEventListener("mouseup",
function(){ isDrag = false }
)
document.addEventListener("mousemove",
function(e){
if(isDrag){
div1.style.left = e.pageX + "px";
div1.style.top = e.pageY + "px";
}
}
)
</script>
Події життєвого циклу
Коли Ви включаєте браузер і відкриваєте в ньому нову веб-сторінку, відбувається певний ланцюжок процесів: браузер знаходить сервер, де знаходиться сторінка, і запитує її HTML код. Отримавши відповідь, браузер, обробляє його і формує структуру сторінки, принагідно завантажуючи всі елементи (картинки, скрипти і т.д.).
Описаний процес має назву життєвого циклу веб-сторінки.
Життєвий цикл веб-сторінки супроводжується наступними подіями
DOMContentLoaded — браузер повністю завантажив HTML, файли стилів та скриптів, побудував структуру документа (DOM-структуру);
load – браузер завантажив усі додаткові ресурси – зображення, фрейми;
beforeunload - браузер отримав команду закрити сторінку (вкладку);
unload - браузер закрив сторінку (вкладку).
DOMContentLoaded
Подія «DOMContentLoaded» є однією з найбільш популярних серед подій життєвого циклу. Воно надсилається об’єкту «document» тоді, коли завантажено код HTML, стильові файли та скрипти та структуру сторінки вже визначено.
Однак зображення та кадри можуть бути не завантажені.
Обробник події «DOMContentLoaded» підклю- чається тільки за допомогою команди addEventListener:
document.addEventListener( "DOMContentLoaded" ,
function() {
alert("DOM loaded")
}
)
Використання атрибутів з префіксом on, як для більшість інших подій не дасть належного ефекту.
document.onDOMContentLoaded = function() {
alert("DOM loaded")
}
load
Подія «load» надсилається після завантаження всіх додаткових ресурсів — зображень, кадрів тощо.
Ця подія відноситься до об’єкта «window» і може бути оброблено всіма допустимими варіантами - як за допомогою методу addEventListener, так і вказівкою атрибутів із префіксом «on»
<body onload="alert('body loaded')">
window.onload = function() {alert('body loaded')}
window.addEventListener( "load",
function() {
alert('body loaded')
})
Слід звернути увагу на те, що завантаження зображень ще не означає їх відображення. Подія “load” посилається за фактом закінчення завантаження, але не після закінчення промальовування. У більшості випадків зображення зберігаються в стислих форматах, і для їх виведення на сторінку браузеру необхідно повести “декомпресію” - відновлення графічної інформації зі стисненого файлу. На це йде певний час, якого може не вистачить до виклику оброблювача події.
Створимо файл index.html, щоб простежити етапи завантаження.
<!doctype html />
<html>
<head>
</head>
<body onload="alert('body loaded')">
<img src="step.jpg" />
<script>
document.addEventListener("DOMContentLoaded" ,
function() {
alert("DOM loaded")
}
)
</script>
</body>
</html>
Першим викликається подія DOMContentLoaded і зображення ще не завантажено та має статус pending.
Потім відбувається подія onload і зображення завантажується.
Оскільки додаткові ресурси сторінки завантажуються окремо від HTML-коду, для них також надсилаються події про підсумковий статус. Такими подіями є “load” та “error”.
Приклад відстеження подій для зображення.
<img src="step.jpg"
onload="addMessage('step.jpg load OK')"
onerror="addMessage('step.jpg load error')"/>
<p id="txt"></p>
<script>
function addMessage(msg) {
window.txt.innerHTML += msg + "<br/>"
}
</script>
beforeunload
Подія «beforeunload» надсилається вікну (об’єкту “window”) і сигналізує про початок закриття (вивантаження, unload) сторінки. На цьому етапі можна попередити користувача, що на сторінці залишилися незбережені дані, незакінчені процеси надсилання чи отримання даних.
<!doctype html />
<html>
<head>
<style>
#text {
height: 200px;
width: 400px;
}
</style>
</head>
<body>
<textarea id="text"></textarea><br/>
<a href="http://itstep.org">IT Step</a>
66Обработка событий
<script>
window.onbeforeunload =
function(e) {
if(text.value.length > 0) {
var msg = 'Text not saved';
e.returnValue = msg;
return msg;
}
return null;
}
</script>
</body>
</html>
Принцип роботи оброблювача у тому, що він має повернути непусте повідомлення.
В даному випадку при заповненому полі текстової області користувачу не вдається перейти за посиланням.
Цей прийом може працювати по-різному в різних браузерах т.к. недобросовісні розробники сайтів з метою утримання відвідувачів на своїх сторінках використовували ці прийоми.
Також з метою безпеки в обробнику події “onbeforeunload” не допускається створення додаткових діалогових вікон.
Стандартні обробники, заборона виклику стандартного оброблювача.
Обробники подій за замовчуванням (стандартні обробники) Для деяких подій у браузері передбачено спеціальні стандартні обробники, які запускаються автоматично – без необхідності додавання їх програмним шляхом.
Наприклад:
-
виклик контекстного меню при натисканні правої кнопки;
-
масштабування контенту при прокручуванні колеса; миші із натиснутою кнопкою «Ctrl»
-
гарячі кнопки і т.д.
У деяких випадках обробники стандартних подій можуть заважати логіці роботи основного вмісту сторінки.
Такі ситуації виникають, якщо в інтерфейсі сторінки використовуються засоби керування, збігаються з «зарезервованими» можливостями.
Розглянемо як приклад наступне завдання: створити блок, який змінюватиме колір при натисканні на ньому клавіші миші: зелений, якщо натиснута ліва клавіша; синій, якщо середня (або колесо), червона — якщо права.
Оскільки всі три клавіші миші надсилають одне і та сама подія «mousedown», вони встановлюють різні значення для властивості «which» об’єкта-події
1 - для лівої клавіші
2 - для середньої
3 - для правої
<div id="d1"></div>
<script>
window.d1.onmousedown = function(e) {
var bgColor;
switch( e.which ) {
case 1:
bgColor = "lime";
break ;
case 2:
bgColor = "green";
break;
case 3:
bgColor = "red";
break ;
}
window.d1.style.backgroundColor = bgColor;
}
</script>
Зверніть увагу, що при натисканні правої клавіші, крім зміни кольору, на блоці з’являється контекстне меню.
Перевизначити цю поведінку можна замінивши стандартний обробник події контекстного меню “oncontextmenu” для блоку.
window.d1.oncontextmenu = function() { return false }
Однак не завжди вдається запобігти стандартному обробнику за допомогою return false.
У таких випадках необхідно скористатися методом preventdefault об’єкта події.
e.preventDefault();
Визначення натискання клавіш клавіатури.
Визначення статусів та кодів натискання кнопок.
ocument.body.onkeydown = function(e) {
console.log(e.ctrlKey);
console.log(e.altKey);
console.log(e.shiftKey);
console.log(e.key);
}
Фронтенд розробка JavaScript. -> Домашнє завдання.
Домашнє завдання.
-
Вивести в лог сторінки всі події завантаження сторінки
-
Вивести кілька картинок на сторінці та у лозі показати події завершення їх завантажень.
-
В елементі div вивести 3 картинки. Відпрацювати клік на будь-якій картинці і підвісити подію на div. Відобразити у лозі посилання на зображення (атрибут src)
-
Помістити в один блок div інший елемент div з border-radius рівним 50%, що перетворить його на коло. Спозиціонувати його центром батьківського контейнера. Забезпечити функцію drag-and-drop переміщення кола без ривків.
-
Відстежити всі переміщення миші всередині div та вивести у консоль її координати. Виводити алерт під час залишення області div.
-
Створити анімоване коло, яке рухається всередині прямокутного блоку вправо та вліво нескінченно.
-
Відстежити натискання клавіш стрілок вправо вліво і відповідно переміщати блок усередині батька, не виходячи за його межі.
Фронтенд розробка JavaScript. -> таймер. Інтервали.
Таймер.
Виконує функцію через вказаний час (затримка).
Синтаксису.
setTimeout(функція/код, затримка, аргумент1, аргумент2, ...)
Затримка встановлюється у мілісікундах.
Функція setTimeout повертає ідентифікатор таймера. Його можна використовувати для того, щоб скасувати спрацювання таймера.
Приклад.
function HelloWorld(){
alert("Hello world!");
}
setTimeout(HelloWorld, 1000);
Із аргументами.
function Sum(a,b){
alert(a+b);
}
setTimeout(Sum, 1000,1,2);
Скасування таймера.
clearTimeout(ідентифікатор_таймера)
Приклад.
var id = setTimeout(function(){
alert("Boom!")},50000
);
clearTimeout(id);
Інтервали.
Використовуються, коли нам необхідно викликати функцію переодично через вказаний інтервал часу.
Синтаксис
setInterval(функция/код, интервал_времени, аргумент1,
аргумент2, ...)
Приклад.
setInterval(
function(){
alert("Boom!");
},
2000);
У цьому коді ми не викликали clearInterval тому вікно повідомлення з написом Boom буде викликатись кожні дві секунди, поки вікно або вкладка браузера не буде закрито.
Приклад з clearInterval
var id = setInterval(IntervalFunc,2000);
var counter = 0;
function IntervalFunc(){
if(counter == 3){
clearInterval(id);
return;
}
counter++;
alert("Boom");
}
Альтернативою використання setInterval є рекурсивний виклик setTimer.
var id = setTimeout(TimeOutFunc, 2000);
var counter = 0;
function TimeOutFunc() {
// якщо таймер спрацював уже тричі
// зупиняємо процес
if (counter == 3) {
clearTimeout(id);
return;
}
counter++;
alert("Boom Timer");
// ставимо знову таймер на дві секунди
id = setTimeout(TimeOutFunc, 2000);
}
Хоча функція «setInterval» здається більш привабливою для створення таймера - періодичного запуску. ска певної функції, вона має низку недоліків.
По-перше, вона встановлює час лише між початками запуск функції. Наприклад, якщо функція сама по собі виконується 0,4 секунди, і ми вказали інтервал запуску 1 секунду, то пауза між зупинкою попередньої та за- пуском нової функції буде 0,6 секунди.
По-друге, функція “setInterval” накопичує помилку. Якщо з якихось причин відбуваються затримки таймера, то надалі вони не коригуються і можуть навести до відхилень очікуваного та реального процесів.
Годинники, створені за допомогою функції «setInterval» відставатимуть від дійсного часу, причому, чим довше працюватиме програма, тим сильнішим буде відставання.
По-третє, браузер може сам призупинити або уповільнити роботу таймера, коли сторінка неактивна або комп’ютер переходить живлення від батарей.
Також по-різному таймер може спотворювати свій хід у разі появи діалогових вікон.
Як результат, функція “setInterval” вкрай ненадійна.
Замість неї рекомендується використовувати періодичний перезапуск функції одноразового відкладеного запуску “setTimeout”