Javascript - Cara mendeteksi apakah dokumen telah dimuat (IE 7 / Firefox 3)

163

Saya ingin memanggil fungsi setelah dokumen dimuat, tetapi dokumen mungkin atau mungkin belum selesai memuat. Jika itu memuat, maka saya bisa memanggil fungsi. Jika TIDAK dimuat, maka saya dapat melampirkan pendengar acara. Saya tidak dapat menambahkan daftar acara setelah onload telah dipecat karena tidak akan dipanggil. Jadi bagaimana saya bisa mengecek apakah dokumen sudah dimuat? Saya mencoba kode di bawah ini tetapi tidak sepenuhnya berfungsi. Ada ide?

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
sumber
5
"Saya ingin memanggil fungsi setelah dokumen dimuat, tetapi dokumen mungkin atau mungkin belum selesai memuat." Ini tidak menghitung.
Richard Simões
7
Saya percaya dia berarti dia tidak memiliki kontrol ketika blok kode awalnya dijalankan, tetapi ingin memastikan DoStuffFunction () tidak dipanggil sebelum dokumen selesai dimuat.
Ben Blank

Jawaban:

257

Tidak perlu untuk semua kode yang disebutkan oleh galambalazs. Cara lintas-browser untuk melakukannya dalam JavaScript murni hanya dengan menguji document.readyState:

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

Ini juga bagaimana jQuery melakukannya.

Bergantung pada tempat JavaScript dimuat, ini dapat dilakukan di dalam interval:

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

Bahkan, document.readyStatedapat memiliki tiga negara:

Mengembalikan "memuat" saat dokumen memuat, "interaktif" setelah selesai diurai tetapi masih memuat sub-sumber daya, dan "selesai" setelah dimuat. - document.readyState di Mozilla Developer Network

Jadi, jika Anda hanya perlu DOM untuk siap, periksa document.readyState === "interactive". Jika Anda perlu seluruh halaman siap, termasuk gambar, periksa document.readyState === "complete".

laurent
sumber
3
@costa, jika document.readyState == "complete", artinya semuanya, termasuk gambar, telah dimuat.
laurent
Saya menggunakan kombinasi dari kedua peristiwa dan document.readyStateuntuk memastikan fungsi dimulai setelah DOM telah diuraikan, atau yang lebih baru, tergantung pada saat dipanggil. Apakah ada acara interaktif readyState ?
Tomáš Zato - Reinstate Monica
3
Saya akan menggunakan /loaded|complete/.test(document.readyState). Beberapa browser diatur document.readyStateke "dimuat" alih-alih "lengkap". Juga, document.readyState TIDAK memastikan font telah dimuat, tidak ada cara yang sangat baik untuk menguji tanpa plugin.
Ryan Taylor
2
Bagaimana dengan document.onreadystatechange? Ini tampak lebih ramping jika browser mendukungnya. stackoverflow.com/questions/807878/…
2
Saya pikir akan lebih baik untuk memeriksa document.readyState !== "loading", untuk keadaan "DOM ready". Ini mencegah masalah muncul jika readyStatediperiksa terlambat karena alasan tertentu (setelah keadaan "interaktif").
rnevius
32

Tidak perlu perpustakaan. jQuery menggunakan skrip ini untuk sementara waktu, btw.

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
sumber
1
Persis apa yang saya cari - jQuery.ready berfungsi tanpa perpustakaan jQuery. Terima kasih!
stricjux
3
Benar-benar melewatkan inti pertanyaan. inittidak akan berjalan jika kode yang Anda posting dimasukkan setelah halaman telah dimuat, yang merupakan poin OP: ia tidak dapat mengontrol kapan skripnya disertakan. (perhatikan bahwa hanya setIntervalcabang yang akan bekerja)
Roatin Marth
3
Ini milik perpustakaan. Seiring dengan semua roda lainnya orang biasanya menemukan kembali.
B01
14

Anda mungkin ingin menggunakan sesuatu seperti jQuery, yang membuat pemrograman JS lebih mudah.

Sesuatu seperti:

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

Tampaknya akan melakukan apa yang Anda cari.

dan
sumber
2
Dan jika dia ingin melihat bagaimana jQuery melakukannya dengan cara yang portabel, sumber jQuery ada di sana untuk inspeksi :-)
Thomas L Holaday
7
Dan jika tidak jelas, jika ready()dipanggil setelah pemuatan dokumen, fungsi yang diteruskan dijalankan segera.
Ben Blank
2
@ Ben Blank: kecuali tentu saja jQuery sendiri disertakan setelah dokumen dimuat;)
Roatin Marth
@Roatin Marth - Sebenarnya, itu berfungsi dengan baik juga. (Baru mencobanya dengan jQuery 1.7.1 pada FF8 dan IE8.)
Ben Blank
35
-1: bahkan jika jawabannya masuk akal OP tidak pernah menyebutkan jQuery. Menggunakan seluruh proyek jQuery hanya untuk mendapatkan dokumen siap adalah cara yang berlebihan.
marcgg
8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
Jman
sumber
Tampaknya tidak berfungsi di Chrome terbaru document.loadedselalu tidak ditentukan
Aniket
ini 2010 :). Sekarang saya akan menggunakanbody.readyState === 'loaded'
Jman
6

Jika Anda benar-benar ingin kode ini dijalankan dimuat , bukan di domready (yaitu Anda perlu memuat gambar juga), maka sayangnya fungsi siap tidak melakukannya untuk Anda. Saya biasanya hanya melakukan sesuatu seperti ini:

Sertakan dalam javascript dokumen (yaitu selalu dipanggil sebelum onload dipecat):

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

Kemudian kode Anda:

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

(Atau yang setara dalam kerangka preferensi Anda.) Saya menggunakan kode ini untuk melakukan pendahuluan tentang javascript dan gambar untuk halaman selanjutnya. Karena hal-hal yang saya dapatkan sama sekali tidak digunakan untuk halaman ini, saya tidak ingin itu lebih diutamakan daripada mengunduh gambar dengan cepat.

Mungkin ada cara yang lebih baik, tetapi saya belum menemukannya.

Nathan Stretch
sumber
4

Mozila Firefox mengatakan itu onreadystatechangeadalah alternatif untuk DOMContentLoaded.

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

Dalam DOMContentLoadeddokumen Mozila mengatakan:

Acara DOMContentLoaded dipecat ketika dokumen telah dimuat dan diuraikan sepenuhnya, tanpa menunggu stylesheet, gambar, dan subframe untuk menyelesaikan pemuatan (peristiwa pemuatan dapat digunakan untuk mendeteksi halaman yang dimuat penuh).

Saya pikir loadacara harus digunakan untuk memuat dokumen lengkap + sumber daya.

Mostafa Talebi
sumber
3

Yang di atas dengan JQuery adalah cara termudah dan sebagian besar digunakan. Namun Anda dapat menggunakan javascript murni tetapi mencoba untuk mendefinisikan skrip ini di kepala sehingga dibaca di awal. Apa yang Anda cari adalahwindow.onload acara.

Di bawah ini adalah skrip sederhana yang saya buat untuk menjalankan penghitung. Penghitung kemudian berhenti setelah 10 iterasi

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

}
Talha
sumber
2

Coba ini:

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);
    }
}
sial
sumber
1

Saya punya solusi lain, aplikasi saya harus dimulai ketika objek baru MyApp dibuat, jadi sepertinya:

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');

itu bekerja pada semua browser, yang saya tahu.

vitus
sumber