| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > JavaScript: для новичков > Все о событиях |
| Автор: Aliance 21.10.2004, 18:36 | ||||||||||
| Доброго всем времени суток! Часто вижу, что события описывают (регистрируют) не верно с точки зрения совсестимости двух документных объектных моделей: IE и W3C. Тут я опишу, как же это делать правельно. Для начала напишу что есть две группы событий: можно сказать основные и дополнительные. Первые поддерживаются обеими моделями, вторые написаны исключительно под IE. Давайте рассмотрим первую группу (более часто используемые):
Данные события работают под:
Данные события работают под:
Данные события работают под:
Этап второй или регистрирование события непосредственно к JS-скрипте:
Это позволяет выполнять дальнейшие действие, если событие ЕСТЬ в обоих разно-модельных браузерах. evt = (evt) ? evt : ((window.event) ? event : null ) Здесь объявляется глобальная переменная (я обозначяю ее обычно как evt), далее проверяется она, равна ли она DOM`овскому значению evt, если нет, то выполняеться следующий этап проверки: (window.event) ? event : null Если значение равно window.event - то это IE`вский event, все очень просто. Трудность и заключается в том, что в W3C evt (переменная) это evt, а в IE evt (переменная) - это event. Так же и с остальными свойствами. Вот они (IE - W3C): cancelBubble - stopPropagation (хотя это пожалуй является исключением, т.к. IE`вский способ поддерживаеться браузерами, основанными на Mozilla) fromElement - relatedTarget returnValue - preventDefault() scrElement - target toElement - relatedTarget x, y - layerX, layerY Таким образом, чтобы, скажем, узнать откуда пришел элемент, нужно писать так (используя совместимый синтаксис):
|
| Автор: Sardar 21.10.2004, 22:30 | ||||||||||||||||||
| Елки, все никак времени "родить" статью нет Соберем в топике хорошие идеи, а затем сделаем ман по событиям Коротко расскажу о типах регистрирования событий: inline(сразу в тег), традиционная модель(нетскейповская времен динозавров), навороченная модель(DOM, IE DOM). Inline обработчики событий это код вставляемый непосредственно в тег:
Браузер берет содержимое свойства onclick и создает по нему функцию, которую регистрирует как обработчика этого события. Это можно представить кодом:
Созданная браузером функция имеет один аргумент: event - обьект содержащий инфу о событии, некоторые из его свойств описал Aliance выше. Для ИЕ это не совсем верно, т.к. обьект event приходит к нам из контекста window, а не аргументом, так что arguments.length вернет нам 0. Ссылка this указывает на тег, т.е. функция-обработчик это метод(или принадлежит, оба утверждения верные) обьекта-тега. Традиционная модель подразумевает вызов браузером определенных методов обьекта, при каждом событии:
Это то же самое что мы сделали выше сами - вызвали метод onmyevent. Заметим что мы получаем те же аргументы что и в inline обработчике, this указывет на тег(ведь это его метод). В обоих способах мы имеем ссылку this, через которую мы работаем с тегом, которому принадлежит обработчик события. Поля srcElement/target, как положенно, содержат ссылки на обьект над которым совершилось событие:
Кликнув по "событий" мы получим alert окошко с именем тега span. T.e. браузер при совершившимся событии создает обьект event, в который устанавливает обьект над которым совершилось событие и затем последовательно вызывает обработчиков событий для всех предков обьекта. Это называется bubbling. Восхождение от предков к обьекту над которым совершилось событие назывется capturing. Древний нетексейп4 поддерживал только capturing, ИЕ поддерживает только bubbling, а Mozilla(Gecko), согласно модели предложенной в DOM2 оба поведения: сначала событие бежит от document к обьекту над которым свершилось событие(capturing mode), а затем спускается назад к document. Это мы рассмотрим ниже, когда придем к "навороченным" моделям событий, и далее в этом топике, тема довольно обьемная. Навороченная(advanced) модель собтыий делится на две ветви: модель DOM2 и модель от MS, у последней у смысл гораздо шире чем просто модель событий. Мы здесь не будем рассматривать behaviors, фича(очень хорошая), но подерживается только ИЕ. Методы addEventListener/removeEventListener позволяют установить/удалить обработчиков событий - на одно событие может быть сколь угодно много обработчиков, в отличии от традиционной модели. Узнать установленно ли собтыие пока нельзя Следующий код работает только в Мозилле и Опере. Устанавливаем события:
Теперь кликнем на "Test3", выполенение: span-test2, span-test3 span-test3, span-test3 div-test, span-test3 То есть событие начало работу в режиме capturing, обошло всех обработчиков зарегистрированных для этого режима(span-test2), затем дошло до обьекта над которым совершилось событие(span-test3), и вернулось обратно в режиме bubbling (div-test). Ссылка this указывает как и раньше на обьект, к которому принадлежит событие. Для того что бы удалить событие, согласно принципам DOM'овцев нужно предоставить самого обработчика события:
Модель ИЕ: attachEvent/detachEvent. Принцип тот же самый, только нет третьего параметра, т.к. ИЕ всегда работает в bubbling режиме. Но есть пара недочётов:
Замечаем что нам передается обьект сбытия первым аргументом, да такой что window.event==ev выдаст нам false, т.е. это не ссылка на window.event. Все имена событий начинаются на префикс on. Но самый большой недостаток, это ссылка this - она указывает на обьект window, а не на тег, к которому принадлежит событие, проще говоря теперь нам эта ссылка как козе баян. Xотя если кто копнёт глубже, то узнает о существовании обьекта element в bechaviors, который указывает на тег. Давайте пификсим "оплошность" ИЕ и сделаем его хоть частично совместимым с DOM2. Для этого нам нужно имплементировать метод addEventListener для каждого обьекта тега. И тут мы наткнёмся на самое большое надругательство над JavaScript - у тегов нет свойства prototype Поэтому мы будем проверять каждый обьект, на существование addEventListener, если метода нет, то добавим его. И так имплементируем пока 3 функции:
Фиксим только ИЕ5.5 - ИЕ6.0, убожество под именем ИЕ5.0 не поддерживает метода call для функций, push для массивов и многое другое. В результате имеем стандартное(DOM2) поведение для ИЕ, правда работающее только в bubbling режиме. А самое главное, что теперь имеем ссылку this, ради которой все и начиналось. Пример использования:
Код будет работать везде правильно. Удаление обработчика имплементируйте сами |
| Автор: Sardar 22.10.2004, 15:48 |
| Что же обозначают три аргумента этого метода: Первый аргумент - строка - имя события, имена событий всегда идут без префикса on, что логично Второй аргумент - функция - функция обработчик, вызываемая для обработки события Третитй аргумент - boolean - направление в котором мы хотим зарегистрировать обработчика: capturing - true, bubbling - false. Что это за направления читайте выше. Скоро раскрою эту тему дальше в этом топике. |
| Автор: Aliance 4.11.2004, 20:49 | ||||
Помогаю: Многие часто пытаються предотвратить просмотр страницы путем блокирования нажатия на правую кнопку мыши. До конца это Вам все равно не удасться сделать
============================================================== Значения свойства button в модели событий: (IE 4+ === NN 6+) Нет кнопки: 0 === null Левая: 1 === 0 Средняя: 4 === 1 Правая: 2 === 2 Л+П: 3 === - Л+С: 5 === - П+С: 6 === - Л+С+П: 7 === - ============================================================== Чаще всего, имхо, события используються при работе с элементами формы и ссылками. В дальнейший сообщениях я расскажу как предотвратить повторный щелчок на кнопке; как избежать повторной отправки данных; как исключить отправку данных формы при нажатии на клавишу Enter; и многое другое 8)) http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/howto/mousecapturecm.asp |
| Автор: Aliance 23.4.2005, 17:02 |
| Вот неплохая вещица, возможна поможет понимать (!) что есть такое событие: http://www.quirksmode.org/js/eventexample.html |
| Автор: Иль 9.7.2005, 22:09 | ||
Sardar, получается это
у тебя в качестве декоротивной заглушки, так сказать, чтоб соответствовать стандартам DOM2 Скажи, я не улавил такую тонкость, разве нельзя переделав твой скрипт capturing организовать, ну для не меняемой особо ветви DOM? |
| Автор: Sardar 10.7.2005, 20:14 | ||||
Угу, на то и имеет префикс dummy
Не реально, ведь код использует механизм "традиционных" событий, а они работают только в bubbling режиме(проход пузырька от того на ком кликнули до корня документа). По сути код ведёт список "делегатов", которые вызывает как только возникнет событие, похоже как в C#. Capturing mode используеться крайне редко, я ещё никогда не использовал. Впрочем это скорее из-за того что ИЕ ни в какую capturing поддерживать не хочет. |
| Автор: Иль 10.7.2005, 22:36 |
| А разве нельзя по событию на элементе в его обработчике пробежаться по ветви к document, собрать информацию кто имеет такое же событие, например onclick, запомнить порядок нод, да и запулить от корня к ноде на которой сработало событие все эти обработчики. Или fireEvent не запустит заданные традиционно события, а работает только с прикрепленными attachEvent. Покрайней мере можно запустить обработчики. Sardar, мне правда это не надо совсем, просто ужасно интересно. Отдельное спасибо, конечно, за тонкости навороченной модели в ИЕ. Как говорится, меньше придется испытать на своей шкуре |
| Автор: Aliance 10.7.2005, 23:24 |
| Иль, в событийной модели IE, в отличие от модели DOM Level 2, нет понятия перехвата события (capturing). Однако, в модели IE - так же, как в модели DOM, события всплывают по иерархии включения их в документ. В обоих моделях всплывание события относится только к необработаным событиям или событиям воода (это, собственно, уже другой вопрос), но не к "высокоуровневым" событиям. Основное различие между всплыванием в IE и в DOM состоит в способе остановки всплывания. В IE нет метода stopPropagation(). Чтобы предотвратить всплывание события или остановить всплывание далее по иерархии, обработчик в IE должен установить свойство cancelBubble равным true. Оно применяется только к текущему событию. |
| Автор: Sardar 11.7.2005, 01:43 |
| Aliance почти, модель одна, просто DOM'овские события чуть мощней. Обычно при возникновении события, от его источника оно бежит к предкам вызывая своих обработчиков на лету. Любой получив событие может его остановить. Это bubbling mode. Capturing mode это подьём обьекта события от предка до виновника события, то есть то же самое, только направление меняеться. В Gecko любое событие проходит две фазы, capturing, т.е. оно начинаеться от document и бежит к виновнику события, затем bubbling, оно спускаеться назад. Иль, конечно можно получив событие под ИЕ, остановить его, а затем собрать все обработчики событий до предка, вызвать их в capturing и в bubbling mode, НО ты ведь понимаешь как это будет глючно и медленно |
| Автор: Aliance 11.7.2005, 09:01 | ||
Позволь не согласится. Даже DOM`овская модель бывает не одна - Event DOM Level 0 и Event DOM Level 2. В Событийной модели Level 0 браузер передает событие тем элементам документа, в которых они происходят. Если объект имеет соотв. обработчик события - этот обработчик запускается. И больше ничего не происходит. В DOM Level 2 все гораздо сложнее :-) Там когда событие происходит в узле документа (кстати, его еще называют целевым узлом события), вызывается обработчик(и) события целевого узла, но, кроме того, каждый из узлов-предков имеет 1-2 возможности обработать это событие. Распространение события осуществляется в 3 этапа:
|
| Автор: Sardar 11.7.2005, 13:28 |
| DOM 0 существует условно, его нет, нет такой спецификации (поправте если не прав). DOM 0 это наследие прошлых лет, обьекты window и прочие, "традиционная модель" событий и т.д. "Традиционная модель" поддерживала только одного обработчика на одно событие и режим только bubbling, т.е. "этап перехвата" не существовал. Затем парни из W3C поняли что это не совсем удобно и решили сделать механизм регистрации и зажигания событий, для которых существовала бы ещё одна фаза capturing. Ты прав когда говоришь что модели событий разные, да они разные. Но идея всплывания события была давно, W3C DOM'овские события работают по такому же принципу, только добавилась ещё одна фаза |
| Автор: Иль 5.8.2005, 20:26 | ||
Что-то я не нашел такого в DOM, это что? |
| Автор: Sardar 5.8.2005, 20:55 |
| Это координаты от верхнего левого угла бокса элемента. Да, это не входит в DOM(парни из W3C похоже вообще об этом не подумали |
| Автор: Иль 15.1.2006, 20:15 | ||
Наверное браузер берет текстовое содержимое атрибута onclick тега HTML и присваивает свойству onclick соответствующей ноды DOM ссылку на метод составленный из текста атрибута |
| Автор: Иль 15.1.2006, 20:56 | ||
Я бы продолжил - ... но это не важно для нас, потому что объекты на которые ссылаются параметр ev и свойство window.event имеют одинаковые свойства (в "видимом" диапазоне) с одинаковыми значениями. Sardar, еслиб не ты, даже не заметил. Пасиб, может заюзается где-нибудь. |
| Автор: rcdimon 26.1.2007, 09:46 | ||
Подскажите как можно отменить все события для элемента.
А теперь мне необходимо отменить собятия для tempValue_textBox. |
| Автор: Иль 27.1.2007, 19:52 | ||||
но лучше так
если, rcdimon, я вас правильно понял |
| Автор: GZep 27.1.2007, 20:30 |
| Иль, а чем второй вариант лучше? |
| Автор: Deja_Vu 16.6.2007, 23:23 | ||
Ни 1 ни 2 вариант не работают в IE. -(( Необходио подключать событие о нажатии клавиши в скрипте. |
| Автор: AKS 17.6.2007, 07:06 |
А Вы почитайте первую страницу этой темы... |
| Автор: Loengreen 21.7.2007, 12:54 | ||||
| Есть некий div, который изначально невидим. по нажатию на ссылку (кнопку) это div становится видимым. На div-е несколько input-ов и кнопка отправить. Как сделать так, что бы в случае, если хотя бы один input не заполнен кнопка была неактивной, а когда input-ы заполнены становилась активной. Помогите пожалуйста! Не понимаю куда вставлять этот самый листнер и как его написать. :( Подсмотрел у yandexa решение. Все оказалось нереально просто.
На страницы для каждого input-a.
|
| Автор: Johnny_B 13.9.2007, 01:00 | ||||
помогите пофиксить код скрипта, что бы работал не только в ИЭ... Пробовал event менять на evt, не получается, 1ю страницу прочел ниче не понял |
| Автор: egao 13.9.2007, 12:20 |
| http://php.ru/forum/viewtopic.php?p=61461#61461 |
| Автор: kodi 19.11.2007, 12:48 | ||
Подскажите как можно перехватить событие передачи ссылки в iframe и реально ли такое?
|
| Автор: Egor__ 10.12.2007, 12:03 |
| раскажите как присвоить обработчик onkeydown; onkeypress. |
| Автор: eee 14.4.2008, 11:38 | ||
ну вообщем-то существует много больше событий - "вторых", так сказать "фирменная модель Netscape и IE"
|
| Автор: guinnes 6.10.2008, 15:47 | ||
| Доброго всем время суток. Мне нужна Ваша помощь. Проблема у меня в следующем: Есть 2 почтовые формы на одной и той же странице, мне нужно, чтоб при выборе значения из списка в одной форме оно сразу присваивалось полю другой формы. С chekbox и radio у меня всё получается, я использую
|
| Автор: bars80080 6.10.2008, 17:53 | ||||
|
| Автор: guinnes 6.10.2008, 19:49 |
| bars80080, Спасибо, попробую Добавлено через 12 минут и 22 секунды bars80080, спасибо |
| Автор: guinnes 6.10.2008, 20:05 |
| Всё, спасибо, разобрался, работает |
| Автор: Parvana 13.11.2008, 23:27 | ||||
| Хочу задат вопросик. На странице который я дольжен отредактировать есть такие <div>-и:
но <href>-и тут вовсе не линки поскольку в <head>-е есть такой JavaScript код:
и когда я кликнаю на картинки из "image_cat"-а броузер переходит в адресс с линком $(this).attr("href"). Если поставить функцию myFunction в коммент все пойдет гладко. Можете, пожалуйста, помочь мне? P.S. простите за ошибки, мне немножко трудновато писать на русском |
| Автор: bars80080 13.11.2008, 23:51 |
| а что сделать то надо? |
| Автор: Shot 23.1.2009, 12:11 | ||||
| добрый день подскажите пожалуйста где ошибка в этом коде и извините если не туда вопрос задаю, если можно покажите как правильно записать этот код только не пищите через IF мне нужно знат именно через switch и через case как заставит заработать этому скрипту скрипт должен при выборе одного из radio и после при нажатый на submit открыт ту страницу которая указана в case помогите кто знает как исправит код:
вот форма которая подключаться
|
| Автор: Elfebet 23.1.2009, 13:43 | ||
| ошибка в "onclick='r(this.value)' " причем тут this.value ? если на то уж пошло то нужно так
|
| Автор: ToxaDR 9.2.2009, 19:36 |
| Друзья, подскажите, как в element.addEventListener ("blur", func, false); добавить аргументы в функцию func ???? Это вообще возможно? |
| Автор: kirov 6.11.2010, 15:11 |
| Такие вещи лучше делать на http://webdev.cz.cc/javascript/jquery, чтобы не мучиться с кросcбраузерностью |
| Автор: Lily78 17.8.2016, 11:51 |
| спасибо |