Браузерные события и примеры их использования в JavaScript

Александр Мальцев
16K
0
Содержание:
  1. Категории событий
  2. События мыши
  3. События при CSS переходе
  4. События при CSS анимации
  5. События клавиатуры
  6. События объектов и фреймов
  7. События формы и элементов управления
  8. События перетаскивания
  9. События буфера обмена
  10. События печати
  11. События, посылаемые сервером
  12. События мультимедиа
  13. Разные события
  14. Задания
  15. Комментарии

На этом уроке мы рассмотрим основные виды событий, которые Вы можете перехватывать с помощью JavaScript для выполнения некоторого кода.

Категории событий

Все события JavaScript можно разделить на следующие категории: события мыши (Mouse Events), события клавиатуры (Keyboard Events), события объектов и фреймов (Frame/Object Events), события формы и элементов управления (Form Events), события перетаскивания (Drag Events), события анимации (Animation Events), события буфера обмена (Clipboard Events), события мультимедиа (Media Events), события трансформации (Transition Events), события, посылаемые сервером (Server-Sent Events), события касания (Touch Events), события печати (Print Events), разные события (Misc Events).

JavaScript - Виды событий

Внимание: все события в JavaScript пишутся строчными (маленькими) буквами.

События мыши

  • mousedown – при нажатии кнопки мыши;
  • mouseup – при отпускании кнопки мыши;
  • click – при клике (порядок возникновения событий при click: mousedown -> mouseup -> click);
  • dblclick – при двойном клике (порядок возникновения событий при dblclick: mousedown -> mouseup -> click -> mousedown -> mouseup -> click -> dblclick);
  • mousemove – при перемещении курсора мыши;
  • mouseover – при вхождении курсора мыши в область, принадлежащей целевому элементу и других элементов, вложенных в него;
  • mouseenter – при вхождении указателя мыши в целевой элемент (в отличие от mouseover происходит только один раз при вхождении курсора в целевой элемент; при дальнейшем движении курсора и его вхождении в другие элементы (находящихся в целевом) – оно больше не возникает);
  • mouseout – при уходе курсора с целевого элемента и других элементов, вложенных в него;
  • mouseleave – при покидании границ целевого элемента (в отличие от mouseout не возникает при покидании курсора элементов вложенных в целевой);
  • contextmenu – при открытии контекстного меню.

События при CSS переходе

  • transitionrun – возникает при создании CSS перехода (т.е. когда он добавляется к набору запущенных переходов, но не обязательно он начался);
  • transitionstart – происходит, когда CSS переход начинает выполняться;
  • transitioncancel – возникает, если CSS переход был отменен;
  • transitionend – происходит при завершении CSS перехода.

Пример:

<style>
#box {
  position: absolute;
  top: 15px;
  left: 15px;
  width: 100px;
  height: 100px;
  background-color: #03a9f4;
}
.transform {
  transform: translateX(300px);
  transition: transform 1s ease-in-out;
}
</style>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    document.addEventListener('click', (e) => {
      const $target = e.target;
      if ($target.matches('#start')) {
        e.preventDefault();
        $box.classList.add('transform');
      } else if ($target.matches('#cancel')) {
        e.preventDefault();
        $box.classList.remove('transform');
      }
    });
    const $box = document.querySelector('#box');
    $box.addEventListener('transitionrun', () => {
      console.log('transitionrun');
    });
    $box.addEventListener('transitionstart', () => {
      console.log('transitionstart');
    });
    $box.addEventListener('transitioncancel', () => {
      console.log('transitioncancel');
    });
    $box.addEventListener('transitionend', () => {
      console.log('transitionend');
    });
  });
</script>

<div id="box"></div>

<a href="#" id="start">Start</a>
<a href="#" id="cancel">Cancel</a>

События при CSS анимации

  • animationstart – происходит, когда CSS анимация начинается;
  • animationiteration – возникает, когда заканчивается одна итерация CSS анимации и начинается другая;
  • animationend – происходит при окончании CSS анимации.

События клавиатуры

Порядок возникновения событий: keydown -> keypress -> keyup.

  • keydown - событие происходит, когда нажата клавиша на клавиатуре над элементом, но ещё не отпущена.
  • keyup - событие происходит, когда нажатая клавиша на клавиатуре над элементом перешла в состояние отпущено.
  • keypress - событие происходит, когда пользователь нажал клавишу на клавиатуре над элементом.

