Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Click() и onclick наносят ответный удар, мой мозг совсем сломался, спасите! 
V
    Опции темы
SelenIT
Дата 5.6.2007, 03:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 49
Всего: 401



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

Итак, моя наивная детская вера в незыблемость основ - напр., того, что обработчики событий вида нечто.onclick и т.п. вызываются исключительно внешними причинами (как-то действия юзера, в частности, клики), но не программными вызовами типа нечто.click(), была беспощадно поругана суровой правдой жизни и разбилась вдребезги о таковую. Хотя подобное утверждалось не только на многих уважаемых форумах, но и, например, здесь:
Цитата

The click() method does not trigger the onClick event handler so you should not worry about the script getting into an infinite loop here.

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

Поэтому, когда на другом уважаемом форуме я наткнулся на рекомендацию вызывать onclick кнопки путем вызова ее click(), я испытал нешуточное нервное потрясение. К моему удивлению, такой вариант:
Код

<input id="b1" onclick="alert('Surprise!')" type="button" value="Button1"><br>
<input onclick="document.getElementById('b1').click()" type="button" value="Button2">

радостно выкинул алерт по клику на Button2... Какого же, простите, censored-переcensored, оно вызывается, если в тех же самых "умных книжках" четко сказано следующее?
Цитата

A button’s click() method simulates the user’s action of clicking that button. It causes the same action as would a human click, except that the button’s onClick event handler is not triggered. Since their only usefulness is in triggering the onClick event handler, this method is not useful for TYPE="button" buttons.


Небольшое расследование привело меня лишь в еще большее недоумение. Слегка изменив код из первой ссылки:
Код

<script language="javascript">
function connectMe(destination) {
 document.forms[0].elements[destination].click()
 alert(destination);
}
</script>
<form>
    <input onclick="connectMe(1)" type="checkbox">    Number 1<br>
    <input onclick="connectMe(0)" type="checkbox">    Number 2<br>
    <input onclick="connectMe(3)" type="button" value="Button 1"><br>
    <input onclick="connectMe(2)" type="button" value="Button 2">
</form>

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

И совсем странно ведет себя это безобразие в Опере 9.20 и последней альфе FF3 (Gecko/20070604 Minefield/3.0a6pre). В первой никаких алертов вообще нет, но чекбоксы после первого клика... начинают часто мерцать и перестают реагировать на новые клики - неужели то самое зацикливание? Хорошо еще, браузер от этого не зависает намертво... Во второй же алерт выскакивает... трижды - получается, что "привязываемый" чекбокс оказывается "кликнут" дважды и его состояние в итоге не меняется!

Ни в MSDN, ни в MDC, ни в стандарте DOM я так и не нашел хотя бы примерной рекомендации, как должен вести себя браузер в таком случае... может, плохо искал? Вообще, откуда повелась такая свистопляска именно с onclick-ом? Onsubmit у формы ведь, насколько я помню, никогда не вызывается при ее программном submit()-е (хотя теперь уже я ни в чем не уверен...)?

Уважаемые гуру и корифеи! Пожалуйста, натолкните меня на хоть какую-нибудь твердую почву, не дайте свихнуться окончательно! А то у меня только-только стала своя жизнь налаживаться, обидно все потерять и кончить дни в дурке из-за такого, по сути, пустяка... ;)


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
AKS
Дата 5.6.2007, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



Цитата

но не программными вызовами типа нечто.click()...

??? Вообще-то, как-раз он ( click() )для того и существует.
Но ближе к делу. На мой взгляд данный тест всего лишь подтверждает то, что все браузеры работают по-разному и не более того.
Взять, к примеру, IE. Все, как будто, логично - событие, происходящее в данный момент вновь не инициируется.
Если взять Opera, то впечатление такое, как-будто у нее нет программного click() в том виде, в каком он имеется в IE. У нее происходит прямой вызов того, что в атрибуте onclick (т.е. происходит не click(), а вызов onclick()). Если таким же образом подойти к проблеме в IE, то возникнет точно такая же бесконечная рекурсия...
С Gecko интересней, но не думаю, что это необъяснимо - это всего лишь свои особенности...

