События и обработчики событий в JavaScript

События и обработчики событий в JavaScript

Одной из самых важных возможностей языка JavaScript, которая, пожалуй, является основной в этом языке, это возможность обрабатывать какие-то события . Такая возможность является особенностью для JavaScript по сравнению с другими языками из web программирования, потому что только этому языку в силе сделать подобное.

Что такое событие и обработчики событий

Событие - это некое действие, которое может производить либо пользователь, либо другие объекты на странице.

Самым ярким примером события это клик пользователя по какому-то объекту(click ), будь то это кнопка, ссылка или любой другой элемент. Другой пример события, это наведение мыши над каким-то объектом(mouseover ), скажем над изображением. Также событием является полное загрузка страницы(load ). В общем все действия, которые происходят на сайте являются событиями.

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

И для того чтобы обрабатывать какое-то событие, необходимо использовать специальный обработчик для данного события. Каждое событие имеет свой обработчик, например, у события клик(click ) есть обработчик onclick . У события наведения мыши над объектом(mouseover ) есть обработчик onmouseover . И у события полной загрузки страницы(load ) есть обработчик onload .

То есть как вы поняли название обработчика , формируется из префикса "on" + название события.

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

Обработчик события вызывается в качестве атрибута, в самом теге HTML элемента. В значение обработчика можно написать сразу код JavaScript, но лучше вызывать какую-то функцию, которая сделает необходимые действия. Функцию необходимо описать внутри тега script, который может находится как внутри блока head, так и в конце тега body. В качестве параметра для этой функции передаётся слово this , то есть текущий объект.

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

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry"s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.

