| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > JavaScript: Общие вопросы > Click() и onclick наносят ответный удар |
| Автор: SelenIT 5.6.2007, 03:30 | ||||||||
| Вчера наш любимый самый-недопонимаемый-язык-программирования-в-мире нанес моему самоуважению очередную смертельную рану ниже пояса. Я-то уже, можно сказать, привык к таким сюрпризам и перестал из-за каждого из них уходить в депрессию и запой на полгода, но... хочется ведь разобраться! Итак, моя наивная детская вера в незыблемость основ - напр., того, что обработчики событий вида нечто.onclick и т.п. вызываются исключительно внешними причинами (как-то действия юзера, в частности, клики), но не программными вызовами типа нечто.click(), была беспощадно поругана суровой правдой жизни и разбилась вдребезги о таковую. Хотя подобное утверждалось не только на многих уважаемых форумах, но и, например, http://ods.com.ua/win/eng/web-tech/js/htm/22-13.phtml#Heading72:
И действительно, пример связанных чекбоксов по http://ods.com.ua/win/eng/web-tech/js/htm/22-13.phtml#Heading72 (надо полагать, из старинной, но серьезной http://ods.com.ua/win/eng/web-tech/js/index.phtml) и в IE6, и в FF2 работает в точности по описанному - ничего не зацикливается, меняются они синхронно, как положено... Поэтому, когда на другом уважаемом форуме я наткнулся на рекомендацию вызывать onclick кнопки путем вызова ее click(), я испытал нешуточное нервное потрясение. К моему удивлению, такой вариант:
радостно выкинул алерт по клику на Button2... Какого же, простите, censored-переcensored, оно вызывается, если в тех же самых http://ods.com.ua/win/eng/web-tech/js/htm/22-12.phtml#Heading62 четко сказано следующее?
Небольшое расследование привело меня лишь в еще большее недоумение. Слегка изменив код из первой ссылки:
я с удивлением увидел, что в IE для каждой пары (и чекбоксов, и кнопок) выскакивает аккурат по 2 алерта - для каждого элемента из пары: получается, лишь первый программный клик вызывает обработчик, а дальше какой-то другой механизм борется с зацикливанием - так, что ли? И совсем странно ведет себя это безобразие в Опере 9.20 и последней альфе FF3 (Gecko/20070604 Minefield/3.0a6pre). В первой никаких алертов вообще нет, но чекбоксы после первого клика... начинают часто мерцать и перестают реагировать на новые клики - неужели то самое зацикливание? Хорошо еще, браузер от этого не зависает намертво... Во второй же алерт выскакивает... трижды - получается, что "привязываемый" чекбокс оказывается "кликнут" дважды и его состояние в итоге не меняется! Ни в MSDN, ни в MDC, ни в стандарте DOM я так и не нашел хотя бы примерной рекомендации, как должен вести себя браузер в таком случае... может, плохо искал? Вообще, откуда повелась такая свистопляска именно с onclick-ом? Onsubmit у формы ведь, насколько я помню, никогда не вызывается при ее программном submit()-е (хотя теперь уже я ни в чем не уверен...)? Уважаемые гуру и корифеи! Пожалуйста, натолкните меня на хоть какую-нибудь твердую почву, не дайте свихнуться окончательно! А то у меня только-только стала своя жизнь налаживаться, обидно все потерять и кончить дни в дурке из-за такого, по сути, пустяка... ;) |
| Автор: AKS 5.6.2007, 09:18 | ||
??? Вообще-то, как-раз он ( click() )для того и существует. Но ближе к делу. На мой взгляд данный тест всего лишь подтверждает то, что все браузеры работают по-разному и не более того. Взять, к примеру, IE. Все, как будто, логично - событие, происходящее в данный момент вновь не инициируется. Если взять Opera, то впечатление такое, как-будто у нее нет программного click() в том виде, в каком он имеется в IE. У нее происходит прямой вызов того, что в атрибуте onclick (т.е. происходит не click(), а вызов onclick()). Если таким же образом подойти к проблеме в IE, то возникнет точно такая же бесконечная рекурсия... С Gecko интересней, но не думаю, что это необъяснимо - это всего лишь свои особенности... |
| Автор: SelenIT 5.6.2007, 11:41 |
Хм... я был уверен, что click() существует главным образом для программного переключения чекбоксов/радиокнопок, а onclick() всегда нужно вызывать явно, поэтому-то до сих пор не сталкивался с этой странностью;)... да и вышеприведенные цитаты (где дважды повторено, что click() onclick-а не вызывает) на чем-то ведь основываются? Если это просто устаревшая информация - то где можно прочитать о том, когда и почему это поведение было изменено? Если же заведомо ложная - то где найти истину? И опять же, почему тогда программный submit() формы не вызывает ее обработчика onsubmit - даже в Опере (только что проверил)? Почему разные события в этом плане ведут себя по-разному и отчего это зависит? Да уж - на работе у меня в FF 2.0.0.4 пример связанных взаимным click()-ом чекбоксов работает, а дома ведет себя аналогично FF3 (тройное срабатывание)... может, дело в extension-ах каких-нибудь? Жалко, пока нет времени на масштабное исследование... И все же я был бы очень благодарен, если бы меня ткнули носом в TFM, объясняющий различие поведения click() - onclick vs. submit() - onsubmit и тому подобные (для меня абсолютно неочевидные, более того - субъективно нелогичные) элементарные вещи... |
| Автор: SelenIT 5.6.2007, 14:31 | ||
Zeroglif, огромное спасибо!
Т.е. строгой системы нет, все определяется исторически сложившимися обстоятельствами? Если уж submit() и reset() по этой части оказались полными антиподами, хотя, казалось бы, сами события - явные "близнецы" (по "всплываемости", "отменяемости" и т.п.)... Выходит, это скорее submit() по части (не-)запуска обработчика стоит особняком... кстати, везде ли это так или тут тоже "возможны варианты"? P.S. Отдельное спасибо за последнюю ссылку - не понимаю, как я сам вчера не приметил в ней слона в самом первом абзаце... |
| Автор: Zeroglif 5.6.2007, 16:14 |
Откуда взяться строгой системе для методов/свойств на хосте, если разные движки умудряются местами даже единый стандарт (ECMAScript) по-своему интерпретировать? Уверенности про все браузеры нет, я бы сказал, что нельзя полагаться на то, что submit() плюс onsubmit обязательно не наложатся друг на друга (если есть необходимость иметь их обоих, то при submit() лучше бы временно заглушить обработчик). |
| Автор: AKS 5.6.2007, 18:46 | ||||
SelenIT, вот решил продолжить вашу "славную традицию по мозгодробильным опытам":
Итак, какие тут есть "варианты". 1. Событие, как видно из примера, можно прервать. Но если для FF и Opera раскоментить preventDefault, то никакого эффекта не будет. Вывод - "древний" метод click() требует к себе соответствующего отношения (использовать местами запрещенный cancelBubble). 2. Если событие не прерывать (в условии заменить 1 на 0), и кликнуть по боксу в FF, то имя тэга будет написано аж ШЕСТЬ раз. В IE/Opera лишь дважды. 3. В FF метод click() симулируя событие на боксе не делает его мишенью события - чтобы в этом убедиться, нужно кликнуть по документу и будет распечатано трижды (если событие не прервано) или дважды HTML. В IE/Opera клик по документу возвращает HTML Input (Input). Наверняка есть и еще какие-нибудь причуды, но я пока больше не нашел. ;) |