События объектов и фреймов

  • beforeunload - событие происходит, перед тем как документ будет выгружен. Это событие позволяет отображать дополнительное сообщение в диалоговом окне подтверждения "Вы действительно хотите покинуть эту страницу?". Стандартное сообщение, которое появляется при закрытии документа, может отличаться в разных браузерах. Но его Вы не можете изменить или удалить, Вы можете только с помощью этого метода добавить к нему собственное сообщение, которое будет отображаться вместе с сообщением по умолчанию.
  • error - событие срабатывает при возникновении ошибки, которая происходит при загрузке внешнего файла (например, документа или изображения).
  • hashchange - событие происходит при изменении якорной части (начинается с символа '#') текущего URL.
  • load - событие происходит, когда загрузка объекта завершена. Событие load наиболее часто используется для элемента body, чтобы выполнить сценарий сразу же после того как веб-страница полностью загрузится.
  • unload - событие происходит при выгрузке страницы (например, при закрытии вкладки (окна) браузера).
  • pageshow - событие происходит, когда пользователь переходит на веб-страницу, т.е. после того как страница становится доступна пользователю. Событие pageshow похоже на событие load, за исключением того, что оно срабатывает каждый раз при загрузке страницы, даже если она загружается из кэша. При первой загрузке страницы событие pageshow срабатывает сразу после события load.
  • pagehide - событие происходит, когда пользователь уходит со страницы (событие pagehide происходит до события unload). Кроме этого данное событие, в отличие от события unload не препятствует кэшированию страницы.
  • resize - событие происходит при изменении размеров окна браузера.
  • scroll - событие происходит, когда вы прокручиваете содержимое элемента, имеющего полосу прокрутки.

События формы и элементов управления

  • focus - событие происходит, когда элемент получает фокус. Данное событие не всплывает.
  • blur - событие происходит, когда объект теряет фокус. Данное событие не всплывает.
  • focusin - событие происходит, когда элемент получает фокус. Событие focusin подобно событию focus, но отличается от него тем, что оно всплывает. Поэтому его можно использовать, когда Вам необходимо выяснить, кто теряет фокус: элемент или его ребёнок?
  • focusout - событие происходит, когда элемент собирается потерять фокус. Событие focusout подобно событию blur, но отличается от него тем, что оно всплывает. Поэтому его можно использовать, когда Вам необходимо выяснить, кто теряет фокус: элемент или его ребёнок?
  • change - событие происходит при изменении значения элемента, но уже после того как элемент потерял фокус. Кроме события change в JavaScript есть также похожее событие input, которое отличается от события change тем, что происходит сразу же после изменения значения элемента. Событие сhange в отличие от события input также работает с элементами keygen и select. Для радиокнопок (radiobuttons) и флажков (checkboxes) событие change происходит при изменении состояния этих элементов.
  • input - событие происходит после того как изменяется значение элемента input или элемента textarea.
  • invalid - событие происходит, когда элемент input, данные которого необходимо отправить вместе с другими данными формы на сервер, содержит недопустимые данные.
  • reset - событие происходит перед очисткой формы, которая осуществляется элементом input с type="reset".
  • search - событие возникает после того как пользователь нажимает на клавишу Enter или нажимает кнопку "x" (отмена) в элементе input с type="search".
  • select - событие происходит после того как Вы выбрали некоторый текст в элементе. Событие select в основном используется для элемента input с type="text" или textarea.
  • submit - событие происходит перед отправкой формы на сервер.

События перетаскивания

События, связанные с перетаскиваемым объектом (draggable target, исходный объект):

  • dragstart – событие происходит, когда пользователь начал перетаскивать элемент;
  • drag – событие происходит, когда пользователь перетаскивает элемент;
  • dragend – событие происходит, когда пользователь закончил перетаскивания элемента, т.е. когда отпустил курсор мыши.

