Присоединение и повторное подключение обработчиков событий - PullRequest
1 голос
/ 25 августа 2009

Я использую обработчики событий из фреймворка (конкретный прототип), чтобы прикрепить листеры к определенным элементам страницы, например так:

//html
<a href="?default=1" class="default">Set Default</a>
//js
document.observe('dom:loaded', function(){
        //get all elements with d 'default' classname
        for(i = 0;i < document.getElementsByClassName('default').length;i++)
        {
                s = document.getElementsByClassName('default')[i];
                //attach an onclick event
                s.observe('click', function(e){
                        //prevent the default action (i.e loading the page)
                        e.preventDefault();
                        //read d link attribute
                        ref = this.readAttribute('href');
                        //and now, do it the ajax way
                        new Ajax.Request('js/ajax/handler.php'+ref, {
                                method:'get',
                                onSuccess:function(transport){}
                        });
                });
        }
});

Работает хорошо. Очень хорошо. Но есть проблема. В большинстве случаев такие действия манипулируют DOM и могут добавить один или несколько элементов класса «по умолчанию» (т.е. где-нибудь еще установить «По умолчанию»). Это на самом деле намеренно. Но затем к новому добавленному элементу класса «по умолчанию» не будет прикреплено событие click. Дерьмовая работа в данный момент заключается в том, чтобы снова пройтись по всем классам «по умолчанию» и повторно присоединить события. Есть другие идеи?

Ответы [ 2 ]

2 голосов
/ 25 августа 2009

Обычный способ решения этой проблемы - делегирование событий. Если вы подключите событие click к контейнеру, который содержит все эти .default элементы, вы можете ответить одним обработчиком:

document.observe('click', function(event) {
    var elm;

    elm = event.findElement('.default');
    if (elm) {
        // do your nifty stuff with the element
    }
});

Это не должно быть document, если они совместно используют какой-то контейнер более высокого уровня. Документы для Event#findElement здесь здесь .

Кстати, у вас большая проблема с производительностью в цикле for. Вы звоните document.getElementsByClassName на каждой итерации! Если вы используете делегирование событий, этот цикл все равно пропадает, но если по какой-то причине это не сработает, назовите его один раз , а затем переберите результат:

var defaults = document.getElementsByClassName('default');
for (i = 0; i < defaults.length; i++)
1 голос
/ 25 августа 2009

Вы можете прослушать все события кликов на странице, а затем использовать цель , чтобы определить, нажал ли пользователь элемент с именем класса по умолчанию «default».

...