Читать «Разгони свой сайт» онлайн - страница 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)) {