что такое onclick javascript

Введение в браузерные события

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

Вот список самых часто используемых DOM-событий, пока просто для ознакомления:

События мыши:

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

Клавиатурные события:

События документа:

CSS events:

Существует множество других событий. Мы подробно разберём их в последующих главах.

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

Событию можно назначить обработчик, то есть функцию, которая сработает, как только событие произошло.

Именно благодаря обработчикам JavaScript-код может реагировать на действия пользователя.

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

Использование атрибута HTML

Атрибут HTML-тега – не самое удобное место для написания большого количества кода, поэтому лучше создать отдельную JavaScript-функцию и вызвать её там.

Следующий пример по клику запускает функцию countRabbits() :

Использование свойства DOM-объекта

К примеру, elem.onclick :

Если обработчик задан через атрибут, то браузер читает HTML-разметку, создаёт новую функцию из содержимого атрибута и записывает в свойство.

Этот способ, по сути, аналогичен предыдущему.

Обработчик всегда хранится в свойстве DOM-объекта, а атрибут – лишь один из способов его инициализации.

Эти два примера кода работают одинаково:

В примере ниже назначение через JavaScript перезапишет обработчик из атрибута:

Кстати, обработчиком можно назначить и уже существующую функцию:

Доступ к элементу через this

Внутри обработчика события this ссылается на текущий элемент, то есть на тот, на котором, как говорят, «висит» (т.е. назначен) обработчик.

В коде ниже button выводит своё содержимое, используя this.innerHTML :

Частые ошибки

Если вы только начинаете работать с событиями, обратите внимание на следующие моменты.

…А вот в разметке, в отличие от свойства, скобки нужны:

Так что разметка генерирует такое свойство:

Используйте именно функции, а не строки.

Назначение обработчика строкой elem.onclick = «alert(1)» также сработает. Это сделано из соображений совместимости, но делать так не рекомендуется.

Не используйте setAttribute для обработчиков.

Такой вызов работать не будет:

Регистр DOM-свойства имеет значение.

addEventListener

Например, одна часть кода хочет при клике на кнопку делать её подсвеченной, а другая – выдавать сообщение.

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

Синтаксис добавления обработчика:

Для удаления обработчика следует использовать removeEventListener :

Для удаления нужно передать именно ту функцию-обработчик которая была назначена.

Вот так не сработает:

Обработчик не будет удалён, т.к. в removeEventListener передана не та же функция, а другая, с одинаковым кодом, но это не важно.

Метод addEventListener позволяет добавлять несколько обработчиков на одно событие одного элемента, например:

Так что addEventListener более универсален. Хотя заметим, что таких событий меньшинство, это скорее исключение, чем правило.

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

Чтобы хорошо обработать событие, могут понадобиться детали того, что произошло. Не просто «клик» или «нажатие клавиши», а также – какие координаты указателя мыши, какая клавиша нажата и так далее.

Когда происходит событие, браузер создаёт объект события, записывает в него детали и передаёт его в качестве аргумента функции-обработчику.

Пример ниже демонстрирует получение координат мыши из объекта события:

Некоторые свойства объекта event :

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

Объект-обработчик: handleEvent

Мы также можем использовать класс для этого:

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

Теперь обработка событий разделена по методам, что упрощает поддержку кода.

Итого

Есть три способа назначения обработчиков событий:

HTML-атрибуты используются редко потому, что JavaScript в HTML-теге выглядит немного странно. К тому же много кода там не напишешь.

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

Не важно, как вы назначаете обработчик – он получает объект события первым аргументом. Этот объект содержит подробности о том, что произошло.

Мы изучим больше о событиях и их типах в следующих главах.

Источник

Выразительный JavaScript: Обработка событий

Содержание

Вы властны над своим разумом, но не над внешними событиями. Когда вы поймёте это, вы обретёте силу.
Марк Аврелий, «Медитации».

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

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

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

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

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

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

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

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

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

Пример назначает обработчик на DOM-узел кнопки. Нажатия на кнопку запускают обработчик, а нажатия на другие части документа – не запускают.

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

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

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

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

В примерах мы проигнорировали тот факт, что функциям-обработчикам передаётся аргумент – объект события. В нём хранится дополнительная информация о событии. К примеру, если надо узнать, какая кнопка мыши была нажата, мы можем обратиться к свойству which этого объекта.

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

Распространение (propagation)

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

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

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

Следующий пример регистрирует обработчики «mousedown» как на кнопке, так и на окружающем параграфе. При щелчке правой кнопкой обработчик кнопки вызывает stopPropagation, который предотвращает запуск обработчика параграфа. При клике другой кнопкой запускаются оба обработчика.

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

Также возможно использовать свойство target, чтобы распространить обработку конкретного типа события. К примеру, если у вас есть узел, содержащий длинный список кнопок, было бы удобнее зарегистрировать один обработчик событий для узла, и в нём выяснять, нажали ли на кнопку – вместо того, чтобы регистрировать обработчики каждой кнопки по отдельности.

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

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

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

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

Не делайте так – если у вас нет очень серьёзной причины! Пользователям вашей страницы будет очень неудобно, когда они столкнутся с неожиданными результатами своих действий. В зависимости от браузера, некоторые события перехватить нельзя. В Chrome нельзя обрабатывать горячие клавиши закрытия текущей закладки (Ctrl-W or Command-W).

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

При нажатии кнопки на клавиатуре браузер запускает событие «keydown». Когда она отпускается, происходит событие «keyup».

Несмотря на название, «keydown» происходит не только тогда, когда на кнопку нажимают. Если нажать и удерживать кнопку, событие будет происходить каждый раз по приходу повторного сигнала от клавиши (key repeat). Если вам, к примеру, надо увеличивать ускорение игрового персонажа, когда нажата кнопка со стрелкой, и уменьшать его, когда она отпущена – надо быть осторожным, чтобы не увеличивать ускорение каждый раз при повторе сигнала от кнопки, иначе скорость возрастёт очень сильно.

Читайте также:  что делать при свище

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

Для цифр и букв код будет кодом символа Unicode, связанного с прописным символом, изображённым на кнопке. Метод строки charCodeAt даёт нам этот код.

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

Кнопки-модификаторы типа Shift, Ctrl, Alt, и Meta (Command на Mac) создают события, как и нормальные кнопки. Но при разборе комбинаций клавиш можно выяснить, были ли нажаты модификаторы, через свойства shiftKey, ctrlKey, altKey, и metaKey событий клавиатуры и мыши.

События «keydown» и «keyup» дают информацию о физическом нажатии кнопок. А если вам нужно узнать, какой текст вводит пользователь? Создавать его из нажатий кнопок – неудобно. Для этого существует событие «keypress», происходящее сразу после «keydown» (и повторяющееся вместе с «keydown», если клавишу продолжают удерживать), но только для тех кнопок, которые выдают символы. Свойство объекта события charCode содержит код, который можно интерпретировать как код Unicode. Мы можем использовать функцию String.fromCharCode для превращения кода в строку из одного символа.

Источником события нажатия клавиши узел становится в зависимости от того, где находился фокус ввода во время нажатия. Обычные узлы не могут получить фокус ввода (если только вы не задали им атрибут tabindex), а такие, как ссылки, кнопки и поля форм – могут. Мы вернёся к полям ввода в главе 18. Когда ни у чего нет фокуса, в качестве целевого узла событий работает «document.body».

Щелчки мышью

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

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

Если два щелчка происходят достаточно быстро друг за другом, запускается событие «dblclick» (double-click), сразу после второго запуска “click”.

Для получения точных координат места, где произошло событие мыши, обратитесь к свойствам pageX и pageY – они содержат координаты в пикселях относительно верхнего левого угла документа.

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

Свойства clientX и clientY похожи на pageX и pageY, но дают координаты относительно части документа, которая видна сейчас (если документ был прокручен). Это удобно при сравнении координат мыши с координатами, которые возвращает getBoundingClientRect – его возврат тоже связан с относительными координатами видимой части документа.

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

Каждый раз при сдвиге курсора мыши запускается событие «mousemove». Его можно использовать для отслеживания позиции мыши. Обычно это нужно при создании некоей функциональности, связанной с перетаскиванием объектов мышью.

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

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

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

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

Для обхода проблемы можно использовать свойство relatedTarget объекта событий. Он сообщает, на каком узле была до этого мышь при возникновении события «mouseover», и на какой элемент она переходит при событии «mouseout». Нам надо менять эффект, только когда relatedTarget находится вне нашего целевого узла. Только в этом случае событие на самом деле представляет собой переход на наш узел (или уход с узла).

Функция isInside перебирает всех предков узла, пока не доходит до верха документа (и тогда узел равен null), или же не находит заданного ей родителя.

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

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

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

В примере в правом верхнем углу документа создаётся индикатор процесса, который заполняется по мере прокрутки элемента вниз.

Позиция элемента fixed означает почти то же, что absolute, но ещё и предотвращает прокручивание элемента вместе с остальным документом. Смысл в том, чтобы оставить наш индикатор в углу. Внутри него находится другой элемент, который изменяет размер, отражая текущий прогресс. Мы используем проценты вместо px для задания ширины, чтобы размер элемента изменялся относительно размера всего индикатора.

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

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

События, связанные с фокусом

При получении элементом фокуса браузер запускает событие “focus”. Когда он теряет фокус, запускается событие “blur”.

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

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

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

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

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

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

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

Устранение помех (debouncing)

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

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

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

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

Можно использовать немного другой подход, если нам надо разделить ответы минимальными промежутками времени, но при этом запускать их в то время, когда происходят события, а не после. К примеру, надо реагировать на события «mousemove», показывая текущие координаты мыши, но только каждые 250 миллисекунд.

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

У событий есть определяющий их тип («keydown», «focus», и так далее). Большинство событий вызываются конкретными узлами DOM, и затем распространяются на их предков, позволяя связанными с ними обработчикам обрабатывать их.

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

Нажатия на клавиши запускают события «keydown», «keypress» и «keyup». Нажатия на кнопки мыши запускают события «mousedown», «mouseup» и «click». Движения мыши запускают события «mousemove», и возможно «mouseenter» и «mouseout».

Прокрутку можно обнаружить через событие “scroll”, а изменения фокуса через события «focus» и «blur». Когда заканчивается загрузка документа, у объекта window запускается событие “load”.

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

Упражнения

Цензура клавиатуры

В промежутке с 1928 по 2013 год турецкие законы запрещали использование букв Q, W и X в официальных документах. Это являлось частью общей инициативы подавления курдской культуры – эти буквы используются в языке курдов, но не у турков.

Читайте также:  что делать при гнойном отите

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

След мыши

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

Я хочу, что бы вы в упражнении сделали такой след. Используйте

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

К этому можно подойти многими способами. Можно сделать очень простое или очень сложное решение, как угодно. Простое – хранить фиксированное количество элементов и проходить по ним в цикле, двигая каждый следующий на текущее место курсора, каждый раз когда случается событие «mousemove».

Закладки

Интерфейс закладок встречается часто. Он позволяет вам выбирать панель интерфейса, выбирая одну из нескольких торчащих закладок над элементом.

В упражнении вам нужно сделать простой интерфейс закладок. Напишите функцию asTabs, которая принимает узел DOM, и создаёт закладочный интерфейс, показывая дочерние элементы этого узла. Ей нужно вставлять список элементов вверху узла, по одному на каждый дочерний элемент, содержащих текст, полученный из атрибута data-tabname. Все, кроме одного из дочерних элементов, должны быть спрятаны (при помощи значения none свойства стиля display), а текущий видимый узел можно выбирать нажатием кнопки.

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

Источник

Форум

Справочник

Введение в события

Практически все JavaScript-приложения выполняют те или иные действия, откликаясь на различные события.

Есть множество самых различных событий.

Именно DOM-события связывают действия, происходящие в документе, с кодом JavaScript, тем самым обеспечивая динамический веб-интерфейс.

Назначение обработчиков

Существует несколько способов назначать обработчик на конкретное событие элемента. Все они представлены ниже.

Через атрибут HTML-тега

Этот код в действии:

Можно назначить и функцию.

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

Когда использовать

Впрочем, сколько-нибудь сложные обработчики в HTML никто не пишет. Вместо этого лучше устанавливать обработчики из JavaScript способами, которые будут представлены ниже.

Через свойство объекта

Вот пример установки обработчика события click на элемент с id=»myElement» :

Этот код в действии:

Стоит сразу обратить внимание на две детали:

В этом смысле эти два кода работают одинаково:

Иначе узел просто не будет найден.

Конечно, можно и не создавать анонимную функцию, а использовать любую уже готовую:

Когда использовать

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

Специальные методы

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

Существует два основных интерфейса для установки событий.

Решение Microsoft

Методы, предложенные Microsoft, работают только в браузерах Internet Explorer и Opera(она поддерживает метод Microsoft для лучшей совместимости).

Так было бы неправильно:

Как уже говорилось ранее, вы можете установить несколько обработчиков на одно событие одного элемента:

Этот код в действии (будет работать только в Internet Explorer/Opera):

Установка по стандарту W3C

Решение W3C работает во всех современных браузерах, кроме Internet Explorer.

Обратите внимание, что имя события указывается без префикса «on».

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

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

Объект «событие» ( event )

Объект событие всегда передается обработчику и содержит массу полезной информации о том где и какое событие произошло.

Способов передачи этого объекта обработчику существует ровно два, и они зависят от способа его установки и от браузера.

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

При вызове обработчика объект события event будет передан ему первым аргументом.

Можно назначить и вот так:

Internet Explorer

То есть, все должно работать так:

Обратите внимание, что доступ к event при назначении обработчика в HTML (см. пример выше) по-прежнему будет работать. Такой вот надежный и простой кросс-браузерный доступ к объекту события.

Кросс-браузерное решение

Можно кросс-браузерно получить объект события, использовав такой приём:

Получение события при inline-записи

Этот код в действии:

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

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

Например, для события по клику мыши ( onclick ), свойство event.target (в IE event.srcElement ) содержит DOM-элемент, на котором этот клик произошел.

Более подробно это описано в следующей статье Свойства объекта событие.

Порядок срабатывания событий

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

Рассмотрим ситуацию, когда у вас есть три элемента «вложенных» друг в друга.

Всего существует 2 модели поведения, они не имеют преимуществ между собой, но используют принципиально разные подходы. Стандарт W3C объединяет две модели в одну универсальную.

Всплывающие события (Bubbling)


В этой модели сначала будет выполнен обработчик на элементе 3, затем на элементе 2, и последним будет выполнен обработчик на элементе 1.

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

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

Остановка всплытия

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

Можно уложить блок if/else в одну строчку:

Перехват событий (Capturing)

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

Такой порядок был предложен Netscape и никогда не поддерживался в Internet Explorer, поэтому в IE вы не сможете увидеть этот пример в действии.

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

Порядок обработки в стандарте W3C

Решение от W3C объединяет обе модели: перехват и всплытие в одну универсальную.

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

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

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

При установке обработчиков классическими методами (через свойство элемента или атрибут html тега) события всегда будут срабатывать на фазе всплытия.

Дальше мы вообще не будем рассматривать фазу захвата, так как в реальной жизни используется только всплытие.

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

Браузер имеет своё собственное поведение по умолчанию для различных событий.

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

Вместо if/else можно записать одну строчку:

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

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

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

Смысл return false из обработчика

Возвращение return false из обработчика события предотвращает действие браузера по умолчанию, но не останавливает всплытие. В этом смысле следующие два кода эквивалентны:

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

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

Поэтому тем более один обработчик никак не может влиять на другие того же типа на том же элементе.

Резюме

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

Спасибо за статью.
Эта часть наверное самая важная для понимания javascript

Полностью согласен, давно ждал подобной статьи. Огромное спасибо.

Статья супер, адрес в избранное

А вы знаете что когда вы нажимаете посмотреть! на одном из скриптов происходит xss атака??у меня просто защита стоит(noscript) всем посоветую

А вы знаете что когда вы нажимаете посмотреть! на одном из скриптов происходит xss атака??у меня просто защита стоит(noscript) всем посоветую

А если в FireFox тег div не реагирует на onkeyup (press и т.п.), можно ли ему прописать обработчик на событие onkeyup?

Вот еще один метод установки нескольких обработчиков событий, о котором не было сказано в статье:

И вызов данного метода:

А каким образом в данном подходе можно удалить один из вложенных обработчиков?

т.е. alert(‘1’); произойдет лишь один раз, в момент первого клика, после оно никогда не повториться (сколько не кликай). Но при ситуации нескольких обработчиков на одно событие данный код начнёт разрастаться как снежный ком. И код может стать не универсальным.
Хотя, может кто из читателей сайта то придумает более симпатичное решение по удалению обработчика?

Непонятно как реализовать функционал detachEvent в таком подходе.

Ну если честно, то по-моему мнению, в хорошем коде вообще в событии стоит лишь вызов функции, реагирующих на событие и ни какой логики по обработке события! 🙂

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

Непонятно как реализовать функционал detachEvent в таком подходе.

Сам думал долго над этим, но кроме варианта показанного чуть выше ничего не нашел.

Читайте также:  что делать если мышка иногда не кликает


С уважением, Владимир Вашурин

Отличная статья! Спасибо.

Есть еще нюанс, связанный со стилями для элементов. Если есть абсолютное позиционирование.
Например:

Если в стилях поменять position: relative на position: absolute для элемента (чем выше по дереву DOM, тем хуже), то в IE(6/7) событие даже не будет генерироваться.
Например поменяем для wndMain, то события вообще не будут генериться для его внутренних элементов и его самого(хоть какой кнопкой кликать).

Выложили бы что ли где-нибудь этот код. Я пока не понимаю, что такого IE делает не так.

У меня лично абсолютно позиционированные элементы обрабатывались всегда без проблем. Может, чего-то не заметил?

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

P.S. Знаю что некропост, просто такие комменты могу ввести в заблуждение тех кто этот инструмент (javascript) осваивает.

Спасибо! Это лучший сайт по ява-скрипту! )))

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

Например, при таком назначении в момент прикрепления сразу произойдёт вызов alert(‘test’)

Если же вместо al(‘test’) использовать function()< al('test') >, то позже, как я понимаю, будет сложность снять этот обработчик?

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

При установке обработчиков методами attachEvent/detachEvent this внутри обработчика всегда указывает на объект window и совершенно бесполезен.

Поэтому при использовании этих методов в библиотеках и фреймворках добавляется дополнительная «обертка для обработчика», устанавливающая правильный this.

Приведите, пожалуйста, пример реализации «обертки» или посоветуйте где об этом можно почитать?

Спасибо за статью, за существование этого сайта.

тут наверно вместо fromElement надо toElement;

Спасибо полезная информация особенно про захват

Методы
myElement.attachEvent(«on» + событие, обработчик) и
myElement.detachEvent(«on» + событие, обработчик)
поддерживает не только IE, но и Opera

Универсальный кроссбраузерный способ обработки событий:

а функцию attachEvents записать вот так:

Да, ну и вызвать функцию main() в документе:

Объясните пожалуйста,
если у DOM элемента несколько свойств,
на которые повешены обработчики событий мыши,
то в какой последовательности они будут срабатывать?

Например при наведении на него и щелчке мыши:

и еще, чем отличается
onmouseover=»return fun1(arg1,arg2)»
от
onmouseover=»fun1(arg1,arg2)»

и куда собственно эти функции возвращают значение(если возвращают)?

Вот не пойму никак, а чего событие onclick() можно только Id присваивать, всему классу одно событие нельзя?
Например:
Вот так работает:

Кстати, селекторы библиотеки jQuery предоставляют возможность вешать обработчики на список.

Илья Кантор спасибо
Просто я уже третий день бьюсь вот над такой задачей:

И нужно присвоить одно событие onclick для всех ссылок. Не подскажете как это можно организовать?

Все решил задачу Спасибо за наводку, сам бы не догадался

никогда не задумывался и писал всегда «ev = ev || window.event».

но ведь «ev» не передается только если обработчик задан так

те если нигде не ошибся то «ev = ev || window.event» совсем и не нужно когда речь идет о EventListener

В Internet Explorer существует глобальный объект window.event, который хранит в себе информацию о последнем событии. А первого аргумента обработчика просто нет.

это не так. еще ие6 вполне корректно выполнял строчку

Ещё один способ напоследок:

Доброго всем дня.
Объясните пожалуйста для «чайников» как правильно кроссбраузерно остановить всплытие. на своих примерах получается только для IE сделать или только для FF.

в javascript документе

Судя по описанной вами проблеме, строчка:

Выполняется до того как сгенерится сам элемент. И следовательно выполнится:

И корректно (вернее не корректно, а так чтобы работало) обработает только Опера. В остальных браузерах скрипт упадет в ошибку. А вот если перенести скрипт в конец, то все будет работать.

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

На самом деле, capturing в IE использовать можно. Ограничений масса: метод расчитан только на события мыши, перехват теряется при потере окном фокуса, геморройная работа с preventDefault и масса других факторов.
Но если в целом, это вкупе с альтернативными макрософтовыми событиями (напр. activate и deactivate — такие же focus и blur, только бабблятся) может помочь сделать более-менее вменяемую эмуляцию capturing.

Иллюстрация метода setCapture:

Не пугайтесь: в IE6 этот код может вызвать блокировку окна.

Под диспетчером (dispatcher) подразумевается некий корневой элемент, собирающий события, и потом обрабатывающий их с учетом (e.srcElement||e.target), т.е., непосредственно практическое применение capturing.

вызов идет до создания кнопки?

Не могли бы подробнее?

«Кликни меня
При клике перехода не произойдет, а рамка вокруг ссылки появится.»

В IE8 сыпется иксепшн а в хроме нет рамки

Chrome не выделяет таким образом активные ссылки по стандарту.
Но можно сделать, добавив в css:

Аналогичным же способом данную пунктирную рамку можно убрать из firefox.
(P.S. Извиняюсь что не по коду, IE для меня пока не доступен.)

А в ie «перебрасывает» на верх страницы, наверное из-за #

Че то вообще ничего не понятно. Когда начнется объяснение нормальное.. Может кто нить подкинет что нибудь по проще..Для новичка?7

С какого момента непонятно? Что непонятно?

А можно вопрос, использую

в FF срабатывает нормально, а в IE событие не присваивается

все разобрался для IE написал

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

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

Но из статьи я так и не понял как ОСТАНОВИТЬ срабатывание события на «дочерних» к первому элементах, или если сказать по другому. как запретить наследование события «дочерними» элементами.

Очень надеюсь на помощь знающих людей.

Вписать обработчик того же события для всех потомков первого уровня, в котором добавить event.stopPropagation()(для Лисы)

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

А сделать страбатывание Алерта в любом случае, даже когда onmouseover происходит над областями даже перекрытое Div с и

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

Теперь перейдем собственно к вашему вопросу. Для удобства понимания сути проблемы лучше переформулировать задачу так: mouseover не должен вызываться в случае, если переход мыши осуществляется между потомками одного корневого элемента(или между потомками и самим корневым элементом). Теперь способ решения становится очевиден. В обработчике корневого элемента производится проверка target и relatedTarget(toElement и fromElement). Если оба объекта имеют общим предком корневой элемент, то обработчик ничего не делает.

отличная статья, но меня интересует вопрос: можно ли из javascript управлять перемещением курсоры мышки?

Помогите пожалуйста
есть такая функция(код из вашей статьи)

эта функция присваивается событию onScroll,в идеале нужно чтобы при прокручивании скрола,блок «my-message» оставался на месте,но при этом он перескакивает-как это можно исправить?

Для этого существует css правило position:fixed. А ИЕ6 бодро идет лесом

Ах, я вас так понимаю.

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

Устанавливать флажок в событии mouseover. Снимать флажок в событии mouseout. В «некоторой другой» функции проверять значение флажка.

Гость, спасибо! Да, старею я, похоже.

Что в этой шняге неправильно?

Вообще понять не могу. У меня в браузере кнопка не получила никакого события. Страница загрузилась и сразу «Не активный кнопкоо! ))». Почему так? При том такая ситуация только в FF 3.5. Opera, Chrome, Safari выполняют скрипт именно так, как я ожидаю. В IE не пробовал.

Это проблема FF, как оказалось Разобрался

После данной статьи, я возненавидел окончательно и основательно, бесповоротно и навсегда IE.

В IE6 «йа кнопкоо» работает нормально.

Добрый вечер!Не могу понять, почему не работает обычный пример как в статье(в JS совсем еще зеленый), то есть при клике на #pip эффекта никакого

и соответственно html

Причем Лис FireBug’ом ошибок не выдает

Привет
Не работает потому что
1. addEventListener в качестве первого параметра принимает имя события без префикса on h.addEventListener(«click», p, false);
2. li с обработчиком event.stopPropagation() перекрывает распространиение события к предку, попробуйте раскрасить список и все станет очевидно. Красная область кликабельная, так как клик происходит непосредственно на элементе ul, а вот синяя перекрытая stopPropagation и алерта нету.

Мне надо заблокировать все события на странице, в особенности onmousedown, onkeydown (onclick, ondblclick тоже). Чтобы и мышка, и клавиатура страницей на какое-то время не обрабатывалась. Как это сделать?

Такая штука не срабатывает (explorer игнорирую):

Мне надо заблокировать все события на странице, в особенности onmousedown, onkeydown (onclick, ondblclick тоже). Чтобы и мышка, и клавиатура страницей на какое-то время не обрабатывалась. Как это сделать?

Вариант 1. Вернуть false при возникновении события.
Пример:

но в таком случае вложенные элементы со своими событиями будут отрабатывать (из-за перехвата).
Вариант 2. Заблокировать клики мыши лежащим слоем overlay по верх всех элементов.
Пример:

и 2 варианта вместе тоже можно применять.

У меня такой вопрос: допустим написал свою очень нужную функцию (myfunction), приаттачил к HTML такой файлик:

Источник

Строительный портал