Div{ padding-left: 50px; width: 200px; border: 1px solid #000; }

JavaScript код:

Function blockOver(block){ alert("Вы находитесь в текстовой области "); }

Сохраняем документ, открываем его в браузере, наводим курсор мыши над текстом и видим результат обработки данного события:


Как получить значение атрибута в javascript ?

С помощью параметра функций (this), можно получить значение какого-то атрибута текущего объекта , например, узнать его id.

Для примера, создадим кнопку и зададим ей id со значением "justButton". Когда кликнем на данную кнопку, то выведем такое сообщение: "Вы кликнули по кнопке, с идентификатором значение_id". Здесь необходимо уже использовать обработчик onclick .

JavaScript код:

Function clickOnButton(button){ alert("Вы кликнули по кнопке, с идентификатором: " + button.id); }

Сохраняем документ, открываем его в браузере и кликаем по кнопке.


Таким же образом можно вывести имя кнопки(button.name ) или её значение(button.value )

Получаем значение ширины и высоты элемента

Ещё можно узнать значения CSS свойства элемента , например, ширину и высоту. Для получения ширины используются свойства clientWidth и offsetWidth , а для высоты clientHeight и offsetHeight . Для примера, выведем значения ширины и высоты кнопки, по которой кликнули.

Теперь содержимое функции clickOnButton будет такой:

Function clickOnButton(button){ //alert("Вы кликнули по кнопке, с идентификатором: " + button.id); var width = button.clientWidth || button.offsetWidth; var height = button.clientHeight || button.offsetHeight; alert("Ширина кнопки: " + width + "\nВысота кнопки: " + height); }

Результат данного примера:


Напоминаю, что ширина элемента считается вместе со значением padding, поэтому она и равна 111px [ 99px(width) + 6px(padding-left) + 6px(padding-right) ].

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

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

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

И в конец данной статьи разберём простой пример обработки формы. Обработка формы на JavaScript, во-первых, уменьшает загрузку на сервер и во-вторых придаёт дополнительный плюс к юзабилити сайта.

Форма состоится из одного поля для логина, и кнопки отправить. При отправке формы, будем проверять длину логина. Его длина должна быть больше трёх символов.

Начнём, мы с HTML структуры данной формы.

Теперь, тегу формы добавим в качестве атрибута обработчик onsubmit , события submit . Следующим образом:

Событие submit срабатывает при отправке формы. Оператора return мы написали для того чтобы запретить отправку формы, в случае обнаружения ошибки в вводе данных. Если функция вернёт значение false, то значение обработчика onsubmit будет «return false», это значит, что форма не отправиться на сервер. В противном случае, если форма вернёт true, то значение обработчика будет «return true» и форма отправится без проблем.

Иногда бывает необходимо чтобы полностью запретить отправку формы, в таком случае значение обработчика onsubmit будет таким:

Onsubmit = "checkForm(this); return false;"

Как Вы наверняка уже догадались, checkForm это название функции, которая вызовется, когда сработает событие submit. Вы можете назвать её как хотите, следуя правилам наименования функции.

И так, вернёмся к нашему примеру. Теперь нам необходимо описать функцию checkForm. В ней будет такое условие: если длина логина меньше трёх символов, то мы возвращаем false и форма не отправится, в противном случае, если данные были введены правильно, то, мы отправляем форму на сервер.

Function checkForm(form){ //Получаем значение поля формы, у которой name равен login var login = form.login.value; //Проверяем, если длина логина меньше трёх символов то выводим сообщение об ошибке и отменяем отправку формы. if(login.length > 3){ alert("Длина логина должна быть больше трёх символов"); return false; }else{ return true; } }

Сохраняем документ, открываем его в браузере и тестируем.


Таким вот образом можно проверить форму на языке JavaScript и отменить её отправку в случае ошибки.

Ну и на этом всё дорогие читатели. Подведём итоги.
События используются очень часто, поэтому Вы должны уметь работать с ними на все 100.

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

Задачи
  • Создайте простой калькулятор сложения цифр.
    • Создайте форму с двумя числовыми полями(type="number") для ввода чисел и кнопку с надписью "Сложить"
    • При нажатии на кнопку отправить, вызовите функцию обработки данного события.
    • Внутри функции получите значения полей и методом alert, выведите результат сложения введённых чисел.
    • Сделайте так чтобы форма не отправлялось после нажатия по кнопке.
  • Пожалуй, события (а точнее, обработчики событий) в javascript играют чуть ли не самую важную роль - именно благодаря обработке событий возможно интерактивное общение веб-приложения с пользователем. Изначально обработчики событий начал поддерживать браузер Netscape 2, следом IE3, и затем уже все остальные браузеры. В этом посте я начну рассказывать про события в js, в течение месяца постараюсь "добить" тему событий и приступить к более интересным вещам.

    Способы установки обработчиков

    Существуют четыре варианта "навешивания" обработчиков на определенное событие:

  • **псевдопротокол javascript: **. Псевдопротокол javascript: по-настоящему бывает необходим очень редко, но, к сожалению, используется повсеместно. Делают это так: link

    Изначально этот протокол был создан для тестов - и до сих пор удобно проверять что-то по-быстрому, вписав в адресную строку выражение (например, в IE я раньше проверял hasLayout таким образом - писал в адресную строку javascript:alert(someElement.currentStyle.hasLayout)). Этот протокол никогда не был предназначен для навешивания обработчиков событий. Но люди поняли, что при нажатии на ссылку происходит выполнение содержимого её атрибута href (вспомните, что происходит при нажатии на ссылку, имеющую href="mailto:[email protected] "), и стали использовать псевдопротокол javascript: для замены основного предназначения ссылки (исполнения роли идентификатора связанного документа посредством универсального локатора ресурса (URL)).

  • Но мы эти методы рассматривать не будем, т.к. до поддержки XML events самому популярному браузеру (IE) гораздо дальше, чем до поддержки событийной модели w3c, а script for нарушает принцип отделения логики от содержания (и работает только в IE).

    Как Вы успели заметить, первая пара методов отличается от второй коренным образом - обработчики, определяемые в (x)html-документе, представляют собой последовательность javascript-команд, обработчик же, установленный в самом скрипте, обязан быть объектом типа "функция".

    Также при использовании второй пары способов возникает одна проблема - если скрипт расположен в документе до элемента, событие которого будет обрабатывать какая-то функция из скрипта, велика вероятность того, что браузер попытается "навесить" обработчик на ещё несуществующий элемент. Такое может произойти, если браузер уже получил содержимое скрипта и распарсил его, но ещё не получил сам элемент в (x)html-документе. Это далеко не такая редкая ситуация, как может показаться - скрипты, вынесенные во внешние файлы, часто кэшируются, и несколько документов используют одни и те же скрипты, потому браузер часто берёт файлы скриптов из кэша, соответственно, сразу же исполняя их. Впрочем, скрипты, описанные внутри элемента head (x)html-документа, также будут исполнены сразу же, не дожидаясь полной загрузки (x)html-документа в память. Проблема эта решается просто - в структуре DOM, предоставляемой каждым браузером скриптам, есть объект window, имеющий кучу свойств, методов и событий, и одно из таких событий - window.onload . Это событие вызывается браузером после получения и парсинга всего (х)html-документа. Соответственно, в js наиболее безопасно работать с документом и его элементами после появления этого события.

    test **window.onload = function(e) {** //it"s safe inside var handler = function(e){ alert("clicked on paragraph"); }; document.all["text"].onclick = handler; **};** header

    Так как пример будет работать во всех браузерах в quirks mode, я имею полное право использовать document.all (к тому же, так ещё и IE4 будет поддержан). Цель примера исключительно иллюстрационная, потому кому нужен standarts compliancy mode, переделайте document.all["text"] на document.getElementById("text") .

    Итак, мы выяснили, когда добавлять обработчики, договорились не использовать первые два метода (inline-описание и псевдопротокол javascript:). Теперь я подробнее остановлюсь на последних двух методах.

    Метод установки element.onclick хорош тем, что прост. Основной же его минус заключается в том, что он не позволяет добавить обработчик , он даёт лишь возможность заменить существующий (если таковой был определён). Получается, что с помощью установки свойства onclick невозможно использовать несколько обработчиков на одном элементе, что иногда бывает нужно. Вообще, конечно, добавить можно и через onclick, только геморрой. Методы же addEventListener и attachEvent позволяют именно добавлять обработчики (для них существуют и соответствующие методы удаления обработчиков - removeEventListener и detachEvent).

    При установке какому-то событию определенного элемента одного и того же обработчика, дупликат не будет установлен.

    В следующем примере обработчик divHandler будет вызван только один раз:

    test window.onload = function(e) { var handler = function(e) { alert("clicked on div"); }; document.all["text"].addEventListener("click", handler, false); document.all["text"].addEventListener("click", handler, false); }; header text

    Когда на одном элементе "висит" несколько обработчиков, они выполняются в том порядке, в каком были установлены - стэк, хранящий обработчики событий, имеет тип FIFO.

    Var elem = document.getElementById("note"); var handler1 = function(e){ alert("handler1"); }; var handler2 = function(e){ alert("handler2"); }; var handler3 = function(e){ alert("handler3"); }; note.addEventListener("click", handler1, false); //note.attachEvent("onclick", handler1); note.addEventListener("click", handler2, false); //note.attachEvent("onclick", handler2); note.addEventListener("click", handler3, false); //note.attachEvent("onclick", handler3);

    В этом примере выполнится сначала handler1 , затем handler2 , потом handler3 .

    Несмотря на то, что в msdn сказано, что обработчики, буде таких несколько на событии объекта, выполняются в рандомном порядке, опыт говорит, что они выполняются именно в FIFO-порядке.

    Резюмируем: Порядок запуска обработчиков события

    Так как (x)html-документ имеет иерархическую древовидную структуру, разработчики браузеров посчитали, что "пропускание события" по всей иерархии документа даст б`ольшую свободу веб-разработчикам в реализации интересных обработчиков.

    Итак, предположим, у нас есть следующий код:

    test window.onload = function(e) { var pHandler = function(e){ alert("clicked on paragraph"); }; var bodyHandler = function(e){ alert("clicked on body");} var docHandler = function(e){ alert("clicked on document"); }; document.onclick = docHandler; document.body.onclick = bodyHandler; document.all["text"].onclick = pHandler; }; header

    Если нажать на p , запустится сначала обработчик pHandler , затем bodyHandler и уже потом docHandler .

    Событийная модель, в которой браузер выстраивает очередь обработчиков от целевого элемента, инициировавшего событие до корневого элемента document , называется bubbling-моделью (bubble, англ., - пузырь).

    Событие как бы "всплывает" по иерархии документа от элемента, вызвавшего его и до корня. При прохождении каждого родительского элемента браузер проверяет, не установлен ли у этого родителя обработчик события такого же типа, и если установлен, вызывает его.

    Эта модель реализована в IE.

    Если запустить этот пример в браузере Netscape4(с небольшими изменениями), обработчики будут выполнены в обратном порядке - docHandler → bodyHandler → divHandler .


    Событийная модель, в которой браузер выстравивает очередь обработчиков от корневого элемента document до целевого элемента (инициировавшего событие), называется capturing-моделью (capturing, англ., - захват). При прохождении каждого элемента вниз по иерархии браузер проверяет наличие обработчика события такого же типа, и если обработчик есть, вызывает его.

    Эта модель появилась в браузере Netscape3 и со времен Netscape4 в диком виде не наблюдается.

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

    Позже, когда проблемы с разными событийными моделями всем надоели, дядьки из W3C решили стандартизировать событийную модель. Назвали они ее нехитро - DOM Events .

    Они попытались объединить обе модели. К сожалению, этой спецификации следуют только браузеры Firefox1.5 и Opera9, но в свете проснувшегося интереса IETeam к следованию стандартов, к 8-й версии IE также можно ожидать поддержки этой спецификации. И потому я попытаюсь рассказать о ней.

    Как я уже сказал, событийная модель w3c объединяет capturing и bubbling модели с небольшими изменениями. В стандарте w3c для установки обработчика события используется метод addEventListener. Он описан в интерфейсе EventTarget , который авторы браузеров обязаны реализовать для любого элемента.

    Interface EventTarget { void addEventListener(in DOMString type, in EventListener listener, in boolean useCapture); void removeEventListener(in DOMString type, in EventListener listener, in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); };

    Для нас сейчас существенно то, что третий параметр метода addEventListener (useCapture) - флаг, говорящий браузеру, на какой стадии прохождения события должен быть запущен добавляемый обработчик.

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

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

    Таким образом, любой элемент документа в w3c-модели (в отличие от IE bubbling model и NN4 capturing model) имеет два стэка для хранения обработчиков событий - для хранения обработчиков для capturing-стадии и для хранения обработчиков, назначенных на исполнение в bubbling-стадии.

    Возьмём для примера следующий код:

    test window.onload = function(e) { var doc1Capturing = function(e) { alert("document: first capturing handler"); }; var doc2Capturing = function(e) { alert("document: second capturing handler"); }; var doc3Capturing = function(e) { alert("document: third capturing handler"); }; var doc1Bubbling = function(e) { alert("document: first bubbling handler"); }; var doc2Bubbling = function(e) { alert("document: second bubbling handler"); }; var doc3Bubbling = function(e) { alert("document: third bubbling handler"); }; var body1Capturing = function(e) { alert("body: first capturing handler "); }; var body2Capturing = function(e) { alert("body: second capturing handler"); }; var body3Capturing = function(e) { alert("body: third capturing handler "); }; var body1Bubbling = function(e) { alert("body: first bubbling handler "); }; var body2Bubbling = function(e) { alert("body: second bubbling handler"); }; var body3Bubbling = function(e) { alert("body: third bubbling handler "); }; var div1Capturing = function(e) { alert("div: first capturing handler "); }; var div2Capturing = function(e) { alert("div: second capturing handler"); }; var div3Capturing = function(e) { alert("div: third capturing handler "); }; var div1Bubbling = function(e) { alert("div: first bubbling handler "); }; var div2Bubbling = function(e) { alert("div: second bubbling handler"); }; var div3Bubbling = function(e) { alert("div: third bubbling handler "); }; document.addEventListener("click", doc1Capturing, true); document.addEventListener("click", doc2Capturing, true); document.addEventListener("click", doc3Capturing, true); document.addEventListener("click", doc1Bubbling, false); document.addEventListener("click", doc2Bubbling, false); document.addEventListener("click", doc3Bubbling, false); document.body.addEventListener("click", body1Capturing, true); document.body.addEventListener("click", body2Capturing, true); document.body.addEventListener("click", body3Capturing, true); document.body.addEventListener("click", body1Bubbling, false); document.body.addEventListener("click", body2Bubbling, false); document.body.addEventListener("click", body3Bubbling, false); document.all["text"].addEventListener("click", div1Capturing, true); document.all["text"].addEventListener("click", div2Capturing, true); document.all["text"].addEventListener("click", div3Capturing, true); document.all["text"].addEventListener("click", div1Bubbling, false); document.all["text"].addEventListener("click", div2Bubbling, false); document.all["text"].addEventListener("click", div3Bubbling, false); }; header text

    Если нажать в приведённом примере на div , порядок выполения обработчиков должен быть следующим:

    Я не забыл указать в capturing-фазе обработчики события, установленные на элемент div на исполнение в capturing-фазе (div1Capturing , div2Capturing , div3Capturing), они не должны быть запущены. Спецификация указывает, что обработчики событий, назначенные на capturing-фазу, должны выполняться только для родителей целевого элемента. В данном случае только Opera следует стандарту.

    Этот баг в FF открыт уже 2 с половиной года, когда же будет решение, неизвестно.

    При появлении события в соответствии с w3c-моделью браузер должен:

      подготовить маршрут для обхода дерева от корневого элемента до целевого (приготовление к capturing-фазе). Этот пункт важен, так как в процессе прохождения фазы порядок

      запустить обхода дерева в capturing-фазе: для каждого последующего элемента в иерархии проверить наличие обработчиков события данного типа, в случае наличия таковых, запустить. Как только событие приходит к целевому элементу, исполнение capturing-фазы прекратить.

      подготовить маршрут для обхода дерева от целевого элемента до корневого (приготовления для bubbling-фазы). Этот пункт важен, так как в процессе прохождения фазы порядок исполнения обработчиков нельзя будет изменить даже посредством удаления элементов, на которые они установлены, можно будет лишь остановить процесс прохождения фазы вообще.

      запустить обхода дерева в bubbling-фазе: для каждого последующего элемента в иерархии проверить наличие обработчиков события данного типа, в случае наличия таковых, запустить. После исполнения обработчиков события данного типа, назначенных на корневой элемент (document) на исполнение в bubbling-фазе закончить процесс прохождения фазы.

    Фактически получается, что изменить порядок выполнения обработчиков можно только для обработчиков, назначенных на исполнение в bubbling-фазе и только из обработчиков, выполняющихся в capturing-фазе.

    Резюмируем:

    bubbling-модель подразумевает прохождение дерева (x)html-документа снизу вверх, от целевого элемента, возбудившего события, до корневого элемента document . При прохождении каждого элемента проверяется, не зарегистрировано ли у него обработчиков события такого же типа, если да, запуск этих обработчиков.

    capturing-модель подразумевает прохождение дерева (x)html-документа сверху вниз, от корневого элемента document до целевого элемента, возбудившего событие. При прохождении каждого элемента проверяется, не зарегистрировано ли у него обработчиков события такого же типа, если да, запуск этих обработчиков.

    W3C DOM2 Events-модель сочетает в себе обе модели. При возбуждении события браузер обходит документ сначала сверху вниз по иерархии (capturing-фаза), при наличии выполняя обработчики события данного типа у каждого из предков целевого элемента; затем переходит к bubbling-фазе, при которой сначала запускаются обработчики целевого элемента, назначенные на bubbling-фазу, затем браузер идёт вверх по иерархии документа, запуская обработчики события данного типа (в случае наличия) у каждого следующего элемента в иерархии, достигая корневого элемента document , выполняя его обработчики события, назначенные на bubbling-фазу. Ещё раз акцентирую внимание: обработчики, назначенные на capturing-фазу, не должны быть запущены на целевом элементе. Я думаю, баг в FF всё-таки исправят и этот браузер тоже начнет следовать стандарту.

    Во время работы со страницей пользователь совершает различные действия: нажимает кнопки мыши, вводит текст на клавиатуре. Каждое такое действие - это событие браузера. Его можно отследить и выполнить определённые строки программы при их возникновении. Для этого в JavaScript есть обработчики событий. Кроме действий пользователя, существуют и другие события браузера, например полная загрузка страницы.

    Каждое событие имеет своё название. click - это нажатие левой кнопки мыши, keydown - нажатие клавиши, focus - появление в фокусе элемента формы, Обработка события

    Функция, которая выполняется при срабатывании события называется обработчик события . Для каждого типа событий есть свой обработчик. Название обработчика состоит из слова on и названия события. Например, обработчик события click называется onclick . События происходят не на странице вообще, а на конкретном элементе. Соответственно и обработчик - это не отдельная функция. Обработчик ставится на какой-то элемент страницы.

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

    1
    2
    3
    4
    5
    6
    7

    Страница

    JavaScript:

    JavaScript:

    17
    18
    19
    20
    21
    22

    var inform = function () { alert("Другая кнопка"); }; var mbutton = document.getElementById("mbutton"); mbutton.onclick = inform;

    Когда функция присваивается обработчику, то после имени функции нет скобок. Если поставить скобки, то это будет не присваивание функции, а вызов на исполнение.

    Существует метод addEventListener() , который также назначает обработчик события элементу. Он считается более современным. Сейчас он применяется не часто, но в JavaScript есть новые события, обработать которые можно только с помощью этого метода.

    элемент.addEventListener (событие, функция)

    Параметры:

    событие - событие, которое нужно обрабатывать

    функция - функция, которая становится обработчиком

    В параметрах данного метода название события пишется в кавычках и слово on перед ним писать не нужно.

    HTML код:

    Новая кнопка

    JavaScript:

    24
    25
    26
    27
    28
    29

    var newinform = function () { alert("Нажата новая кнопка"); }; var newbutton = document.getElementById("newbutton"); newbutton.addEventListener("click", newinform);

    Метод removeEventListener() позволяет удалить обработчик.

    элемент.removeEventListener (событие, функция)

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

    Объект события

    При каждом срабатывании события формируется объект события. Объект содержит информацию о событии. У разных типов событий разные объекты. Но существуют и свойства, которые есть у любого объекта. Например, свойство type содержит тип события.

    Объект события передаётся в качестве параметра в функцию, которая является обработчиком. Для доступа к объекту нужно в функции создать параметр. Через этот параметр и производится обращение к объекту. Если у функции предполагаются ещё другие параметры, то объект события должен быть первым параметром. Изменим обработчик для кнопки, у которой id равно "button". Получим доступ к объекту события. Вместо сообщения о нажатии кнопки, выведем тип события. Теперь обработчик будет выглядеть так:

    13
    14
    15
    16

    button.onclick = function (event) { alert(event.type); };

    Нажмите на кнопку, будет выведен тип сработавшего события.

    У всех объектов события есть свойство currentTarget . Оно возвращает элемент, на котором сработало событие. Это может показаться бессмысленным. Ведь обработчик назначен конкретному элементу. Зачем ещё раз возвращать этот элемент? Но с событимяи браузера всё несколько сложнее. Чуть позже Вы узнаете, как это используется. Другие свойства мы рассмотрим при изучении конкретных событий.

    Объектная модель Java Script

    Язык Java Script является объектно-ориентированным. Базовый элемент языка - объект, представляющий собой документ HTML или его элемент, окно браузера или его управляющий элемент. Объект имеет:

    · свойства, описывающие его состояния. Свойствами объекта могут быть другие объекты или просто числовые значения. Если значение свойства не может быть изменено, такие свойства при описании объектов помечаются как Readonly ;

    · методы - функции, позволяющие выполнять какие-либо действия над объектом;

    · обработчики событий, которые позволяют выполнять определенные действия, когда происходит событие, т.е. меняется состояние объекта.

    Обработчик событий выполняет программу JavaScript, когда происходит соответствующее событие.

    Обработчики событий определяются атрибутом с соответствующим именем в HTML-теге, который создает данный объект JavaScript. Значением может быть любое число операторов JavaScript, разделенных точкой с запятой.

    Пример определения обработчика:

    Обработчики событий могут вызываться явно, например - button.onClick().

    С помощью обработчиков можно, например, выдавать сообщения в ответ на действия пользователя, проверять данные, введенные в форме перед ее отправкой и т.д. Можно отменить или изменить стандартное действие, выполняемое при определенном событии. Для отмены обработчик должен вернуть значение false. Например, при нажатии на ссылку не грузится новый документ, а выдается сообщение:

    Определены следующие события и обработчики:

    onBlur - cобытие blur происходит, когда окно навигатора или поля формы select, text или textarea теряют фокус.

    onFocus - событие focus происходит, когда окно навигатора или поле получает фокус ввода с клавиатуры или щелчком "мыши". Выбор результатов внутри поля связан с событием select, но не с событием focus.

    Объекты: window, select, text, textarea.

    onChange - событие change происходит, когда поля формы select, text или textarea теряют фокус и их значения были изменены.

    Обработчик событий onChange может использоваться для проверки данных после их изменения пользователем.

    Объекты: select, text, textarea.

    onSelect - событие select происходит, когда пользователь выбирает пункт меню или списка select или некоторый текст внутри поля text или textarea.

    Объекты: text, textarea, select.

    onClick - событие click происходит при щелчке "мышью" на объекте формы или элементе документа.



    Объекты: button, checkbox, radio, link, reset, submit.

    onMouseOver - событие mouseOver происходит каждый раз, когда курсор "мыши" попадает на объект.

    onMouseOut - событие mouseOotr происходит каждый раз, когда курсор "мыши" покидает границы объекта.

    Объекты: link.

    onSubmit - событие submit происходит, когда пользователь отправляет форму на Web-сервер.

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

    onReset - событие reset происходит, когда пользователь сбрасывает значения всех элементов формы в установленные по умолчанию.

    В NN4.0 и выше вы можете использовать обработчик событий onReset для отмены сброса данных формы; для этого используется выражение return, которое возвращает false в обработчик событий.

    Объекты: form.

    onLoad - событие load происходит, когда браузер завершает загрузку изображения, окна или всех фреймов внутри тега .

    Объекты: window, image.

    onUnload - событие unload происходит, когда вы выходите из документа.

    Обработчики событий onLoad и onUnload описываются внутри тегов или , например, .

    События onLoad и onUnload, описанные внутри фрейма в теге , происходят перед аналогичными событиями, описанными в теге .

    Объекты: window.

    onError - событие error происходит, когда при загрузке документа или изображения произошла ошибка.

    Объекты: window, image.

    onAbort - событие abort происходит, когда загрузка изображения прервана пользователем.

    Объекты: image.

    Чтобы отключить стандартную обработку события, обработчик должен возвратить логическое значение FALSE (return false).

    Исключение : для отмены стандартной обработки событий onMouseOver, onMouseOut, onError обработчик должен возвратить логическое значение TRUE (return true).

    Некоторые программы с применением JavaScript event работают напрямую с вводимыми пользователем данными. Момент возникновения и порядок таких взаимодействий не могут быть предсказаны заранее.

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

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

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

    В период от нажатия клавиши и до обнаружения программой этого события, она фактически не отвечает на запросы. Такой подход называется поллингом (опросом ).

    Большинство программистов стараются избегать его, если это возможно.

    Самым лучшим способом считается реализация системы, которая дает коду возможность реагировать на события, когда они происходят. Браузеры реализуют ее, предоставляя возможность регистрировать функции обработчиков для конкретных JavaScript event :

    Кликните по этому документу, чтобы активировать обработчик.

    addEventListener("click", function() { console.log("You clicked!"); });

    Функция addEventListener регистрируется таким образом, что ее второй аргумент вызывается всякий раз, когда происходит событие, описанное первым аргументом.

    События и узлы DOM

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

    Нажмите на меня

    Здесь нет обработчика.

    var button = document.querySelector("button"); button.addEventListener("click", function() { console.log("Button clicked."); });

    В данном примере обработчик подключен к узлу кнопки. JavaScript mouse events приводит в действие обработчик, а клик в остальной части документа — нет.

    Установив для узла атрибут onclick , мы получим тот же результат. Но узел имеет только один атрибут onclick , поэтому можно зарегистрировать для каждого узла только один обработчик. Метод addEventListener позволяет добавлять любое количество обработчиков. Так мы застрахованы от случайной замены обработчика, который уже был зарегистрирован.

    Метод removeEventListener , вызывается с аргументами, аналогичными addEventListener . Он удаляет обработчик:

    Одноразовая кнопка var button = document.querySelector("button"); function once() { console.log("Done."); button.removeEventListener("click", once); } button.addEventListener("click", once);

    Чтобы отменить функцию обработчика, мы задаем для нее имя (например, once ). Так мы передаем ее как в addEventListener , так и в removeEventListener .

    Объекты событий

    Хотя мы не упоминали об этом в приведенных выше примерах, в функции обработчиков JavaScript event передается аргумент: объект события. Он предоставляет дополнительную информацию о событии. Например, если мы хотим знать, какая клавиша мыши была нажата, нужно получить значение свойства объекта события which :

    Кликните по мне любой клавишей мыши var button = document.querySelector("button"); button.addEventListener("mousedown", function(event) { if (event.which == 1) console.log("Left button"); else if (event.which == 2) console.log("Middle button"); else if (event.which == 3) console.log("Right button"); });

    Информация, хранящаяся в объекте, различается зависимости от типа события. Свойство объекта type всегда содержит строку, идентифицирующую событие (например, «click » или «mousedown «).

    Распространение

    Обработчики событий (например, JavaScript touch events ), зарегистрированные для родительских узлов, также будут принимать события, которые происходят в дочерних элементах. Если была нажата кнопка, находящаяся внутри абзаца, обработчики событий абзаца также получат событие click .

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

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

    В следующем примере мы регистрируем обработчики «MouseDown » как для кнопки, так и для абзаца. При клике правой клавишей (JavaScript mouse events ) обработчик вызывает метод stopPropagation , который предотвращает запуск обработчика абзаца. При нажатии на кнопку другой клавишей мыши запускаются оба обработчика:

    Абзац и в нем кнопка.

    var para = document.querySelector("p"); var button = document.querySelector("button"); para.addEventListener("mousedown", function() { console.log("Handler for paragraph."); }); button.addEventListener("mousedown", function(event) { console.log("Handler for button."); if (event.which == 3) event.stopPropagation(); });

    Большинство объектов событий имеют свойство target , которое указывает на узел, в котором они возникли. Вы можете использовать это свойство, чтобы случайно не обрабатывать какое-то событие, которое распространяется вверх из узла.

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

    A B C document.body.addEventListener("click", function(event) { if (event.target.nodeName == "BUTTON") console.log("Clicked", event.target.textContent); });

    Действия по умолчанию

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

    Для большинства типов событий обработчики JavaScript event вызываются до выполнения действий по умолчанию. Если не нужно, чтобы выполнялось поведение по умолчанию, нужно вызвать для объекта события метод preventDefault .

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

    MDN var link = document.querySelector("a"); link.addEventListener("click", function(event) { console.log("Nope."); event.preventDefault(); });

    Старайтесь не делать так, если у вас нет на это веских причин.

    В зависимости от браузера некоторые события не могут быть перехвачены. В Google Chrome , например, сочетание клавиш (event keycode JavaScript ) для закрытия текущей вкладки (Ctrl-W или Command-W ) не может быть обработано с помощью JavaScript .

    События клавиш

    Когда пользователь нажимает клавишу на клавиатуре, браузер запускает событие «keydown «. Когда он отпускает клавишу, срабатывает событие «keyup «:

    Эта страница становится фиолетовой, когда вы нажимаете клавишу V.

    addEventListener("keydown", function(event) { if (event.keyCode == 86) document.body.style.background = "violet"; }); addEventListener("keyup", function(event) { if (event.keyCode == 86) document.body.style.background = ""; });

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

    В предыдущем примере использовано свойство объекта event keycode JavaScript . С его помощью определяется, какая именно клавиша была нажата или отпущена. Ноне всегда очевидно, как привести числовой код клавиши к фактической клавише.

    Для считывания значений клавиш букв и цифр используется код символа Unicode . Он связан с буквой (в верхнем регистре ) или цифрой, обозначенной на клавише. Метод charCodeAt для строк позволяет получить это значение:

    console.log("Violet".charCodeAt(0)); // → 86 console.log("1".charCodeAt(0)); // → 49

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

    Такие клавиши, как Shift , Ctrl , Alt порождают события, как обычные клавиши. Но при отслеживании комбинаций клавиш также можно определить, нажаты ли эти клавиши, по свойствам событий клавиатуры и JavaScript mouse events : shiftKey , ctrlKey , altKey и metaKey :

    Чтобы продолжить, нажмите Ctrl-Space.

    addEventListener("keydown", function(event) { if (event.keyCode == 32 && event.ctrlKey) console.log("Continuing!"); });

    События «keydown » и «keyup » предоставляют информацию о фактическом нажатии клавиш. Но что, если нам нужен сам вводимый текст? Получать текст из кодов клавиш неудобно. Для этого существует событие, «keypress «, которое срабатывает сразу после «keydown «. Оно повторяется вместе с «keydown «, пока клавиша нажата. Но только для клавиш, с помощью которых производится ввод символов.

    Свойство charCode в объекте события содержит код, который может быть интерпретирован, как код символа Unicode . Мы можем использовать функцию String.fromCharCode , чтобы преобразовать этот код в строку из одного символа.

    Установите фокус ввода на этой странице и наберите что-нибудь.

    addEventListener("keypress", function(event) { console.log(String.fromCharCode(event.charCode)); });

    Узел DOM , в котором происходит событие зависит, от того элемента, который находился в фокусе ввода при нажатии клавиши. Обычные узлы не могут находиться в фокусе ввода (если не установить для них атрибут tabindex ), но такие элементы, как ссылки, кнопки и поля формы, могут.

    Если никакой конкретный элемент не выделен фокусом ввода, то в качестве целевого узла для событий клавиши и JavaScript touch events выступает document.body .

    Клики мыши

    Нажатие клавиши мыши также приводит в действие ряд событий. События «mousedown » и «mouseup » похожи на «keydown » и «keyup «. Они запускаются, когда нажата и отпущена клавиша мыши. Данные события возникают в узлах DOM, на которые был наведен указатель мыши, когда возникло событие.

    Для общего узла, к которому относилось как нажатие, так и освобождение клавиши мыши, после события «mouseup » запускается событие «click «. Например, если нажать клавишу мыши на одном пункте, а затем переместить курсор на другой пункт и отпустить кнопку, то событие «click » будет происходить в элементе, который содержит оба эти пункта.

    Если два клика возникли близко друг к другу, также запускается событие «dblclick » (двойной клик ). Оно возникает после второго клика. Чтобы получить точную информацию о месте, где произошло событие мыши, нужно получить значение свойств pageX и pageY , которые содержат координаты события (в пикселях ) относительно левого верхнего угла документа.

    Ниже приведена реализация примитивной программы для рисования. Каждый раз при нажатии мыши в документе (под курсором ) добавляется точка:

    body { height: 200px; background: beige; } .dot { height: 8px; width: 8px; border-radius: 4px; /* закругленные углы */ background: blue; position: absolute; } addEventListener("click", function(event) { var dot = document.createElement("div"); dot.className = "dot"; dot.style.left = (event.pageX - 4) + "px"; dot.style.top = (event.pageY - 4) + "px"; document.body.appendChild(dot); });

    Свойства clientX и clientY подобны pageX и pageY , но они относятся к видимой части документа. Они могут использоваться для сравнения координат мыши с координатами, возвращаемыми функцией getBoundingClientRect .

    Движение мыши

    Каждый раз, когда перемещается курсов мыши, срабатывает событие «mousemove » из набора JavaScript mouse events . Оно может быть использовано для отслеживания положения мыши. Это применяется при реализации возможности перетаскивания элементов мышью.

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

    Потяните за край панели, чтобы изменить ее ширину:

    var lastX; // Отслеживает последнюю позицию X мыши var rect = document.querySelector("div"); rect.addEventListener("mousedown", function(event) { if (event.which == 1) { lastX = event.pageX; addEventListener("mousemove", moved); event.preventDefault(); // Предотвращает выделение } }); function buttonPressed(event) { if (event.buttons == null) return event.which != 0; else return event.buttons != 0; } function moved(event) { if (!buttonPressed(event)) { removeEventListener("mousemove", moved); } else { var dist = event.pageX - lastX; var newWidth = Math.max(10, rect.offsetWidth + dist); rect.style.width = newWidth + "px"; lastX = event.pageX; } }

    Обратите внимание, что обработчик «mousemove » зарегистрирован для всего окна. Даже если во время изменения размеров мышь выходит за пределы панели, мы все равно обновляем ширину панели и прекращаем JavaScript touch events , когда клавиша мыши была отпущена.

    Мы должны прекратить изменение размера панели, когда пользователь отпускает клавишу мыши. К сожалению, не все браузеры устанавливают для событий «mousemove » свойство which . Существует стандартное свойство buttons , которое предоставляет аналогичную информацию, но оно также поддерживается не во всех браузерах. К счастью, все основные браузеры поддерживают что-то одно: либо buttons , либо which . Функция buttonPressed в приведенном выше примере сначала пытается использовать свойство buttons , и, если оно не доступно, переходит к which .

    Когда курсор мыши наводится или покидает узел, запускаются события «mouseover » или «mouseout «. Они могут использоваться для создания эффектов при наведении курсора мыши, вывода какой-нибудь подписи или изменения стиля элемента.

    Чтобы создать такой эффект, недостаточно просто начать его отображение при возникновении события «mouseover » и завершить после события «mouseout «. Когда мышь перемещается от узла к одному из его дочерних элементов, для родительского узла происходит событие «mouseout «. Хотя указатель мыши не покинул диапазон распространения узла.

    Что еще хуже, эти JavaScript event распространяются так же, как и другие события. Когда мышь покидает один из дочерних узлов, для которого зарегистрирован обработчик, возникнет событие «mouseout «.

    Чтобы обойти эту проблему, можно использовать свойство объекта события relatedTarget . В случае возникновения события «mouseover » оно указывает, на какой элемент был наведен курсор мыши до этого. А в случае возникновения «mouseout » — к какому элементу перемещается указатель. Мы будем изменять эффект наведения мыши только, когда relatedTarget находится вне нашего целевого узла.

    В этом случае мы изменяем поведение, потому что курсор мыши был наведен на узел из-за его пределов (или наоборот ):

    Наведите курсор мыши на этот абзац.

    var para = document.querySelector("p"); function isInside(node, target) { for (; node != null; node = node.parentNode) if (node == target) return true; } para.addEventListener("mouseover", function(event) { if (!isInside(event.relatedTarget, para)) para.style.color = "red"; }); para.addEventListener("mouseout", function(event) { if (!isInside(event.relatedTarget, para)) para.style.color = ""; });

    Функция isInside отслеживает родительские связи заданного узла или пока не будет достигнута верхняя часть документа (когда node равен нулю ). Либо не будет найден родительский элемент, который нам нужен.

    Эффект наведения гораздо проще создать с помощью псевдоселектора CSS:hover , как показано в следующем примере. Но когда эффект наведения предполагает что-то более сложное, чем просто изменение стиля целевого узла, тогда нужно использовать прием с использованием событий «mouseover » и «mouseout » (JavaScript mouse events ):

    События прокрутки

    Каждый раз, когда элемент прокручивается, в нем срабатывает JavaScript scroll event . Его можно использовать для отслеживания того, что в данный момент просматривает пользователь; для отключения анимации, расположенной вне окна просмотра.

    В следующем примере мы выводим индикатор прогресса в правом верхнем углу документа и обновляем его, чтобы он по частям заливался другим цветом по мере прокрутки страницы вниз:

    .progress { border: 1px solid blue; width: 100px; position: fixed; top: 10px; right: 10px; } .progress > div { height: 12px; background: blue; width: 0%; } body { height: 2000px; }

    Scroll me...

    var bar = document.querySelector(".progress div"); addEventListener("scroll", function() { var max = document.body.scrollHeight - innerHeight; var percent = (pageYOffset / max) * 100; bar.style.width = percent + "%"; });

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

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

    Глобальная переменная innerHeight содержит высоту окна, которую мы должны вычесть из общей доступной прокручиваемой высоты документа. Нельзя прокручивать окно ниже при достижении нижней части документа. С innerHeight также может использоваться innerWidth . Разделив pageYOffset (текущую позицию окна прокрутки ) на максимально допустимую позицию прокрутки и умножив на 100, мы получаем процент для индикатора прогресса.

    Вызов preventDefault для JavaScript scroll event не предотвращает прокрутку. Обработчик события вызывается только после того, как происходит прокручивание.

    События фокуса ввода

    Когда элемент находится в фокусе ввода, браузер запускает в нем событие «focus «. Когда фокус ввода снимается, запускается событие «blur «.

    Эти два события не имеют распространения. Обработчик родительского элемента не уведомляется, когда дочерний элемент выделяется фокусом ввода.

    В следующем примере выводится подсказка для текстового поля, которое в данный момент находится в фокусе ввода:

    Имя:

    Возраст:

    var help = document.querySelector("#help"); var fields = document.querySelectorAll("input"); for (var i = 0; i < fields.length; i++) { fields[i].addEventListener("focus", function(event) { var text = event.target.getAttribute("data-help"); help.textContent = text; }); fields[i].addEventListener("blur", function(event) { help.textContent = ""; }); }

    Объект окна получает события «focus » и «blur «, когда пользователь переходит или покидает вкладку, окно браузера, в котором выводится документ.

    Событие загрузки

    Когда завершается загрузка страницы, для объектов тела документа и окна возникает JavaScript event «load» . Оно используется для планирования инициализации действий, для которых требуется загрузка всего документа. Не забывайте, что содержимое запускается сразу, когда встречается этот тег. Иногда это слишком рано. Например, когда скрипт должен сделать что-то с частями документа, которые загружаются после тега .

    и теги скриптов, которые загружают внешние файлы, также содержат событие «load «. Оно указывает, что файл, который был связан с ними, загружен. Как и события фокуса ввода, события загрузки не распространяются.

    Когда мы закрываем страницу или переходим на другую (например, нажав на ссылку ), срабатывает событие «beforeunload «. Оно применяется, чтобы предотвратить возможность случайной потери пользователем того, с чем он работал, после закрытия документа.

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

    Последовательность выполнения скриптов

    Запустить выполнение скрипта могут разные факторы: считывание тега, возникновение события. Метод requestAnimationFrame , задает вызов функции, перед тем как будет заново построена следующая страница. Это еще один способ, с помощью которого могут запускаться скрипты.

    События JavaScript select events и все остальные могут запускаться в любой момент, но в одном документе два скрипта никогда не запустятся одновременно. Если скрипт уже выполняется, обработчикам событий и фрагментам кода, запланированным другим скриптом, придется подождать своей очереди. Именно по этой причине документ замирает, когда скрипт работает в течение длительного времени. Браузер не реагирует на клики и другие события, поскольку не может запустить обработчики событий, пока текущий скрипт не закончит работу.

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

    Если нужно запустить процессы в фоновом режиме без замораживания страницы, браузеры предоставляют нам то, что называется web workers . Это изолированная среда JavaScript , которая работает с документом вместе с основной программой и может общаться с ним только путем отправки и получения сообщений.

    Предположим, что в файле с именем code/squareworker.js у нас есть следующий код:

    addEventListener("сообщение", function(event) { postMessage(event.data * event.data); });

    Представьте себе, что возводимое в квадрат число является очень большим, затягивающим вычисление, и нужно выполнить вычисления в фоновом потоке. Этот код запускает web workers , посылает ему несколько сообщений и выводит ответы:

    var squareWorker = new Worker("code/squareworker.js"); squareWorker.addEventListener("message", function(event) { console.log("The worker responded:", event.data); }); squareWorker.postMessage(10); squareWorker.postMessage(24);

    Функция postMessage отправляет сообщение, которое инициирует возникновение в приемнике события «message «. Скрипт, который создал web workers , отправляет и получает сообщения через объект Worker . С помощью этого объекта среда взаимодействуют с создавшим ее скриптом, посылая информацию и прослушивая его в своем глобальном с оригинальным скриптом.

    Установка таймеров

    Функция setTimeout похожа на requestAnimationFrame . Она задает вызов еще одной функции, которая будет вызываться позже. Но вместо того, чтобы вызывать функцию при следующем формировании страницы, она ждет определенное количество миллисекунд. В этом примере JavaScript event фон страницы из синего становится желтым через две секунды:

    document.body.style.background = "blue"; setTimeout(function() { document.body.style.background = "yellow"; }, 2000);

    Иногда нужно отменить функцию, которую мы запланировали. Это делается путем сохранения значения, возвращаемого функцией setTimeout , и вызова для нее clearTimeout :

    var bombTimer = setTimeout(function() { console.log("BOOM!"); }, 500); if (Math.random() < 0.5) { // 50% chance console.log("Defused."); clearTimeout(bombTimer); }

    Функция cancelAnimationFrame работает так же, как clearTimeout . Она вызывается значением, возвращаемым requestAnimationFrame , чтобы отменить кадр (если он еще не был вызван ).

    Похожий набор функций, setInterval и clearInterval используется для установки таймера, который должен повторять действие каждые X миллисекунд:

    var ticks = 0; var clock = setInterval(function() { console.log("tick", ticks++); if (ticks == 10) { clearInterval(clock); console.log("stop."); } }, 200);

    Дробление

    Некоторые типы событий могут запускаться много раз в течение короткого периода времени (например, «mousemove » и javascript scroll event ). При обработке таких событий, нужно быть осторожным, чтобы это не происходило очень долго, иначе обработчик будет выполнять действие столько времени, что взаимодействие с документом станет медленным и скачкообразным.

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

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

    Напечатайте что-нибудь здесь... var textarea = document.querySelector("textarea"); var timeout; textarea.addEventListener("keydown", function() { clearTimeout(timeout); timeout = setTimeout(function() { console.log("Вы перестали печатать."); }, 500); });

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

    Можно использовать иной сценарий, если нужно разделить ответы небольшим промежутком времени. Но чтобы при этом они запускались во время серии событий, а не только после нее. Например, можно отправлять в ответ на события «mousemove » (JavaScript mouse events ) текущие координаты мыши, но только через каждые 250 миллисекунд:

    function displayCoords(event) { document.body.textContent = "мышь находится в точке " + event.pageX + ", " + event.pageY; } var scheduled = false, lastEvent; addEventListener("mousemove", function(event) { lastEvent = event; if (!scheduled) { scheduled = true; setTimeout(function() { scheduled = false; displayCoords(lastEvent); }, 250); } });

    Заключение

    Обработчики событий позволяют обнаруживать и реагировать на события, над которыми мы не имеем прямого контроля. Для регистрации такого обработчика используется метод addEventListener .

    Каждое событие относится к определенному типу («keydown «, «focus » и так далее ), который идентифицирует его. Большинство событий вызывается для конкретного элемента DOM , а затем распространяются на родительские узлы элемента. Это позволяет обработчикам, связанным с этими элементами, обрабатывать их.

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

    Нажатие клавиш порождает события «keydown «, «keypress » и «keyup «. Нажатие мыши порождает события «mousedown «, «mouseup » и «click «. Перемещение мыши — «mousemove «, «mouseenter » и «mouseout «.

    JavaScript scroll event можно определить с помощью события «scroll «, а смена фокуса — «focus » и «blur «. После завершения загрузки документа для окна возникает событие «load «.

    Только одна часть JavaScript программы может работать одновременно. Обработчики событий и другие запланированные скрипты должны дожидаться, когда закончится выполнение других скриптов в очереди.

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



    © 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows