Events (Браузерные события)

Событие — это сигнал от браузера о том, что что-то произошло. Все DOM-узлы подают такие сигналы (хотя события бывают и не только в DOM).

Зачем нужны:

На такие события можно назначит функцию-обработчик, которая сработает, как только событие произошло. Благодаря этому код JavaScript может реагировать на различные действия пользователя.

Какие бывают:
  • События мыши
    click — происходит, когда кликнули на элемент левой кнопкой мыши (на устройствах с сенсорными экранами оно происходит при касании).
    contextmenu — происходит, когда кликнули на элемент правой кнопкой мыши.
    mouseover/mouseout — когда мышь наводится на/покидает элемент.
    mousedown/mouseup — когда нажали/отжали кнопку мыши на элементе.
    mousemove — при движении мыши.
  • События на элементах управления
    submit — пользователь отправил форму <form>.
    focus — пользователь фокусируется на элементе, например нажимает на <input>.
  • Клавиатурные события
    keydown/keyup — когда пользователь нажимает/отпускает клавишу.
    keypress — событие происходит, когда пользователь нажал клавишу на клавиатуре над элементом.
  • События документа
    DOMContentLoaded — когда HTML загружен и обработан, DOM документа полностью построен и доступен.
Есть еще много разных событий, их полный список можно посмотреть здесь.
Как назначить событие:
  • Атрибут HTML: onclick="..."
    HTML-атрибуты используются редко потому, что JavaScript в HTML-теге выглядит немного странно. К тому же много кода там не напишешь.
    Обработчик может быть назначен прямо в разметке, в атрибуте, который называется on<событие> (onclick, onkeydown, onmouseout и другие).
                                                    
    <script>
        function count() {
            for(let i=1; i<=3; i++) {
                alert("Считаем: " + i);
            }
        }
    </script>
    
    <input type="button" onclick="count()" value="Считать до трёх!">
                                                    
                                                
  • DOM-свойство: elem.onclick = function
    DOM-свойства вполне можно использовать, но мы не можем назначить больше одного обработчика на один тип события. Во многих случаях с этим ограничением можно мириться.
    Можно назначать обработчик, используя свойство DOM-элемента on<событие>.
                                                    
    <input id="elem" type="button" value="Нажми на кнопку!">
    <script>
        elem.onclick = function() {
            alert('Получишь результат!');
        };
    </script>
                                                    
                                                
  • Специальные методы: elem.addEventListener(event, handler[, phase]) для добавления, removeEventListener для удаления
    Этот способ самый гибкий, однако нужно писать больше всего кода. Есть несколько типов событий, которые работают только через него, к примеру transitionend и DOMContentLoaded. Также addEventListener поддерживает объекты в качестве обработчиков событий. В этом случае вызывается метод объекта handleEvent.

    element.addEventListener(eventType, handler, options)
    • element — любой HTMLElement на странице
    • eventType — строка, содержащая название события. Наиболее популярные события 'click', 'change', 'submit', 'keydown', 'mousemove', 'mouseenter', 'mouseleave'.
    • handler — функция, которая будет вызвана, когда событие произойдет.
    • options/capture — необязательный параметр, который описывает дополнительные свойства для срабатывания события.
      • capture — включает или выключает захват события элементом, на который установлен обработчик. Это значит, что событие сначала сработает на элементе и только потом сработает на всех вложенных элементах. Принимает значение true или false.
      • options: { capture: bool, passive: bool, once: bool } — при передаче объекта аргумент будет распознан как объект настроек, так можно установить больше параметров.
        • passive – говорит о том, что внутри handler никогда не будет вызвана функция event.preventDefault(), если функция event.preventDefault() все-таки вызвана, браузер должен её игнорировать и выводить предупредительное сообщение в консоль.
        • once – включает автоматическую отписку от события после первого срабатывания.

    У объекта event есть специальные методы, такие как preventDefault() и stopPropagation(). Остальные методы практически не используются:
    • preventDefault() позволяет заблокировать стандартное поведение браузера. Например, по клику на ссылке — заблокировать переход по этой ссылке;
    • stopPropagation() позволяет остановить всплытие события по DOM-дереву.

    В этом примере с помощью preventDefault заменено стандартное поведение ссылки при клике на нее.
                                                    
    <a href="http://slither.io/" target="_blank">Ссылка на червячков</a>
    <a href="http://slither.io/" target="_blank" id="custom">Ссылка с измененным поведением</a>
    <div id="result"></div>
    
    <script>
        const linkElement = document.querySelector('#custom')
        const resultElement = document.querySelector('#result')
    
        linkElement.addEventListener('click', function (event) {
        event.preventDefault()
    
        resultElement.innerText = 'Вы нажали на ссылку, но ничего не произошло!'
            setTimeout(function () {
            resultElement.innerText = ''
        }, 2500)
    })
    </script>
                                                    
                                                
    Ссылка на червячков
    Ссылка с изменённым поведением
А теперь повеселимся!

Ниже будут примеры использования событий. Почувствуй разницу!

Жидкость
В данной анимации используются 4 браузерных события: mouseup, mousemove, mousedown и click (для кнопки изменения цветов).

Исходный код этой модели можно посмотреть здесь.


Конфетти
А здесь использованы всего 2 события: mousedown — конфетти появляются и живут своей жизнью, mouseup — они исчезают (ощути отличие от click). Как далеко разлетятся эти наглые цветные шарики? Решать только тебе!



Исходный код этой модели можно посмотреть здесь.


Коды клавиш
Поставь курсор в поле ввода и нажми любую клавишу:
А ты заметила, что keypress не такой как все? На какие клавиши это событие не реагирует? Как отличаются коды заглавных букв и строчных? А цифр верхнего блока клавиатуры и бокового? А совпадают ли keyCode одной и той же клавиши, но с разной языковой раскладкой? А code? Войдет ли это в топ-7 загадок Вселенной?
key keyCode code charCode
keydown
keypress
keyup


На самом деле, все вполне логично.KeyPress возвращает ASCII код нажатого символа. Это значит, что событие вернёт разные коды, если пользователь нажал по букве "а", или "А", или "f", несмотря на то, что на клавиатуре это одна и та же кнопка. Т.е. это событие учитывает регистр символа, языковую раскладку, состояние клавиш Shift, Caps Lock, Alt, Ctrl. Можно сказать, что это более «интеллектуальное» событие по сравнению с keyDown/keyUp.
Хоть onKeyPress и учитывает состояние Shift, Caps Lock, Alt, Ctrl, т.к. они влияют на то, как и какой именно отобразится символ, но с помощью этого события нельзя определить состояние этих клавиш. Для этого нужно использовать keyUp/keyDown.
Два простых и похожих свойства: keyCode возвращает код нажатой клавиши, keyCharASCII код нажатого символа. Как понимаешь, при нажатии одной клавиши, значения этих свойств должны отличаться.