Показать сообщение отдельно
  #3 (permalink)  
Старый 10.11.2009, 08:56
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

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 $;
};

})();

Последний раз редактировалось Riim, 10.11.2009 в 09:15.
Ответить с цитированием