У цьому розділі ми докладніше розглянемо події миші та їх властивості.
Зверніть увагу: подібні події можуть надходити не тільки від миші, але й з інших пристроїв, таких як телефони та планшети, де вони емулюються для сумісності.
Типи подій миші
Ми вже бачили деякі з цих подій:
mousedown/mouseup
- Клікання/відпускання кнопки миші над елементом.
mouseover/mouseout
- Курсор заходить/виходить з елемента.
mousemove
- Кожне переміщення миші над елементом викликає цю подію.
click
- Спрацьовує після
mousedown
, а потімmouseup
над тим же елементом, якщо була використана ліва кнопка миші. dblclick
- Спрацьовує після двох кліків на одному елементі за короткий проміжок часу. На сьогоднішній день рідко використовується.
contextmenu
- Спрацьовує при натисканні правої кнопки миші. Є й інші способи відкрити контекстне меню, напр. за допомогою спеціальної клавіші на клавіатурі, але це вже не зовсім подія миші.
…Також існують кілька інших подій, про них ми розповімо пізніше.
Порядок подій
Як ви можете бачити зі списку вище, дія користувача може викликати безліч подій.
Наприклад, клік лівою кнопкою спочатку ініціює mousedown
, коли кнопку натиснуто, потім mouseup
і click
, коли її відпускають.
У випадках, коли одна дія ініціює декілька подій, їх порядок фіксується. Тобто обробники викликаються в порядку mousedown
→ mouseup
→ click
.
Клікніть кнопку нижче, і ви побачите події. Спробуйте також клікнути двічі.
Всі події миші реєструються у тестовому вікні нижче, і якщо між ними є затримка більше 1 секунди, вони розділяються горизонтальною лінією.
Також ми можемо побачити властивість button
, яка дозволяє виявити яку саме кнопку миші клікнули, це пояснюється нижче.
Кнопка миші
Події, пов’язані з кліками, завжди мають властивість button
, що дозволяє отримати точну кнопку миші.
Зазвичай ми не використовуємо її для подій click
і contextmenu
, оскільки перше відбувається лише при натисканні лівою кнопкою миші, а останнє – лише при натисканні правою кнопкою миші.
З іншого боку, обробникам mousedown
та mouseup
може знадобитися event.button
, тому що ці події запускаються на будь-якій кнопці, тому button
дозволяє розрізняти “праву кнопку миші” та “ліву кнопку миші”.
Можливі значення event.button
:
Стан кнопки | event.button |
---|---|
Ліва кнопка (основна) | 0 |
Середня кнопка (допоміжна) | 1 |
Права кнопка (другорядна) | 2 |
Кнопка X1 (назад) | 3 |
Кнопка X2 (вперед) | 4 |
Більшість пристроїв мають лише ліву та праву кнопки, тому можливі значення 0
або 2
. Сенсорні пристрої також генерують подібні події, коли на них натискають.
Також є властивість event.buttons
, яка містить усі натиснуті кнопки як ціле число, по одному біту на кнопку. На практиці ця властивість використовується дуже рідко, деталі можна знайти на сторінці MDN, якщо вона вам колись знадобиться.
event.which
Старий код може використовувати властивість event.which
, що є застарілим нестандартним способом отримання кнопки з можливими значеннями:
event.which == 1
– ліва кнопка,event.which == 2
– середня кнопка,event.which == 3
– права кнопка.
На даний момент властивість event.which
застаріла, ми не повинні її використовувати.
Модифікатори: shift, alt, ctrl і meta
Усі події миші містять інформацію про натиснуті клавіші-модифікатори.
Властивості події:
shiftKey
: ShiftaltKey
: Alt (чи Opt для Mac)ctrlKey
: CtrlmetaKey
: Cmd для Mac
Вони мають значення true
, якщо відповідна клавіша була натиснута під час події.
Наприклад, кнопка нижче працює лише на Alt+Shift + клік:
<button id="button">Alt+Shift+Клікни мене!</button>
<script>
button.onclick = function(event) {
if (event.altKey && event.shiftKey) {
alert('Ура!');
}
};
</script>
Cmd
замість Ctrl
На Windows і Linux є клавіші-модифікатори Alt, Shift і Ctrl. На Mac є ще одна: Cmd, що відповідає властивості metaKey
.
У більшості застосунків, коли Windows/Linux використовує Ctrl, на Mac використовується Command.
Тобто: коли користувач Windows натискає Ctrl+Enter або Ctrl+A, користувач Mac натискає Cmd+Enter або Cmd+A, і так далі.
Отже, якщо ми хочемо підтримувати такі комбінації, як Ctrl+ клік, то для Mac має сенс використовувати Cmd+ клік. Це зручніше для користувачів Mac.
Навіть якщо ми б хотіли змусити користувачів Mac застосувати Ctrl+клік – це трохи складно. Проблема полягає в тому, що клік лівою кнопкою миші за допомогою Ctrl інтерпретується як клік правою кнопкою миші у MacOS, і він генерує подію contextmenu
, а не click
, як Windows/Linux.
Тож якщо ми хочемо, щоб користувачі всіх операційних систем відчували себе комфортно, то разом із ctrlKey
ми повинні перевірити metaKey
.
Для JS-коду це означає, що ми повинні перевірити if (event.ctrlKey || event.metaKey)
.
Комбінації клавіатури хороші як доповнення до робочого процесу. Так що якщо відвідувач використовує клавіатуру – вони працюють.
Але якщо в їхньому пристрої цього немає – то має бути спосіб жити без клавіш-модифікаторів.
Координати: clientX/Y, pageX/Y
Усі події миші надають координати у двох варіантах:
- Відносно Window:
clientX
таclientY
. - Відносно Document:
pageX
таpageY
.
Ми вже розглянули різницю між ними у розділі Координати.
Коротше кажучи, відносні до документа координати pageX/Y
відраховуються від лівого верхнього кута документа і не змінюються під час прокручування сторінки, тоді як clientX/Y
відраховуються від лівого верхнього кута поточного вікна. Коли сторінка прокручується, вони змінюються.
Наприклад, якщо у нас є вікно розміром 500x500, а миша знаходиться в лівому верхньому куті, то clientX
і clientY
дорівнюють 0
, незалежно від того, як прокручується сторінка.
А якщо миша знаходиться в центрі, то clientX
і clientY
дорівнюють 250
, незалежно від того, яке місце в документі це. У цьому аспекті вони схожі на position:fixed
.
Наведіть курсор миші на поле введення, щоб побачити clientX/clientY
(приклад знаходиться в iframe
, тому координати є відносно цього iframe
):
<input onmousemove="this.value=event.clientX+':'+event.clientY" value="Наведіть курсор на мене">
Запобігання виділенню при наведенні миші
Подвійний клік миші має побічний ефект, який може створювати незручності в деяких інтерфейсах: він виділяє текст.
Наприклад, подвійний клік на тексті нижче виділяє його на додаток до нашого обробника:
<span ondblclick="alert('dblclick')">Клікни мене двічі</span>
Якщо натиснути ліву кнопку миші і, не відпускаючи її, пересунути, це також додасть виділення, часто небажане.
Існує кілька способів запобігти виділенню, про які ви можете прочитати в розділі Selection і Range.
У цьому конкретному випадку найрозумнішим способом є запобігання дії браузера на mousedown
. Таким чином ми запобігнемо двом виділенням:
До...
<b ondblclick="alert('Клік!')" onmousedown="return false">
Клікни мене двічі
</b>
...Після
Тепер виділений жирним елемент не виділяється подвійними кліком, і натискання на ньому лівої кнопки не почне виділення.
Зверніть увагу: текст всередині нього все ще можна виділити. Однак виділення слід починати не з самого тексту, а до або після нього. Зазвичай, це нормально сприймається користувачами.
Якщо ми хочемо вимкнути виділення, щоб захистити вміст нашої сторінки від копіювання, ми можемо використовувати іншу подію: oncopy
.
<div oncopy="alert('Копіювання заборонено!');return false">
Шановний користувач,
Копіювання заборонено.
Якщо ви знаєте JS або HTML, ви можете отримати все з джерела сторінки.
</div>
Якщо ви спробуєте скопіювати фрагмент тексту в <div>
, це не спрацює, оскільки типову дію oncopy
заборонено.
Безумовно, користувач має доступ до HTML-джерела сторінки, і може взяти звідти вміст, але не всі знають, як це зробити.
Підсумки
Події миші мають такі властивості:
-
Кнопка:
button
. -
Клавіші-модифікатори (
true
, якщо їх натиснути):altKey
,ctrlKey
,shiftKey
іmetaKey
(Mac).- Якщо ви хочете працювати з Ctrl, то не забувайте про користувачів Mac, вони зазвичай використовують Cmd, тому краще перевірити
if (e.metaKey || e.ctrlKey)
.
- Якщо ви хочете працювати з Ctrl, то не забувайте про користувачів Mac, вони зазвичай використовують Cmd, тому краще перевірити
-
Координати відносно Window:
clientX/clientY
. -
Координати відносно Document:
pageX/pageY
.
Типова дія браузера mousedown
– виділення тексту, якщо в інтерфейсі воно швидше заважає, йому слід запобігти.
У наступному розділі ми дізнаємось більше деталей про події, які слідують за рухом курсора, і про те, як відстежувати зміни елементів під ним.
Коментарі
<code>
, для кількох рядків – обгорніть їх тегом<pre>
, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)