PM MAIL   Вверх
SelenIT
Дата 5.6.2007, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 49
Всего: 401



Цитата(AKS @  5.6.2007,  09:18 Найти цитируемый пост)
как-раз он ( click() )для того и существует

Хм... я был уверен, что click() существует главным образом для программного переключения чекбоксов/радиокнопок, а onclick() всегда нужно вызывать явно, поэтому-то до сих пор не сталкивался с этой странностью;)... да и вышеприведенные цитаты (где дважды повторено, что click() onclick-а не вызывает) на чем-то ведь основываются? Если это просто устаревшая информация - то где можно прочитать о том, когда и почему это поведение было изменено? Если же заведомо ложная - то где найти истину?

И опять же, почему тогда программный submit() формы не вызывает ее обработчика onsubmit - даже в Опере (только что проверил)? Почему разные события в этом плане ведут себя по-разному и отчего это зависит?

Цитата(AKS @  5.6.2007,  09:18 Найти цитируемый пост)
С Gecko интересней

Да уж - на работе у меня в FF 2.0.0.4 пример связанных взаимным click()-ом чекбоксов работает, а дома ведет себя аналогично FF3 (тройное срабатывание)... может, дело в extension-ах каких-нибудь? Жалко, пока нет времени на масштабное исследование...

И все же я был бы очень благодарен, если бы меня ткнули носом в TFM, объясняющий различие поведения click() - onclick vs. submit() - onsubmit и тому подобные (для меня абсолютно неочевидные, более того - субъективно нелогичные) элементарные вещи...


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
Zeroglif
Дата 5.6.2007, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(SelenIT @  5.6.2007,  11:41 Найти цитируемый пост)
вышеприведенные цитаты (где дважды повторено, что click() onclick-а не вызывает) на чем-то ведь основываются?

На старых доках и собственно ситуации на момент написания этой древнейшей книжки.

Цитата(SelenIT @  5.6.2007,  11:41 Найти цитируемый пост)
где можно прочитать о том, когда и почему это поведение было изменено?

Много чего постоянно менялось в угоду пользователям или же а-ля "сделаем как у IE", чтиво по таким изменениям с ходу фиг найдёшь...

Цитата(SelenIT @  5.6.2007,  11:41 Найти цитируемый пост)
И опять же, почему тогда программный submit() формы не вызывает ее обработчика onsubmit - даже в Опере (только что проверил)? Почему разные события в этом плане ведут себя по-разному и отчего это зависит?

Потому что это просто разные методы, метод click ака эмулирует реальный клик рукой/пальцем ;-) , он более универсален (им же и сабмитить можно), его можно прицепить к множеству элементов (у того же IE, например), в общем, click всегда был сам по себе, а submit и проч. сами по себе. Я бы резюмировал так:

Метод, типа "эмулирующий" левый клик. Не равнозначен этому клику. Стандартен (w3c), но только для инпутов с определёнными атрибутами, в разных браузерах исторически был реализован по-разному, как с точки зрения элементов, к которым применим, так и с точки зрения всего остального: взаимодействия с обработчиками и проч. событиями, и т.д. и т.п. Осюда - жди сюрпризов...

Цитата

Simulate a mouse-click. For INPUT elements whose type attribute has one of the following values: "button", "checkbox", "radio", "reset", or "submit". 
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-2651361

The click method is intended to be used with INPUT elements of type button, checkbox, radio, reset or submit. Gecko does not implement the click method on other elements that might be expected to respond to mouse–clicks such as links (A elements), nor will it necessarily fire the click event of other elements. 
Non–Gecko DOMs may behave differently. When a click is used with elements that support it (e.g. one of the INPUT types listed above), it also fires the element's click event which will bubble up to elements higher up the document tree (or event chain) and fire their click events too. However, bubbling of a click event will not cause an A element to initiate navigation as if a real mouse-click had been received.
http://developer.mozilla.org/en/docs/DOM:element.click


