Читать «Разгони свой сайт» онлайн - страница 100
Николай Мациевский
Загружается меньше кода на странице. Одной из главных проблем для сложных веб-приложений является задержка при загрузке JavaScript для исполнения и визуализации документа. Два цикла из первого примера отсутствуют во втором.
«Исполнение по требованию». Второй пример выполняет немного больше действий, когда вызывается конечный обработчик событий, но это лучше, чем выполнять все действия при загрузке страницы, когда мы даже не знаем, будет ли запущен каждый конкретный обработчик событий. Ссылок на странице может быть сотня, а пользователь нажмет только одну или две из них.
Боремся с Internet Explorer
Есть одна небольшая проблема при использовании изложенного выше кода. Определение целевого элемента у события, на самом деле, не является просто вызовом e.target. В Internet Explorer необходимо использовать e.srcElement. Самым простым решением для устранения этой проблемы является небольшая функция getEventTarget. Ниже представлена наиболее актуальная версия.
function getEventTarget(e) {
var e = e || window.event;
var target = e.target || e.srcElement;
if (target.nodeType == 3) { // боремся с Safari
target = target.parentNode;
}
return target;
}
Переопределение событий в настоящее время является самой распространенной практикой, если речь заходит о большом числе обработчиков событий (например, о карте с сотнями точек, к которым назначены обработчики событий-кликов). Лучше всего для этого по умолчанию использовать простой, интуитивно понятный и хорошо оптимизированный метод для применения в качестве шаблона в программировании на стороне клиента, и он не должен требовать сотен строчек JavaScript-библиотек для своей работы.
Пойдем дальше
А что, если нам нужно добавить такой обработчик на все ссылки (или почти на все)? Правильно: тогда для контейнера всех этих ссылок стоит выбрать document.body. Ниже приведен пример кода, который позволяет так сделать.
var MenuNavigation = {
init: function() {
document.body.onclick = function(e) {
var target = getEventTarget(e);
if ( target && /bundle/i.test(target.className) ) {
target.href += '?name=value';
}
return true;
};
}
var getEventTarget = function(e) {
var e = e || window.event;
var target = e.target || e.srcElement;
// боремся с Safari и вложенностью
while ( !target.href || target.nodeType == 3 ) {
target = target.parentNode;
}();
return target;
}
}
window.onload = MenuNavigation.init;
Если мы собираемся обрабатывать все ссылки, то нужно учесть, что в них могут быть вложены и картинки, и другие теги, поэтому добавлено рекурсивное «всплытие» ссылки: проверяется родитель объекта, на котором сработало событие, и если у него не определен атрибут href, то перебор продолжается, иначе возвращаем искомый объект. Вложение ссылок друг в друга запрещено стандартами, так что если мы сами же проектируем HTML-код, то бояться нечего.
Обработка событий в браузерах