Javascript - Как определить, загружен ли документ (IE 7 / Firefox 3)

163

Я хочу вызвать функцию после загрузки документа, но документ может или не может завершить загрузку еще. Если он загрузился, то я могу просто вызвать функцию. Если он НЕ загружается, тогда я могу прикрепить прослушиватель событий. Я не могу добавить список событий после того, как onload уже запущен, так как он не будет вызван. Так как я могу проверить, загружен ли документ? Я попробовал код ниже, но он не совсем работает. Любые идеи?

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if (body && body.readyState == 'loaded') {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
Marcos
источник
5
«Я хочу вызвать функцию после загрузки документа, но документ может или не может завершить загрузку». Это не вычисляет.
Ричард Симойс
7
Я полагаю, что он имеет в виду, что он не контролирует, когда первоначально запускается его блок кода, но хочет убедиться, что DoStuffFunction () не вызывается до завершения загрузки документа.
Бен Бланк

Ответы:

257

Нет необходимости во всем коде, упомянутом галамбалазами. Кросс-браузерный способ сделать это на чистом JavaScript - это просто проверить document.readyState:

if (document.readyState === "complete") { init(); }

Это также, как это делает jQuery.

В зависимости от того, где загружен JavaScript, это может быть сделано в интервале:

var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
        clearInterval(readyStateCheckInterval);
        init();
    }
}, 10);

На самом деле document.readyStateможет иметь три состояния:

Возвращает «загрузку» во время загрузки документа, «интерактивную» после завершения анализа, но по-прежнему загружая подресурсы, и «завершенную» после загрузки. - document.readyState в сети разработчиков Mozilla

Так что, если вам нужен только DOM, проверьте document.readyState === "interactive". Если вам нужна вся страница, включая изображения, проверьте document.readyState === "complete".

Laurent
источник
3
@costa, если document.readyState == "complete"это означает, что все, включая изображения, были загружены.
Лоран
Я использую комбинацию обоих событий и document.readyStateчтобы убедиться, что функция запускается после анализа DOM или позже, в зависимости от того, когда она была вызвана. Есть ли мероприятие для интерактива readyState ?
Томаш Зато - Восстановить Монику
3
Я бы использовал /loaded|complete/.test(document.readyState). Некоторые браузеры устанавливают document.readyState«загружен» вместо «завершен». Кроме того, document.readyState НЕ гарантирует, что шрифты были загружены, нет действительно хорошего способа проверить это без плагина.
Райан Тейлор
2
Как насчет document.onreadystatechange? Это кажется более упорядоченным, если браузеры поддерживают его. stackoverflow.com/questions/807878/…
2
Я думаю, что было бы лучше проверить document.readyState !== "loading"состояние "DOM ready". Это предотвращает возникновение проблем, если readyStateпо какой-либо причине проверка выполняется поздно (после «интерактивного» состояния).
Rnevius
32

Нет необходимости в библиотеке. JQuery использовал этот сценарий некоторое время, кстати.

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
window.onload = init;
gblazex
источник
1
Именно то, что я искал - функция jQuery.ready без библиотеки jQuery. Thanx!
stricjux
3
Совершенно упустил суть вопроса. initне будет работать, если этот код, который вы опубликовали, включен после того, как страница уже загружена, что является точкой ОП: он / она не может контролировать, когда включен его сценарий. (обратите внимание, что setIntervalбудет работать только ветка)
Роатин Март,
3
Это принадлежит в библиотеке. Наряду со всеми другими колесами люди обычно заново изобретают.
b01
14

Вы, вероятно, хотите использовать что-то вроде jQuery, что облегчает программирование на JS.

Что-то вроде:

$(document).ready(function(){
   // Your code here
});

Казалось бы, делать то, что вы после.

Дан
источник
2
И если он хочет увидеть, как jQuery делает это портативным способом, источник jQuery будет для проверки :-)
Томас Л. Холэдэй
7
А в случае, если непонятно, ready()вызывается ли после загрузки документа, переданная функция запускается немедленно.
Бен Бланк
2
@Ben Blank: если, конечно, сам jQuery не включен после загрузки документа;)
Роатин Март,
@Roatin Marth - На самом деле, это тоже хорошо работает. (Только что попробовал с jQuery 1.7.1 на FF8 и IE8.)
Бен Бланк
35
-1: даже если ответ имеет смысл, ОП никогда не упоминал jQuery. Использование всего проекта jQuery просто для того, чтобы подготовить документ, является излишним.
Marcgg
8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
Jman
источник
Не похоже на работу в последней Chrome document.loadedвсегда определено
Аникет
это был 2010 год :). Теперь я буду использоватьbody.readyState === 'loaded'
Jman
6

Если вы действительно хотите, чтобы этот код выполнялся при загрузке , а не при загрузке (т. Е. Необходимо, чтобы изображения также загружались), то, к сожалению, функция ready не делает этого за вас. Я вообще просто делаю что-то вроде этого:

Включить в документ javascript (то есть всегда вызывать до запуска onload):

var pageisloaded=0;
window.addEvent('load',function(){
 pageisloaded=1;
});

Тогда ваш код:

if (pageisloaded) {
 DoStuffFunction();
} else {
 window.addEvent('load',DoStuffFunction);
}

(Или эквивалент в вашей структуре предпочтений.) Я использую этот код для предварительного кэширования javascript и изображений для будущих страниц. Поскольку материал, который я получаю, вообще не используется для этой страницы, я не хочу, чтобы он имел приоритет над быстрой загрузкой изображений.

Возможно, есть лучший способ, но я еще не нашел его.

Натан Стретч
источник
4

Mozila Firefox говорит, что onreadystatechangeэто альтернатива DOMContentLoaded.

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "complete") {
        initApplication();
    }
}

В документе DOMContentLoadedМозила говорится:

Событие DOMContentLoaded наступает, когда документ полностью загружен и проанализирован, не дожидаясь окончания загрузки таблиц стилей, изображений и подкадров (событие загрузки может использоваться для обнаружения полностью загруженной страницы).

Я думаю, что loadсобытие должно использоваться для полной загрузки документа + ресурсов.

Мостафа Талеби
источник
3

Вышеупомянутый с JQuery является самым простым и наиболее часто используемым способом. Однако вы можете использовать чистый javascript, но попытаться определить этот скрипт в голове, чтобы он читался в начале. То, что вы ищете, это window.onloadсобытие.

Ниже приведен простой скрипт, который я создал для запуска счетчика. Счетчик останавливается после 10 итераций

window.onload=function()
{
    var counter = 0;
    var interval1 = setInterval(function()
    { 
        document.getElementById("div1").textContent=counter;
        counter++; 
        if(counter==10)
        {
            clearInterval(interval1);
        }
    },1000);

}
Talha
источник
2

Попробуй это:

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if ((body && body.readyState == 'loaded') || (body &&  body.readyState == 'complete') ) {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload',DoStuffFunction);
    }
}
Smit
источник
1

У меня есть другое решение, мое приложение должно быть запущено при создании нового объекта MyApp, поэтому оно выглядит так:

function MyApp(objId){
     this.init=function(){
        //.........
     }
     this.run=function(){
          if(!document || !document.body || !window[objId]){
              window.setTimeout(objId+".run();",100);
              return;
          }
          this.init();
     };
     this.run();
}
//and i am starting it 
var app=new MyApp('app');

это работает на всех браузерах, которые я знаю.

Витус
источник