|
Модераторы: Sardar, Aliance |
|
Aliance |
|
||||||||||
I ♥ <script> Профиль Группа: Модератор Сообщений: 6418 Регистрация: 2.8.2004 Где: spb Репутация: 17 Всего: 137 |
Доброго всем времени суток!
Часто вижу, что события описывают (регистрируют) не верно с точки зрения совсестимости двух документных объектных моделей: 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 Таким образом, чтобы, скажем, узнать откуда пришел элемент, нужно писать так (используя совместимый синтаксис):
Это сообщение отредактировал(а) Aliance - 23.4.2005, 13:43 |
||||||||||
|
|||||||||||
Sardar |
|
||||||||||||||||||
Бегун Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
Елки, все никак времени "родить" статью нет
Соберем в топике хорошие идеи, а затем сделаем ман по событиям Коротко расскажу о типах регистрирования событий: 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 . Вот как, после такого это все JavaScript'ом назвать... Поэтому мы будем проверять каждый обьект, на существование addEventListener, если метода нет, то добавим его. И так имплементируем пока 3 функции:
Фиксим только ИЕ5.5 - ИЕ6.0, убожество под именем ИЕ5.0 не поддерживает метода call для функций, push для массивов и многое другое. В результате имеем стандартное(DOM2) поведение для ИЕ, правда работающее только в bubbling режиме. А самое главное, что теперь имеем ссылку this, ради которой все и начиналось. Пример использования:
Код будет работать везде правильно. Удаление обработчика имплементируйте сами Это сообщение отредактировал(а) Aliance - 22.4.2005, 11:23 -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||||||||||||||||
|
|||||||||||||||||||
Sardar |
|
|||
Бегун Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
Что же обозначают три аргумента этого метода:
Первый аргумент - строка - имя события, имена событий всегда идут без префикса on, что логично Второй аргумент - функция - функция обработчик, вызываемая для обработки события Третитй аргумент - boolean - направление в котором мы хотим зарегистрировать обработчика: capturing - true, bubbling - false. Что это за направления читайте выше. Скоро раскрою эту тему дальше в этом топике. Это сообщение отредактировал(а) Aliance - 23.4.2005, 13:45 -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
Aliance |
|
||||
I ♥ <script> Профиль Группа: Модератор Сообщений: 6418 Регистрация: 2.8.2004 Где: spb Репутация: 17 Всего: 137 |
Помогаю: Многие часто пытаються предотвратить просмотр страницы путем блокирования нажатия на правую кнопку мыши. До конца это Вам все равно не удасться сделать Невозможно предотвратить возможность, скажем, пользователю сохранить картинку (если она не сгенерирована сервером). Но все же, т.к. ВОпрос ЧАстозадаваемый, то я открою занавесу над этой процедурой:
============================================================== Значения свойства button в модели событий: (IE 4+ === NN 6+) Нет кнопки: 0 === null Левая: 1 === 0 Средняя: 4 === 1 Правая: 2 === 2 Л+П: 3 === - Л+С: 5 === - П+С: 6 === - Л+С+П: 7 === - ============================================================== Чаще всего, имхо, события используються при работе с элементами формы и ссылками. В дальнейший сообщениях я расскажу как предотвратить повторный щелчок на кнопке; как избежать повторной отправки данных; как исключить отправку данных формы при нажатии на клавишу Enter; и многое другое 8)) Подробнее... Это сообщение отредактировал(а) Aliance - 6.4.2005, 21:07 |
||||
|
|||||
Aliance |
|
|||
I ♥ <script> Профиль Группа: Модератор Сообщений: 6418 Регистрация: 2.8.2004 Где: spb Репутация: 17 Всего: 137 |
Вот неплохая вещица, возможна поможет понимать (!) что есть такое событие:
http://www.quirksmode.org/js/eventexample.html |
|||
|
||||
Иль |
|
|||
Опытный Профиль Группа: Участник Сообщений: 544 Регистрация: 3.3.2005 Где: Москва Репутация: нет Всего: 14 |
Sardar, получается это
у тебя в качестве декоротивной заглушки, так сказать, чтоб соответствовать стандартам DOM2 . Скажи, я не улавил такую тонкость, разве нельзя переделав твой скрипт capturing организовать, ну для не меняемой особо ветви DOM? -------------------- Ты виндусятник?... А я да. |
|||
|
||||
Sardar |
|
||||
Бегун Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
Угу, на то и имеет префикс dummy
Не реально, ведь код использует механизм "традиционных" событий, а они работают только в bubbling режиме(проход пузырька от того на ком кликнули до корня документа). По сути код ведёт список "делегатов", которые вызывает как только возникнет событие, похоже как в C#. Capturing mode используеться крайне редко, я ещё никогда не использовал. Впрочем это скорее из-за того что ИЕ ни в какую capturing поддерживать не хочет. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||
|
|||||
Иль |
|
|||
Опытный Профиль Группа: Участник Сообщений: 544 Регистрация: 3.3.2005 Где: Москва Репутация: нет Всего: 14 |
А разве нельзя по событию на элементе в его обработчике пробежаться по ветви к document, собрать информацию кто имеет такое же событие, например onclick, запомнить порядок нод, да и запулить от корня к ноде на которой сработало событие все эти обработчики. Или fireEvent не запустит заданные традиционно события, а работает только с прикрепленными attachEvent. Покрайней мере можно запустить обработчики.
Sardar, мне правда это не надо совсем, просто ужасно интересно. Отдельное спасибо, конечно, за тонкости навороченной модели в ИЕ. Как говорится, меньше придется испытать на своей шкуре , да и времени сэкономится. -------------------- Ты виндусятник?... А я да. |
|||
|
||||
Aliance |
|
|||
I ♥ <script> Профиль Группа: Модератор Сообщений: 6418 Регистрация: 2.8.2004 Где: spb Репутация: 17 Всего: 137 |
Иль,
в событийной модели IE, в отличие от модели DOM Level 2, нет понятия перехвата события (capturing). Однако, в модели IE - так же, как в модели DOM, события всплывают по иерархии включения их в документ. В обоих моделях всплывание события относится только к необработаным событиям или событиям воода (это, собственно, уже другой вопрос), но не к "высокоуровневым" событиям. Основное различие между всплыванием в IE и в DOM состоит в способе остановки всплывания. В IE нет метода stopPropagation(). Чтобы предотвратить всплывание события или остановить всплывание далее по иерархии, обработчик в IE должен установить свойство cancelBubble равным true. Оно применяется только к текущему событию. |
|||
|
||||
Sardar |
|
|||
Бегун Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
Aliance почти, модель одна, просто DOM'овские события чуть мощней. Обычно при возникновении события, от его источника оно бежит к предкам вызывая своих обработчиков на лету. Любой получив событие может его остановить. Это bubbling mode.
Capturing mode это подьём обьекта события от предка до виновника события, то есть то же самое, только направление меняеться. В Gecko любое событие проходит две фазы, capturing, т.е. оно начинаеться от document и бежит к виновнику события, затем bubbling, оно спускаеться назад. Иль, конечно можно получив событие под ИЕ, остановить его, а затем собрать все обработчики событий до предка, вызвать их в capturing и в bubbling mode, НО ты ведь понимаешь как это будет глючно и медленно -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
Aliance |
|
|||
I ♥ <script> Профиль Группа: Модератор Сообщений: 6418 Регистрация: 2.8.2004 Где: spb Репутация: 17 Всего: 137 |
Позволь не согласится. Даже DOM`овская модель бывает не одна - Event DOM Level 0 и Event DOM Level 2. В Событийной модели Level 0 браузер передает событие тем элементам документа, в которых они происходят. Если объект имеет соотв. обработчик события - этот обработчик запускается. И больше ничего не происходит. В DOM Level 2 все гораздо сложнее :-) Там когда событие происходит в узле документа (кстати, его еще называют целевым узлом события), вызывается обработчик(и) события целевого узла, но, кроме того, каждый из узлов-предков имеет 1-2 возможности обработать это событие. Распространение события осуществляется в 3 этапа:
|
|||
|
||||
Sardar |
|
|||
Бегун Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
DOM 0 существует условно, его нет, нет такой спецификации (поправте если не прав). DOM 0 это наследие прошлых лет, обьекты window и прочие, "традиционная модель" событий и т.д.
"Традиционная модель" поддерживала только одного обработчика на одно событие и режим только bubbling, т.е. "этап перехвата" не существовал. Затем парни из W3C поняли что это не совсем удобно и решили сделать механизм регистрации и зажигания событий, для которых существовала бы ещё одна фаза capturing. Ты прав когда говоришь что модели событий разные, да они разные. Но идея всплывания события была давно, W3C DOM'овские события работают по такому же принципу, только добавилась ещё одна фаза -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
Иль |
|
|||
Опытный Профиль Группа: Участник Сообщений: 544 Регистрация: 3.3.2005 Где: Москва Репутация: нет Всего: 14 |
Что-то я не нашел такого в DOM, это что? -------------------- Ты виндусятник?... А я да. |
|||
|
||||
Sardar |
|
|||
Бегун Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 2 Всего: 317 |
Это координаты от верхнего левого угла бокса элемента. Да, это не входит в DOM(парни из W3C похоже вообще об этом не подумали ). Пришло как наследие из нетскейпа по моему.
-------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
Иль |
|
|||
Опытный Профиль Группа: Участник Сообщений: 544 Регистрация: 3.3.2005 Где: Москва Репутация: нет Всего: 14 |
Sardar, интересно, почему используеш call? Пример без call -------------------- Ты виндусятник?... А я да. |
|||
|
||||
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | JavaScript: для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |