Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   live click выполняется несколько раз (https://javascript.ru/forum/jquery/9858-live-click-vypolnyaetsya-neskolko-raz.html)

hara 08.06.2010 21:44

live click выполняется несколько раз
 
Вложений: 2
Здравствуйте,
в общем то уже задал данный вопрос на одном форуме, но не думаю что это является проблемой.

Итак:

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

То есть, другими словами:

Нажимаем на ссылку -> загружается Html внутри которого есть скрытый элемент и jquery код который вешает событие на этот элемент.
Так вот если этот элемент после загрузки сделать видимым - то на него вешается событие onClick и всё в порядке, - но если опять нажать на
первую ссылку - событие отработает дважды.
Причём такая проблема только если грузится html со скрытым элементом, который показывается только после загрузки.

Для того что бы можно было лучше понять что я имею ввиду привожу код:

Код файла index.html (ненужные теги удалены)
<script type="text/javascript">
            $(document).ready(function(){
                $('a.upload').bind('click',function(){
                    $('div#uploadContainer').load('./upload.html');
                });
                $('a.uploadedLink').live('click',function(){
                    $('a.hiddenLink').show();
                })
            });
        </script>
        <a href="#" class="upload">Upload content</a>&nbsp;&nbsp;
        <br><br><br>
        <div id="uploadContainer">
            Click above to load here some html
        </div>

Весь код файла upload.html
<script type="text/javascript">
    $(document).ready(function(){
        $('a.hiddenLink').live('click',function(){
            alert('Hello from hidden link');
        });
    });
</script>
<a href="#" class="uploadedLink">Click me to show hidden content</a><br><br>
<a href="#" class="hiddenLink" style="display:none;">Click me to trigger live event one or multiple times</a>


Возможно кто то уже сталкивался с данной проблемой?

Если будет нужно, - файлы приложил.
test.zip - только файлы index.html и upload.html (799Б)
и test-with-jquery.zip - три файла index.html, upload.html и jquery-1.4.2.min.js (24.2Кб) (что бы можно было просто распаковать и проверить результат)

Gvozd 08.06.2010 21:54

вы вообще представляете себе как работает метод live, и в чем его отличие от обычного назначения обработчика?

прочитайте внимательно документацию, а затем по шагам, подумайте, что будет происходить при очередном щелчке по div#uploadContainer

hara 08.06.2010 22:14

Представляю что отличие в том, что метод live назначает обработчик событий вновь появляющимся элементам.

При щелчке по div#uploadContainer происходит ничего не будет, видимо опечатка.

При щелчке на a.upload файл upload.html подгружается в div#uploadContainer затем там выполняется $('a.hiddenLink').live('click' и назначается(реально ещё не назначается) обработчик пока ещё скрытой ссылке.
При щелчке на a.uploadedLink cкрытая ссылка появляется и обработчик назначается(вот теперь точно назначается) скрытой ссылке. При нажатии на которую видим alert.

Теперь если нажать опять на ссылку a.upload произойдёт всё тоже самое, но уже при нажатии на скрытую ранее ссылку мы увидим alert дважды. - т.е. при удалении html метод live сохраняет его событие и когда он появляется вновь он добавляет его (а так помойму быть не должно).

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

По поводу опять же отличий live от bind - покажите мне где тут можно заменить Live на Bind без потери функционала, - если вообще вопрос конечно был к этому.

И в принципе если вынести js код из подгружаемого файла в index.html - то будет работать корректно, но этог сделать сложно - т.к. сайт полностью на ajax и не хотелось бы всегда подгружать все события на элементы, которые возможно и не загрузят. - хотя в общем то если нет решения проблемы, то прийдётся как то изворачиваться.

А теперь, судя по тону вашего ответа, - скажите мне где же я сильно затупил, потому как сам я пока этого не понимаю.

hara 08.06.2010 22:21

Пардон, до меня дошло. Каюсь. Остаётся вопрос, - можно ли определить не назначен ли какой нибудь обработчик уже данному элеменету. Буду разбираться, спасибо.

sysya 08.06.2010 22:32

А зачем в коде upload.html live? отсюда и повторяется навешивание click

hara 08.06.2010 22:34

Ну почему повторяется я уже понял.
А почему именно там, - потому что вообще сайт весь на ajax и там достаточно много обработчиков, не очень хорошо их кучковать в одном месте. Буду видимо подгружать js по мере необходимости один раз.

Gvozd 08.06.2010 22:36

Цитата:

Сообщение от hara
При щелчке по div#uploadContainer происходит ничего не будет, видимо опечатка.

имел ввиду подгрузку в div#uploadContainer по щелчку на a.upload
Цитата:

Сообщение от hara
По поводу опять же отличий live от bind - покажите мне где тут можно заменить Live на Bind без потери функционала, - если вообще вопрос конечно был к этому.

http://javascript.ru/forum/jquery/95...html#post56292
djn rjulf yflj tuj cbgjkmpdjfnm/
но вопрос, был вообще-то не к этому.
Цитата:

Сообщение от hara
И в принципе если вынести js код из подгружаемого файла в index.html - то будет работать корректно

Именно!)
Цитата:

Сообщение от hara
не хотелось бы всегда подгружать все события на элементы, которые возможно и не загрузят

вы это уже сделали:
$('a.uploadedLink').live('click',function(){
                    $('a.hiddenLink').show();
                })


теперь же поясню вам:
к сожалению, напрямую в справке об этом нигде не говорится, но, насколько я знаю, при назначении live, на самом деле вешается событие на window.document и при возникновении любого клика по документу, проверяется "а кликнули не по нужному ли нам типу элемента"
когда, ты вызываешь второй и так далее разы код
$('a.hiddenLink').live('click',function(){ 
	            alert('Hello from hidden link'); 
	        });

из подгружаемого документа, то вешаются ДОПОЛНИТЕЛЬНЫЕ обработчики события на window.document
и каждый из них выполняется при щелчке, один за другим.
То есть, ты не снимаешь старые обработчики.

Именно, из-за такого непонимания базовых вещей, все адекватные разработчики JS советуют вначале досконально изучить чистый JS, а лишь затем учить и использовать jQuery.

PS отвлекался, и поэтому долго писал.
но в моем посте остались еще вещи, на которые вам надо обратить внимаиние

hara 08.06.2010 22:42

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

sysya 08.06.2010 22:44

можно вот так сделать:
<script type="text/javascript"> 
            $(document).ready(function(){ 
                $('a.upload').bind('click',function(){ 
                    $('div#uploadContainer').load('./upload.html'); 
                }); 
            }); 
        </script> 
        <a href="#" class="upload">Upload content</a>&nbsp;&nbsp; 
        <br><br><br> 
        <div id="uploadContainer"> 
            Click above to load here some html 
        </div>
Вот мясцо $('a.uploadedLink').live('click',function(){ $('a.hiddenLink').show();}) вырезать и всё

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

e1f 09.06.2010 10:58

Цитата:

Сообщение от Gvozd (Сообщение 58574)
к сожалению, напрямую в справке об этом нигде не говорится, но, насколько я знаю, при назначении live, на самом деле вешается событие на window.document и при возникновении любого клика по документу, проверяется "а кликнули не по нужному ли нам типу элемента"

Gvozd, не совсем. Можно указать контекст, на который навешивается обработчик.
Лишь тогда, когда в jquery это реализоали, появился смысл использовать live.


Часовой пояс GMT +3, время: 07:25.