Читать «Разгони свой сайт» онлайн - страница 93
Николай Мациевский
Используя этот удобный атрибут, можно создать мини-скрипт, который и будет вызывать наш обработчик onload:
<script defer src="ie_onload.js" type="text/javascript"></script>
Содержание этого внешнего скрипта будет состоять только из одной строчки кода:
init();
Условные комментарии
С этим подходом есть некоторая проблема. Другие браузеры проигнорируют атрибут defer и загрузят этот скрипт сразу же. Существует несколько способов, как можно с этим побороться. Можно воспользоваться условными комментариями, чтобы скрыть «отложенный» скрипт:
<!--[if IE]><script defer="defer" src="ie_onload.js"></script><![endif]-->
IE также поддерживает условную компиляцию. Следующий код будет JavaScript-эквивалентом для заявленного выше HTML-кода:
// для Internet Explorer
/*@cc_on @*/
/*@if (@_win32)
document.write("<script defer=\"defer\"
src=\"ie_onload.js\"><\/script>");
/*@end @*/
Все так просто?
И конечно же, нам нужно обеспечить поддержку для остальных браузеров. У нас есть только один выход — стандартное событие window.onload:
// для остальных браузеров
window.onload = init;
Двойное выполнение
Остается одна маленькая неприятность (кто сказал, что будет легко?). Поскольку мы устанавливаем событие onload для всех (оставшихся) браузеров, то init сработает дважды — в IE и Firefox. Чтобы это обойти, нам нужно сообщить функции, что она должна выполняться только один раз. Итак, наш метод init будет выглядеть примерно так:
function init() {
// выходим, если функция уже выполнялась
if (arguments.callee.done) return;
// устанавливаем флаг, чтобы функция не исполнялась дважды
arguments.callee.done = true;
// что-нибудь делаем
};
Стоит также рассмотреть выставление глобальной переменной READY в данном случае. Ведь иногда знать, что страница начала функционировать, может потребоваться не только одной функции init.
Избавляемся от внешнего файла
У описанного решения существует пара минусов:
Для IE нам требуется внешний JavaScript-файл.
Не поддерживается Safari (Opera 9 поддерживает DOMContentLoaded).
Однако есть решение и для Internet Explorer, которое не зависит от внешних файлов (к сожалению, на данный момент вызывает предупреждение безопасности в IE7 при использовании защищенного соединения):
// для Internet Explorer (используем условную компиляцию)
/*@cc_on @*/
/*@if (@_win32)
<\/script>");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
init(); // вызываем обработчик для onload
}
};
/*@end @*/
И для Safari!
if (/WebKit/i.test(navigator.userAgent)) { // условие для Safari
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {