JavaScript с нуля — страница 24 из 30

Глава 31. События

Многие приложения и веб-сайты, оставленные без внимания, становятся очень скучными. Запускаются они с шиком и помпой, но вся эта напыщенность очень быстро пропадает, если мы перестаем взаимодействовать с ними:

Причина проста. Приложения существуют, чтобы реагировать на наши в них действия. Хоть они и имеют определенную базовую мотивацию, проявляющуюся при запуске, которая вытаскивает их из постели и приводит в рабочее состояние, все дальнейшие их действия уже по большей части диктуются нами. Тут все и становится интересно.

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

Поехали!

Что такое события?

На высоком уровне все создаваемое нами может быть смоделировано следующей инструкцией:

Когда___ совершится, то____

Мы можем заполнить пробелы этой инструкции великим множеством способов. Первый пробел описывает то, что происходит, а второй уже описывает реакцию на это. Вот некоторые примеры с заполненными пробелами:

Когда страница будет загружена, начнется воспроизведение видео с кошкой, скользящей на картоне.

Когда произойдет щелчок, покупка будет отправлена.

Когда ЛКМ будет освобождена, вылетит гигантская / не очень довольная птичка.

Когда клавиша удаления будет нажата, файл отправится в корзину.

Когда произойдет касание, к фотографии будет применен старый фильтр.

Когда файл будет загружен, обновится индикатор выполнения.

Эта обобщенная модель применима ко всему коду, который мы с вами написали. Она также применима ко всему коду, который написали для своих приложений наши друзья-разработчики/дизайнеры. От этой модели никуда не деться, поэтому и смысла противиться ей нет. Наоборот, следует хорошенько познакомиться с важным и очень талантливым представителем этой модели — событием.

Событие — это не более чем сигнал. Оно сообщает о том, что что-то только что произошло. Это что-то может быть щелчком мыши, нажатием клавиши клавиатуры, изменением размера окна или загрузкой документа. Главное здесь — понять, что этим сигналом могут послужить сотни встроенных в JavaScript явлений, равно как бессчетное множество отдельных пользовательских решений, созданных под конкретное приложение.

Вернемся к нашей модели, где события составляют первую ее половину:

Событие определяет то, что происходит, и передает сигнал. Вторая часть модели определяет реакцию на это событие:

При этом какая польза от сигнала, если кто-то где-то не ожидает его, чтобы предпринять соответствующее действие? Хорошо, теперь, когда у нас есть высокоуровневое представление о том, что такое событие, давайте поглядим на их жизнь в природном заповеднике JavaScript.

События и JavaScript

Учитывая важность событий, вас не должно удивлять, что JavaScript дает богатые возможности для работы с ними. Всего для их использования нам понадобится делать две вещи:

1. Прослушивать события.

2. Реагировать на события.

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

1. Прослушивание событий

Практически все, что мы делаем внутри приложения, заканчивается срабатыванием событий. Иногда наше приложение будет запускать события автоматически, например при своей загрузке. В других случаях оно будет запускать их в виде реакции на наши действия. Здесь стоит отметить, что наше приложение постоянно бомбардируется событиями независимо от того, хотим мы, чтобы они срабатывали, или нет. Наша же задача — указать приложению прослушивать только те события, которые нас интересуют.

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

Используется она следующим образом:

source.addEventListener(eventName, eventHandler, false);

Наверняка так не совсем понятно, поэтому давайте разберем, что именно означает каждая часть этой функции.

Source (источник)

Мы вызываем addEventListener через элемент или объект, в котором мы хотим прослушивать события. Как правило, это будет элемент DOM, но им также может быть document, window или другой объект, специально созданный для запуска событий.

Event Name (имя события)

В виде первого аргумента для функции addEventListener мы указываем имя события, которое хотим прослушивать. Весь список событий, доступных нам, слишком велик, чтобы полностью его здесь привести, но некоторые из наиболее распространенных перечислены в табл. 31.1.

Табл. 31.1. Распространенные события

Событие

Событие срабатывает…

Click

…когда вы нажимаете и отпускаете основную кнопку мыши, сенсорной панели и т. п.

Mousemove

…при движении курсора мыши

Mouseover

…при наведении курсора мыши на элемент. Это событие используется для обнаружения наведения

Mouseout

…при перемещении курсора мыши за границы элемента

Dblclick

…при быстром двойном клике

DOMContentLoaded

…когда DOM документа полностью загрузилась. Подробнее об этом событии в следующей главе

Load

…когда загрузился весь документ (DOM, внешние изображения, сценарии и т. п.)

Keydown

…при нажатии клавиши клавиатуры

Keyup

…при прекращении нажатия клавиши клавиатуры

Scroll

…при прокрутке элемента

wheel and DOMMouseScroll

…при использовании колесика мыши для прокрутки

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

Обработчик событий

Во втором аргументе нужно указать функцию, которая будет вызвана, когда событие будет услышано. Эта функция (а иногда объект) в кругу семьи и друзей зовется обработчик событий. Через несколько мгновений мы узнаем о ней гораздо больше.

Захватывать или не захватывать, вот в чем вопрос!

Последний аргумент состоит из true либо false. Чтобы полноценно понять последствия определения того или иного значения, нам придется подождать до главы «Всплытие и погружение событий», которая как раз будет следующей.

Обобщая все сказанное

Теперь, когда мы разобрали функцию addEventListener, давайте все это свяжем в полноценном заполненном примере:

document.addEventListener("click", changeColor, false);

В этом примере addEventListener прикреплена к объекту document. Когда будет услышано событие click, она вызовет функцию changeColor (то есть обработчик событий), которая отреагирует на это событие. Теперь самое время перейти к следующему разделу, посвященному как раз реагированию на события.

2. Реагирование на события

Как мы видели в предыдущем разделе, за прослушивание событий отвечает addEventListener. За действия, производимые после того, как событие будет услышано, отвечает обработчик событий. И я не шутил про то, что обработчик событий — это не более чем функция или объект:

function normalAndBoring() {

// я люблю походы, щенков и многие другие вещи!

}

Единственным отличием между типичной функцией и установленной мной в качестве обработчика событий в том, что функция обработчика событий специально вызывается по имени в вызове addEventListener (и получает объект Event в виде аргумента):

document.addEventListener("click", changeColor, false);


function changeColor(event) {

// I am important!!!

}

Любой код, который мы поместим в обработчик событий, будет выполнен, когда событие, за которым следит наша функция addEventListener, будет услышано.

Простой пример

Лучшим способом разобраться в этом материале будет рассмотрение его в действии. Чтобы попутно проработать пример самим, добавьте в HTML-документ следующую разметку и код:


Click Anywhere!



Если мы просмотрим наш документ в браузере, то изначально увидим пустую страницу (рис. 31.1).

Но все изменится, если щелкнуть в любом месте этой страницы. По завершении щелчка (то есть как только вы отпустите кнопку мыши) цвет фона страницы изменится на желтый (рис. 31.2).

Причина в коде:

document.addEventListener("click", changeColor, false);


function changeColor() {

document.body.style.backgroundColor = "#FFC926";

}

Вызов addEventListener идентичен тому, что мы уже видели, поэтому его можно пропустить. Вместо этого давайте обратим внимание на обработчика событий changeColor.

document.addEventListener("click", changeColor, false);


function changeColor() {

document.body.style.backgroundColor = "#FFC926";

}

Рис. 31.1. Просто пустая страница

Рис. 31.2. Страница становится желтой после щелчка

Эта функция вызывается, как только событие click в document будет услышано. Когда происходит вызов этой функции, она устанавливает фоновый цвет как желтый. Если связать это с самым началом, где мы в общих чертах обсуждали принцип работы приложений, то вот как будет выглядеть наш пример:

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

Аргументы и типы событий

Наш обработчик событий помимо вызова при срабатывании события совершает и другие действия — обеспечивает доступ к основному объекту события в виде своего аргумента. Чтобы с легкостью обращаться к объекту события, нужно изменить сигнатуру обработчика событий этого аргумента.

Вот пример, в котором мы указываем имя event, чтобы сослаться на наш аргумент события:

function myEventHandler(event) {

// материал для обработки событий для поддержки

}

Обработчик событий — это по-прежнему простая скучная функция, которая просто получает один аргумент — аргумент события. Можно использовать любой доступный идентификатор для этого аргумента, но я склоняюсь к использованию event или просто e, потому что именно так делают все крутые ребята. Тем не менее технически будет верен и следующий идентификатор:

function myEventHandler(isNyanCatReal) {

// материал для обработки событий

}

Нюанс в том, что аргумент события указывает на объект события и этот объект передается как часть срабатывания события. Есть причина, по которой мы уделяем внимание такому, казалось бы, типичному и скучному явлению. Этот объект события содержит свойства, которые связаны со сработавшим событием. Событие, запущенное кликом мыши, будет иметь отличные свойства в сравнении с событием, запущенным нажатием клавиши клавиатуры, загрузкой страницы, анимацией и многим другим. Большинство событий будут иметь свое собственное уникальное поведение, на которое мы будем опираться, а объект события — это наше окно в эту их уникальность.

Несмотря на разнообразие событий и итоговых объектов событий, которые мы можем получить, у них есть некоторые общие свойства. Эта общая часть определяется тем, что все объекты событий происходят от основного типа Event (технически подразумевается Interface). Ниже перечислены некоторые из известных свойств типа Event, которые мы будем использовать:

1. currentTarget

2. target

3. preventDefault

4. stopPropagation

5. type

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

Удаление слушателя событий

Иногда понадобится удалять слушателя событий из элемента. Делается это с помощью злейшего врага addEventListener функции removeEventListener:

something.removeEventListener(eventName, eventHandler, false);

Как видно из примера, эта функция получает в точности такие же типы аргументов, что и функция addEventListener. Причина тому проста. Когда мы прослушиваем событие в элементе или объекте, JavaScript использует eventName, eventHandler и значение true / false, чтобы опознать слушателя событий. Чтобы удалить этого слушателя событий, нам нужно указать в точности такие же аргументы. Вот пример:

document.addEventListener("click", changeColor, false);

document.removeEventListener("click", changeColor, false);


function changeColor() {

document.body.style.backgroundColor = "#FFC926";

}

Слушатель событий, которого мы добавили в первой строке, полностью нейтрализован вызовом removeEventListener в выделенной второй строке. Если вызов removeEventListener использует аргументы, отличные от указанных в соответствующем вызове addEventListener, то его усилия будут проигнорированы и прослушивание продолжится.

КОРОТКО О ГЛАВНОМ

Что ж, это все, что нужно для ознакомления с событиями. Помните: у вас есть функция addEventListener, которая позволяет зарегистрировать функцию обработчика событий. Эта функция обработчика событий будет вызываться при запуске события, которое примет прослушиватель событий. Хотя мы коснулись некоторых других тем, они станут более понятными, если рассмотреть их в контексте более сложных примеров, связанных с событиями.

Глава 32. Всплытие и погружение событий