DOMContentLoaded и defer
Искал в сети как отловить событие загрузки DOM.
Нашел следующий два скрипта 1. Это я вырезал из js кода одноклассников
var d = document, t = this, safariTimeout;
if (/WebKit/i.test(navigator.userAgent)) {
safariTimeout = setInterval(function(){if (/loaded|complete/.test(d.readyState)) {clearInterval(safariTimeout); t.runHandlers() }}, 100);
} else if (d.addEventListener) {
d.addEventListener("DOMContentLoaded", function(){t.runHandlers()}, false);
} else if (d.all && !window.opera) {
var s = d.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", "");
s.setAttribute("defer", "true");
s.onreadystatechange = function(){if (this.readyState == "complete") t.runHandlers()}
this.h.insertBefore(s, this.h.firstChild);
}
и второй
(function(i) {
var u = navigator.userAgent;
var e=/*@cc_on!@*/false;
var st = setTimeout;
if(/webkit/i.test(u)){
st(function(){
var dr=document.readyState;
if(dr=="loaded"||dr=="complete"){
i()
}
else{
st(arguments.callee,10);
}
},10);
}
else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
document.addEventListener("DOMContentLoaded",i,false);
}
else if(e){
(function(){
var t=document.createElement('doc:rdy');
try{
t.doScroll('left');
i();
t=null;
}
catch(e){
st(arguments.callee,0);
}
})();
}
else{
window.onload=i;
}
})(init);
где init это название вызываемой функции при загрузке DOM. В коде одноклассников все ясно, а как тут реализовали проверку в ИЕ? и еще вопрос, всегда ли корректно работает аттрибут defer? И можете чуть подробнее пояснить, что сделали в однок. для ИЕ?Заранее спасибо! |
По-моемк код в try вызывает в ie ошибку и выполняется catch
|
1. необходимо еще на всякий случай устанавливать обычный load для древних браузеров, которые совсем тупые. Я имею в виду не вручную это делать, а скрипт сам должен учитывать это. Во втором способе это делается, но через жопу, а надо через addEventListener и attachEvent.
2. кусок
if (/WebKit/i.test(navigator.userAgent)) {
safariTimeout = setInterval(function(){if (/loaded|complete/.test(d.readyState)) {clearInterval(safariTimeout); t.runHandlers() }}, 100);
написан для safari2, который давно умер (да и не пользовался им никто под windows, слишком глючный был). Т. е. его (safari2) можно (даже нужно, зачем поддерживать лишний код из-за 0.00....01% посетителей) отнести к "остальным" браузерам, для которых делается обычный load (пункт 1). А в safari3 отлично работает DOMContentLoaded. 3. способ с defer появился раньше, чем с doScroll. Сейчас почти все известные фреймворки перешли на doScroll, наверное, он чем-то лучше, но я как не тестировал defer, так и не смог понять чем он плох, все отлично работает, и так как я понимаю этот способ лучше, то использую именно его. 4. в обоих вариантах есть моменты, которые теоретически могут привести к memory leak. Мой вариант (все добавленные события удаляются, ссылка на созданный элемент script не попадает ни в какие замыкания, script.onreadystatechange обнуляется, сам элемент script удаляется из dom, в общем, все аккуратно и полностью чистится, никаких memory leak):
$.isReady = false;
$.ready = (function() {
var handlers = [], load = function() {
if ($.isReady) return;
$.isReady = true;
$d.removeEventListener && $d.removeEventListener('DOMContentLoaded', load, false);
if (IE) {
var script = $d.getElementById('_defered');
if (script) {
script.onreadystatechange = null;
Element.remove(script);
}
}
Event.remove($w, 'load', load);
var i = 0, length = handlers.length;
while (i < length) handlers[i++].call($d);
handlers.length = 0;
};
$d.addEventListener && $d.addEventListener('DOMContentLoaded', load, false);
if (IE) {
$d.write('<script type="text/javascript" src="javascript:void(0);" id="_defered" defer="defer"><\/script>');
$d.getElementById('_defered').onreadystatechange = function() {
this.readyState == 'complete' && load();
};
}
Event.add($w, 'load', load);
return function(handler) {
$.isReady ? handler.call($d) : handlers.push(handler);
return $;
};
})();
|
Цитата:
|
Octane, можно чуть подробней?
|
Чтобы сделать возможным загрузку скрипта с фреймворком, как будто у него атрибут defer установлен. Для оптимизации скорости загрузки страницы используют. Ну или, чтобы использовать вот такую модную штуку: http://code.google.com/intl/ru/apis/ajaxlibs/
|
Riim,
Спасибо, что подсказали на счет удаления событий. Octane, А способ использующий в одноклассниках тоже блокирующий загрузку скрипта? или insertBefore не работает как doScroll ? |
и можно было бы по подробнее объяснить вот этот кусок кода
var t=document.createElement('doc:rdy');
try{
t.doScroll('left');
i();
t=null;
}
catch(e){
st(arguments.callee,0);
}
что это за элемент и как к нему относится doScroll |
Цитата:
Цитата:
<script type="text/javascript">var a = 1</script> <script type="text/javascript" src="script.js"></script> <script type="text/javascript">alert(a); // 2</script> script.js a = 2 А при неблокирующей загрузке: <script type="text/javascript">var a = 1</script> <script type="text/javascript" defer="defer" src="script.js"></script> <script type="text/javascript">alert(a); // 1</script> script.js a = 2 Кстати, defer поддерживает не только IE, но и новые версии Firefox. Цитата:
|
Octane,
Спасибо большое за ответ! |
| Часовой пояс GMT +3, время: 07:18. |