Simulates a click by causing the onclick event to fire. 
http://msdn2.microsoft.com/en-us/library/ms536363.aspx


p.s. почему браузеры самостоятельно выходят из потенциального infinite loop объяснить не могу, сюрррпрыз.

Это сообщение отредактировал(а) Zeroglif - 5.6.2007, 12:22
PM MAIL WWW   Вверх
SelenIT
Дата 5.6.2007, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 49
Всего: 401



Zeroglif, огромное спасибо!

Цитата(Zeroglif @  5.6.2007,  12:18 Найти цитируемый пост)
в общем, click всегда был сам по себе, а submit и проч. сами по себе. ... в разных браузерах исторически был реализован по-разному, как с точки зрения элементов, к которым применим, так и с точки зрения всего остального: взаимодействия с обработчиками и проч. событиями, и т.д. и т.п. Осюда - жди сюрпризов...

Т.е. строгой системы нет, все определяется исторически сложившимися обстоятельствами? Если уж submit() и reset() по этой части оказались полными антиподами, хотя, казалось бы, сами события - явные "близнецы" (по "всплываемости",  "отменяемости" и т.п.)... Выходит, это скорее submit() по части (не-)запуска обработчика стоит особняком... кстати, везде ли это так или тут тоже "возможны варианты"?

P.S. Отдельное спасибо за последнюю ссылку - не понимаю, как я сам вчера не приметил в ней слона в самом первом абзаце... smile



--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
Zeroglif
Дата 5.6.2007, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(SelenIT @  5.6.2007,  14:31 Найти цитируемый пост)
строгой системы нет

Откуда взяться строгой системе для методов/свойств на хосте, если разные движки умудряются местами даже единый стандарт (ECMAScript) по-своему интерпретировать?  smile 

Цитата(SelenIT @  5.6.2007,  14:31 Найти цитируемый пост)
везде ли это так

Уверенности про все браузеры нет, я бы сказал, что нельзя полагаться на то, что submit() плюс onsubmit обязательно не наложатся друг на друга (если есть необходимость иметь их обоих, то при submit() лучше бы временно заглушить обработчик).
PM MAIL WWW   Вверх
AKS
Дата 5.6.2007, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



SelenIT, вот решил продолжить вашу "славную традицию по мозгодробильным опытам":
Код

function connectMe(e) {
    var el = e.srcElement || e.target;
    document.getElementById('test')
            .innerHTML += ' ' + el.tagName;
    document.forms[0].elements[0].click();
    if (1) {
        //e.preventDefault ? e.preventDefault() :
                         e.cancelBubble = true;
    }
}

document.onclick = function (e) {
    connectMe(e || event) 
};

Код

<form>
    <input onclick='connectMe(event)' type='checkbox'> 
</form>

Итак, какие тут есть "варианты".
1. Событие, как видно из примера, можно прервать. Но если для FF и Opera раскоментить preventDefault, то никакого эффекта не будет. Вывод - "древний" метод click() требует к себе соответствующего отношения (использовать местами запрещенный cancelBubble).
2. Если событие не прерывать (в условии заменить 1 на 0), и кликнуть по боксу в FF, то имя тэга будет написано аж ШЕСТЬ раз. В IE/Opera лишь дважды.
3. В FF метод click() симулируя событие на боксе не делает его мишенью события - чтобы в этом убедиться, нужно кликнуть по документу и будет распечатано трижды (если событие не прервано) или дважды HTML. В IE/Opera клик по документу возвращает HTML Input (Input).
Наверняка есть и еще какие-нибудь причуды, но я пока больше не нашел. ;)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0563 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.