Пойдем дальше
А что, если нам нужно добавить такой обработчик на все ссылки (или почти на все)? Правильно: тогда для контейнера всех этих ссылок стоит выбрать 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-код, то бояться нечего.
Обработка событий в браузерах
Давайте рассмотрим несколько практических способов работы с обработчиками событий в браузерах. Например, можно назначить обработчик напрямую:
node.onclick = function(){
}
Если нужно несколько событий или просто «осторожничаем», то можно воспользоваться следующей распространенной записью:
if (node.addEventListener)
node.addEventListener('click', function(e){}, false);
else
node.attachEvent('onclick', function(){});
Или таким модицифицированным вариантом (меньше символов):
if (node.attachEvent)
node.attachEvent('onclick', function(){});
else
node.addEventListener('click', function(e){}, false);
Можно также использовать отдельную переменную для обработчика события:
var addEvent = node.attachEvent || node.addEventListener;
addEvent(/*@cc_on 'on'+@*/'click', function(){}, false);
Или записать в одну строку с использованием условной компиляции:
node[/*@cc_on !@*/0 ? 'attachEvent' : 'addEventListener']
(/*@cc_on 'on'+@*/'click', function(){}, false);
Работаем с событиями
Давайте рассмотрим, что мы можем извлечь из события после перехвата его с помощью соответствующего обработчика:
node[/*@cc_on !@*/0 ? 'attachEvent' : 'addEventListener']
(/*@cc_on 'on'+@*/'click', function(e){
var target = e.target || e.srcElement
// или
if (!e.target) {
e.target = e.srcElement
}
// или, если нам надо всего один раз
(e.target || e.srcElement).tagName
// true везде кроме IE, в котором this === window
this == node;
// отменяем всплытие события
if (e.stopPropagation)
e.stopPropagation()
else
e.cancelBubble
// или просто используем вариант, который
// для совместимости работает во всех браузерах.
e.cancelBubble = true
// убираем действие по умолчанию (в данном случае клик)
if (e.preventDefault)
e.preventDefault()
else
e.returnValue = false
// при attachEvent (как здесь) работает только в IE;
// при назначении напрямую (node.onclick) — везде
return false;
}, false):
7.3. Применение «ненавязчивого» JavaScript
В предыдущих разделах были представлены некоторые теоретические аспекты построения клиентской логики, ориентированной на максимальное быстродействие и адекватную ему замену в проблемных случаях. Ниже приведены практические решения по облегчению наиболее характерных сторон клиентского взаимодействия любого сайта: это счетчики посещений и размещение рекламы. Ведь они встречаются сейчас практически на любом веб-проекте.
Принципы «ненавязчивой» рекламы
Итак, как лучше организовывать размещение рекламы на веб-страницах для того, чтобы доставить посетителям сайтов минимум неудобств? Поскольку большинство выводов последуют из анализа техник «ненавязчивого» JavaScript, то раздел озаглавлен именно таким образом. Речь пойдет о клиентской оптимизации использования рекламы на сайтах.
Как было продемонстрировано в исследованиях 2007–2008 годов, большая часть задержек при загрузке страницы у обычного пользователя приходится на долю рекламы, подключаемой в основном через JavaScript. Далее будут рассмотрены основные типы использования рекламы на сайтах и предложены способы (в большинстве своем опробованные на практике) для разгона ее загрузки.
Можно спросить: зачем нам это? Разве разработчики баннерообменных систем, контекстной рекламы и других сложных клиент-серверных приложений уже не подумали за нас о возможных последствиях? Подумали, но можно подумать и дальше. Конвертация показов рекламы в клики/покупки напрямую зависит от общего удобства пользования сайтом. А оно, в свою очередь, значительно ухудшается при обширном применении различных рекламных сетей.