Метод eventtarget.addeventlistener()
Содержание:
- Кнопка мыши: which/button.
- Отмена действия браузера
- javascript onclick без клика
- Координаты мыши: clientX(Y)/pageX(Y)
- Свойства событий указателя
- Это на самом деле проблема?
- Как передать данные в другой тег по id при onclick
- event.defaultPrevented
- В чем проблема?
- Подписка на событие через код JavaScript с помощью свойства
- Приём проектирования «поведение»
- Обработчики событий
- More Examples
- addEventListener
- Итого
- Итого
После получения события обычно интересно узнать, какая кнопка была нажата. Если, конечно, это не событие , с которым все и так понятно
Для этого в объекте есть два свойства: и , которые содержат числовые значения, соответствующие нажатой кнопке. К сожалению, тут есть некоторые несовместимости.
Internet Explorer | Firefox, Safari Win и Opera | Konqueror | ||
ЛЕВАЯ КНОПКА | event.which | undefined | 1 | 1 |
event.button | 1 | 1 | ||
СРЕДНЯЯ КНОПКА | event.which | undefined | 2 | 2 |
event.button | 4 | 1 | 4 | |
ПРАВАЯ КНОПКА | event.which | undefined | 3 | 3 |
event.button | 2 | 2 | 2 |
Свойство было изначально изобретено Netscape, а использовалось в Internet Explorer.
Через некоторое время браузеры стали использовать оба и все перепуталось.
В стандарте W3C прописано свойство , которое ведет себя, как в Firefox, т.е:
- 0 — левая кнопка
- 1 — средняя кнопка
- 2 — правая кнопка
Подход создателей браузера Internet Explorer, вообще говоря, более универсальный, так как является 3-битовым числом, каждый бит которого отвечает за кнопку мыши.
Так, (первый бит) установлен в 1, если нажата левая кнопка, (второй бит) установлен в 1, если нажата правая кнопка, и (третий бит) — если нажата средняя.
В результате мы не можем отловить, когда, например, нажаты левая и правая кнопки, а когда только левая или только правая. К сожалению, это можно сделать только в IE.
Удобнее всего — взять за основу свойство , которое одинаково поддерживают почти все браузеры.
Остается лишь составить из для Internet Explorer:
if (!e.which && e.button) { if (e.button & 1) e.which = 1 else if (e.button & 4) e.which = 2 else if (e.button & 2) e.which = 3 }
Вот универсальный тестовый стенд по определению клавиш. Выбирайте любую мышь и жмите кнопу из любого браузера — ниже появятся названия событий и значения .
Отмена действия браузера
Есть два способа отменить действие браузера:
- Основной способ – это воспользоваться объектом . Для отмены действия браузера существует стандартный метод .
- Если же обработчик назначен через (не через ), то также можно вернуть из обработчика.
Возвращать не нужно
Обычно значение, которое возвращает обработчик события, игнорируется.
Единственное исключение – это из обработчика, назначенного через .
В других случаях не нужен, он никак не обрабатывается.
Рассмотрим меню для сайта, например:
Данный пример при помощи CSS может выглядеть так:
В HTML-разметке все элементы меню являются не кнопками, а ссылками, то есть тегами . В этом подходе есть некоторые преимущества, например:
- Некоторые посетители очень любят сочетание «правый клик – открыть в новом окне». Если мы будем использовать или , то данное сочетание работать не будет.
- Поисковые движки переходят по ссылкам при индексации.
Например, вот так:
Если мы уберём , то после выполнения обработчика события браузер выполнит «действие по умолчанию» – переход по адресу из . А это нам здесь не нужно, мы обрабатываем клик сами.
Кстати, использование здесь делегирования событий делает наше меню очень гибким. Мы можем добавить вложенные списки и стилизовать их с помощью CSS – обработчик не потребует изменений.
События, вытекающие из других
Некоторые события естественным образом вытекают друг из друга. Если мы отменим первое событие, то последующие не возникнут.
Например, событие для поля приводит к фокусировке на нём и запускает событие . Если мы отменим событие , то фокусирования не произойдёт.
В следующем примере попробуйте нажать на первом – происходит событие . Но если вы нажимаете по второму элементу, то события не будет.
Это потому, что отменено стандартное действие . Впрочем, фокусировка на элементе всё ещё возможна, если мы будем использовать другой способ. Например, нажатием клавиши Tab можно перейти от первого поля ввода ко второму. Но только не через клик мышью на элемент, это больше не работает.
javascript onclick без клика
javascript onclick без клика
но первое, что я подумал… вспомнил старый пошлый анекдот! дети, если вам нет 16, то закрываем страницу на этом месте!
Закрыли!? Я жду!
Теперь продолжим со взрослыми…
Встречается парочка на хате, а у парня был попугай! Девушка:
— я не могу заниматься этим, когда он смотрит…
Парень накинул тряпку на клетку.
И говорит попугаю! Будешь подсматривать — голову оторву!
Начали заниматься любовью!
— Давай я сверху, ты снизу!
— Давай!
…
— Давай ты сверху, я снизу!
— Давай!
…
— А теперь давай ты сверху, и я сверху!
Попугай:
— Пусть мне оторвут голову! Но это я должен увидеть!
Координаты мыши: clientX(Y)/pageX(Y)
При обработке событий, связанных с мышью, нужен кроссбраузерный способ получения координат курсора из события в обработчике.
Координаты курсора мыши относительно окна находятся в стандартных свойствах . Они одинаково поддерживается всеми браузерами.
Если у вас есть окно 500×500, и мышь находится в центре, то и будут оба равны 250. Если вы затем проскроллируете документ вниз, налево или вверх, не двигая курсор — значения не изменятся, так как отсчитываются относительно окна, а не документа.
Как правило, при обработке события нужна позиция мыши относительно документа, учитывающая прокрутку. Стандарт W3C предоставляет для этого свойство .
Если у вас есть окно 500×500, и мышь находится в центре, то и будут оба равны 250. Если вы затем проскроллируете на 250 пикселей вниз, станет равным 750.
Таким образом содержат координаты, на каком месте документа произошло событие, учитывая все прокрутки.
Свойства поддерживаются всеми браузерами, кроме Internet Explorer.
В IE их можно получить из , прибавив к ним .
Обычно оно находится в <body>: , но это не всегда так. Например, при выборе Strict DTD оно высчитывается для <html>: . Кроме того, тэга <body> может просто не быть в документе.
Поэтому мы сначала возьмем (если есть), затем проверим . Если нет ни того, ни того, то 0.
var html = document.documentElement var body = document.body e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0)
Кроме того, в IE может быть немного сдвинут с позиции 0,0. Значение сдвига находится в , и его также необходимо учесть.
Этот код позволяет надежно получить для IE, в котором его изначально нет:
if (e.pageX == null && e.clientX != null ) { var html = document.documentElement var body = document.body e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0) e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0) }
Этот обработчик обновляет координаты мыши относительно документа.
function mouseShowHandler(e){ e = e || window.event if (e.pageX == null && e.clientX != null ) { var html = document.documentElement var body = document.body e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0) e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0) } document.getElementById('mouseX').value = e.pageX document.getElementById('mouseY').value = e.pageY }
Координата X:
Координата Y:
Свойства событий указателя
События указателя содержат те же свойства, что и события мыши, например , и т.п., и несколько дополнительных:
-
– уникальный идентификатор указателя, вызвавшего событие.
Идентификатор генерируется браузером. Это свойство позволяет обрабатывать несколько указателей, например сенсорный экран со стилусом и мульти-тач (увидим примеры ниже).
-
– тип указывающего устройства. Должен быть строкой с одним из значений: «mouse», «pen» или «touch».
Мы можем использовать это свойство, чтобы определять разное поведение для разных типов указателей.
-
– равно для основного указателя (первый палец в мульти-тач).
Некоторые устройства измеряют область контакта и степень надавливания, например пальца на сенсорном экране, для этого есть дополнительные свойства:
- – ширина области соприкосновения указателя (например, пальца) с устройством. Если не поддерживается, например мышью, то всегда равно .
- – высота области соприкосновения указателя с устройством. Если не поддерживается, например мышью, то всегда равно .
- – степень давления указателя в диапазоне от 0 до 1. Для устройств, которые не поддерживают давление, принимает значение (нажато) либо .
- – нормализованное тангенциальное давление.
- , , – специфичные для пера свойства, описывающие положение пера относительно сенсорной поверхности.
Эти свойства большинством устройств не поддерживаются, поэтому редко используются. При необходимости, подробности о них можно найти в .
Это на самом деле проблема?
Давайте проверим это, создав 10 асинхронных задач, которые просто ждут:
const resolvers = []; async function asyncTask() { const controller = new AbortController(); await abortable( controller.signal, new Promise((resolve) => { resolvers.push(resolve); }), ); console.log('async task complete'); } for (let i = 0; i < 10; i++) asyncTask();
И давайте попробуем увидеть это с помощью Chrome DevTools:
И да, наши большие объекты торчат в памяти. И это понятно, потому что асинхронная задача еще не завершена. Давайте завершим их:
while (resolvers) { const resolve = resolvers.shift(); resolve(); }
И посмотрим, есть ли изменения:
Да! Все наши объекты были убраны garbage collected. Итак, ответ: нет, abortable не создает утечку памяти.
Вот демо, которое я создал, что вы могли попробовать это сами.
Как передать данные в другой тег по id при onclick
уникальным идентификаторомid<div id=»demo»></div>
Далее нам понадобится скрипт, который по нажатию, отправит какие-то данные в этот див:
<button onclick=»getElementById(‘demo’).innerHTML = Date()»>Сколько времени!?</button>
Сколько времени!?тегу
Как вызвать функцию по клику, как мы уже раньше говорили, что click можно вызвать
1). В первом случае меняем слово alert на название функции, а в скобках идущих после alert убираем содержимое…
В функции прописываем что-то…
<script> function my_super_foo(){alert(«Вызов функции в теге… по клику»); }</script>
<button onclick=»my_super_foo()»>Вызов функции в теге… по клику</button>
Результат вызова функции из тега
Вызов функции в теге… по клику2). Второй способ… идем во встрой способ… там даже и переделывать ничего не нужно… заменяем только само действие в внутри функции priner_id .innerHTML =»НОВЫЙ ТЕКСТ»; — готовый способ вызова функции по клику…
3). Третий способ аналогичен второму… копируем все, что описано в третье пункте, заменяем внутри функции на ваше действие…
В качестве примера рекомендую — страницу с кнопками — все события производится именно кнопками, на которых повешено событие onclick.
1). Как повесить на одну кнопку сразу две функции!? Или три!? Или четыре… так можно продолжать до бесконечности:
Если говорить о двух событиях на onclick, то во всех , кроме первого(в теге) — этот вопрос кажется немного странным! Почему!? Просто во внутрь функции ставишь не одно событие, а столько сколько захочешь!
Если говорить об onclick два события в теге, то внутри onclick прописываем стандартные действия как в js
<button onclick=»getElementById(‘demo’).innerHTML = Date();alert(‘Щелчок мыши!’)»>Два события.</button>
<kod id=»demo»></kod>
Два события.
2). Если мы возьмем и сделаем функцию, обрабатывающую нажатие на кнопку…, то там тоже нет никакой проблемы повесить на кнопку два, три, пять, 100 функций!
<button id=»new_id»>Две функции onclick на одну кнопку js</button>
<script>
new_id .addEventListener(«click», myFoo);
function myFoo()
{
alert(«одна функция onclick на одну кнопку js»);
alert(«Две функции onclick на одну кнопку js»);
alert(«Три функции onclick на одну кнопку js»);
}
</script>
Две функции onclick на одну кнопку js
Если , например нужно изменить где-то цвет, то можно посмотреть пример с помощью onclick
Код:
<button onclick=»getElementById(‘rezult’).setAttribute(‘style’, ‘color: red;’);»>Изменить цвет</button>
<div id=»rezult»>Здесь текст, который будет менять при нажатии</div>
Результат:
Изменить цвет
Здесь текст, который будет менять при нажатии
4.
Например, когда надо много событий навесить в onclick, то можно навесить на onclick только функцию, а в функции написать функцию, которая и будет выполнять все, что нужно при нажатии на кнопку…
Далее изменение текста и одновременное изменение цвета.
Код:
далее скрипт, либо можно выделить в отдельный файл скрипта…
<script> function foo() {
document.getElementById(«rezult_1»).innerHTML = «привет»;
document.getElementById(«rezult_1»).setAttribute(«style», «color: red» );
}
</script>
Результат:
Нажми здесь
Здесь текст, который будет менять при нажатии
event.defaultPrevented
Свойство установлено в , если действие по умолчанию было предотвращено, и , если нет.
Рассмотрим практическое применение этого свойства для улучшения архитектуры.
Помните, в главе Всплытие и погружение мы говорили о и упоминали, что останавливать «всплытие» – плохо?
Иногда вместо этого мы можем использовать , чтобы просигналить другим обработчикам, что событие обработано.
Давайте посмотрим практический пример.
По умолчанию браузер при событии (клик правой кнопкой мыши) показывает контекстное меню со стандартными опциями. Мы можем отменить событие по умолчанию и показать своё меню, как здесь:
Теперь в дополнение к этому контекстному меню реализуем контекстное меню для всего документа.
При правом клике должно показываться ближайшее контекстное меню.
Проблема заключается в том, что когда мы кликаем по элементу , то мы получаем два меню: контекстное меню для кнопки и (событие всплывает вверх) контекстное меню для документа.
Как это поправить? Одно из решений – это подумать: «Когда мы обрабатываем правый клик в обработчике на кнопке, остановим всплытие», и вызвать :
Теперь контекстное меню для кнопки работает как задумано. Но цена слишком высока. Мы навсегда запретили доступ к информации о правых кликах для любого внешнего кода, включая счётчики, которые могли бы собирать статистику, и т.п. Это слегка неразумно.
Альтернативным решением было бы проверить в обработчике , было ли отменено действие по умолчанию? Если да, тогда событие было обработано, и нам не нужно на него реагировать.
Сейчас всё работает правильно. Если у нас есть вложенные элементы и каждый из них имеет контекстное меню, то код также будет работать. Просто убедитесь, что проверяете в каждом обработчике .
event.stopPropagation() и event.preventDefault()
Как мы можем видеть, и (также известный как ) – это две разные функции. Они никак не связаны друг с другом.
Архитектура вложенных контекстных меню
Есть также несколько альтернативных путей, чтобы реализовать вложенные контекстные меню. Одним из них является единый глобальный объект с обработчиком и методами, позволяющими хранить в нём другие обработчики.
Объект будет перехватывать любой клик правой кнопкой мыши, просматривать сохранённые обработчики и запускать соответствующий.
Но при этом каждый фрагмент кода, которому требуется контекстное меню, должен знать об этом объекте и использовать его вместо собственного обработчика .
В чем проблема?
Давайте сделаем более «экстремальную» версию:
async function abortable(signal, promise) { if (signal.aborted) throw new DOMException('AbortError', 'AbortError'); // Выделим 100 Мб памяти const lotsOfMemory = new Uint8Array(1000 * 1000 * 100); return Promise.race([ promise, new Promise((_, reject) => { signal.addEventListener('abort', () => { // выводим часть памяти console.log('async task aborted', lotsOfMemory); reject(new DOMException('AbortError', 'AbortError')); }); }), ]); }
В этой версии я выделяю 100 Мб памяти в массиве Uint8Array. На этот объект ссылается слушатель ‘abort‘, поэтому он должен оставаться в памяти. Но как долго он будет оставаться в памяти?
‘abort‘ может никогда не сработать, но также ‘abort‘ может срабатывать несколько раз.
Если вы вызываете controller.abort() несколько раз, браузер вызовет событие ‘abort‘ только один раз. Но это обычное событие DOM, так что ничто не мешает кому-то делать что-то странное, типа этого:
signal.dispatchEvent(new Event('abort')); signal.dispatchEvent(new Event('abort')); signal.dispatchEvent(new Event('abort'));
Подписка на событие через код JavaScript с помощью свойства
Этот способ подписки на событие осуществляется через код JavaScript с помощью задания элементу свойства . Основной принцип данного метода заключается в следующем:
- Найти элемент (объект) в DOM-дереве, на событие которого Вы хотите подписаться.
- Добавить найденному объекту свойство, которое должно иметь следующий вид:
, где — это имя определённого события.После этого необходимо данному свойству присвоить обработчик, т.е. безымянную или некоторую указанную функцию, которая будет выполняться при наступлении этого события.
Например, подписаться на событие элемента, имеющего . При наступлении этого события () выполнить его обработку с помощью безымянной функции:
<button id="myBtn" value="Демонстрация события click"> <script> //в качестве обработчика события будем использовать безымянную функцию: document.getElementById("myID").onclick = function { alert("Событие click"); } </script>
Например, добавить к кнопке, имеющей событие , при наступлении которого выполняется указанная функция:
//Найти элемент на событие, которого Вы хотите подписаться var myButton = document.getElementById("myButton"); //добавить к объекту свойство, имеющее имя on //при наступлении события click выполняется функция myFunction myButton.onclick = myFunction; //функция myFunction function myFunction() { //код функции //... }
Если событие задаётся через атрибут, то браузер, читая код HTML, создаёт соответствующее свойство автоматически. Т.е. браузер работает с событиями только с помощью соответствующих свойств объекта (элемента).
Если Вы подпишитесь на событие различными способами, т.е. через атрибут и с помощью свойства, то браузер в этом случае будет использовать только вариант реализации события, выполненный с помощью свойства.
Подписываться на события лучше только с помощью соответствующих свойств объекта (элемента), использовать атрибуты для этих целей не рекомендуется.
Приём проектирования «поведение»
Делегирование событий можно использовать для добавления элементам «поведения» (behavior), декларативно задавая хитрые обработчики установкой специальных HTML-атрибутов и классов.
Приём проектирования «поведение» состоит из двух частей:
- Элементу ставится пользовательский атрибут, описывающий его поведение.
- При помощи делегирования ставится обработчик на документ, который ловит все клики (или другие события) и, если элемент имеет нужный атрибут, производит соответствующее действие.
Например, здесь HTML-атрибут добавляет кнопкам поведение: «увеличить значение при клике»:
Если нажать на кнопку – значение увеличится. Конечно, нам важны не счётчики, а общий подход, который здесь продемонстрирован.
Элементов с атрибутом может быть сколько угодно. Новые могут добавляться в HTML-код в любой момент. При помощи делегирования мы фактически добавили новый «псевдостандартный» атрибут в HTML, который добавляет элементу новую возможность («поведение»).
Всегда используйте метод для обработчиков на уровне документа
Когда мы устанавливаем обработчик событий на объект , мы всегда должны использовать метод , а не , т.к. в случае последнего могут возникать конфликты: новые обработчики будут перезаписывать уже существующие.
Для реального проекта совершенно нормально иметь много обработчиков на элементе , установленных из разных частей кода.
Ещё один пример поведения. Сделаем так, что при клике на элемент с атрибутом будет скрываться/показываться элемент с заданным :
Ещё раз подчеркнём, что мы сделали. Теперь для того, чтобы добавить скрытие-раскрытие любому элементу, даже не надо знать JavaScript, можно просто написать атрибут .
Это бывает очень удобно – не нужно писать JavaScript-код для каждого элемента, который должен так себя вести. Просто используем поведение. Обработчики на уровне документа сделают это возможным для элемента в любом месте страницы.
Мы можем комбинировать несколько вариантов поведения на одном элементе.
Шаблон «поведение» может служить альтернативой для фрагментов JS-кода в вёрстке.
Обработчики событий
Последнее обновление: 1.11.2015
Встроенные обработчики
В прошлой теме были рассмотрены встроенные обработчики (inline event handler), которые определяются в коде элемента с
помощью атрибутов:
<div id="rect" onclick="handler(event)"></div>
Хотя этот подход прекрасно работает, но он имеет кучу недостатков:
-
Код html смешивается с кодом JavaScript, в связи с чем становится труднее разрабатывать, отлаживать и поддерживать приложение
-
Обработчики событий можно задать только для уже созданных на веб-странице элементов. Динамически создаваемые элементы в этом случае
лишаются возможности обработки событий -
К элементу для одного события может быть прикреплен только один обработчик
-
Нельзя удалить обработчик без изменения кода
Свойства обработчиков событий
Проблемы, которые возникают при использовании встроенных обработчиков, были призваны решить свойства обработчиков. Подобно тому, как у html-элементов
есть атрибуты для обработчиков, так и в коде javascript у элементов DOM мы можем получить свойства обработчиков, которые соответствуют атрибутам:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style> #rect{ width:50px; height:50px; background-color:blue; } </style> </head> <body> <div id="rect"></div> <script> function handler(e){ alert(e.type); } document.getElementById("rect").onclick = handler; </script> </body> </html>
В итоге нам достаточно взять свойство и присвоить ему функцию, используемую в качестве обработчика. За счет
этого код html отделяется от кода javascript.
Стоит также отметить, что в обработчик события браузер автоматически передает объект Event, хранящий всю информацию о событии. Поэтому
также мы можем получить этот объект в функции обработчика в качестве параметра.
Слушатели событий
Несмотря на то, что свойства обработчиков решают ряд проблем, которые связаны с использованием атрибутов, в то же время это также
не оптимальный подход. Еще один способ установки обработчиков событий представляет использование слушателей.
Для работы со слушателями событий в JavaScript есть объект EventTarget, который определяет методы
addEventListener() (для добавления слушателя) и removeEventListener()
для удаления слушателя. И поскольку html-элементы DOM тоже являются объектами EventTarget, то они также имеют эти методы. Фактически слушатели представляют те же функции обработчиков.
Метод принимает два параметра: название события без префикса on и функцию обработчика этого события. Например:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style> #rect{ width:50px; height:50px; background-color:blue; } </style> </head> <body> <div id="rect"></div> <script> var rect = document.getElementById("rect"); rect.addEventListener("click", function (e) { alert(e.type); }); </script> </body> </html>
То есть в данном случае опять же обрабатывается событие click. И также можно было бы в качестве второго параметра название функции:
function handler(e){ alert(e.type); } var rect = document.getElementById("rect"); rect.addEventListener("click", handler);
Удаление слушателя аналогично добавлению:
rect.removeEventListener("click", handler);
Преимуществом использования слушателей является и то, что мы можем установить для одного события несколько функций:
var clicks = 0; function handlerOne(e){ alert(e.type); } function handlerTwo(e){ clicks++; var newNode = document.createElement("p"); newNode.textContent = "произошло нажатие " + clicks; document.body.appendChild(newNode); } var rect = document.getElementById("rect"); // прикрепляем первый обработчик rect.addEventListener("click", handlerOne); // прикрепляем второй обработчик rect.addEventListener("click", handlerTwo);
НазадВперед
More Examples
Example
You can also refer to an external «named» function.
This example demonstrates how to execute a function when a user clicks on a <button> element:
document.getElementById(«myBtn»).addEventListener(«click», myFunction);function myFunction() { document.getElementById(«demo»).innerHTML = «Hello World»;
}
Example
You can add many events to the same element, without overwriting existing
events.
This example demonstrates how to add two click events on the same <button> element:
document.getElementById(«myBtn»).addEventListener(«click», myFunction);document.getElementById(«myBtn»).addEventListener(«click», someOtherFunction);
Example
You can add events of different types to the same element.
This example demonstrates how to add many events on the same <button> element:
document.getElementById(«myBtn»).addEventListener(«mouseover», myFunction);document.getElementById(«myBtn»).addEventListener(«click», someOtherFunction);
document.getElementById(«myBtn»).addEventListener(«mouseout», someOtherFunction);
Example
When passing parameter values, use an «anonymous function» that calls the
specified function with the parameters:
document.getElementById(«myBtn»).addEventListener(«click», function() { myFunction(p1, p2);});
Example
Change the background color of a <button> element:
document.getElementById(«myBtn»).addEventListener(«click», function() { this.style.backgroundColor = «red»;});
Example
Using the optional useCapture parameter to demonstrate the
difference between bubbling and capturing:
document.getElementById(«myDiv»).addEventListener(«click», myFunction, true);
Example
Using the removeEventListener() method to remove an event handler that has
been attached with the addEventListener() method:
// Attach an event handler to <div>document.getElementById(«myDIV»).addEventListener(«mousemove», myFunction);// Remove the event handler from <div>document.getElementById(«myDIV»).removeEventListener(«mousemove», myFunction);
Example
For browsers that don’t support the addEventListener() method, you can use
the attachEvent() method.
This example demonstrates a cross-browser solution:
var x = document.getElementById(«myBtn»);if (x.addEventListener) { // For all major browsers, except IE 8 and earlier
x.addEventListener(«click», myFunction);} else if (x.attachEvent) { // For IE 8 and earlier versions
x.attachEvent(«onclick», myFunction);}
addEventListener
Фундаментальный недостаток описанных выше способов назначения обработчика –- невозможность повесить несколько обработчиков на одно событие.
Например, одна часть кода хочет при клике на кнопку делать её подсвеченной, а другая – выдавать сообщение.
Мы хотим назначить два обработчика для этого. Но новое DOM-свойство перезапишет предыдущее:
Разработчики стандартов достаточно давно это поняли и предложили альтернативный способ назначения обработчиков при помощи специальных методов и . Они свободны от указанного недостатка.
Синтаксис добавления обработчика:
- Имя события, например .
- Ссылка на функцию-обработчик.
- Дополнительный объект со свойствами:
- : если , тогда обработчик будет автоматически удалён после выполнения.
- : фаза, на которой должен сработать обработчик, подробнее об этом будет рассказано в главе Всплытие и погружение. Так исторически сложилось, что может быть , это то же самое, что .
- : если , то указывает, что обработчик никогда не вызовет , подробнее об этом будет рассказано в главе Действия браузера по умолчанию.
Для удаления обработчика следует использовать :
Удаление требует именно ту же функцию
Для удаления нужно передать именно ту функцию-обработчик которая была назначена.
Вот так не сработает:
Обработчик не будет удалён, т.к
в передана не та же функция, а другая, с одинаковым кодом, но это не важно
Вот так правильно:
Обратим внимание – если функцию обработчик не сохранить где-либо, мы не сможем её удалить. Нет метода, который позволяет получить из элемента обработчики событий, назначенные через
Метод позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
Как видно из примера выше, можно одновременно назначать обработчики и через DOM-свойство и через . Однако, во избежание путаницы, рекомендуется выбрать один способ.
Обработчики некоторых событий можно назначать только через
Существуют события, которые нельзя назначить через DOM-свойство, но можно через .
Например, таково событие , которое срабатывает, когда завершена загрузка и построение DOM документа.
Так что более универсален. Хотя заметим, что таких событий меньшинство, это скорее исключение, чем правило.
Итого
Действий браузера по умолчанию достаточно много:
- – начинает выделять текст (если двигать мышкой).
- на – ставит или убирает галочку в .
- – при нажатии на или при нажатии клавиши Enter в форме данные отправляются на сервер.
- – при нажатии клавиши в поле ввода появляется символ.
- – при правом клике показывается контекстное меню браузера.
- …и многие другие…
Все эти действия можно отменить, если мы хотим обработать событие исключительно при помощи JavaScript.
Чтобы отменить действие браузера по умолчанию, используйте или . Второй метод работает, только если обработчик назначен через .
Опция для сообщает браузеру, что действие по умолчанию не будет отменено. Это очень полезно для некоторых событий на мобильных устройствах, таких как и , чтобы сообщить браузеру, что он не должен ожидать выполнения всех обработчиков, а ему следует сразу приступать к выполнению действия по умолчанию, например, к прокрутке.
Если событие по умолчанию отменено, то значение становится , иначе .
Сохраняйте семантику, не злоупотребляйте
Технически, отменяя действия браузера по умолчанию и добавляя JavaScript, мы можем настроить поведение любого элемента. Например, мы можем заставить ссылку работать как кнопку, а кнопку вести себя как ссылка (перенаправлять на другой URL).
Но нам следует сохранять семантическое значение HTML элементов. Например, не кнопки, а тег должен применяться для переходов по ссылкам.
Помимо того, что это «хорошо», это делает ваш HTML лучше с точки зрения доступности для людей с ограниченными возможностями и с особых устройств.
Также, если мы рассматриваем пример с тегом , то обратите внимание: браузер предоставляет возможность открывать ссылки в новом окне (кликая правой кнопкой мыши или используя другие возможности). И пользователям это нравится
Но если мы заменим ссылку кнопкой и стилизуем её как ссылку, используя CSS, то специфичные функции браузера для тега всё равно работать не будут.
Итого
Чтобы сгенерировать событие из кода, вначале надо создать объект события.
Базовый конструктор принимает обязательное имя события и – объект с двумя свойствами:
- чтобы событие всплывало.
- если мы хотим, чтобы работал.
Особые конструкторы встроенных событий , и другие принимают специфичные для каждого конкретного типа событий свойства. Например, для событий мыши.
Для пользовательских событий стоит применять конструктор . У него есть дополнительная опция , с помощью которой можно передавать информацию в объекте события. После чего все обработчики смогут получить к ней доступ через .
Несмотря на техническую возможность генерировать встроенные браузерные события типа или , пользоваться ей стоит с большой осторожностью. Весьма часто, когда разработчик хочет сгенерировать встроенное событие – это вызвано «кривой» архитектурой кода
Весьма часто, когда разработчик хочет сгенерировать встроенное событие – это вызвано «кривой» архитектурой кода.
Как правило, генерация встроенных событий полезна в следующих случаях:
- Либо как явный и грубый хак, чтобы заставить работать сторонние библиотеки, в которых не предусмотрены другие средства взаимодействия.
- Либо для автоматического тестирования, чтобы скриптом «нажать на кнопку» и посмотреть, произошло ли нужное действие.
Пользовательские события со своими именами часто создают для улучшения архитектуры, чтобы сообщить о том, что происходит внутри наших меню, слайдеров, каруселей и т.д.