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, время: 09:09. |