Как проверить, готова ли DOM без рамки?
Вопрос так похож на миллион других здесь и в Интернете. Как проверить, загружен ли DOM в Javascript? Но вот улов:
- Без использования фреймворка, такого как jQuery и т.д.
- Не зная, загружен ли ваш script через статически размещенный тег
<script>
или через какой-либо другой Javascript гораздо позже после того, как DOM уже загружен.
Можно ли это сделать более или менее надежно и с кросс-браузерной совместимостью?
Добавлено: Позвольте мне пояснить: я пишу автономный файл .JS, который может быть включен в произвольные веб-страницы. Я хочу выполнить код ПОСЛЕ, DOM был загружен. Но я не знаю КАК мой script будет включен. Это может быть путем размещения тега <script>
(в этом случае будут использоваться традиционные решения onload
или DOM-готовность); или он может быть загружен через AJAX или некоторые другие средства, намного позже после того, как DOM уже загружен (так что ранее упомянутые решения никогда не будут срабатывать).
Ответы
Ответ 1
Свойство document.readyState
можно использовать для проверки готовности документа. Из MDN:
Значения
ReadyState документа может быть одним из следующих:
- загрузка - документ все еще загружается.
- интерактивный - документ завершил загрузку, и документ был проанализирован, но все еще загружаются подресурсы, такие как изображения, таблицы стилей и рамки.
- завершено - документ и все подресурсы завершили загрузку. Состояние указывает, что событие load вот-вот сработает.
Пример кода:
if(document.readyState === "complete") {
// Fully loaded!
}
else if(document.readyState === "interactive") {
// DOM ready! Images, frames, and other subresources are still downloading.
}
else {
// Loading still in progress.
// To wait for it to complete, add "DOMContentLoaded" or "load" listeners.
window.addEventListener("DOMContentLoaded", () => {
// DOM ready! Images, frames, and other subresources are still downloading.
});
window.addEventListener("load", () => {
// Fully loaded!
});
}
Ответ 2
В браузерах Firefox, Opera и Webkit есть событие уровня документа DOMContentLoaded
, которое вы можете прослушать с помощью document.addEventListener("DOMContentLoaded", fn, false)
.
Это сложнее в IE. Что делает jQuery в IE, это смотреть onreadystatechange
на объект документа для определенного readystate с резервной копией события document.onload. document.onload срабатывает позже, чем DOM готов (только когда все изображения закончили загрузку), поэтому он используется только в качестве блокиратора обратного хода, если предыдущие события не работают по какой-либо причине.
Если вы потратите некоторое время на Google, вы найдете код для этого. Я считаю, что наиболее проверенный код для этого - в больших рамках, таких как jQuery и YUI, поэтому, даже если я не использую эту структуру, я смотрю их исходный код для техник.
Здесь основная часть источника jQuery 1.6.2 для document.ready()
:
bindReady: function() {
if ( readyList ) {
return;
}
readyList = jQuery._Deferred();
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( jQuery.ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", jQuery.ready, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent( "onreadystatechange", DOMContentLoaded );
// A fallback to window.onload, that will always work
window.attachEvent( "onload", jQuery.ready );
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
},
Ответ 3
Если полагаться на document.readyState
в порядке, быстрое и грязное решение с опросом:
(function() {
var state = document.readyState;
if(state === 'interactive' || state === 'complete') {
// do stuff
}
else setTimeout(arguments.callee, 100);
})();
Ответ 4
Это работает для всех браузеров и является коротким и кратким:
var execute = function () {
alert("executing code");
};
if ( !!(window.addEventListener) )
window.addEventListener("DOMContentLoaded", execute)
else // MSIE
window.attachEvent("onload", execute)
Ответ 5
Событие DOMContentLoaded
запускается, когда исходный HTML-документ полностью загружен и проанализирован, не дожидаясь завершения стилей, изображений и подкадров, чтобы завершить загрузку. Хорошая вещь: хром, firefox, IE9, опера и сафари поддерживают его в равной степени
document.addEventListener("DOMContentLoaded", function(event)
{
console.log("DOM fully loaded and parsed");
}
ПРИМЕЧАНИЕ. Internet Explorer 8 поддерживает событие readystatechange, которое может использоваться для обнаружения, когда DOM готов.
Ответ 6
Вот один из способов, запустив script в нижней части страницы. Кроме того, используя window.onload, вы можете дождаться загрузки всех изображений/скриптов. Или вы можете просто поместить код внизу, не дожидаясь загрузки изображений.
<html>
<head>
</head>
<body>
</body>
<script language="text/javascript">
window.onload = (function (oldOnLoad) {
return function () {
if (oldOnLoad) {
olOnLoad(); //fire old Onload event that was attached if any.
}
// your code to run after images/scripts are loaded
}
})(window.onload);
// your code to run after DOM is loaded
</script>
</html>
Отредактировано: для комментария Vilx
Многие привязки onload - это пример http://jsfiddle.net/uTF2N/3/