Проблема window.onload() и ее решение
Собственно, вся проблема состоит в том, что событие onload() возникает после полной загрузки документа. Конечно, было бы здорово выполнить какие-нибудь действия с загруженным html-документом не дожидаясь загрузки изображений, flash-роликов и пр.
В браузерах Mozilla, а также в Opera9 для этого определено событие(не документированное) DOMContentLoaded
. Для них, чтобы определить, что html-код документа уже загружен достаточно будет написать:
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", init, false);
}
Internet Explorer при массе недостатков имеет и некоторые достоинства, к которым можно отнести поддержку атрибута defer
для тэга . Этот атрибут сообщает браузеру, что скрипт не должен быть запущен для генерации какого-либо контента(например, "document.write" в javascript), а браузер может продолжить загрузку документа, его обработку и вывод. Чтобы скрипт, написанный для IE, не обрабатывали другие браузеры - его придется заключить в комментарии, понятные только самому же IE. Для Internet Explorer скрипт такой:
/*@cc_on @*/
/*@if (@_win32)
document.write("
Для Safari подойдет такой код:
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
clearInterval(_timer);
delete _timer;
init(); // call the onload handler
}
}, 10);
}
А для остальных браузеров, которые не Mozilla, не Opera9 (не используют DOMContentLoaded) и не IE (выполняют скрипт немедленно, не обращая внимание на атрибут defer) и не Safari, остается использовать обыкновенный:
window.onload = init;
Как можно было заметить, все примеры вызвают функцию init(), поэтому следующий код посвящен именно ей:
function init() {
// выход из функции, если она уже вызывалась
if (arguments.callee.done) return;
// флаг, чтобы не запускать функцию дважды
arguments.callee.done = true;
// далее пишите скрипт
}
Полный пример кроссбраузерного решения описанной проблемы.
Замечу, что скрипт лучше брать из примера, а для демонстрации работы скрипта используется "тяжелая" (примерно 1,5МБ) картинка. Javascript в примере размещен внутри html-документа с единственной целью - так проще его продемонстрировать. Javascript из примера правильнее размещать в отдельном файле (например, script.js).
The window.onload Problem - Solved!
window.onload (again)
А ведь все можно сделать намного проще! Достаточно лишь проверять загружено ли тело документа через определенные промежутки времени.
Вот здесь можно взглянуть на мой пример:
тест
2006-06-21 at 1:19 pm
Почему бы просто перед закрытием body не вызвать функцию init.
2006-06-21 at 1:40 pm
Насколько я знаю, проблема таких очевидных решений по крайней мере в gecko в том что ДО нступления определенного момента (очевидно DOMContentLoaded) не гарантируется полный доступ к DOM, т.е. корректная работа getElementById/cloneNode/appendChild
сразу скажу что эксперименты чаще всего показывают обратное :)
2006-06-21 at 11:21 pm
AKS, наверное, так тоже можно, хотя правильно ли проверять загрузку body? для чистоты эксперимента предлагаю попробовать на каком-нибудь большом документе. clearTimeout тоже не помешал бы, думаю. кстати, к картинке надо случайное число добавить в примере, а то она в кэше остается, приходится чистить, чтобы посмотреть еще раз.
2006-06-26 at 11:47 pm
Vitaly Harisov, если вас не смущает смесь html и javascript в одном файле, то можно и так сделать. однако, в том случае, когда по каким-либо причинам не загрузится внешний файл с javascript, а функцию init разместите именно в нем, то последует предупреждение об ошибке, что вряд ли украсит сайт. в-общем, так действительно просто, но и не лишено недостатков.
2006-06-26 at 11:55 pm
Андрей, я ведь не готовое решение предложил, лишь концепт. На самом деле, лучше проверять нужно загрузку тех элементов, с которыми нам не терпится начать работать.
clearTimeout? Так ведь при выполнении первого условия в функции test таймера просто нет…
?, вообще, мне придется скоро убрать пример – не мой домен, так что не до картинки…
2006-06-27 at 8:41 am
AKS, давайте его здесь тогда разместим, все-таки для обсуждения лучше видеть обсуждаемый предмет.
… собственно, теперь он уже здесь. .
2006-06-27 at 10:02 am
А почему нельзя ?
2006-07-04 at 12:57 pm
Съелись тэги.
&lgbody onload=”init ()”>
2006-07-04 at 12:58 pm
2 Виктор
Вы что, не прочли первый параграф?
2006-07-04 at 3:35 pm
Прошу прощения, действительно, не заметил.
2006-07-09 at 10:57 pm
“однако, в том случае, когда по каким-либо причинам не загрузится внешний файл с javascript, а функцию init разместите именно в нем, то последует предупреждение об ошибке, что вряд ли украсит сайт”
Решается очень просто:
if(init) init();
Но в любом случае, если уж вынесли скрипт в отдельный файл, то придется дожидаться события onload. ?ли добавлять вызов init() в конец файла со скриптом.
2006-08-01 at 4:18 pm
а если нужно запустить скрипт из основной формы
до загрузки страницы внутри Iframe (грузится долго)
то как такое сделать
2007-12-05 at 1:08 pm