<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CTAPbIu_MABP&#039;s BLOG &#187; Opera</title>
	<atom:link href="http://mabp.kiev.ua/tag/opera/feed/" rel="self" type="application/rss+xml" />
	<link>http://mabp.kiev.ua</link>
	<description>энтузиазм = 1/опыт © Старый Мавр</description>
	<lastBuildDate>Sat, 12 May 2012 07:40:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2</generator>
		<item>
		<title>Console2</title>
		<link>http://mabp.kiev.ua/2009/01/05/console2/</link>
		<comments>http://mabp.kiev.ua/2009/01/05/console2/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 17:54:46 +0000</pubDate>
		<dc:creator>CTAPbIu_MABP</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[FireFox]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Opera]]></category>
		<category><![CDATA[Safari]]></category>

		<guid isPermaLink="false">http://mabp.kiev.ua/?p=401</guid>
		<description><![CDATA[Все меньше и меньше остается времени у шестого IE, все больше и больше сайтов объявляют, что они перестают поддерживать дизайн и скрипты для него. Напомню что шестой IE был выпущен в 1999 году то есть 10 лет назад, а до сих пор "популярен". Уже даже сам мелкософт заявил о том что будет распространять седьмой IE [...]]]></description>
			<content:encoded><![CDATA[<p>Все меньше и меньше остается времени у шестого IE, все больше и больше сайтов объявляют, что они перестают поддерживать дизайн и скрипты для него. Напомню что шестой IE был выпущен в 1999 году то есть 10 лет назад, а до сих пор "популярен". Уже даже сам мелкософт заявил о том что будет распространять седьмой IE как стандартное обновление. Но эта тема все еще может быть актуально потому что даже в седьмом IE нет консоли, и потому что в Opera и у Safari она находиться в зачаточном состоянии по сравнению с firebug'ом. Так вот я и решил то пока еще не поздно написать вторую версию консоли. Заодно углубил свои знания и отточил практику. Теперь она работает еще быстрее и надежнее, хотя все еще не лишена кое каких глюков, например типа-массив arguments так и не покорился. И еще я не хочу чтоб вы думали что дальше я начну накладывать какие-то визуальные эффекты типа плавающих дивов вместо аллертов, я не хочу создавать второй furebug lite.</p>
<span id="more-401"></span>
<p>Итак собственно код, его стало немного больше но на много повысилась производительность. Возможно стоило собрать все методы в объект и наверное я это сделаю но не сейчас, сейчас ее надо потестить в реальных условиях.</p>

<pre><code class="html">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;script&gt;
var cast = function(i) {
	// call lazy function definition
	return  (cast = !document.fileSize  // IE any version
		? function(i){return Array.prototype.slice.call(i);}
		: function(i){var l=i.length,a=[];while(l--){a[l]=i[l];}return a;}
	)(i);
},

show = function(m) {
	return (show=window.opera?window.opera.postError:window.alert)(m);
},

dump = function (x, max, sep, l) {
	l = l || 0, max = max || 3, sep = sep || "\t";
	if (l &gt; max) return "[WARNING: Too much recursion]\n";
	var i, r = '', t = typeof x, tab = '';

	if (x === null) {
		r += "(null)\n";
	} else if (t == "object") {
		for (i=0,l++;i&lt;l;i++) {tab += sep;}
		if (x &#038;& (x.length || x.length==0)) {t = 'array';}
		r += "(" + t + ") :\n";
		for (i in x)
			try { r += tab + "[" + i + "] : " + dump(x[i], max, sep, l+1);} catch(e) { return "[ERROR: " + e + "]\n"; }
	} else {
		if (t=="string"&#038;&x=="") 
			x = '(empty)';
		r += "(" + t + ") " + x + "\n";
	}
	return r;

},

myConsole = function(){
	var args = cast(arguments);
	
	if (args.length&gt;2){
		show(args.shift() +":\n"+ args.shift().replace(/(%[ds])/g, function(){
			return args.shift();
			})
		)
	}else{
		show(args.shift() +":\n"+ dump(args.shift()));
	}
};

if (window.loadFirebugConsole) { // since FireBug 1.2
	window.loadFirebugConsole();
} else if (!window.console) {
	window.console = {};
	var names = ["log", "debug", "info", "warn", "error"];
	for (var i in names){
		window.console[names[i]] = (function(name){return function(){
			myConsole.apply(null,[name].concat(cast(arguments)))
		}})(names[i]);
	}
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>И собственно мои тест-кейсы:</p>

<pre><code class="javascript">
window.onload = function(){
	console.log("string: %d %s %d", 10, "text", 10);
	console.info({});
	console.info([]);
	console.info(null);
	console.info(window);
	console.info(document);
	console.info(document.getElementsByTagName("body"));
	console.info(document.getElementsByTagName("body")[0]);
	console.info(Math);
	(function(z){try {x.y = z;}catch(e){console.info(e);}})(null);
	//(function(x,y,z){console.info(arguments)})(1,2,3); // fail

}
</code></pre>]]></content:encoded>
			<wfw:commentRss>http://mabp.kiev.ua/2009/01/05/console2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Консоль для всех браузеров</title>
		<link>http://mabp.kiev.ua/2008/12/25/myconsole/</link>
		<comments>http://mabp.kiev.ua/2008/12/25/myconsole/#comments</comments>
		<pubDate>Thu, 25 Dec 2008 19:43:55 +0000</pubDate>
		<dc:creator>CTAPbIu_MABP</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[FireFox]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Opera]]></category>
		<category><![CDATA[Safari]]></category>

		<guid isPermaLink="false">http://mabp.kiev.ua/?p=312</guid>
		<description><![CDATA[Это попытка заставить работать синтаксис консоли FireBug'a со всеми браузерами. ИМХО кроссбраузерный дебаг звучит не ок, но это именно он! А все получилось как-то само собой когда я сегодня что-то дебажил на тестовой платформе и для того чтобы тестеры не видели ошибок прикрывал вызовы консоли заглушками. if(window.console) console.log("myLog"); В общем это как-то гнило, нашел что [...]]]></description>
			<content:encoded><![CDATA[<p>Это попытка заставить работать синтаксис консоли FireBug'a со всеми браузерами. ИМХО кроссбраузерный дебаг звучит не ок, но это именно он! А все получилось как-то само собой когда я сегодня что-то дебажил на тестовой платформе и для того чтобы тестеры не видели ошибок прикрывал вызовы консоли заглушками.</p>
<span id="more-312"></span>
<pre><code class="javascript">
if(window.console)
	console.log("myLog");
</code></pre>

<p>В общем это как-то гнило, нашел что по данному поводу пишут разработчики <a href="http://mir.aculo.us/2008/12/19/little-javascript-hints-episode-1" rel="nofollow">Prototype</a> и <a href="http://docs.jquery.com/Plugins/Authoring" rel="nofollow">jQuery</a>, и даже сами разработчики FireBug'a склоняются к <a href="http://getfirebug.com/firebug/firebugx.js" rel="nofollow">заглушкам</a></p>
<p>Уж очень мне эти затычки не нравятся. И решил я выяснить что можно с этим сделать. Уточнив с какой версии у браузеров появилась консоль (и текущую версию): IE8b2 (IE7), Opera 9.50 (9.63), Safari 1.3 (3.21), FireFox 2.0.0 (3.0.5), я принялся за работу.</p>

<p>Первое что приходило на ум это что-то вроде</p>
<pre><code class="javascript">
if (!window.console) {
	window.console = {};
	window.console.log = alert;
		
}
</code></pre>

<p>Но не все так просто, FireBug славится тем что показывает содержимое любого объекта и может делать форматированный вывод. То есть во-первых можно сделать</p>
<pre><code class="javascript">
console.info({a:null});
</code></pre>
<p>и увидеть содержимое объекта в закладке DOM, а во-вторых можно сделать форматированный вывод</p>
<pre><code class="javascript">
console.info("string: %d %s %d", 10, "text", 10);
</code></pre>
<p>и увидеть строку "string: 10 text 10". В остальных же браузерах можно наблюдать только строку [object Object] и "string: %d %s %d" соответственно, кроме IE8b2, он поддерживает форматный вывод, выпендрился, блин!</p>

<p>Я решил начать с написания форматного вывода, но функция <a href="http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_sprintf/" rel="nofollow">sprintf</a> оказалась настолько громоздкой и избыточной что я решил обойтись небольшим регулярным выражением, для своих нужд, тем более что FireBug тоже не различает %d и %s ;) в отличие от IE8b2 который корректно выводит 0 вместо %d которому соответствует строка. Из этого вывод что достаточно использовать только %s.</p>

<p>Потом я решили что было бы неплохо научиться отображать содержимое объектов и массивов, для этого как нельзя хорошо подходила одна известная функция, написанная очень нелюбимым мной человеком, имя которого можете прочитать в комментарии в коде. Единственные минус этой функции в том что она не может корректно отобразить объекты типа window, на нем она уходит куда-то в глубь рекурсии и безнадежно вешает браузер. Но этот недостаток я постараюсь решить в следующей версии, если такая появиться.</p>

<p>Уже неплохо. Последним штрихом к портрету было прикручивание уровня дебага "log", "debug", "info", "warn", "error". Тут для меня было несколько откровений. Первое это то что массив arguments не такой уже и массив потому что содержит в себе еще и метод callee. Второе - что объект arguments прекрасно превращается в массив с помощью волшебной строки</p>
<pre><code class="javascript">
var args = Array.prototype.slice.call(arguments);
</code></pre>
<p>Третье - что этот метод не работает (правильно!) в IE7 и <a href="http://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=364463" rel="nofollow">IE8b2</a>, а поэтому не годиться. И наконец четвертое и последние что чертов arguments не возможно обойти циклом через <b>in</b> нужно обязательно это делать через длину</p>
<pre><code class="javascript">
for(var i in arguments) // fail
	alert(arguments[i]);
for(var i=0,j=arguments.length;i&lt;j;i++) // ok
	alert(arguments[i]);
</code></pre>

<p>Но это все не помешало мне дописать сегодня этот скрипт и выложит его на ваше растерзание</p>

<pre><code class="javascript">
myConsole = function(){
	var args = (function(a,x){for(var i=0,j=a.length;i&lt;j;i++){x.push(a[i])};return x;})(arguments,[]);
	
	if (args.length&gt;2){
		(window.opera?opera.postError:window.alert)(args.shift() +'':\\n''+ args.shift().replace(/(%[ds])/g, function(){
			return args.shift();
			})
		)
	}else{
		// автор функции dump - Дмитрий Котеров
		// http://dklab.ru/chicken/nablas/38.html
		(window.opera?opera.postError:window.alert)(args.shift() +'':\\n''+ (function dump(d,l) {
			if (l == null) l = 1;
			var s = '''';
			if (typeof(d) == "object") {
				s += typeof(d) + " {\\n";				for (var k in d) {
					for (var i=0; i&lt;l; i++){
						s += "  ";
					}
					s += k+": " + dump(d[k],l+1);
				}
				for (var i=0; i&lt;l-1; i++){
					s += "  ";
				}
				s += "}\\n"
			} else {
				s += "" + d + "\\n";
			}
			return s;
		})(args.shift()));
	}
}

if (window.loadFirebugConsole) { // since FireBug 1.2
	window.loadFirebugConsole();
} else if (!window.console) {
	window.console = {};
	var names = ["log", "debug", "info", "warn", "error"];
	for (var i in names){
		window.console[names[i]] = (function(name){return function(){
			myConsole.apply(null,(function(a,x){for(var i=0,j=a.length;i&lt;j;i++){x.push(a[i])};return x;})(arguments,[name]))
		}})(names[i]);
	}
}
</code></pre>

<p>Кому пригодиться пишите в каменты...</p>]]></content:encoded>
			<wfw:commentRss>http://mabp.kiev.ua/2008/12/25/myconsole/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dragonfly</title>
		<link>http://mabp.kiev.ua/2008/05/06/opera_dragonfly/</link>
		<comments>http://mabp.kiev.ua/2008/05/06/opera_dragonfly/#comments</comments>
		<pubDate>Tue, 06 May 2008 16:06:40 +0000</pubDate>
		<dc:creator>CTAPbIu_MABP</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[Opera]]></category>

		<guid isPermaLink="false">http://mabp.localhost/?p=207</guid>
		<description><![CDATA[Ура!!! Наконец то это свершилось! Сегодня вышел в свет дебагер для Opera под названием «Dragonfly». Он доступен в стандартном дистрибутиве браузера по умолчанию, начиная в версии 9.5 beta 2. При большом внешнем сходстве с FireBug, Dragonfly имеет клиент-серверную архитектуру, то есть через какое-то время (после публикации протокола Scope) появятся плагины к Eclipse и другим IDE, [...]]]></description>
			<content:encoded><![CDATA[<p>Ура!!! Наконец то это свершилось! Сегодня вышел в свет дебагер для Opera под названием «Dragonfly». Он доступен в стандартном дистрибутиве браузера по умолчанию, начиная в версии 9.5 beta 2.</p>
<p>При большом внешнем сходстве с FireBug, Dragonfly имеет клиент-серверную архитектуру, то есть через какое-то время (после публикации протокола Scope) появятся плагины к Eclipse и другим IDE, из которых можно будет отлаживать страницы, отображаемые Opera. Это уже не просто расширение для дебага внутри браузера, а настоящий фреймворк для дебаггинга, где движком для рендеринга страниц и исполнения скриптов будет Opera, а дебаг-средой - выбранный самим разработчиком IDE, т.е. совсем необязательно тулза, встроенная в саму Opera. Это также позволяет работать не только с настольной Opera, а отлаживать, например, Opera для мобильных устройств, на экране которых толком и окно дебаггера не разместишь. И хоть «Dragonfly» еще очень сырой и далёк от заявленных фичасетов но, я думаю это веский аргумент в новом витке браузерных воин.</p>
<div style="text-align:center;">
<img src="/content/img/dragonfly1.png" alt="Dragonfly"/>
</div>]]></content:encoded>
			<wfw:commentRss>http://mabp.kiev.ua/2008/05/06/opera_dragonfly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Простой comet</title>
		<link>http://mabp.kiev.ua/2008/04/26/simple_comet/</link>
		<comments>http://mabp.kiev.ua/2008/04/26/simple_comet/#comments</comments>
		<pubDate>Sat, 26 Apr 2008 15:01:38 +0000</pubDate>
		<dc:creator>CTAPbIu_MABP</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[Opera]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://mabp.localhost/?p=179</guid>
		<description><![CDATA[Всю неделю готовил эту статью, и вот наконец публикую. Что же первое приходит в голову, когда видишь слово "comet", правильно - чистящее средство, потом комета, а оно почему-то означает технологию (хотя это, наверное, громко сказано, скорее паттерн) постоянного соединения с сервером. Все же в толстых книжках читали, что после того как сервер получил запрос и [...]]]></description>
			<content:encoded><![CDATA[<p>Всю неделю готовил эту статью, и вот наконец публикую.</p>
<p>Что же первое приходит в голову, когда видишь слово "comet", правильно - чистящее средство, потом комета, а оно почему-то означает технологию (хотя это, наверное, громко сказано, скорее паттерн) постоянного соединения с сервером. Все же в толстых книжках читали, что после того как сервер получил запрос и отдал ответ браузеру, он забывает, что к нему вообще кто-то обращался. А тут поседели умные люди и стали седыми. Нет, посидели и придумали идею, как заставить передавать браузеру информацию, изменившуюся на сервере.</p>

<span id="more-179"></span>
<script type="text/javascript" src="/content/source/jquery.comet.js"></script>
<script type="text/javascript">
jQuery().ready(function($){
	$().comets({
		update:function(data){
			$("#clock").text(data);
		},
		connect:function(sid){
			$(this).attr({src:"/content/polygon/comet_clock.php?sid="+sid});
		},
		url:"/content/polygon/comet_clock.php?sid="
	});
	$().comets({
		update:function(data){
			$("#timer").text(data);
		},
		connect:function(sid){
			$(this).attr({src:"/content/polygon/comet_timer.php?sid="+sid});
		},
		url:"/content/polygon/comet_timer.php?sid="
	});
});
</script>

<style>
iframe {
	width:1px;
	height:1px;
	top:-2000px;
	position:absolute;
}
</style>

<p>Вот собственно об этом мы с вами сегодня и поговорим, а собственно я как обычно буду высказывать свои ламерские мысли, а вы, как обычно, будете комментировать...</p>
<img src="/content/img/comet.jpg" alt="comet" align="right" />
<p>И так с чего же начать, начать надо с того что выберем серверным языком php а клиентским как это не странно — javascript. Для того чтобы соединение не разрывалось, php скрипт должен все время работать, но тут мы встречаем два ограничения. Первое вполне логичное у нас нет бесконечного скрипта который бы все время что-то делал, да это и не надо, достаточно включить в код бесконечный цикл. А вот собственно второе ограничение уже куда более неприятное: по умолчанию php скрипт может выполняться только 30 секунд, после чего сервер выдает ошибку о зависании скрипта. С этим мы будем бороться, но об этом потом.</p>
<p>Теперь когда мы имеем серверную часть нужно придумать как она будет контактировать с клиентской. Для этого нужно написать еще какую-то функцию на javascript, которую бы мог вызвать сервер, причем это должно работать параллельным потоком относительно основной страницы. Для реализации параллельного запроса идеально подходит AJAX, но, к сожалению IE и Opera, не умеют корректно обрабатывать событие onreadystatechange==3 , поэтому для реализации параллельного потока в них используют iframe, а я буду использовать его и для остальных браузеров.</p>

<p>В общем пора переходить к делу. Для реализации порционного отдавания контента на php нужно использовать буферизацию, а то php будет хранить все у себя, аж пока не закончит работу скрипта, чего мы собственно пытаемся избежать. Дальше я приведу пример скрипта, который каждую секунду отдает браузеру команду обновить часы и текущее время.</p>

<pre><code class="php">
// устанавливаем неограниченное время выполнения скрипта
ini_set('max_execution_time', 0);

// начинаем буферизацию
ob_start();
// ставим флаг отдавать буфер каждый раз как он больше не нужен
ob_implicit_flush(true);

// отдаем заголовки, чтобы избежать кэширования
header('Expires: Sut, 01 Jan 2000 00:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');

// выбрасываем в поток килобайт пробелов, 
// это нужно из-за того, что php первый раз меньше отдавать не хочет
echo str_repeat(chr(32), 1024);
ob_get_clean();   

// в бесконечном цикле описываем то передачу информации в браузер
while(true){
	echo ""
		."&lt;script type='text/javascript'&gt;\n"
		."parent.$(parent.document).trigger('comet".$_GET['sid']."',['".date("D, d M Y H:i:s O")."']);\n"
		."&lt;/script&gt;\n";
	ob_get_clean();
	// ждем 1 секунду до следующего обновления
	sleep(1);
}
</code></pre>

<p>А вот и пример работы этого скрипта находиться сразу под кодом.</p>

<div id="clock" style="width:300px;border: 2px dashed red; font-weight:bold; font-size:1.2em; margin:auto;text-align:center;">Hello from comet!</div>

<p>Теперь давайте разберем, клиентскую часть, она тоже весьма не большая. Как я уже говорил, ее задача в основном создать iframe и приаттачить нужные события. Событий может быть всего два: обновление с новыми данными и разрыв соединения с сервером. Оба события необязательные, потому что сервер и сам вполне может отдавать готовый javascript код, а разорванное соединение можно восстанавливать, а можно предположить, что все обновления с сервера уже пришли и новых больше не будет.</p>

<pre><code class="javascript">
(function($) {

	// конструктор объекта
	var comets = function(options){
		this.init(options);
	}
	
	// собственно сам объект
	comets.prototype = {
		comets : [], // итератор соединений
		options : { // массив функций по умолчанию
			connect:function(sid){
				// функция, выполняющаяся при разрыве соединения с сервером
			},
			update:function(data){
				// функция, вызываемая сервером с новыми данными
			},
			url:"", // адрес бэкэнда
		},
		init : function(options){
			var self = this, 
				comet = {},
				sid = self.comets.push([]); // i++

			// создаем реальный массив параметров
			$.extend(comet,self.options,options)
			
			// создаем iframe и соединение
			$("&lt;iframe/&gt;")
				.appendTo("body")
				.attr({src:comet.url+sid})
				.bind("load", function(){comet.connect.apply(this,[sid]);})
				
			// аттачим события, к ифрейму аттачить нельзя, так как он еще не загрузился
			$(document).bind("comet"+sid, function(event,data){comet.update.apply(this,[data])})
		}
	}

	$.fn.comets = function(options){
		// создаем новый comet
		new comets(options);
		
		// не нарушаем цепочку
		return this;
	}
})(jQuery);
</code></pre>

<p>Теперь надо передать в этот плагин (да я как всегда все делаю плагином под jQuery) наши функции.</p>

<pre><code class="javascript">
$().comets({
	// функция которая обновит такст часов
	update:function(data){
		$("#clock").text(data);
	},
	// функция которая востановит соединение с сервером
	connect:function(sid){
		$(this).attr({src:"clock.php?sid="+sid});
	},
	// адресс бэкэнда
	url:"clock.php?sid="
});
</code></pre>

<p>Как я говорил в начале я расскажу как бороться с временем выполнения скрипта если вам недоступна функция ini_set(); Для этого надо узнать сколько времени может выполняться скрипт и прерывать его работу незадолго до этого времени. Если передать браузеру команду восстановить соединение, то этого можно не указывать в параметрах  в javascript. Вносим правки в алгоритм работы скрипта:</p>


<pre><code class="php">
// узнаем время рабы и отнимаем 5 секунд запаса
$metime = ini_get('max_execution_time') - 5;

// узнаем время начала и конца работы скрипта
$start = $stop = array_sum(explode(" ",microtime()));

ob_start();
ob_implicit_flush(true);
header('Expires: Sut, 01 Jan 2000 00:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');

echo str_repeat(chr(32), 1024);
ob_get_clean();   

// по условию, что время начала больше чем время конца минус время исполнения прерываем процедуру
while($start > $stop-$metime){
	echo ""
		."&lt;script type='text/javascript'&gt;\n"
		."parent.$(parent.document).trigger('comet".$_GET['sid']."',['".date("D, d M Y H:i:s O")."']);\n"
		."&lt;/script&gt;\n";
	ob_get_clean();
	$stop = array_sum(explode(" ",microtime()));
	sleep(1);
}

// echo "&lt;script type='text/javascript'&gt;window.location='".$_SERVER['PHP_SELF']."?sid=".$_GET['sid']."';&lt;/script&gt;n";
</code></pre>

<p>Вот пример работы этого кода, только для наглядности я поставил обрыв соединения каждые 10 секунд.</p>

<div id="timer" style="width:300px;border: 2px dashed red; font-weight:bold; font-size:1.2em; margin:auto; text-align:center;">Hello from comet!</div>

<p>Вот такие вот у меня получились простые комёты ;) , возможно, я их немного доделаю и опубликую, свежую версию, но это не сейчас.</p>
]]></content:encoded>
			<wfw:commentRss>http://mabp.kiev.ua/2008/04/26/simple_comet/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Локальная  глобальная область видимости</title>
		<link>http://mabp.kiev.ua/2008/04/25/local_global_scope/</link>
		<comments>http://mabp.kiev.ua/2008/04/25/local_global_scope/#comments</comments>
		<pubDate>Fri, 25 Apr 2008 15:00:04 +0000</pubDate>
		<dc:creator>CTAPbIu_MABP</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[FireFox]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Opera]]></category>

		<guid isPermaLink="false">http://mabp.localhost/?p=177</guid>
		<description><![CDATA[Всю неделю готовлю сразу две статьи, первая о comet (постоянное соединение с сервером) и вторая о ранжированном поиске который наконец таки заработал на сайте но на этот раз будет махонькая заметка о корректной работе браузеров. Все учебники по JavaScript наперебой рассказывают о присвоении значений переменным, и об области их видимости. Сейчас мы на примере рассмотрим, [...]]]></description>
			<content:encoded><![CDATA[<p>Всю неделю готовлю сразу две статьи, первая о comet (постоянное соединение с сервером) и вторая о ранжированном поиске который наконец таки заработал на сайте но на этот раз будет махонькая заметка о корректной работе браузеров.</p>
<span id="more-177"></span>
<p>Все учебники по JavaScript наперебой рассказывают о присвоении значений переменным, и об области их видимости. Сейчас мы на примере рассмотрим, что хотя то что они говорят и есть правильно но не всегда работает. Итак, в глобальной области видимости мы проверим чему у нас равен указатель <b>this</b>, а заодно создадим функцию в любой области видимости главное, чтоб ее можно было вызвать.</p>
<pre><code class="javascript">
alert(this === window);

var func = function(){
	alert("hello from onload!");
};
</code></pre>
<p>Как и следовало ожидать мы находимся в глобальной области видимости и <b>this</b> у нас равен (и того же типа что и) <b>window</b>, то есть объявляя какую-либо переменную мы можем не указывать ключевое слово <b>var</b>.</p>
<pre><code class="javascript">
onload = function (){
	func();
}
</code></pre>
<p>В результате работы этого скрипта мы получим наш алерт, потому что событие <b>window.onload</b> срабатывает когда страница полностью загружена.</p>
<p>Вам еще не надоело перечитывать материалы учебника для ламеров? Ну ладно начинается вкусненькое!</p>
<p>Создадим переменную в локальной области видимости, поскольку локальная у нас глобальна (во загнул!), то мы собственно еще раз попытаемся присвоить значение событию <b>window.onload</b>.</p>
<pre><code class="javascript">
var onload = function (){
	func();
}
</code></pre>
<p>Вот тут и начинаются косяки, работает это только в FireFox, а Opera и IE начисто игнорируют нашу писанину! Листаем учебник дальше и видим что определение функции с именем эквивалентно определению переменной с тем же именем в локальной области видимости.</p>
<pre><code class="javascript">
function onload (){
	func();
}
</code></pre>
<p>И что бы вы думали?! Действительно абсолютно эквивалентно, потому что оно также не работает, как и прошлый пример. Вы можете сказать, что я где-то что-то мухлюю и во втором и третьем примере переменные не попадают в объект <b>window</b>, но для всех трех примеров и всех трех браузеров алерт выдает один и тот же результат.</p>
<pre><code class="javascript">
alert(window.onload);
</code></pre>

<p>Из всего вышесказанного можно сделать два вывода, даже три: Первый и самый главный - FireFox снова на высоте! Второй заключается в том, что для Opera и IE локальная область видимости скрипта не такая уже и глобальная, как хотелось бы. Ну и третий маловероятный, что все учебники врут.</p>
]]></content:encoded>
			<wfw:commentRss>http://mabp.kiev.ua/2008/04/25/local_global_scope/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