События, связанные с объектом (drop target), который принимает перетаскиваемый объект (draggable target):

  • dragenter – событие происходит, когда перетаскиваемый объект (draggable target) вошёл в область элемента (drop target), который может принять перетаскиваемый объект (draggable target).
  • ragleave – событие происходит, когда перетаскиваемый объект (draggable target) покидает пределы элемента (drop target), который может его принять.
  • dragover - событие происходит, когда перетаскиваемый объект (draggable target) перемещается в области элемента (drop target), который может его принять.
  • drop - событие происходит, когда пользователь отпускает перетаскиваемый объект (draggable target) в область элемента (drop target), который может его принять.

События буфера обмена

  • сopy - событие происходит, когда пользователь копирует содержимое элемента. Событие copy также происходит, когда пользователь копирует элемент (например, изображения, созданные с помощью элемента img). Событие copy используется в основном для элементов input с type="text".
  • сut - событие происходит, когда пользователь вырезает содержимое элемента.
  • paste - событие происходит, когда пользователь вставляет некоторое содержимое в элемент.

События печати

  • afterprint - событие происходит, когда страница начинает печататься (т.е. после нажатия кнопки "Печать" в диалоговом окне) или если диалоговое окно "Печать" было закрыто.
  • beforeprint - событие возникает перед печатью страницы, т.е. до открытия диалогового окна "Печать".

События, посылаемые сервером

  • error - событие возникает при возникновении ошибки с источником события. Ошибка обычно возникает, когда связь нарушается. Если это произойдет, то объект EventSource будет автоматически пытаться подключиться к серверу.
  • open - событие возникает, когда соединение с источником события открыто.
  • message - событие возникает, когда сообщение получено через источник события.
    Объект event события message поддерживает следующие свойства:
    • data - содержит сообщение.
    • origin - URL документа, который вызвал событие.
    • lastEventId - идентификатор (id) последнего полученного сообщения.

События мультимедиа

В процессе загрузки аудио/видео события происходят в следующем порядке: loadstart -> durationchange -> loadedmetadata -> loadeddata -> progress -> canplay -> canplaythrough.

  • abort - событие возникает, когда прерывается загрузка аудио/видео. Это событие возникает именно когда загрузка медиа данных была прервана (отменена), а не, потому что возникла ошибка.
  • error - событие возникает, когда произошла ошибка при загрузке аудио/видео.
  • stalled - событие возникает, когда браузер пытается получить медиа данные, но данные недоступны.
  • suspend - событие возникает, когда браузер не может получить медиа данные, т.е. загрузка медиа останавливается по какой-то причине.
  • loadstart - событие происходит, когда браузер начинает искать указанное аудио/видео, т.е. когда начинается процесс загрузки.
  • durationchange - событие возникает, когда изменяется длительность аудио/видео. Если аудио/видео загружается, то длительность будет меняться от значения "NaN" до фактической длительности аудио/видео.
  • loadedmetadata - событие возникает, когда метаданные для указанного аудио/видео загружены. Метаданные аудио/видео состоят из: длительности, размера (только видео) и текстовой дорожки.
  • loadeddata - событие возникает, после того как первый кадр медиа загрузился.
  • progress - событие происходит, когда браузер загружает указанное аудио/видео.
  • canplay - событие возникает, когда браузер может начать воспроизведение указанного аудио/видео (т.е. когда буферизация потока аудио/видео достаточна для того чтобы браузер мог начать его воспроизводить).
  • canplaythrough - событие возникает в тот момент времени, когда браузер может проигрывать указанное медиа без остановки на буферизацию.
  • ended - событие происходит, когда воспроизведение аудио/видео завершилось (достигло конца). Это событие может использоваться для вывода сообщений типа "Спасибо за внимание", "Спасибо за просмотр" и др.
  • pause - событие происходит, когда воспроизведение аудио/видео приостановлено пользователем или с помощью кода (программно).
  • play - событие происходит, когда начинается воспроизведение аудио/видео. Оно также происходит, когда аудио/видео было снято с паузы и начинает воспроизводиться.
  • playing - событие происходит, когда аудио/видео воспроизводится после того как оно было поставлено на паузу или остановилось для буферизации.
  • ratechange - событие происходит, когда изменяется скорость воспроизведения аудио/видео.
  • seeking - событие происходит, когда пользователь начинает перемещение ползунка (переход) к новой временной позиции проигрываемого аудио/видео.
  • seeked - событие происходит, когда пользователь закончил перемещение ползунка (переход) в новую временную позицию проигрываемого аудио/видео. Событие seeked противоположно событию seeking. Для того чтобы получить текущую позицию воспроизведения, используйте свойство currentTime объекта Audio/Video.
  • timeupdate - событие происходит при изменении временной позиции воспроизводимого аудио/видео.
    Это событие происходит:
    • при воспроизведении потока аудио/видео.
    • при перемещении ползунка в новую временную позицию воспроизводимого аудио/видео.
    Событие timeupdate часто используется вместе со свойством объекта Audio/Video currentTime, которое возвращает текущую временную позицию воспроизводимого аудио/видео в секундах.
  • volumechange – событие происходит каждый раз при изменении громкости воспроизводимого потока видео/аудио.
    Это событие происходит, при:
    • увеличении или уменьшении громкости;
    • отключении или включении звука.
  • waiting - событие происходит, когда видео останавливается для буферизации.

Разные события

  • toggle - событие происходит, когда пользователь открывает или закрывает элемент details. Элемент details предназначен для создания дополнительных сведений, которые пользователь при необходимости может просматривать или скрывать.
  • wheel - событие происходит при прокручивании колеса мыши вперёд или назад над элементом.

Задания

  1. Является ли событие "Нажатие клавиши на клавиатуре (onkeypress)" сложным? И если является, то в результате, каких простых событий оно возникает?
  2. Например, у Вас есть 2 элемента р и пользователь перемещает мышку с области, принадлежащей одному элементу р, на область, принадлежащую другому элементу р. То, какие в этом случае возникают события, и какие элементы их генерируют?

Комментарии ()

  1. Александр
    24 ноября 2020, 09:13
    Александр, приветствую.
    А как можно отличить закрытие вкладки/браузера от перезагрузки страницы?
    Задача в том, чтобы отправлять серверу команду только если вкладка действительно закрывается.
    Если я правильно понимаю при перезагрузке страницы сначала возникают beforeunload и unload и только потом документ загружается.
    1. Александр Мальцев
      24 ноября 2020, 15:48
      Привет! События beforeunload и unload происходят перед закрытием страницы. Сначала beforeunload, потом unload. Нажатия любых клавиш, в том числе F5 можно отследить, а остальное – нет.
      1. Александр
        25 ноября 2020, 09:59
        Опыты «на кошках» показали, что в:
        — Google Chrome, Версия 86.0.4240.111,
        — Opera, Версия:72.0.3815.320,

        при обновлении страницы не возникает события unload

        В FireFox, Версия 83.0 — все наоборот при обновлении возникают оба (beforeunload и unload) а при закрытии только beforeunload.

        Таким образом можно отличить обновление страницы от закрытия.

        ie и safari пока не тестировал.
        То-есть по большому счету и клавиши можно не отслеживать.

        Может кому-то будет полезно.
        1. Александр Мальцев
          25 ноября 2020, 15:01
          Добавил на страницу такой скрипт:
          <script>
          window.addEventListener('beforeunload', () => {
            localStorage.setItem('beforeunload', Date.now());
          });
          window.addEventListener('unload', () => {
            localStorage.setItem('unload', Date.now());
          });
          </script>
          
          Открываю страницу в Chrome, а затем перезагружаю. Событие unload возникает:

          Событие unload в Chrome возникает
          1. Александр
            25 ноября 2020, 17:00
            Я тестил несколько иначе.
            JS (vue)
            mounted: function(){
                            window.addEventListener('beforeunload', this.refreshPage);
                            window.addEventListener('unload', this.closePage);
                        },
            methods:{
                            closePage:function(e){
                                e.preventDefault();
                                let q={
                                    event:'unload',
                                    eventData: e.currentTarget.performance.navigation
                                }
                                axios
                                  .post('evlist.php', q);
                            },
                            refreshPage:function(e){
                                e.preventDefault();
                                let q={
                                    event:'beforeunload',
                                    eventData: e.currentTarget.performance.navigation
                                }
                                axios
                                  .post('evlist.php', q);
                            }
            }
            
            Ну и соответственно evlist.php:
            <?php
            session_start();
            $query=file_get_contents('php://input');
            $events=file_get_contents('events.log');
            $events =$events.PHP_EOL.date_format(date_create(), 'd.m.Y H:i:s').':'.chr(9).'query: '.$query;
            file_put_contents('events.log', $events);
            ?>
            
            ну и смотрим содержимое файла events.log
            1. Александр
              26 ноября 2020, 06:37
              Правда, как оказалось, такое поведение не стабильное ))) Гарантий не дает.
              1. Александр Мальцев
                26 ноября 2020, 13:53
                Это точно.
                1. Александр
                  26 ноября 2020, 16:24
                  Вот и вопрос, как быть?
                  Основная задача — убить PHP сессию по закрытию пользователем сайта.
                  Документация по PHP говорит примерно следующее:
                  «Когда мы делаем session_start(); если PHP получает куку — возобновляет сессию, не получает куку, — то стартует новую сессию и отдает клиенту куку с PHPSESSID.
                  Чтобы кука стала сессионной (до закрытия браузера) делайте session_set_cookie_params(0);
                  перед каждым session_start().»

                  Может оно конечно и работает так как говорит документация, может чтобы оно работало надо Целиком Браузер закрыть.
                  Но все же мы усиленно используем вкладки, а вот на закрытие вкладки оно у меня пока не заработало так, как написано.
                  1. Александр Мальцев
                    05 декабря 2020, 14:52
                    Если однозначно это не определить, то тогда может изменить саму задачу.
          2. Александр
            25 ноября 2020, 10:38
            Остался один вопрос в свете поведения Фаерфокса как в его случае повесить обработчик именно на закрытие страницы, а не на обновление?
            1. Александр Мальцев
              25 ноября 2020, 15:04
              Определить браузер можно через «navigator.userAgent».
              1. Александр
                25 ноября 2020, 17:04
                Да можно, но я не в курсе как повесить обработчик на не сработавшее событие, пока мне кажется, что нельзя.

                Мне надо отдавать бэкэнду команду только при закрытии вкладки.
        2. Александр
          24 ноября 2020, 09:45
          Понятно как отследить обновление/перезагрузку инициированное по F5. А как отследить обновление (клик) по кнопке «Обновить» браузера?
        3. Maksim
          27 апреля 2016, 12:48
          Разобрался.

          сделал вот так.
                  var currentscroll = $(window).scrollTop();
                  $('input').on('blur', function(event) {
                          setTimeout(function() {
                              if (!event.relatedTarget) {
                              $(window).scrollTop(currentscroll);
                              }
                          }, 0);
                  });
          
          задумка такая. при вызове экранной клавиатуры на iOS, сдвигается окно. нажав кнопку «готово» (done) клавиатура убирается, у элементов input фокус убирается, но окно не возвращается в прежнюю позицию. попробовал отследить событие blur у input и если элемент без фокуса — вернуть скролл окна в старое положение. через event blur не получилось, попробовал через event.relatedTarget. он дает Null если нажата кнопка «готово».
          1. Maksim
            27 апреля 2016, 11:47
            Здравствуйте.

            Пытаюсь в форму с несколькими input добавить обработчик события blur. Задача такая — если все поля без фокуса, выводим сообщение.
            $('form').on('blur', function(event) {
                setTimeout(function() {
                    if (!event.delegateTarget.contains(document.activeElement)) {
                        document.write('Form blur');
                    }
                }, 0);
            });
            
            Этот скрипт не срабатывает. Если заменить 'form' на 'input', то работает некорректно. при переходе от одного поля к другому срабатывает условие, хотя второе поле становится в фокусе. Таймер тоже не помогает. Как сделать, чтобы условие отрабатывалось только когда все элементы input без фокуса?
            1. Дамир
              30 июня 2015, 19:40
              Классные уроки,
              В этом году выходит ES6 (там будут классы начледование как в настоящем ООП) и сразу после него Ангуляр 2, планируешь делать уроки по ним?
              1. Александр Мальцев
                01 июля 2015, 16:14
                Спасибо, Дамир.
                Уроки по ECMAScript 6 планирую в виде нового раздела в категории, посвященной изучению JavaScript.
                Про Angular 2 писать пока не собираюсь, возможно, позже, когда завершу начатые разделы.
                1. Дамир
                  02 июля 2015, 11:21
                  Привет, напиши мне на емаил есть парочка интересных предложений ;)
              Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.