onLoad, readyState, DOMContentLoaded

18th August 2005 - 18:55

[info]david_m напомнил вопрос, который давно хотелось поковырять. Так как все интересные вопросы имеют свойство заявлять о своём существовании именно тогда, когда разгребается завал вопросов менее интересных, то я просто приведу куски того кода, до которого дотянулись руки, остальное рассматривать не буду.

Берём супер-пупер-валидную-болванку-XHTML и наполняем её следующим содержимым:

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <title>OnLoad Test</title>
  <script type="text/javascript"><!--//--><![CDATA[//><!--
    var a = [];

    function domReady() {
      document.body ? a.push('domReady') : setTimeout('domReady()', 250);
    };
    domReady();

    function test() {
      try {
        a.push(document.getElementsByTagName('p')[0]
          .tagName.toLowerCase() + ':found')
      } catch(e) { a.push('p:null') }
    };
    
    typeof document.onbeforeactivate != 'undefined' ? document.onbeforeactivate = test :
        document.addEventListener('DOMContentLoaded', test, null);

    window.onload = function() {
      a.push('window.onload');
      alert(a);
    }
  //--><!]]></script>
</head>
<body>
  <p><img alt="" src="test.gif.php" onload="a.push('img.onload')"/></p>
  <script type="text/javascript">a.push('body-script')</script>
</body>
</html>
<?php
  // test.gif.php
  sleep(2);
  fpassthru(fopen('test.gif', 'rb'));
?>

domReady — сокращённая версия оригинальной функции domReady (наиболее предпочтительный с точки зрения кроссбраузерности вариант, но есть свои нюансы).

О DOMContentLoaded впервые прочитал в комментариях у Dean Edwards.

Вот то, что выдаёт alert:

  • IE: body-script, p:found, domReady, img.onload, window.onload
  • Mozilla: body-script, p:found, domReady, img.onload, window.onload
  • Opera: body-script, domReady, img.onload, window.onload

В IE можно привязаться к другим событиям, например, onreadystatechange (здесь файрить будет дважды: сначала readyState == interactive, потом complete. Можно проверять значение или просто обнулить после первого срабатывания). Но это уже мелочи.

Opera… Эх, Opera… Есть лишь readyState, отследить изменение которого не представляется возможным.

Между делом, пока искал хоть какое-нибудь решение, существенно отличающееся от domReady, решил подлить валидности (всё-таки супер-пупер-XHTML, а не кисель какой), узаконив img.onload:

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
[<!ATTLIST img onload CDATA #IMPLIED>]>

В Mozilla и IE работа функции domReady сбилась и начала срабатывать раньше реальной загрузки страницы. Сама страница отдавалась как text/html. После смены на корректный application/xhtml+xml, Mozilla убирает «баг» отрисовки символов ]> и срабатывание domReady возвращается на положеное место. В Opera же при таком MIME-Type domReady «убегает» на первое место, срабатывая до «body-script» (что не расходится с действительностью, т.к. уже можно бродить по DOMу). Кто-то сказал «IE»? ;)

Терзают смутные сомнения, что помимо MIME-Type поведение domReady могут изменить и другие вещи, но на проверку этих сомнений времени нет.

Categories: dHtml | comments: (0)

Комментарии временно отключены.