Присоединение и повторное присоединение обработчиков событий

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

//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 и могут добавить один или несколько элементов класса «по умолчанию» (например, где-то еще установить значение по умолчанию). Это намеренно на самом деле. Но тогда к недавно добавленному элементу класса «по умолчанию» не будет прикреплено событие щелчка. На данный момент дерьмовая работа заключается в том, чтобы снова перебрать все классы «по умолчанию» и повторно прикрепить события. Любые другие идеи?


person kehers    schedule 25.08.2009    source источник


Ответы (2)


Обычный способ решить эту проблему — делегирование событий. Если вы перехватываете событие 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++)
person T.J. Crowder    schedule 25.08.2009

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

person Dan Lew    schedule 25.08.2009
comment
Спасибо за ответ. Очень помог - person kehers; 26.08.2009