<?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>Чудо{вищные} заметки &#187; js</title>
	<atom:link href="http://miracle.rpz.name/category/js/feed/" rel="self" type="application/rss+xml" />
	<link>http://miracle.rpz.name</link>
	<description>Sorry for my terrible english. My native language is PHP.</description>
	<lastBuildDate>Thu, 12 Jan 2012 20:42:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4-alpha-19719</generator>
		<item>
		<title>Jabber-нотификация в redmine</title>
		<link>http://miracle.rpz.name/2011/06/27/redmine-with-jabber-notifications/</link>
		<comments>http://miracle.rpz.name/2011/06/27/redmine-with-jabber-notifications/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 17:35:38 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[jabber]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[redmine]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=498</guid>
		<description><![CDATA[Просматривая статистику посещений, обратил внимание на то, что многих интересует словосочетание &#171;redmine jabber&#187;. Пришла пора удовлетворить спрос. В начале &#171;как обычно&#187; небольшая предыстория о том, &#171;как всё начиналось&#187;: Несколько лет назад мне удалось внедрить redmine на &#171;производстве&#187;, коллеги потихоньку втягиваясь в процесс, затребовали &#171;книгу отзывов и предложений&#187;. Одним из первых пожеланий была замена стандартных уведомлений [...]]]></description>
			<content:encoded><![CDATA[<p>Просматривая статистику посещений, обратил внимание на то, что многих интересует словосочетание &laquo;redmine jabber&raquo;. Пришла пора удовлетворить спрос. В начале &laquo;как обычно&raquo; небольшая предыстория о том, &laquo;как всё начиналось&raquo;:</p>
<blockquote><p> Несколько лет назад мне удалось внедрить <a href="http://redmine.org/">redmine</a> на &laquo;производстве&raquo;, коллеги потихоньку втягиваясь в процесс, затребовали &laquo;книгу отзывов и предложений&raquo;. Одним из первых пожеланий была замена <span title="политика настройки которых мягко говоря идиотская">стандартных уведомлений по email</span> на, успевшие уже войти в моду, <a href="http://miracle.rpz.name/2009/02/24/commit-jabber-php/">jabber-уведомления, которые мы используем для нотификации о новых коммитах в svn</a>. Я вооружился тем самым поисковым запросом, о котором упомянул и немедленно нашёл нужной функциональности <a href="https://github.com/mszczytowski/redmine_messenger/tree" title="Messenger plugin for Redmine">готовый плагин</a>. Помимо уведомлений, автор обещал нам некие таймеры, которые можно стартовать/останавливать посредством команд боту в чате, тем самым &laquo;точно&raquo; подсчитывать затраченное на решение задачи время. В теории это казалось очень нужной и удобной игрушкой, на деле же оказалось, что плагин был выпилен для старой версии redmine и с trunk-версией работать по полной программе отказался. Худо-бедно он иногда стартовал какие-то таймеры, иногда присылал какие-то уведомления, от полученных команд иногда впадал в ступор и потом долго игнорировал собеседника, в общем  вёл себя непозволительно загадочно и непростительно таинственно, но скиллов для исправления обнаруженных проблем мне не хватало, а автор на открытые тикеты особо не реагировал. Мыши плакали, кололись и продолжали есть кактус до одного смешного стечения обстоятельств: я находился в другом городе, бессовестно тратил отпускное время на прогулки, осмотры достопримечательностей и дивных пейзажей, внезапно получил входящий звонок от коллег. Слёзно просили выручать &#8211; что-то мол случилось, трах-бах-тарарах &#8230;и всё, нет у нас больше redmine. Немного порассуждав вслух, источник проблемы вроде бы вычислили, каким-то временным образом проблему по телефону решили, но в тот же вечер, добравшись до интернета, плагин я без сожалений выкинул. Случилось следующее &mdash; при старте redmine, плагин коннектился к jabber-серверу, а уж затем поднимался сам редмайн, но в тот роковой момент соединение с интернетом пропало, от чего случился обширный exception и redmine умер не приходя в сознание.
</p></blockquote>
<div align="center">***</div>
<p>
Тогда стало понятно, что схема со злобным плагином не работает и уведомления надо рассылать внешним по отношению к redmine решением (здесь знатоки rails могли бы долго возражать, но уже поздно). Параллельно с этой проблемой существовали другие.<span id="more-498"></span> <a href="http://miracle.rpz.name/2009/02/24/commit-jabber-php/">Cкрипт, о котором уже упомянул выше</a>, работал прямо скажем неэффективно. Во-первых он <span title="казалось бы - какая разница?! часто что ли коммиты бывают? нет, но всё равно раздражает!">соединялся с xmpp-сервером после каждого коммита</span>, порой делал это долго, порой это у него не получалось, порой сообщения не доставлялись адресату, даже если соединение с сервером было успешным. Поэтому рассылку уведомлений сразу после коммита пришлось разбить на два шага: 1) положить в очередь сообщения для адресатов 2) забрать уведомление из очереди и разослать, после подтверждения доставки удалить его из очереди. Теперь второй скрипт запускался периодически (не после коммита) рассылал уведомления, удалял их из очереди (подтверждения о получении я реализовать не смог). По-прежнему оставалась проблема с пропадающими сообщениями. Немного покопавшись в недрах протокола я обнаружил что клиент получателя, сервер получателя или мой xmpp-сервер при возникновении ошибки возвращают моё сообщение но с типом <em>error</em>: это значило, что периодический запуск &laquo;рассылатора-уведомлятора&raquo; не подходит &mdash; надо держать постоянное соединение с сервером и должным образом обрабатывать входящие сообщения. Так &laquo;в муках&raquo; родился прототип <a href="http://miracle.rpz.name/2009/12/05/jabber-web-status/">бота webstatus-а</a>, а с ним и рабочая реализация механизма уведомлений по xmpp. Первоначально это был скрипт на php, который при запуске подключался к jabber-серверу, периодически дёргал mysql запросом на получение новых сообщений и рассылал их, помечал как отправленные, если потом возвращались ошибки &#8211; вновь отмечал сообщения как непрочитанные. В mysql-таблицу сообщения попадали от разных источников &#8211; от post-commit хука в svn, от различных скриптов, которые запускаются cron-ом и собирают необходимые нам данные. </p>
<div align="center">***</div>
<p>
Таким образом прикрутить это решение к redmine стало просто делом техники &mdash; требовалось лишь сделать &laquo;триггеры&raquo; в нужных моделях, которые бы добавляли новые записи в таблицу с очередью сообщений для xmpp-бота. Уже позднее <a href="http://miracle.rpz.name/2010/11/20/jabber-web-status-2/">php-решение было переписано на модной нынче node-платформе</a>. Потребовалась лишь прослойка в виде <a href="http://code.nytimes.com/projects/dbslayer">dbslayer</a> для того чтобы соединить node и mysql.</p>
<p> Теперь всё выглядит следующим образом:</p>
<ul>
<li>Сообщения от разных источников попадают в mysql (например :after_save в issue модели редмайна, post-commit хук в svn и т.д.)
<li>Jabber-бот (на <a href="http://nodejs.org">node</a>) периодически делает запрос в mysql (через <a href="http://code.nytimes.com/projects/dbslayer">dbslayer</a>) вида <code>select msg, recipient from msg where recipient in (cписок тех, кто сейчас в онлайне)</code>, если получен непустой результат, то сообщения отправляет адресату и отмечает их прочитанными.
<li> Если сообщение вернулось с ошибкой &#8211; бот отмечает его непрочитанным, а адресата на некоторое время отправляет &laquo;на скамейку запасных&raquo; (чтобы не долбить его повторяющимися запросами)
<li> Бот поддерживается на плаву с помощью <a href="http://supervisord.org/">supervisord</a> (случаются ошибки, как правило сетевые, которые не удаётся поймать стандартными try-catch в коде бота, после некоторых попыток обработать все возможные проблемы я пришёл к выводу, что проще &laquo;упасть и товарищи поднимут&raquo; нежели пытаться &laquo;любой ценой устоять&raquo; &mdash; всё-таки данные не настолько критичные и безвозратная потеря сообщения терпима.
</ul>
<div align="center">***</div>
<p id="download"> Тех, кто дочитал до этого места и всё ещё жаждет получить ссылку <a href="#download">&laquo;скачать&raquo;</a> мне придётся огорчить &mdash; описанный код сильно заточен под наши конкретные нужды и планов его публикации не было, поэтому redmine-зависимая часть кода просто на-тяп-ляплена посреди моделей самого редмайна безо всякой попытки вынести эти части в отдельный плагин, node-часть тоже не обошлась без влезания в &laquo;чужие&raquo; библиотеки. А это всё значит лишь одно: plug-n-play решения у меня нет. Но <a href="http://miracle.rpz.name/2011/06/27/redmine-with-jabber-notifications/#dsq-comments">в комментариях</a> вы можете попробовать наладить конструктивный диалог и мы совместными усилиями создадим работающий у вас плагин, с чаем и шахматистками. Вас это интересует?</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2011/06/27/redmine-with-jabber-notifications/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>jabber web status</title>
		<link>http://miracle.rpz.name/2010/11/20/jabber-web-status-2/</link>
		<comments>http://miracle.rpz.name/2010/11/20/jabber-web-status-2/#comments</comments>
		<pubDate>Sat, 20 Nov 2010 17:00:44 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[jabber]]></category>
		<category><![CDATA[node]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=373</guid>
		<description><![CDATA[В поисках прикладной задачи для предметного изучения node.js вспомнил про заброшенный проектик &#8211; jabber web status. И за несколько часов переписал на node. По сравнению с предыдущей версией написанной на PHP (XMPPHP) потребление памяти, а главное, нет ГЛАВНОЕ &#8211; потребление CPU снизилось до статистической погрешности (по непонятным причинам php-бот иногда забирает до 60% процессорного времени) [...]]]></description>
			<content:encoded><![CDATA[<p>В поисках прикладной задачи для предметного изучения <a href="http://nodejs.org">node.js</a> вспомнил про заброшенный проектик &#8211; <a href="http://miracle.rpz.name/2009/12/05/jabber-web-status/">jabber web status</a>.</p>
<p>И за несколько часов переписал на <strong>node</strong>. По сравнению с предыдущей версией написанной на PHP (<a href="http://code.google.com/p/xmpphp/">XMPPHP</a>) потребление памяти, а главное, нет ГЛАВНОЕ &#8211; потребление CPU снизилось до статистической погрешности (по непонятным причинам php-бот иногда забирает до 60% процессорного времени) . Скорость работы &#8211; отдельная, приятная на слух песня. Избавился от промежуточного хранилища (а значит и от лага в обновлении информации), в котором хранились статусы пользователей &#8211; скрипт не только работает с xmpp, но и сам раздаёт результат по http.</p>
<p>Работать с node  ново и свежо. Удручает только то, что свежесть во всём &#8211; в библиотеках, в сборке, установке дополнительных модулей. Написание и отладка скриптика отняли от силы час, правка библиотек ещё два<span style="text-decoration: line-through;">, установка node и модулей на сервере с дебильной Centos &#8211; целую вечность</span>.  Но всё-таки оно того стоит &#8211; писать на javascript легко и приятно, очень интересно использовать его вне привычных рамок браузера, асинхронность везде и во всём, интерпретатор, шустрый как электровеник, человеко-понятно ругается ошибками, неплохая документация к основным модулям. В общем хороший массаж не только для коры головного мозга, но и самой его древесины, изрядно дубеющих от PHP ;o)</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2010/11/20/jabber-web-status-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Cross Domain XMLHttpRequest</title>
		<link>http://miracle.rpz.name/2008/10/03/crossdomain-xhr-with-flash/</link>
		<comments>http://miracle.rpz.name/2008/10/03/crossdomain-xhr-with-flash/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 21:50:52 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[flash]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=116</guid>
		<description><![CDATA[Задачи обмена информацией ставятся и успешно решаются каждый день. Но обмениваться можно по-разному. Кто-то дарит удобоваримый доступ к своей базе посредством распространённых обменных форматов (xml, csv, json, lisiy_chert), кто-то реализует собственные API, а кто-то идёт другими путями. Моя задача состояла в следующем &#8211; на ресурсах-сателитах необходимо разместить сложную форму. &#8220;Сложность&#8221; формы заключается в том, что [...]]]></description>
			<content:encoded><![CDATA[<p>Задачи обмена информацией ставятся и успешно решаются каждый день. Но обмениваться можно по-разному. Кто-то дарит удобоваримый доступ к своей базе посредством распространённых обменных форматов (xml, csv, json, lisiy_chert), кто-то реализует собственные API, а кто-то идёт другими путями.</p>
<p>Моя задача состояла в следующем &#8211; на ресурсах-сателитах необходимо разместить сложную форму. &#8220;Сложность&#8221; формы заключается в том, что данные подгружаются с главного ресурса и не могут быть загружены единовременно(при загрузке ресурса) или доставлены на ресурс-сателит заранее (так-так данных очень много и они достаточно быстро устаревают). Всевозможные API для доступа к информации основного ресурса в настоящий момент разрабатывать нецелесообразно, поэтому было решено для сателитов предоставлять некий готовый комплекс (аля plug-n-play).</p>
<blockquote><p>
Ещё до начала разработки я тщательно изучил уже имеющиеся механизмы для межсайтового обмена данными. Первым и самым перспективным был вариант использования flash-плеера, но единственный вменяемый пример <a href="http://blog.monstuff.com/archives/000294.html">FlashXmlHttpRequest</a> был только лишь примером, а не законченным куском кода, которым бы можно было воспользоваться. <a href="http://jquery.com/">jQuery</a> на тот момент даже не содержала функции $.getScript,  <a href="http://dklab.ru/lib/JsHttpRequest/">JSHttpRequest</a> с созданием тега script удачно справлялся, но POST по понятным причинам делать не мог.
</p></blockquote>
<p>Данные с главного ресурса могут подгружатся  посредством динамического создания тега script <a href="http://docs.jquery.com/Ajax/jQuery.getScript">jQuery.getScript</a>, с этим казалось бы проблемы нет. Но! Но последним шагом в указанной форме нужно отправить на основной сервер внушительный объём данных, которые могут не влезть в GET (тоже кстати говоря весьма интересный вопрос &#8211; а каково ограничение на длину URL в разных браузерах? в различных веб-серверах,прокси и фильтрах? &#8211; в <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a> об этом не сказано). Можно конечно изобрести какие-либо механизмы, например отправлять данные небольшими порциями GET-ом, но скорости такая схема явно не прибавит, поэтому такие варианты оставлены другим изобретателям.<br />
<span id="more-116"></span></p>
<p>В первом рабочем варианте проблема решалась php-скриптом на сервере-сателите, через который данные POST-ом прокачивались на головной сайт. Но такая схема имела ряд недостатков, основным из которых опять же является скорость работы и дополнительное требование к ПО на сервере (наличие PHP) или требование к нам, разработчикам &#8211; создать прокси-скрипт для других распространнёных серверных платформ. </p>
<p><strike>И вот относительно недавно</strike> я наткнулся на занимательную библиотеку <a href="http://flxhr.flensed.com/">flxhr</a>. Автор довёл до конца идею и наваял интерфейс, который может <b>прозрачно заменять XMLHttpRequest</b> используя flash. Использовать flxhr легко и просто &#8211; <a href="http://flxhr.flensed.com/code/tests/flxhr-7f.html">заменяете стандартный XMLHTTPRequest</a> и дальше всё почти как обычно. </p>
<p>В дополнение ко всему, флеш-плеер решает ещё одно требование к разрабатываемому проекту &#8211; необходимо пресечь бесконтрольное распространение клиентского модуля(который устанавливается на сайт-сателит). Дело в том что в флеш-плеер от рождения встроен механизм контроля над внешними данными. Ранее это был ресурс crossdomain.xml в корне веб-сервера, содержащего скачиваемые данные. В нём описывалось откуда и что можно скачать. В новом плеере (а для использования flxhr необходим плеер версии не ниже 9.0.0.124) появился более удобный механизм &#8211; можно указать путь к ресурсу с политиками <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html#goal_control">policyURL</a>.</p>
<blockquote><p>
 Кстати о версии плеера:  автор flxhr предусмотрел не только проверку версии плеера, но и возможность его апгрейдить не отходя от кассы (тот самый <a href="http://blog.deconcept.com/swfobject/#expressinstall">expressinstall из swfobject</a>).
</p></blockquote>
<p> Думаю стоит ещё раз упомянуть тот факт, что данная схема <b>не позволит</b> обратиться js-скрипту с произвольного сайта A на произвольный ресурс B без согласия его владельца. &#8220;Согласие&#8221;  выражается в виде правил, описываемых в файле crossdomain.xml(или указанным в loadPolicyFile), который располагается на сервере B. Другими словами данные, которые вы желаете публиковать, не должны быть &#8220;ворованными&#8221;.</p>
<p> Единственным неудобством, с которым пока довелось столкнуться в ходе обкатки flxhr, является тот факт, что данные в кодировке отличной от UTF-8 безвозвратно портятся. В остальном это самый <b>лёгкий и удобный</b> способ обмениваться данными между разными доменами уже <b>сейчас</b>, не дожидаясь появления сверхновых версий браузеров, в которых реализуют <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/">XMLHttpRequest Level 2</a>, и скоропостижной смерти всех старых.</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2008/10/03/crossdomain-xhr-with-flash/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>firebug для отладки серверного кода</title>
		<link>http://miracle.rpz.name/2008/05/06/firebug-console-for-server-side-messages/</link>
		<comments>http://miracle.rpz.name/2008/05/06/firebug-console-for-server-side-messages/#comments</comments>
		<pubDate>Tue, 06 May 2008 10:41:31 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[firebug]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=107</guid>
		<description><![CDATA[За последние пару лет firebug стал стандартным инструментом для отладки клиентской части веб-приложений у большинства разработчиков. Тем, у кого это не так &#8211; от души сочувствую ;o) Но многие не догадываются, что с помощью firebug можно отлаживать и серверный код. Не breakpoint-ами конечно. Но как замена унылым print-ам и var_dump-ам очень даже! Собственно делается всё [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="tn" href="http://miracle.rpz.name/shared/fb/firebug.png"><img class="tn" src="http://miracle.rpz.name/shared/fb/tn_firebug.png" alt="" align="right" /></a><br />
За последние пару лет <a href="http://getfirebug.com">firebug</a> стал стандартным инструментом для отладки клиентской части веб-приложений у большинства разработчиков.<br />
Тем, у кого это не так &#8211; от души сочувствую ;o)<br />
Но многие не догадываются, что с помощью firebug можно отлаживать и серверный код. Не breakpoint-ами конечно. Но как замена унылым print-ам и var_dump-ам очень даже!</p>
<p>Собственно делается всё очень просто. Для того чтобы в консоли firebug-а появилось сообщение, необходимо написать js-код:</p>
<pre class="js:nocontrols">
console.log('сообщение');
console.group('разные типы сообщений');
console.info('к вашему сведению, мы тут логи пишем...');
console.warn('предупреждаем о разном');
console.error('и информируем об ошибках!!!');
console.groupEnd();
console.dir({сложная: {структура: [1,2,3]}});</pre>
<p>Подробнее о возможностях консоли firebug-а можно узнать в <a href="http://getfirebug.com/console.html">документации</a>.</p>
<p>Дело за малым &#8211; сформировать эти строки на вашей серверной платформе.<br />
Сложность представляет лишь последнее &#8211; <a href="http://json.org/">json</a>-упаковка сложных структур, но и она уже во многих платформах решена. Сам я пользуюсь функцией, описанной в коментариях к <a href="http://php.net/json_encode">json_encode</a>, т.к. родная слишком консервативна в вопросах кодировок(<a title="JSON text SHALL be encoded in Unicode.  The default encoding is UTF-8." href="http://www.ietf.org/rfc/rfc4627.txt?number=4627">по стандарту в json можно упаковать только уникод</a>, но браузеры более лояльны нежели писатели стандартов).</p>
<p>Собственно теперь чем это лучше всяких принтов и вар_дампов?<br />
Тем, что не меняют визуально документ, что существенно в современных сложных веб-приложениях.<br />
К тому же это в разы удобнее &#8211; все сообщения в одном месте, красиво представлены&#8230;</p>
<p>В заключение скажу о якобы готовых решениях для PHP:<br />
<a href="http://www.indelible.org/php/Log/guide.html#the-firebug-handler">Log::Firebug</a> из <a href="http://pear.php.net">PEAR</a> &#8211; драйвер для довольно распространнённого pear::log<br />
<a href="http://firephp.org/">FirePHP</a> &#8211; более комплексное решение, плагин к firebug-у и обёртка к серверному коду.</p>
<p>Я ни тем, ни другим не пользуюсь, т.к. первое сделано левой ногой, а второе заворачивает оригинальный документ в страшную multipart-кашу&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2008/05/06/firebug-console-for-server-side-messages/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Всплытие покажет</title>
		<link>http://miracle.rpz.name/2008/05/05/event-bubbling/</link>
		<comments>http://miracle.rpz.name/2008/05/05/event-bubbling/#comments</comments>
		<pubDate>Mon, 05 May 2008 09:51:14 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/2008/05/05/event-bubbling/</guid>
		<description><![CDATA[Предположим у нас есть html-таблица 100&#215;100 ячеек,в каждой ячейке &#8211; ссылка. При нажатии на каждую, должно происходить что-либо невероятное. Мы можем сделать 10 тыс обработчиков onclick и медленно, но верно добиться своей цели. А можем глупостей не делать. Ведь хватит только одного! Дело в том, что события в DOM умею &#8220;всплывать&#8221; &#8211; т.е. если представить [...]]]></description>
			<content:encoded><![CDATA[<p>
Предположим у нас есть html-таблица 100&#215;100 ячеек,в каждой ячейке &#8211; ссылка. При нажатии на каждую, должно происходить что-либо невероятное.<br />
Мы можем сделать 10 тыс обработчиков onclick и медленно, но верно добиться своей цели.<br />
А можем глупостей не делать. Ведь хватит только одного!
</p>
<p><img src="http://miracle.rpz.name/shared/event_bubbling.gif" align="right"><br />
 Дело в том, что события в DOM умею &#8220;всплывать&#8221; &#8211; т.е. если представить документ в виде слоёной структуры, где сам document находиться сверху, радуя глаз хрустящей корочкой, а все дочерние элементы под ним, то событие возбуждённое на нижних уровнях, не найдя свой законный обработчик у потревоженного объекта начинает потихоньку лезть наверх, шевеля всё на своём пути, и искать свой обработчик последовательно у всех предков.<br />
Что это собственно даёт? Это может существенно сократить количество обработчиков событий на странице. На идеальной сферической странице вакуумного веб-приложения всего один обработчик!
</p>
<p>Перейду к примерам:<span id="more-106"></span></p>
<pre class="js:nocontrols">
  window.onload = function(){
  var tbl = document.getElementById('tbl'), links = tbl.getElementsByTagName('a'), linkcount = links.length;
     for (var i = 0; i < linkcount; i++){
                  (function(){
                    var num = i;
                     x[i].onclick  = function(){
                     alert('Это обработчик номер ' + num + ' из ' + linkcount + ', ужас правда?');
                     return false;
                  };
        })();
     }
  }
</pre>
<p>Готово. 10000 обработчиков. Легко. Просто. И долго…</p>
<p>А теперь Горбатый! (Я сказал "Горбатый?!?")</p>
<pre class="js:nocontrols">
      window.onload = function(){
         var tbl = document.getElementById("tbl");
         tbl.onclick = function(e) {
                e = e || window.event;
                var elem = e.target || e.srcElement;
                    if ('a' === elem.nodeName.toLowerCase()) {
                            alert('Это обработчик. Один. ЕДИНСТВЕННЫЙ!');
                    }
             }
      }
</pre>
<p>А если не видно разницы, то зачем платить <strike>больше</strike> ?</p>
<p>С jQuery эта техника будет выглядеть следующим образом:</p>
<pre class="js:nocontrols">
    $('#tbl').bind('click',function(e) {
            if ($(e.target).is('a')) {
                    alert('Это обработчик. Один. ЕДИНСТВЕННЫЙ!');
                    return false;
            }
    });
</pre>
<p>В заключение пару плагинов для <a href="http://jquery.com">jQuery</a>, берущие "пыльную" работу в свои руки: </p>
<p><a href="http://flesler.blogspot.com/2007/10/jquerylisten.html">jQuery.listen</a> </p>
<pre class="js:nocontrols">
$('#tbl').listen('click', 'a', function (e) {
    alert('Это обработчик. Один. ЕДИНСТВЕННЫЙ!');
    e.preventDefault();
});
</pre>
<p>и <a href="http://dev.distilldesign.com/log/2008/jan/27/event-delegation-jquery/">jquery.eventdelegation</a></p>
<pre class="js:nocontrols">
$('#tbl').delegate('click', 'a', function () {
    alert('Это обработчик. Один. ЕДИНСТВЕННЫЙ!');
    return false;
});
</pre>
<p>Удачного всплытия!</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2008/05/05/event-bubbling/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>jQuery 1.2.3</title>
		<link>http://miracle.rpz.name/2008/02/07/jquery-release-v123/</link>
		<comments>http://miracle.rpz.name/2008/02/07/jquery-release-v123/#comments</comments>
		<pubDate>Thu, 07 Feb 2008 19:20:41 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[advertise]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/2008/02/07/jquery-release-v123/</guid>
		<description><![CDATA[.4.5.6.7&#8230; Тихо и незаметно зарелизился jQuery: jquery-1.2.3.js, jquery-1.2.3.min.js, jquery-1.2.3.pack.js Поскольку официального анонса пока нету, перечислю &#8220;вкусности&#8221; сам: Вот официальный анонс, а ниже мой: первое, оно же главное &#8211; namespace-ы в event-ах. $(&#8216;#cal&#8217;) .bind(&#8216;click.calendar&#8217;,fnclk) .bind(&#8216;change.calendar&#8217;,fnchg) .bind(&#8216;change.maskedinput&#8217;,fn); Накой ляд оно сдалось? Код становиться на порядок понятнее для чтения и отладки (разумеется если авторы многочисленных плагинов &#8220;прочухают&#8221; фишку). [...]]]></description>
			<content:encoded><![CDATA[<p>.4.5.6.7&#8230;</p>
<p>Тихо и незаметно зарелизился <a href="http://jquery.com">jQuery</a>:</p>
<p><a href="http://code.jquery.com/jquery-1.2.3.js">jquery-1.2.3.js</a>, <a href="http://code.jquery.com/jquery-1.2.3.min.js">jquery-1.2.3.min.js</a>, <a href="http://code.jquery.com/jquery-1.2.3.pack.js">jquery-1.2.3.pack.js</a></p>
<p><span style="text-decoration: line-through;">Поскольку официального анонса пока нету, перечислю &#8220;вкусности&#8221; сам:</span><br />
<a href="http://jquery.com/blog/2008/02/08/jquery-123-air-namespacing-and-ui-alpha/">Вот официальный анонс</a>, а ниже мой:<br />
<span id="more-96"></span><br />
первое, оно же главное &#8211; namespace-ы в event-ах.</p>
<blockquote><p>$(&#8216;#cal&#8217;)<br />
.bind(&#8216;click.calendar&#8217;,fnclk)<br />
.bind(&#8216;change.calendar&#8217;,fnchg)<br />
.bind(&#8216;change.maskedinput&#8217;,fn);</p></blockquote>
<p>Накой ляд оно сдалось?<br />
Код становиться на порядок понятнее для чтения и отладки (разумеется если авторы <a href="http://plugins.jquery.com/">многочисленных плагинов</a> &#8220;прочухают&#8221; фишку). Теперь когда мне надоест функционал календаря на input-е, я могу убрать его:</p>
<blockquote><p>$(&#8216;#cal&#8217;).unbind(&#8216;.calendar&#8217;);</p></blockquote>
<p><em>change</em> от maskedinput продолжит функционировать.<br />
Обработчики &#8220;обычных&#8221; событий будут так же обрабатывать все &#8220;вложенные&#8221; события, т.е. в приведённом выше примере:</p>
<blockquote><p>$(&#8216;#cal&#8217;).bind(&#8216;change&#8217;,fn);</p></blockquote>
<p><em>fn</em> вызовется при срабатывании как <em>change.calendar</em>, так и <em>change.maskedinput</em>; если же потребуется обработать ТОЛЬКО change, обработчик будет необходимо <del datetime="2009-09-27T08:41:50+00:00" title="спасибо Mel">вызвать</del> добавить так:</p>
<blockquote><p>$(&#8216;#cal&#8217;).bind(&#8216;change!&#8217;,fn);</p></blockquote>
<p><a href="http://docs.jquery.com/Internals/jQuery.data">$.data()</a> теперь вызывает события <em>setData</em> и <em>getData</em> что позволит удобно &#8220;подменять&#8221; сохранённые данные и должным образом обрабатывать их изменения в плагинах&#8230;</p>
<p>Остальные изменения &#8211; исправление некоторых на мой взгляд незначительных багов.</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2008/02/07/jquery-release-v123/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>jQuery 1.2.2</title>
		<link>http://miracle.rpz.name/2008/01/15/jquery-122/</link>
		<comments>http://miracle.rpz.name/2008/01/15/jquery-122/#comments</comments>
		<pubDate>Tue, 15 Jan 2008 12:27:26 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[advertise]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/2008/01/15/jquery-122/</guid>
		<description><![CDATA[К своему &#8220;второгодию&#8221; jQuery решил явиться миру обновлённым. Много исправлений направленных на ускорение и &#8220;устабилизацию&#8221;. Решена крайне досадная проблема с тем, что $(document).ready не срабатывал в IE если, документ находился в [и]фрейме. Из новшеств &#8211; этот самый $(document).ready(func) теперь можно писать в более привычном виде через $.bind &#8211; $(document).bind(&#8216;ready&#8217;,func); Появились два новых event-а &#8211; mouseenter [...]]]></description>
			<content:encoded><![CDATA[<p>  К своему &#8220;второгодию&#8221; <a href="http://jquery.com">jQuery</a> решил явиться миру <a href="http://docs.jquery.com/Release:jQuery_1.2.2">обновлённым</a>.</p>
<p> Много исправлений направленных на ускорение и &#8220;устабилизацию&#8221;.<br />
Решена крайне досадная проблема с тем, что $(document).ready не срабатывал в IE если, документ находился в [и]фрейме.<br />
Из новшеств &#8211; этот самый $(document).ready(func) теперь можно писать в более привычном виде через $.bind &#8211; $(document).bind(&#8216;ready&#8217;,func);<br />
Появились два новых event-а &#8211; mouseenter и mouseleave, которые вероятно скоро пойдут в массы в качестве основы для разнообразных dropdown-менюшек.<br />
В &#8220;ajax&#8221;-части добавились &#8220;умолчальные&#8221; заголовки Accept, для разных типов dataType. (<a href="http://softwaremaniacs.org/blog/2007/09/12/http-ajax-%d0%b8-jquery/">зачем это надо</a>? и <a href="http://softwaremaniacs.org/blog/2007/12/26/accept-header-inconsistencies/">что из этого выйдет</a> ?)</p>
<p> Перед тем как обновиться не забудьте &#8211; некоторые плагины могли &#8220;сломаться&#8221; &#8211; будьте готовы поработать напильником&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2008/01/15/jquery-122/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google using jQuery</title>
		<link>http://miracle.rpz.name/2007/11/03/google-using-jquery/</link>
		<comments>http://miracle.rpz.name/2007/11/03/google-using-jquery/#comments</comments>
		<pubDate>Sat, 03 Nov 2007 10:15:55 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[advertise]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=74</guid>
		<description><![CDATA[Вот здесь упомянуто, что в обновлённой версии гуглокода инопланетяне решили использовать распрекрасную jQuery. Есть ещё сомневающиеся в правильности выбора jQuery? Или даже те, кто и вовсе ещё не выбрал? Задумайтесь! &#8211; даже гости из будущего почувствовали Великую Силу, которую даёт jQuery отбирая взамен лишь не многим больше 20кБ трафика. Но овладеть магией не просто. А [...]]]></description>
			<content:encoded><![CDATA[<p>Вот <a href="http://google-code-updates.blogspot.com/2007/11/my-how-weve-grown.html">здесь</a> упомянуто, что в обновлённой версии <a href="http://code.google.com">гуглокода</a> инопланетяне  решили использовать распрекрасную <a href="http://jquery.com">jQuery</a>.</p>
<p>Есть ещё сомневающиеся в правильности выбора jQuery? Или даже те, кто и вовсе ещё не выбрал? Задумайтесь! &#8211; даже гости из будущего почувствовали Великую Силу, которую даёт jQuery отбирая взамен лишь не многим больше 20кБ трафика. </p>
<p>Но овладеть магией не просто. А <a href="http://rsdn.ru/article/inet/jQuery.xml">очень просто</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2007/11/03/google-using-jquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>jQuery.facts II</title>
		<link>http://miracle.rpz.name/2007/10/18/jquery-facts-2/</link>
		<comments>http://miracle.rpz.name/2007/10/18/jquery-facts-2/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 12:19:58 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=70</guid>
		<description><![CDATA[Выдам ещё одну порцию фактов, связанных с jQuery. jQuery.get() и jQuery.post() принимают последним четвёртым параметром dataType. Ну принимает и бог с ним, скажут некоторые. А другие смогут этот факт использовать во благо. Вот пример такого &#8220;блага&#8221;: $.post(backend_url,params,callback,&#8217;script&#8217;); // и вуаля &#8211; все вернувшееся с бэкэнда интерпретируется как javascript.Опять-таки внимательный (и просвещённый) читатель скажет &#8220;ну и [...]]]></description>
			<content:encoded><![CDATA[<p>Выдам ещё одну порцию фактов, связанных с jQuery.</p>
<ul>
<li>jQuery.get() и jQuery.post() принимают последним четвёртым параметром dataType.  Ну принимает и бог с ним, скажут некоторые. А другие смогут этот факт использовать во благо. Вот пример такого &#8220;блага&#8221;:<br />
$.post(backend_url,params,callback,&#8217;script&#8217;); // и вуаля &#8211;  все вернувшееся с бэкэнда интерпретируется как javascript.Опять-таки внимательный (и просвещённый) читатель скажет &#8220;ну и нафига? есть же jQuery.getScript ?&#8221;. Тут мне ответить уже нечего. Разве что напомнить о том факте, что getScript передаёт параметры GET-ом, длина которого как мы знаем весьма ограничена.</li>
<li>Кстати о jQuery.getScript() &#8211; начиная с версии 1.2.1 getScript умеет кросс-доменные запросы (все урлы начинающиеся с http автоматом будут тянуться не через XmlHttpRequest, а посредством добавления тега script). Это открыло нам такие просторы, что ни в сказке сказать, ни трактором убрать&#8230; (правда имеется одно <a href="http://dev.jquery.com/ticket/1584">досадное недоразумение</a>, <strike>но видимо оно беспокоит только меня</strike> UPDATE: <a href="http://dev.jquery.com/changeset/3668">пофиксили</a>).</li>
<li>Не совсем jQuery, но тоже важный факт &#8211; расчудесный плагин <a href="http://brandonaaron.net/docs/livequery/">jQuery.livequery</a> аналог <a href="http://www.bennolan.com/behaviour/">Behaviour </a> &#8211; помогающий создавать скрипты работающие &#8220;на манер css&#8221;.
<pre class="js:nocontrols">
$('span.bugaga').livequery('click',function(){
   alert('Бугага');
});
$('span.gygygy').livequery(function(){
   $(this).bind('click',function(){
      alert('Надо же - кликнули. Гыгыгы');
   });
   alert('В документе появились span-ы c классом gygygy');
});
</pre>
<p>Поясняю &#8211; работает это так же как и jQuery.bind, за одним лишь исключением &#8211; элементов на странице к моменту вызова функции может и не быть. Когда они появяться &#8211; livequery &#8220;навесит&#8221; на них нужные обработчики. Очень удобно. Но будьте внимательны и осторожны &#8211; не стоит увлекаться &#8211; чем больше элементов будут переданы в livequery, тем &#8220;тормознее&#8221;  будет система &#8211; каждые 20мс проводиться поиск элементов в целью <strike>найти и обезвредить</strike> навесить нужные эвенты (а также после разнообразных манипуляций с dom).</li>
<li> И последний на этот раз факт &#8211; как известно jQuery &#8220;оборачивается&#8221; в функцию $() &#8211; уж больно кратко,красиво и удобно в использовании. Но в эту же функцию любят &#8220;оборачиваться&#8221; многие известные js-фреймворки. И это казалось бы ставит крест на совместном их использовании&#8230; Но не в случае с jQuery &#8211; его авторы понимают что они не одни на белом свете. jQuery.noConflict(); &#8220;отпустит&#8221; функцию $(), правда сам код использующий jQuery в этом случае должен содержать либо полное название функции [ jQuery("selector").action(); ] или же должен быть &#8220;завёрнут&#8221; в анонимную функцию [ (function($) { original_code})(jQuery); ]</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2007/10/18/jquery-facts-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>firebug 1.1 (beta)</title>
		<link>http://miracle.rpz.name/2007/10/01/firebug-11-beta/</link>
		<comments>http://miracle.rpz.name/2007/10/01/firebug-11-beta/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 11:00:46 +0000</pubDate>
		<dc:creator>MiRacLe</dc:creator>
				<category><![CDATA[advertise]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://miracle.rpz.name/?p=68</guid>
		<description><![CDATA[И всё-таки он обновляется! (да-да &#8211; а земля круглая и вертится). Самые, на мой взгляд, вкусные изменения это закладка &#8220;Stack&#8221; в отладчике. (Её как раз стало очень нехватать &#8211; ранее стек вызова показывался в строке с меню и тупо не помещался в ней) и возможность использовать внешний редактор(!) по умолчанию это aptana. Появились и визуальные [...]]]></description>
			<content:encoded><![CDATA[<p>И всё-таки он обновляется! (да-да &#8211; а земля круглая и вертится).</p>
<p>Самые, на мой взгляд, вкусные изменения это закладка &#8220;Stack&#8221; в отладчике. (Её как раз стало очень нехватать &#8211; ранее стек вызова показывался в строке с меню и тупо не помещался в ней)  и возможность использовать внешний редактор(!) по умолчанию это <a href="http://aptana.org">aptana</a>.</p>
<p>Появились и визуальные изменения &#8211; подсветка исполняемого блока кода например. А вот «“better” debugging icons» по-моему паршивые &#8211; старые были привычнее и симпатичнее&#8230;</p>
<p>Вы можете <a href="http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt">взглянуть на полный список изменений в этой версии</a> и <a href="http://fireclipse.xucia.com/#Downloads">на свой страх и риск установить себе эту глючную версию, которая страдает падучей&#8230;</a></p>
<p>Technorati Tags: <a class="performancingtags" href="http://technorati.com/tag/firefox" rel="tag">firefox</a>, <a class="performancingtags" href="http://technorati.com/tag/firebug" rel="tag">firebug</a></p>
]]></content:encoded>
			<wfw:commentRss>http://miracle.rpz.name/2007/10/01/firebug-11-beta/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Served from: miracle.rpz.name @ 2012-02-06 16:56:38 by W3 Total Cache -->
