Текст ниже — перевод статьи "Unobtrusive Javascript", чей автор Christian Heilmann любезно дал мне согласие на перевод. Оригинальный адрес статьи http://www.onlinetools.org/articles/unobtrusivejavascript/chapter4.html
Главная техника, которую мы используем, чтобы сохранить наш Javascript ненавязчивым, это хранение скрипта в отдельном файле, что предпочтительней, чем смешивать его с разметкой страницы. Чтобы исполнить функции в нашем .js файле, нам надо вызвать их, когда страница загружена. Это может быть достигнуто различными способами, каждый имеет свои достоинства и недостатки.
Когда-то давно, когда мы были молоды и невинны, мы добавляли атрибут onload
к элементу body
.
HTML: <body onload="foo();">
Что нам надо запомнить — мы поступали плохо и больше так не будем!
Если мы вызываем скрипт(ы) в элементе body
, мы возвращаемся к старому, так как продолжаем смешивать разметку и вызовы событий. Переместить вызов скрипта в файл .js — вот что нам надо сделать.
Мы вызываем скрипт, прикрепляя вызов к событию onload
объекта window
.
Когда у нас только одна функция, мы не ставим круглых скобок на конце имени функции, это должно возвращать результаты функции лучше, чем запускать функцию.
Если у нас более чем одна функция, мы должны, чтобы вызвать остальные, использовать анонимную функцию, в этот раз уже с круглыми скобками.
Javascript: window.onload=foo; или window.onload=function(){ foo(); bar(); baz(); }
Этот метод вызова функций применим, конечно, не только к объекту window. Как показано ранее, мы можем добавить его к любому объекту страницы. Это поддерживается каждым Javascript/DOM браузером.
Недостаток этого решения в том, что мы не совсем ненавязчивы. Если у нас больше чем один подключенный .js, вызываемые скрипты могут переписать вызовы onload один у другого.
Существует возможность добавлять обработчики событий в комплект к уже существующим обработчикам. Довольно печально, что различные браузеры оснащены этой функциональностью по-разному, а IE на Mac'ах так вообще не оснащен.
Эта функциональность реализована, например, в прекрасной многократно используемой функции, написанной Scott Andrew. При вызове функции вы передаете ей объект, который нужно привязать к событию, тип события и имя функции.
function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, false); return true; } else if (obj.attachEvent){ var r = obj.attachEvent(\"on\"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', foo); addEvent(window, 'load', bar);
Очевидный существующий недостаток в том, что функция не привязывает ничего в IE на Macintosh.
Я получил письмо от службы технической поддержки Opera объясняющее, что в предыдущем примере есть упущения, поэтому теперь он отличается от примера на сайте Скотта.
Функция
addEvent
не вполне соответствует стандартам. Она вроде бы должна работать в FireFox, но с тех пор как они пофиксили этот баг, она наверняка не будет больше работать в FireFox. Функция возможно не будет делать того что вы хотите в Опере, которая поддерживает стандарты правильно.Проблема в том, что вы настраиваете "перехватывающий" обработчик события, используя
true
в качестве третьего аргумента в функцииaddEventListener
:if (obj.addEventListener){ obj.addEventListener(evType, fn, true);Этому
true
следовало бытьfalse
. Если переменная равнаtrue
, прослушка события не должна возбуждаться ни для одного элемента для которого она зарегистрирована. Например, если вы используете это с элементомLI
, она не будет ничего делать покаLI
имеет дочерние элементы. Проверьте в Опере :)
События — очень многоплановая и запутанная тема в Javascript. Для разработки веб-сайтов, указанных примеров достаточно, но если мы переходим к разработке веб-приложений, мы можем захотеть большего. Проверьте указанные в дополнении ссылки к полезным статьям, чтобы получить больше информации о событиях и о том, как привязывать их к элементам.