<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Insight IT</title><link>https://www.insight-it.ru/</link><description></description><atom:link href="https://www.insight-it.ru/tag/javascript/feed/index.xml" rel="self"></atom:link><lastBuildDate>Fri, 08 Feb 2013 10:20:00 +0400</lastBuildDate><item><title>Вакансии: команда Python разработчиков в EVAplacer</title><link>https://www.insight-it.ru//vacancy/2013/vakansii-komanda-python-razrabotchikov-v-evaplacer/</link><description>&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансии более не актуальны&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Новая &lt;em&gt;международная геоинформационная социальная сеть&lt;/em&gt; EVAplacer
набирает команду разработчиков.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="vedushchii-razrabotchik-servernoi-chasti-na-python"&gt;Ведущий разработчик серверной части на Python&lt;/h2&gt;
&lt;h3 id="zadachi"&gt;Задачи&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Разработка серверной части проекта на Python&lt;/li&gt;
&lt;li&gt;Проектирование архитектуры системы и схемы базы данных&lt;/li&gt;
&lt;li&gt;Организация взаимодействия серверной части проекта с клиентской&lt;/li&gt;
&lt;li&gt;Принятие технических решений&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="trebovaniia"&gt;Требования&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Свежий опыт веб-разработки на Python &lt;em&gt;без использования Django&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Суммарный опыт веб-разработки от 5 лет&lt;/li&gt;
&lt;li&gt;Самостоятельность и заинтересованность в качестве результата своей
    работы&lt;/li&gt;
&lt;li&gt;Умение делегировать часть работы коллегам&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="tekhnologii"&gt;Технологии&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Предстоит работать со следующими технологиями:&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/2e568974/" rel="nofollow" target="_blank" title="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; +
    &lt;a href="https://www.insight-it.ru/goto/35c21496/" rel="nofollow" target="_blank" title="http://jinja.pocoo.org/"&gt;Jinja2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/bf2b1e00/" rel="nofollow" target="_blank" title="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt; +
    &lt;a href="https://www.insight-it.ru/goto/a6920afe/" rel="nofollow" target="_blank" title="http://lucene.apache.org/solr/"&gt;Solr&lt;/a&gt; +
    &lt;a href="https://www.insight-it.ru/goto/9ecaff4c/" rel="nofollow" target="_blank" title="http://memcached.org/"&gt;memcached&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/39ecae7b/" rel="nofollow" target="_blank" title="http://www.zeromq.org/"&gt;ZeroMQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Опыт работы именно с ними очень желателен, но не обязателен&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="zarplata"&gt;Зарплата&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;В диапазоне 100-150 тысяч рублей в месяц в зависимости от опыта&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="klientskii-razrabotchik_1"&gt;Клиентский разработчик&lt;/h2&gt;
&lt;h3 id="zadachi_1"&gt;Задачи&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Разработка клиентской части проекта&lt;/li&gt;
&lt;li&gt;Работа на стыке с серверной частью (Python), создание HTML и других
    шаблонов на Jinja2&lt;/li&gt;
&lt;li&gt;Оптимизация скорости загрузки страниц&lt;/li&gt;
&lt;li&gt;Принятие технических решений по клиентской части&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="trebovaniia_1"&gt;Требования&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Опыт разработки на JavaScript/CoffeeScript и валидной верстки на
    HTML5&lt;/li&gt;
&lt;li&gt;Понимание основных принципов клиентской оптимизации&lt;/li&gt;
&lt;li&gt;Суммарный опыт веб-разработки от 3 лет&lt;/li&gt;
&lt;li&gt;Усидчивость, самостоятельность и заинтересованность в качестве
    результата своей работы&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="tekhnologii_1"&gt;Технологии&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Предстоит работать со следующими технологиями:&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/35c21496/" rel="nofollow" target="_blank" title="http://jinja.pocoo.org/"&gt;Jinja2&lt;/a&gt; +
    &lt;a href="https://www.insight-it.ru/goto/312f4825/" rel="nofollow" target="_blank" title="http://elsdoerfer.name/docs/webassets/"&gt;webassets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/834fa52/" rel="nofollow" target="_blank" title="http://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt; +
    &lt;a href="https://www.insight-it.ru/goto/dca1748a/" rel="nofollow" target="_blank" title="http://sass-lang.com/"&gt;SASS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/f573c764/" rel="nofollow" target="_blank" title="http://twitter.github.com/bootstrap/"&gt;Twitter Bootstrap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/3b02d98c/" rel="nofollow" target="_blank" title="http://jquery.com/"&gt;jQuery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/96340c7c/" rel="nofollow" target="_blank" title="http://leafletjs.com/"&gt;Leaflet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Опыт работы именно с ними очень желателен, но не обязателен&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="zarplata_1"&gt;Зарплата&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;В диапазоне 60-100 тысяч рублей в месяц в зависимости от опыта&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="spetsialist-po-testirovaniiu_1"&gt;Специалист по тестированию&lt;/h2&gt;
&lt;h3 id="zadachi_2"&gt;Задачи&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Основные:&lt;ul&gt;
&lt;li&gt;Разработка автоматических тестов для серверной части проекта на
    Python&lt;/li&gt;
&lt;li&gt;Регрессионное тестирование сайта с помощью
    &lt;a href="https://www.insight-it.ru/goto/561c2b8c/" rel="nofollow" target="_blank" title="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt; или альтернатив&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Дополнительные:&lt;ul&gt;
&lt;li&gt;Нагрузочное тестирование с использованием
    &lt;a href="https://www.insight-it.ru/goto/52bdc53f/" rel="nofollow" target="_blank" title="http://jmeter.apache.org/"&gt;JMeter&lt;/a&gt; или альтернатив&lt;/li&gt;
&lt;li&gt;Ручное визуальное тестирование, в т.ч. на кроссбраузерность&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="trebovaniia_2"&gt;Требования&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Свежий опыт тестирования интернет-проектов, желательно на Python&lt;/li&gt;
&lt;li&gt;Суммарный опыт в тестировании от 3 лет&lt;/li&gt;
&lt;li&gt;Внимательность, самостоятельность и заинтересованность в качестве
    результата работы команды&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="zarplata_2"&gt;Зарплата&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;В диапазоне 50-100 тысяч рублей в месяц в зависимости от опыта&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usloviia_1"&gt;Условия&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Премии по достижении ключевых вех проекта&lt;/li&gt;
&lt;li&gt;Офис в центре Москвы (м. Охотный ряд, меньше 5 минут пешком)&lt;/li&gt;
&lt;li&gt;Работа на MacBook Pro&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансии более не актуальны&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Fri, 08 Feb 2013 10:20:00 +0400</pubDate><guid>tag:www.insight-it.ru,2013-02-08:vacancy/2013/vakansii-komanda-python-razrabotchikov-v-evaplacer/</guid><category>CoffeeScript</category><category>EVAplacer</category><category>Flask</category><category>html5</category><category>JavaScript</category><category>Jinja2</category><category>JMeter</category><category>JQuery</category><category>Leaflet</category><category>MacBook Pro</category><category>Memcached</category><category>MongoDB</category><category>Python</category><category>sass</category><category>Selenium</category><category>Solr</category><category>Twitter Bootstrap</category><category>webassets</category><category>ZeroMQ</category><category>вакансии</category><category>разработчик</category><category>тестировщик</category></item><item><title>Оптимизация интерактивных сайтов</title><link>https://www.insight-it.ru//interactive/2012/optimizaciya-interaktivnykh-sajjtov/</link><description>&lt;p&gt;Возвращаясь к теме&amp;nbsp;&lt;a href="https://www.insight-it.ru/interactive/"&gt;"Интерактивных сайтов"&lt;/a&gt;,&amp;nbsp;сегодня я хотел бы обсудить заключительную часть повествования, их
&lt;strong&gt;оптимизацию&lt;/strong&gt;. Возможно вы уже успели реализовать все или часть
обсуждавшихся в предыдущих статьях приемов, в этой статье я "подкину"
Вам еще несколько.&amp;nbsp;Настоятельно рекомендую прежде чем читать дальше
ознакомиться хотя бы с первой статьей про общую архитектуру, а лучше,
конечно, со всеми предыдущими статьями серии. В этот раз мы пройдемся по
всем обсуждавшимся в отдельных статьях компонентам, правда в другом
порядке, и будем обсуждать возможные пути их улучшения.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="oglavlenie-serii-interaktivnye-saity"&gt;Оглавление серии "Интерактивные сайты"&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/arkhitektura-interaktivnykh-sajjtov/"&gt;Общая архитектура&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/klientskaya-chast-interaktivnogo-sajjta/"&gt;Организация клиентской части&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/postoyannoe-soedinenie-mezhdu-brauzerom-i-serverom/"&gt;Постоянное соединение между браузером и сервером&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/povtornoe-ispolzovanie-shablonov/"&gt;Повторное использование шаблонов&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/servernaya-chast-interaktivnogo-sajjta-i-potoki-soobshhenijj/"&gt;Серверная часть интерактивного сайта и потоки сообщений&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/optimizaciya-interaktivnykh-sajjtov/"&gt;Оптимизация&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="servernaia-chast"&gt;Серверная часть&lt;/h2&gt;
&lt;p&gt;На серверной стороне есть масса простора для оптимизации, но, чтобы не
распыляться, постараюсь сосредоточиться лишь на том, что напрямую
связано с темой &lt;em&gt;интерактивных сайтов&lt;/em&gt;. В частности на процессе
маршрутизации сообщений и уведомлений между пользователями.&lt;/p&gt;
&lt;p&gt;Когда разрабатывается первая версия сайта, то многие части функционала
проще всего реализовать в виде массовых рассылок, как-то так: произошло
какое-то публично-доступное событие, допустим кто-то куда-то поставил
"мне нравится", отправляем его в брокер сообщений с пометкой "доставить
всем" &lt;em&gt;(fanout)&lt;/em&gt;. В итоге все подключенные на данный момент клиенты
получают это уведомление и каждый сам решает что с ним делать - что-то
менять на текущей странице или просто проигнорировать.&lt;/p&gt;
&lt;p&gt;Но при большом количестве соединений и потоке событий такой подход
становится роскошью. Большинство подобных ситуаций можно реализовать
подпиской на тематические &lt;em&gt;(topic)&lt;/em&gt; рассылки для каждого пользователя
индивидуально, то есть когда пользователь открывает ту или иную
страницу - серверная сторона должна подписать его на уведомления,
связанные именно с тем контентом, который находится у него на экране.
Это позволит свести к минимуму количество&amp;nbsp;доставленных&amp;nbsp;зря сообщений.&lt;/p&gt;
&lt;p&gt;Ситуации, когда правда нужны массовые рассылки по всем пользователям,
хоть и редки, но все же бывают. Если есть возможность их избежать, то
лучшей ей воспользоваться.&lt;/p&gt;
&lt;p&gt;Чтобы реализовать индивидуальные подписки как изложено выше, вероятно
понадобится еще и изменить принцип установления соединений между
брокером сообщений и сервером, поддерживающим постоянное соединение. Для
схемы массовых рассылок достаточно одного такого соединения на сервер.
Каждый сервер хранит список активных соединений с браузерами и, получив
новое сообщение от брокера, просто итеративно проходится по нему,
ретранслируя сообщение в каждое соединение. В таком случае для
последнего соединения в списке задержка может достигать нескольких
секунд, что не всегда приемлемо. Для схемы индивидуальных подписок есть
два основных варианта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Реализовать мини-брокер внутри каждого такого сервера, т.е. сам
    сервер по-прежнему держит лишь одно соединение с настоящим брокером
    и получает все подряд сообщения, но прежде чем ретранслировать
    анализирует его и отправляет лишь части соединений.&lt;/li&gt;
&lt;li&gt;Либо держать создавать много примитивных процессов, которые с одной
    стороны держат соединение с браузером, с другой - с брокером. Каждый
    из них подписан именно на те сообщения, которые нужны данному
    пользователю, и ретранслируют их все без анализа.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="card blue lighten-4"&gt;
&lt;p&gt;&lt;div class="card-content"&gt;
Оба варианта имеют право на существование, какой окажется лучше -
зависит от многих факторов, нужно тестировать. Лично мне больше по душе
второй, но далеко не на каждой платформе его удастся эффективно
реализовать - настоящих системных процессов для такого использования
не&amp;nbsp;напасешься.
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="postoiannoe-soedinenie-mezhdu-brauzerom-i-serverom"&gt;Постоянное соединение между браузером и сервером&lt;/h2&gt;
&lt;p&gt;Помимо выбора удачной библиотеки абстракции протоколов для различных
браузеров, о чем я уже довольно подробно писал в соответствующей статье
серии, здесь я могу предложить еще два момента для значительного
улучшения производительности.&lt;/p&gt;
&lt;h3 id="mezhvkladochnoe-vzaimodeistvie-cross-tab-communication"&gt;Межвкладочное взаимодействие &lt;em&gt;(cross-tab communication)&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;На эту тему в Интернете ходит масса слухов и разговоров, но адекватной
инструкции о том как это можно кроссбраузерно организовать в разумные
сроки я не встречал, если кто знает - дайте в ссылку в комментариях,
пожалуйста. А я пока попробую поделиться своим опытом.&lt;/p&gt;
&lt;p&gt;Вкратце для тех, кто не в курсе: в самой простой реализации постоянное
соединение между браузером и сервером устанавливается для каждой вновь
открытой вкладки заново. Так как каждое такое соединение ресурсоемко, то
этого хотелось бы избежать. Помочь в этом может организация
&lt;strong&gt;межвкладочного взаимодействия&lt;/strong&gt; или, другими словами, общения между
вкладками/окнами браузера: одна вкладка избирается &lt;em&gt;главной&lt;/em&gt; и
устанавливает соединение с сервером, когда она получает новое
сообщение - она переправляет его конкретной открытой вкладке или же всем
сразу; те же, в свою очередь, когда хотят отправить сообщение на сервер,
отправляют его сначала &lt;em&gt;главной&lt;/em&gt; вкладке, а та уже пересылает на сервер.
В итоге все работает как и раньше, но соединений не больше одного на
браузер.&lt;/p&gt;
&lt;p&gt;Вообще в явном виде общение между вкладками браузера, как Вы, вероятно,
знаете, не предусмотрено. Именно из-за этого реализовать это все
кроссбраузерно не просто. Для начала приведу список технологий, которые
так или иначе можно для этого приспособить, большинство из них принято
относить к нынче модному &lt;a href="/tag/html5/"&gt;HTML5&lt;/a&gt;, в порядке возрастания
моих симпатий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/704e1f8a/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Local_shared_object"&gt;Flash Local Shared Cookies&lt;/a&gt; - даже не рассматривал как вариант, так как требуется Adobe Flash, плюс, кажется, постоянно всплывает окно вроде
    &lt;a href="https://www.insight-it.ru/goto/e9a669cc/" rel="nofollow" target="_blank" title="http://www.macromedia.com/support/documentation/en/flashplayer/help/help06.html"&gt;этого&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/732af670/" rel="nofollow" target="_blank" title="http://caniuse.com/#feat=x-doc-messaging"&gt;postMessage&lt;/a&gt;&amp;nbsp;-&amp;nbsp;отправка
    сообщения указанному окну по его идентификатору. Поддержка
    браузерами хорошая, но большинство примеров показывают общение с
    iframe, а сопутствующего API для получения списка всех открытых
    окон/вкладок я не нашел, может быть плохо искал.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/86256a54/" rel="nofollow" target="_blank" title="http://caniuse.com/#feat=webworkers"&gt;Web Workers&lt;/a&gt; - в браузере
    создается не зависящий от вкладок поток, с которым можно общаться из
    вкладок. Поддержка браузерами хромает, а там где её нет -
    polyfill'ов пока не придумали.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/fc6c98e9/" rel="nofollow" target="_blank" title="http://caniuse.com/#feat=namevalue-storage"&gt;Web Storage&lt;/a&gt; -
    локальное хранилище пар ключ-значение с ограничением в 5-10Мб на
    домен. Хорошая поддержка браузерами, а там где её нет - есть
    polyfill'ы. Еще бывает &lt;a href="https://www.insight-it.ru/goto/71a12fd0/" rel="nofollow" target="_blank" title="http://caniuse.com/#feat=sql-storage"&gt;Web SQL&lt;/a&gt;, но для данной задачи это уже перебор.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В общем рекомендую последний вариант, из дополнительных плюсов хранилище
можно использовать и для других целей, но об этом в следующих разделах.&lt;/p&gt;
&lt;p&gt;Если есть желание и время можно работать напрямую с API хранилища, но
все же самостоятельно разбираться с особенностями браузеров - занятие не
благодарное, так что могу посоветовать взглянуть на имеющиеся opensource
библиотеки-обертки. Из тех, что я пробовал, мне больше всего нравится
&lt;strong&gt;&lt;a href="https://www.insight-it.ru/goto/288f4119/" rel="nofollow" target="_blank" title="http://www.jstorage.info/"&gt;jStorage&lt;/a&gt;&lt;/strong&gt;&amp;nbsp;из-за своей "зеленой" таблицы
поддержки браузерами и готовому publish/subscribe API.&lt;/p&gt;
&lt;p&gt;Итак, вкратце пройдемся по ориентировочному алгоритму реализации
межвкладочного взаимодействия:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Каждая вкладка при своем открытии придумывает себе уникальный
    идентификатор (проще всего на основе &lt;em&gt;Math.random&lt;/em&gt;), будем называть
    его &lt;strong&gt;tab_id&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;В хранилище будут храниться список всех активных tab_id, допустим,
    &lt;strong&gt;tabs&lt;/strong&gt; и tab_id &lt;em&gt;главной&lt;/em&gt; &lt;em&gt;вкладки&lt;/em&gt;, допустим,&amp;nbsp;&lt;strong&gt;master&lt;/strong&gt;. Каждая
    новая вкладка смотрит есть ли другие открытые вкладки. Если есть -
    просто дописывает себя в tabs, если нет - то еще и объявляет себя
    главной и открывает соединение с браузером.&lt;/li&gt;
&lt;li&gt;Далее она подписывается на сообщения отправленные лично ей (по её
    tab_id) и на различные типы сообщений, которые могут быть интересны
    всем вкладкам.&lt;/li&gt;
&lt;li&gt;В обработчике события &lt;em&gt;window.onbeforeunload&lt;/em&gt;&amp;nbsp;(происходит сразу же
    перед закрытием вкладки) каждая вкладка убирает себя из &lt;strong&gt;tabs&lt;/strong&gt;&amp;nbsp;и
    если она была главной, то и из &lt;strong&gt;master&lt;/strong&gt; тоже. Альтернативный
    вариант: &lt;strong&gt;master&lt;/strong&gt; сразу может выбирать себе "преемника". Так как
    это событие срабатывает не всегда (когда компьютер жестко вырубился
    питанием, фатальный сбой в браузере, плюс оно не поддерживается
    неоправданно популярной в рунете Оперой и мобильным Safari), то
    придется создать альтернативный механизм проверки активности
    &lt;strong&gt;master&lt;/strong&gt; и очистки &lt;strong&gt;tabs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Так как какого-либо API для проверки открыта ли вкладка по её
    &lt;strong&gt;tab_id&amp;nbsp;&lt;/strong&gt;по очевидным причинам нет, нужно придумать свою схему.
    Самый простой рабочий вариант, пришедший мне в голову:&lt;ul&gt;
&lt;li&gt;Главная вкладка пишет каждые несколько сотен&amp;nbsp;миллисекунд&amp;nbsp;в
    хранилище текущую дату/время, теоретически так как все
    происходит на одном компьютере, то текущее время во всех
    вкладках должно быть одно и то же;&lt;/li&gt;
&lt;li&gt;Не-главные вкладки каждые 1-3 секунд читают значение из того же
    места в хранилище и если оно отстает от текущего на, допустим,
    больше чем секунду, то главную вкладку, вероятно, закрыли и надо
    её "свергнуть" - удалить из &lt;strong&gt;tabs&lt;/strong&gt; и &lt;strong&gt;master&lt;/strong&gt;&amp;nbsp;и назначить,
    например, первую или последнюю запись из списка&amp;nbsp;&lt;strong&gt;tabs&lt;/strong&gt; новой
    главной вкладкой;&lt;/li&gt;
&lt;li&gt;Если выбранная новая вкладка тоже оказалась уже закрыта, не
    беда - во всех случаях, кроме совсем неадекватных, этот не
    хитрый механизм переберет все&amp;nbsp;&lt;strong&gt;tabs&lt;/strong&gt; и найдет-таки нормальную
    открытую;&lt;/li&gt;
&lt;li&gt;Каждая вкладка подписывается на изменения значения &lt;strong&gt;master&lt;/strong&gt;,
    чтобы если новое значение совпадет с её tab_id открыть
    соединение с сервером.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Отправка сообщений происходит по простому publish/subscribe, где
    master подписывается и ретранслирует в соединение с сервером, а
    отправляют все остальные вкладки. Если вкладка отправляет запрос,
    ответ на который хочет получить только она сама (чаще всего переход
    на другую страницу сайта или отправка формы), то она указывает в
    отправляемом запросе свой "обратный адрес" в виде tab_id. Master,
    получив ответ на такое сообщение с указанным обратным адресом,
    перенаправляет его отправителю.&lt;/li&gt;
&lt;li&gt;Также в хранилище полезно иметь переменную-флаг (также с подпиской
    на изменения), обозначающую открыто ли сейчас где-то постоянное
    соединение, чтобы вместо того, чтобы отправлять сообщения&amp;nbsp;в
    никуда&amp;nbsp;вкладки использовали какой-то альтернативный способ (AJAX или
    переход по ссылке / отправка формы средствами браузера). В качестве
    альтернативы можно реализовать очередь неотправленных сообщений, но
    по факту когда с соединением проблемы, то неизвестно когда они
    устранятся и устранятся ли вообще, так что смысла в ней чаще всего
    мало.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Надеюсь вышеизложенное окажется кому-то полезным, если нужны какие-то
уточнения - не стесняйтесь спрашивать в комментариях.&lt;/p&gt;
&lt;h3 id="minimizatsiia-razmera-soobshchenii"&gt;Минимизация размера сообщений&lt;/h3&gt;
&lt;p&gt;&lt;a href="/tag/json/"&gt;JSON&lt;/a&gt; хоть и сильно выигрывает у &lt;a href="/tag/xml/"&gt;XML&lt;/a&gt;&amp;nbsp;по объему
сериализованных сообщений, но все же является текстовым форматом с
указанием схемы (название для каждого значения) внутри самого сообщения.
Почему минимизация объема передаваемых по постоянному соединению
данных - дело полезное, объяснять, думаю, не стоит.&lt;/p&gt;
&lt;p&gt;Первое, что приходит в голову, чтобы уменьшить объем сообщений -
избавиться от включенной в них схемы, оставив только чистые данные.
Изобретать свой формат ни к чему, есть неплохой&amp;nbsp;широко
распространенный&amp;nbsp;кандидат в виде &lt;a href="/tag/google/"&gt;Google&lt;/a&gt;&amp;nbsp;&lt;a href="/tag/protocol-buffers/"&gt;Protocol
Buffers&lt;/a&gt;. Кстати, недавно нашел библиотеку с
&lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt; реализацией Protocol Buffers с хорошими
отзывами, в ближайшее время думаю сам опробую:
&lt;a href="https://www.insight-it.ru/goto/a420ea/" rel="nofollow" target="_blank" title="https://github.com/sirikata/protojs"&gt;protojs&lt;/a&gt;. Если кто уже работал с
ней - буду рад, если поделитесь впечатлениями.&lt;/p&gt;
&lt;p&gt;Но на практике оказалось, что эта самая схема обычно занимает максимум
10-20% от сообщения, так как большинство данных все же текстовые.
Использование Protocol Buffers было бы намного более выгодным, если бы
было необходимо "упаковать" много чисел или флагов, для текстовых данных
выигрыш намного меньше.&lt;/p&gt;
&lt;p&gt;Экономии в разы можно добиться используя обычные алгоритмы компрессии
(или, если так привычнее, архивации) данных.
&lt;a href="/tag/javascript/"&gt;JavaScrtipt&lt;/a&gt; "из коробки" этого делать не умеет, но
есть полно библиотек на любой вкус и цвет, правда все хромают и чаще
всего не кроссбраузерные. Приведу несколько, которые запомнились после
вечера, проведенного за изучением данного вопроса:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/be52f434/" rel="nofollow" target="_blank" title="http://rosettacode.org/wiki/LZW_compression"&gt;LZW&lt;/a&gt; - есть реализации
    на большинстве языков программирования, но компрессия не очень
    сильная (раза в полтора-два в лучшем случае), плюс реализация под
    интересующий меня &lt;a href="/tag/erlang/"&gt;Erlang&lt;/a&gt; оказалась дико неэффективна
    по памяти, а на бинарных строках сходу не нашлась.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/49c64f8e/" rel="nofollow" target="_blank" title="https://github.com/imaya/zlib.js"&gt;zlib.js&lt;/a&gt; - умеет &lt;em&gt;zlib (deflate)&lt;/em&gt;
    и &lt;em&gt;gzip&lt;/em&gt;, но, к сожалению, в моем браузере не могла разжать обратно
    то, что сжала, плюс объем кода библиотеки очень большой.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/730dabaf/" rel="nofollow" target="_blank" title="https://github.com/dankogai/js-deflate"&gt;js-deflate&lt;/a&gt; - не
    обновлялась уже 4 года, отсутствует документация, но зато в целом
    работает. Подбирать метод компрессии для серверной стороны пришлось
    почти экспериментально, оказался &lt;em&gt;zlib (deflate)&lt;/em&gt; без заголовков и
    контрольной суммы (в &lt;a href="/tag/erlang/"&gt;Erlang&lt;/a&gt; встроенная функция zlib:zip). Компрессия примерно в 3-4 раза.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если все же решите использовать компрессию, то рекомендую реализовать
флаг для ситуаций когда в клиенте все же декомпрессия по каким-то
причинам сломана. Достаточно просто сжать-разжать короткую строку и
сравнить с оригиналом, если не совпало или выскочило исключение -
просить сервер отвечать без компрессии.&lt;/p&gt;
&lt;p&gt;По поводу дополнительных вычислительных ресурсов, которые будут
потребляться на компрессию/декомпрессию, вопрос, конечно, спорный, в
целом надо все мерять и делать выводы. Но если учесть, что почти во всех
современных устройствах, даже телефонах, как минимум 1Ггц процессор, а
на сервере можно кэшировать уже сжатые данные, то это не особо большая
проблема. К слову объем сообщений уменьшается тоже не гарантированно,
бывает что "сжатая" версия оказывается такой же или даже чуть больше,
чем оригинал. В общем, использовать компрессию нужно осторожно :)&lt;/p&gt;
&lt;h2 id="povtornoe-ispolzovanie-shablonov_1"&gt;Повторное использование шаблонов&lt;/h2&gt;
&lt;p&gt;Сообщение со списком шаблонов для использование на клиентской части,
вероятно, будет самым большим по объему и больше других выиграет от
компрессии. Но есть возможность легко минимизировать и количество таких
сообщений. Помните, я писал, что локальное хранилище в браузере можно и
для других целей использовать?&lt;/p&gt;
&lt;p&gt;Кэширование шаблонов - идеальный пример. Получив от сервера шаблоны он
кладет их не только в объект-обертку, но и в локальное хранилище. На
сервере помимо самого JSON'а с шаблонами генерируем хэш (md5, sha или
crc - не важно) текущей версии. Клиент, когда открывает соединение,
сообщает серверу есть ли у него какая-то версия и если есть, то какая,
сервер отправляет новую версию в ответ только если хэши не совпали.&lt;/p&gt;
&lt;p&gt;Аналогичным образом можно кэшировать и другую редко меняющуюся объемную
информацию, например данные для автодополнения в текстовых полях
&lt;em&gt;(autocomplete)&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="zakliuchenie"&gt;Заключение&lt;/h2&gt;
&lt;p&gt;Надеюсь предложенные в этой статье приемы окажутся Вам полезны. Буду
рад, если Вы поделитесь своим опытом и приемами по данной теме в
комментариях, а также с удовольствием обсужу подробности.&lt;/p&gt;
&lt;div class="card green"&gt;
&lt;p&gt;&lt;div class="card-content white-text"&gt;
Эта статья - шестая и заключительная в &lt;a class="green-text text-lighten-4" href="https://www.insight-it.ru/interactive/"&gt;серии про Интерактивные сайты&lt;/a&gt;, автор - &lt;a class="green-text text-lighten-4" href="https://www.insight-it.ru/goto/b03d9116/" rel="nofollow" target="_blank" title="http://blinkov.ru"&gt;Иван&amp;nbsp;Блинков&lt;/a&gt;, основано на личном опыте.
До встречи &lt;a class="green-text text-lighten-4" href="/feed/"&gt;на страницах Insight IT&lt;/a&gt;!
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sat, 20 Oct 2012 12:32:00 +0400</pubDate><guid>tag:www.insight-it.ru,2012-10-20:interactive/2012/optimizaciya-interaktivnykh-sajjtov/</guid><category>deflate</category><category>html5</category><category>JavaScript</category><category>JSON</category><category>jStorage</category><category>Protocol Buffers</category><category>Web Storage</category><category>zlib</category><category>клиентская оптимизация</category><category>компрессия</category><category>кэширование</category><category>оптимизация</category></item><item><title>Вакансии: PHP и Python разработчики в Киеве</title><link>https://www.insight-it.ru//vacancy/2012/vakansii-php-i-python-razrabotchiki-v-kieve/</link><description>&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансии более не актуальны&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Киевская команда разработчиков игр для социальных и мобильных платформ
Level UP ищет опытных специалистов по
веб-разработке на Python и PHP.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="senior-python-developer"&gt;Senior Python Developer&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Задачи:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Разработка высоконагруженных веб-приложений;&lt;/li&gt;
&lt;li&gt;Разработка внутренних и публичных API;&lt;/li&gt;
&lt;li&gt;Разработка архитектуры комплексных сервисов;&lt;/li&gt;
&lt;li&gt;Конвертирование бизнес-задач в технические решения (R&amp;amp;D).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Требования:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Опыт разработки на &lt;strong&gt;Python&lt;/strong&gt; более 3х лет;&lt;/li&gt;
&lt;li&gt;Сильные навыки применения реляционных и нереляционных баз данных;&lt;/li&gt;
&lt;li&gt;Опыт в разработке высоконагруженных веб-приложений;&lt;/li&gt;
&lt;li&gt;Дружба с &lt;strong&gt;Linux&lt;/strong&gt; и &lt;strong&gt;Git&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Хорошее знание клиентских технологий (HTML, CSS, Javascript);&lt;/li&gt;
&lt;li&gt;Опыт работы в команде.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Плюсом будет:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Опыт разработки комплексных проектов на &lt;strong&gt;PHP&lt;/strong&gt; или серверном
    &lt;strong&gt;Javascript&lt;/strong&gt; &lt;em&gt;(node.js)&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Опыт разработки инструментов для верстки, автоматизации верстки,
    шаблонизаторов и пр.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="senior-php-developer"&gt;Senior PHP Developer&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Задачи:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Разработка высоконагруженных социальных веб-приложений;&lt;/li&gt;
&lt;li&gt;Работа в небольшой дружной команде до 15 человек;&lt;/li&gt;
&lt;li&gt;Решение нетривиальных задач и создание инструментов для внутреннего
    использования;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Требования:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Опыт разработки на &lt;strong&gt;PHP&lt;/strong&gt; более 3х лет;&lt;/li&gt;
&lt;li&gt;Опыт работы с &lt;strong&gt;MySQL&lt;/strong&gt; и &lt;strong&gt;MongoDB&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Опыт в разработке высоконагруженных веб-приложений;&lt;/li&gt;
&lt;li&gt;Дружба с &lt;strong&gt;Linux&lt;/strong&gt; и &lt;strong&gt;Git&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Хорошее знание клиентских технологий (HTML, CSS, Javascript);&lt;/li&gt;
&lt;li&gt;Опыт примененения функционарного и юнит тестирования.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Плюсом будет:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Опыт разработки на &lt;strong&gt;Python&lt;/strong&gt; или серверном &lt;strong&gt;Javascript&lt;/strong&gt;
&lt;em&gt;(nodejs)&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usloviia-dlia-oboikh-vakansii"&gt;Условия для обоих вакансий&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Зарплата в диапазоне &lt;strong&gt;\$2500-4000&lt;/strong&gt; в месяц по результатам
    собеседования;&lt;/li&gt;
&lt;li&gt;Полный рабочий день в &lt;strong&gt;Киевском офисе&lt;/strong&gt;, иногородним помощь с
    переездом;&lt;/li&gt;
&lt;li&gt;За успешную рекомендацию специалиста по данным вакансиям компания
    выплачивает&amp;nbsp;&lt;strong&gt;бонус в размере $1000&lt;/strong&gt; так что сообщите своим
    знакомым, кому-то это может быть интересно.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="zainteresovalo"&gt;Заинтересовало?&lt;/h2&gt;
&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансии более не актуальны&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Не лишним будет, если кроме резюме Вы напишите - почему Вам нравится
серверная разработка на Python или PHP и почему Вам интересна данная
вакансия. Плюс упомяните, пожалуйста, что Вы узнали о данной вакансии
через &lt;strong&gt;Insight IT&lt;/strong&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 20 Sep 2012 20:16:00 +0400</pubDate><guid>tag:www.insight-it.ru,2012-09-20:vacancy/2012/vakansii-php-i-python-razrabotchiki-v-kieve/</guid><category>css</category><category>Git</category><category>html</category><category>JavaScript</category><category>Level UP</category><category>Linux</category><category>MongoDB</category><category>MySQL</category><category>node.js</category><category>PHP</category><category>Python</category><category>вакансии</category><category>Киев</category></item><item><title>Вакансии: команда IT-звезд</title><link>https://www.insight-it.ru//vacancy/2012/vakansii-komanda-it-zvezd/</link><description>&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансии более не актуальны&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Благодаря сайту &lt;strong class="trebuchet"&gt;Insight IT&lt;/strong&gt;, компания
RDM-Soft нашла ОТЛИЧНОГО тимлида! Теперь, &lt;a href="https://www.insight-it.ru/vacancy/2012/vakansiya-php-polkovodec/"&gt;тимлидер&lt;/a&gt; ищет в свою команду&amp;nbsp;единомышленников и просто IT-звезд.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="o-kompanii"&gt;О компании&lt;/h2&gt;
&lt;p&gt;История компании началась в 2003 году. С этого момента выпущено много
проектов. Некоторыми из них Вы, возможно, так или иначе пользовались.
Сейчас запускается еще один проект:&amp;nbsp;&lt;strong&gt;SEO-биржа&lt;/strong&gt;. У Вас
есть прекрасная возможность оказаться у истоков будущего хита!&lt;/p&gt;
&lt;h2 id="kto-nuzhen"&gt;Кто нужен?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mr. Backend.&lt;/strong&gt; Он же программист.&amp;nbsp;&lt;em&gt;(вакансия закрыта)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Мастер-ломастер.&lt;/strong&gt; Он же инженер по контролю качества, проще
    говоря тестер.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dr. Frontend.&lt;/strong&gt; Он же фронтендщик. &lt;em&gt;(вакансия закрыта)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mr-backend"&gt;Mr. Backend&lt;/h3&gt;
&lt;h4&gt;Требования&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Отличные знания: &lt;strong&gt;PHP&lt;/strong&gt;, &lt;strong&gt;ООП&lt;/strong&gt;, &lt;strong&gt;SQL&lt;/strong&gt;, &lt;strong&gt;MVC&lt;/strong&gt;,
    &lt;strong&gt;ZendFramework&lt;/strong&gt; (либо альтернатив), &lt;strong&gt;Linux&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Опыт работы по специальности: от 3 лет.&lt;/li&gt;
&lt;li&gt;Опыт работы в команде.&lt;/li&gt;
&lt;li&gt;Желание развиваться и изучать новое.&lt;/li&gt;
&lt;li&gt;Отсутствие желания искать работу в ближайшие 3 года.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Задачи&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Разработка серверной части проекта.&amp;nbsp;Включает в себя :&lt;ul&gt;
&lt;li&gt;бухгалтерия;&lt;/li&gt;
&lt;li&gt;бизнес-логика;&lt;/li&gt;
&lt;li&gt;статистика;&lt;/li&gt;
&lt;li&gt;различные парсеры.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="master-lomaster-sqa"&gt;Мастер-Ломастер (SQA)&lt;/h3&gt;
&lt;h4&gt;Требования&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Хорошие знания: &lt;strong&gt;PHP&lt;/strong&gt;, &lt;strong&gt;SQL&lt;/strong&gt;, &lt;strong&gt;Linux&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Отличные знания принципов whitebox и blackbox тестирования.&lt;/li&gt;
&lt;li&gt;Опыт работы по специальности: от 2 лет.&lt;/li&gt;
&lt;li&gt;Опыт работы в команде.&lt;/li&gt;
&lt;li&gt;Желание развиваться и изучать новое.&lt;/li&gt;
&lt;li&gt;Отсутствие желания искать работу в ближайшие 3 года.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Задачи&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Написание юнит-тестов, автотестов.&lt;/li&gt;
&lt;li&gt;Тестирование:&lt;ul&gt;
&lt;li&gt;бекенда;&lt;/li&gt;
&lt;li&gt;фронтенда;&lt;/li&gt;
&lt;li&gt;бизнес-логики;&lt;/li&gt;
&lt;li&gt;производительности;&lt;/li&gt;
&lt;li&gt;безопасности.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;В общем, тоже очень много интересной работы.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="dr-frontend"&gt;Dr. Frontend&lt;/h3&gt;
&lt;h4&gt;Требования&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Понимание, как сделать интерфейс удобным и приятным для пользователя&lt;/li&gt;
&lt;li&gt;Отличные знания: &lt;strong&gt;HTML&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;JavaScript&lt;/strong&gt;&amp;nbsp;(jQuery, ExtJS
    или других распространенных библиотек)&lt;/li&gt;
&lt;li&gt;Опыт проектирования и реализации пользовательского интерфейса&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Задачи&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Прототипирование UI сервиса&lt;/li&gt;
&lt;li&gt;Реализация спроектированного UI&lt;/li&gt;
&lt;li&gt;Разработка расширений&amp;nbsp;для Firefox и Chrome.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usloviia_1"&gt;Условия&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Удаленная работа.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Работа в профессиональной команде.&lt;/li&gt;
&lt;li&gt;Полный рабочий день (5 дней в неделю по 8 часов).&lt;/li&gt;
&lt;li&gt;Карьерный и профессиональный рост.&lt;/li&gt;
&lt;li&gt;Прислушивание к Вашему мнению.&lt;/li&gt;
&lt;li&gt;Зарплата по результатам собеседования:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mr. Backend:&lt;/strong&gt;&amp;nbsp;от $1500 до $2000&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Мастер-Ломастер:&lt;/strong&gt;&amp;nbsp;от $700 до $1500&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dr. Frontend:&lt;/strong&gt; от $1000 до $2000&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансии более не актуальны&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Fri, 04 May 2012 18:20:00 +0400</pubDate><guid>tag:www.insight-it.ru,2012-05-04:vacancy/2012/vakansii-komanda-it-zvezd/</guid><category>css</category><category>html</category><category>JavaScript</category><category>JQuery</category><category>PHP</category><category>RDM-soft</category><category>SQA</category><category>ZendFramework</category><category>вакансии</category></item><item><title>Постоянное соединение между браузером и сервером</title><link>https://www.insight-it.ru//interactive/2012/postoyannoe-soedinenie-mezhdu-brauzerom-i-serverom/</link><description>&lt;p&gt;В статье про &lt;a href="https://www.insight-it.ru/interactive/2012/klientskaya-chast-interaktivnogo-sajjta/"&gt;клиентскую часть интерактивного интернет-проекта&lt;/a&gt; мы подошли к вопросу возможности использования двухстороннего
постоянного соединения между сайтом и JavaScript-клиентом для
синхронизации их состояний. Такое соединение представляет собой канал
для обмена сообщениями &lt;em&gt;в реальном времени&lt;/em&gt; между браузером и серверным
процессом, причем каждая сторона может быть инициатором отправки
сообщения и имеет некую логику реакции на получаемые сообщения.&lt;/p&gt;
&lt;p&gt;Сегодня мы рассмотрим основные варианты реализации этого принципа и как
он сочетается с обсуждавшимися в предыдущих статьях
&lt;a href="https://www.insight-it.ru/interactive/"&gt;серии&lt;/a&gt; темами.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h2 id="transport"&gt;Транспорт&lt;/h2&gt;
&lt;p&gt;Так как одной из сторон постоянного соединения является браузер, вопрос
кроссбраузерности при его реализации стоит не менее остро, чем,
например, при верстке. В 2001 году, когда появился на свет самый часто
вспоминаемый недобрым словом браузер в мире, о подобных технологиях
постоянного соединения между браузером и сервером практически никто не
задумывался даже отдаленно.&lt;/p&gt;
&lt;p&gt;Существуют несколько протоколов и связанных с ними технологий, которые
позволяют реализовать постоянное с точки зрения приложения соединение
между браузером и сервером, обычно их называют &lt;strong&gt;транспортами&lt;/strong&gt;. Каждый
из них обладает разной производительностью, особенностями реализации и
нагрузкой на серверную часть. Возможно не полный их список c краткими
пояснениями:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.insight-it.ru/goto/5ddd244b/" rel="nofollow" target="_blank" title="http://ru.wikipedia.org/wiki/WebSocket"&gt;WebSocket&lt;/a&gt;:&lt;/strong&gt;&amp;nbsp;пожалуй,
    самый эффективный с точки зрения производительности и нагрузки на
    сервер транспорт. Протокол относительно новый, появился в рамках
    работы над &lt;a href="/tag/html5/"&gt;HTML5&lt;/a&gt;. Доступен только в очень свежих
    браузерах, имеет несколько более-менее стандартных версий.
    Используется одно соединение для обоих направлений обмена
    сообщениями.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.insight-it.ru/goto/4587ee12/" rel="nofollow" target="_blank" title="http://dev.w3.org/html5/eventsource/"&gt;EventSource&lt;/a&gt;:&lt;/strong&gt;&amp;nbsp;появился
    примерно в то же время, что и WebSocket, но по задумке должен
    использоваться для получения односторонних уведомлений от сервера. В
    совокупности с простыми AJAX запросами для отправки событий из
    браузера может использоваться для двустороннего общения. Но так как
    он доступен примерно в тех же версиях браузеров, что и WebSocket, со
    сценариями, когда он оказывался бы более предпочтительным, я не
    сталкивался. Технически очень похож на следующий транспорт.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/1a0e9c02/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Push_technology#HTTP_server_push"&gt;&lt;strong&gt;AJAX Multipart&lt;/strong&gt;&lt;/a&gt; aka &lt;strong&gt;&lt;a href="https://www.insight-it.ru/goto/1a0e9c02/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Push_technology#HTTP_server_push"&gt;HTTP Streaming&lt;/a&gt;:&lt;/strong&gt;&amp;nbsp;после
    получения HTTP-запроса от клиента сервер не "отпускает" его и по
    мере поступления отправляет в него свои сообщения. Для отправки
    сообщений из браузера при необходимости создается&amp;nbsp;второе соединение.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.insight-it.ru/goto/dcd446e1/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Push_technology#Long_polling"&gt;AJAX/HTTP Polling&lt;/a&gt;:&lt;/strong&gt;&amp;nbsp;в
    отличии от предыдущего транспорта, сервер закрывает HTTP-соединение
    после каждого отправленного в него сообщения или по прошествии
    определенного таймаута (обычно порядка 20-40 секунд). А браузер
    сразу же после получения сообщения открывает новое соединение, таким
    образом у сервера по-прежнему практически всегда есть соединение,
    куда можно отправить сообщения. Хоть по нагрузке на сервер этот
    вариант самый тяжелый, поддерживают его практически все браузеры.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.insight-it.ru/goto/9344995a/" rel="nofollow" target="_blank" title="https://github.com/gimite/web-socket-js"&gt;Adobe Flash&lt;/a&gt;:&lt;/strong&gt;&amp;nbsp;эта
    платформа может эмулировать поддержку WebSocket при определенном
    стечении обстоятельств (удачная комбинация Flash-плеера и браузера).
    Немного нетривиальна в настройке из-за своих особенностей.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;По поводу поддержки каждого из них различными браузерами было бы неплохо
составить табличку, но на самом деле нюансов там много и многое зависит
не только от версии браузера, но и от других обстоятельств, вроде
наличия и типа прокси, использования трюков с iframe, наличия
Flash-плеера и т.п.&lt;/p&gt;
&lt;p&gt;Все вышеизложенные транспорты в конечном итоге основываются на протоколе
&lt;a href="/tag/http/"&gt;HTTP&lt;/a&gt;. Большинство из современных браузеров ограничивают
количество одновременных HTTP-соединений с доменом &lt;strong&gt;до двух&lt;/strong&gt;, что как
раз достаточно даже для менее эффективных вариантов.&lt;/p&gt;
&lt;p&gt;В любом случае работать напрямую с транспортами не обязательно, благо
существует большое количество библиотек и сервисов, позволяющих от них
абстрагироваться, к ним и переходим.&lt;/p&gt;
&lt;h2 id="abstraktsiia"&gt;Абстракция&lt;/h2&gt;
&lt;p&gt;По сути такие библиотеки состоят из двух частей: клиентской на
&lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt; и серверной для одной или нескольких
платформ. Клиент определяет какой из доступных в текущем браузере
транспортов является наиболее эффективным и с его помощью устанавливает
соединение с сервером, который поддерживает несколько протоколов. С
точки зрения разработчика интерфейс, ими предоставляемый, не зависит от
транспорта и примерно одинаков:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Метод для &lt;strong&gt;отправки&lt;/strong&gt; сообщения противоположной стороне.&lt;/li&gt;
&lt;li&gt;Регистрация обработчика события, который будет вызван &lt;strong&gt;при
    получении&lt;/strong&gt; сообщения от противоположной стороны, с содержанием
    сообщения в аргументе.&lt;/li&gt;
&lt;li&gt;Метод, который будет вызван при установке и разрывании соединения.&lt;/li&gt;
&lt;li&gt;Инициатором соединения по очевидным причинам всегда является клиент,
    так что у него есть дополнительный механизм для этого, с
    возможностью указать какие-то настройки.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;При выборе такой библиотеки для конкретного проекта очень большую роль
играет его основная серверная платформа: обычно хочется использовать тот
же язык программирования для обработки сообщений, что и для реализаций
основной серверной части. Чаще всего используется основанный на
&lt;a href="/tag/epoll/"&gt;epoll&lt;/a&gt; или аналогах HTTP-сервер, что позволяет
поддерживать большое количество пользователей онлайн:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/tag/node-js/"&gt;Node.js&lt;/a&gt; на &lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;На &lt;a href="/tag/erlang/"&gt;Erlang&lt;/a&gt; есть несколько очень эффективных
    HTTP-серверов:&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/82a43b29/" rel="nofollow" target="_blank" title="https://github.com/extend/cowboy"&gt;cowboy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/4567a795/" rel="nofollow" target="_blank" title="https://github.com/ostinelli/misultin"&gt;misultin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/2902d504/" rel="nofollow" target="_blank" title="https://github.com/mochi/mochiweb"&gt;mochiweb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/798908e5/" rel="nofollow" target="_blank" title="http://yaws.hyber.org/"&gt;yaws&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/tornado/"&gt;Tornado&lt;/a&gt;&amp;nbsp;на &lt;a href="/tag/python/"&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/tag/netty/"&gt;netty&lt;/a&gt; на &lt;a href="/tag/java/"&gt;Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Так как самих библиотек этой категории существует примерно пару
десятков, расскажу вкратце о наиболее заслуживающих внимания на мой
взгляд:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/4034b77d/" rel="nofollow" target="_blank" title="http://socket.io"&gt;socket.io&lt;/a&gt;: поддерживает практически все
    возможные транспорты, включая &lt;a href="/tag/flash/"&gt;Flash&lt;/a&gt;. Основная
    серверная платформа - &lt;strong&gt;node.js&lt;/strong&gt;, силами сторонних разработчиков
    есть реализации протокола на других платформах. Имеет спорную
    репутацию, проект довольно громоздкий, в некоторых ситуациях ведет
    себя непредсказуемо.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/4dc9c4cc/" rel="nofollow" target="_blank" title="https://github.com/sockjs/sockjs-client"&gt;SockJS&lt;/a&gt;: очень молодой
    проект, поддерживает необходимый минимум транспортов, прост в
    эксплуатации. Относительно стабилен и предсказуем. Серверная часть
    доступна на &lt;strong&gt;node.js&lt;/strong&gt;, &lt;strong&gt;Tornado&lt;/strong&gt; и &lt;strong&gt;cowboy/misultin,&lt;/strong&gt; активно
    работают над другими платформами.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Существуют коммерческие решения, абсолютно идентичные по принципу работы
и функционалу. Аналогичная обсуждавшимся opensource решениям библиотека
дополняется брокером сообщений для организации паттерна
"публикация-подписка" и в совокупности с хостингом "в облаках" продается
с оплатой за количество переданных сообщений (или по подписке с каким-то
лимитом), естественно с нехилой наценкой. Плюсы и минусы очевидны:
отсутствие необходимости обо всем этом заботиться против относительно
высокой стоимости, потере контроля при сбоях или необходимости
изменений, привязке к стороннему поставщику услуг и т.п. Рекламировать
их не буду, при желании легко гуглятся, ровно как и оставшиеся
альтернативные opensource проекты.&lt;/p&gt;
&lt;h2 id="vernemsia-k-interaktivnym-saitam"&gt;Вернемся к интерактивным сайтам&lt;/h2&gt;
&lt;p&gt;Надеюсь, только что закончившегося лирического отступления на 3/4 статьи
Вам будет достаточно, чтобы составить общее представление о построении
постоянного соединения между браузером и сервером, а желательно и
определиться с каким-то решением для автоматического выбора наиболее
эффективного транспорта в контексте именно Вашего проекта.&lt;/p&gt;
&lt;p&gt;Получив примитивный интерфейс в виде "отправить сообщение /
отреагировать на сообщение" необходимо определиться с тем, что же мы
будем передавать в этих сообщениях и как будем на них реагировать.&lt;/p&gt;
&lt;p&gt;С форматом сериализации сообщений все довольно просто: выбор между XML и
JSON очевиден в пользу последнего, а заморачиваться с чем-то более
экзотическим смысла мало (хотя давно хочу попробовать в этой роли
&lt;a href="/tag/protocol-buffers/"&gt;Protocol Buffers&lt;/a&gt; или &lt;a href="/tag/bson/"&gt;BSON&lt;/a&gt;, но
никак руки не доходят).&lt;/p&gt;
&lt;p&gt;Намного интереснее вопрос о том, что, собственно, будет в этих
сообщениях содержаться. В &lt;a href="https://www.insight-it.ru/interactive/2012/klientskaya-chast-interaktivnogo-sajjta/"&gt;предыдущей статье&lt;/a&gt;
мы остановились на использовании фреймворка для организации кода
JavaScript-клиента. Предлагаемая ими концепция &lt;strong&gt;модели&lt;/strong&gt;&amp;nbsp;обычно
по-умолчанию предоставляет возможность синхронизации с сервером
посредством &lt;a href="/tag/ajax/"&gt;AJAX&lt;/a&gt; запросов и механизм изменения этого
поведения. Для использовавшегося в качестве примера
&lt;a href="/tag/backbone-js/"&gt;Backbone.js&lt;/a&gt;&amp;nbsp;для этого необходимо переопределить
функцию &lt;strong&gt;Backbone.sync&lt;/strong&gt;.&amp;nbsp;При сохранении модели клиент будет отправлять
объект с идентификатором модели и списком её изменений. Запрос изменений
с сервера будет происходить асинхронно, то есть после отправки сообщения
о том, что нужны данные для такой-то модели, посредством метода fetch он
сам не получит ответа. Собственно изменения в модели произведет
обработчик получения сообщений, в котором должна быть реализована
соответствующая логика. Далее подписанные на события изменений в моделях
объекты-представления будут соответствующим образом обновлять DOM-дерево
страницы, отображая пользователю нужную информацию. &lt;em&gt;Это, пожалуй,
наиболее &lt;strong&gt;правильный&lt;/strong&gt; способ интегрировать постоянное соединение и
клиентский фреймфорк.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Основными минусами его является очень серьезный объем работы по
разработке клиентской части, а также дублирование достаточно большой
части логики и HTML-шаблонов между серверной и клиентской сторонами. Я
бы рекомендовал использовать этот подход, только если позволяют трудовые
ресурсы (читай: есть хотя бы отдельный специализирующийся на JavaScript
разработчик), либо когда проект по каким-то причинам решил отказаться от
реализации статичного HTML-интерфейса.&lt;/p&gt;
&lt;p&gt;В следующей статье я расскажу о менее трудозатратном способе добиться
того же результата, который основан на жертве идеологической
правильностью в пользу минимизации повторного написания кода.&lt;/p&gt;
&lt;div class="card green"&gt;
&lt;p&gt;&lt;div class="card-content white-text"&gt;
Эта статья - третья в &lt;a class="green-text text-lighten-4" href="https://www.insight-it.ru/interactive/"&gt;серии про Интерактивные сайты&lt;/a&gt;, автор - &lt;a class="green-text text-lighten-4" href="https://www.insight-it.ru/goto/b03d9116/" rel="nofollow" target="_blank" title="http://blinkov.ru"&gt;Иван&amp;nbsp;Блинков&lt;/a&gt;, основано на личном опыте.
До встречи &lt;a class="green-text text-lighten-4" href="/feed/"&gt;на страницах Insight IT&lt;/a&gt;!
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Tue, 10 Apr 2012 00:47:00 +0400</pubDate><guid>tag:www.insight-it.ru,2012-04-10:interactive/2012/postoyannoe-soedinenie-mezhdu-brauzerom-i-serverom/</guid><category>AJAX</category><category>Comet</category><category>epoll</category><category>EventSource</category><category>Flash</category><category>HTTP</category><category>JavaScript</category><category>polling</category><category>streaming</category><category>WebSocket</category><category>клиентская часть</category><category>серверная часть</category><category>HTML5</category></item><item><title>Клиентская часть интерактивного сайта</title><link>https://www.insight-it.ru//interactive/2012/klientskaya-chast-interaktivnogo-sajjta/</link><description>&lt;p&gt;Клиентская часть сайта играет ключевую роль в обеспечении
его&amp;nbsp;&lt;em&gt;интерактивности&lt;/em&gt;. Именно на нее возлагается переопределение
стандартного поведения для создания впечатления живого организма вместо
кучки бездушных страниц. В статье про
&lt;a href="https://www.insight-it.ru/interactive/2012/arkhitektura-interaktivnykh-sajjtov/"&gt;архитектуру&lt;/a&gt;
интерактивных сайтов я подробно изложил основные функции и требования,
которые перед ним стоят. Сегодня же я представлю свое видение того, как
его грамотно реализовать. На статус единственно-правильного-решения не
претендую, статью можно воспринимать просто как набор практических
советов и рекомендаций.
&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Итак, сегодня мы будем обсуждать создание JavaScript-клиента для
интерактивного сайта. Начнем, пожалуй, с организации кода проекта с
целью облегчения его сопровождения при росте кодовой базы, перейдем к
переопределению ключевых обработчиков событий, затем к сохранению
стандартного поведения браузера и закончим синхронизацией состояния
между клиентом и сервером.&lt;/p&gt;
&lt;h2 id="organizatsiia-koda"&gt;Организация кода&lt;/h2&gt;
&lt;h3 id="sborka"&gt;Сборка&lt;/h3&gt;
&lt;p&gt;Первое, чем стоит обзавестись перед разработкой сложного
JavaScript-приложения, это системой его сборки. С точки зрения
клиентской оптимизации весь &lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;-код по
возможности должен быть минифицирован и собран в один файл, подключенный
в конце &lt;a href="/tag/html/"&gt;HTML&lt;/a&gt;, желательно асинхронно. Работать с ним в
таком виде невозможно, соответственно надо иметь возможность легко
собирать его из набора красиво отформатированных файлов, используемых
при&amp;nbsp;разработке.&lt;/p&gt;
&lt;p&gt;На вопрос &lt;em&gt;"Какую систему сборки использовать?"&lt;/em&gt;&amp;nbsp;в большинстве случаев
правильный ответ: ту же, что и для сборки серверной части. Make, rake,
maven, ant, rebar... - любому из них без труда можно поручить эту
задачу. Для конкатенации можно использовать хоть консольную команду
&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;, для минимизации есть много альтернативных библиотек, в порядке
моих симпатий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/ec53b5fa/" rel="nofollow" target="_blank" title="https://developers.google.com/closure/compiler/"&gt;&lt;strong&gt;Google Closure&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/6ccc0709/" rel="nofollow" target="_blank" title="http://developer.yahoo.com/yui/compressor/"&gt;&lt;strong&gt;YUI Compressor&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/28795a57/" rel="nofollow" target="_blank" title="https://github.com/mishoo/UglifyJS"&gt;&lt;strong&gt;UglifyJS&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если хочется чего-то более гибкого, могу порекомендовать воспользоваться
&lt;a href="https://www.insight-it.ru/goto/5908cea6/" rel="nofollow" target="_blank" title="https://github.com/miracle2k/webassets"&gt;&lt;strong&gt;Webassets&lt;/strong&gt;&lt;/a&gt;, который я уже
упоминал в статье про
&lt;a href="https://www.insight-it.ru/python/2012/jinja2/"&gt;Jinja2&lt;/a&gt;. В
консольном режиме прекрасно подключается к любой системе сборки и языку
программирования. Описать процесс сборки &lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;
и &lt;a href="/tag/css/"&gt;CSS&lt;/a&gt; можно очень подробно и именно так, как считаете
нужным, естественно на &lt;a href="/tag/python/"&gt;Python&lt;/a&gt;. Сопоставимый по
возможностям проект из мира &lt;a href="/tag/ruby/"&gt;Ruby&lt;/a&gt; - &lt;a href="https://www.insight-it.ru/goto/5b3a9a97/" rel="nofollow" target="_blank" title="http://synthesis.sbecker.net/pages/asset_packager"&gt;Asset Packager&lt;/a&gt;, наверняка
есть много других.&lt;/p&gt;
&lt;h3 id="chitabelnyi-kod"&gt;Читабельный код&lt;/h3&gt;
&lt;p&gt;Не знаю как Вы, а я тихо ненавижу &lt;strong&gt;JavaScript&lt;/strong&gt; все ~10 лет, которые я
с ним знаком. Так как он по сути является монополией на рынке браузерных
приложений (Flash, Java апплеты и ActiveX за альтернативы можно даже не
считать), использовать его так или иначе приходится в любом сколько-либо
серьезном интернет-проекте. Даже Google Dart&amp;nbsp;вряд ли&amp;nbsp;всерьез приживется.&lt;/p&gt;
&lt;p&gt;При полном отсутствии конкуренции совершенно не удивительно, что у него
никуда не годящийся синтаксис и набор не знаю откуда взявшихся
абстракций в виде прототипов и замыканий. С этим всем определенно можно
мириться и работать, особенно если только им и заниматься, но привыкший
к серверным языкам программирования мозг определенно чувствует себя&amp;nbsp;не
комфортно.&lt;/p&gt;
&lt;p&gt;Если Вас тоже не раз посещали подобные мысли, то Вы вероятно как и я при
первой же возможности пересядете (или уже пересели) на
&lt;a href="/tag/coffeescript/"&gt;&lt;strong&gt;CoffeeScript&lt;/strong&gt;&lt;/a&gt;, компилируемый в JavaScript язык
программирования.&amp;nbsp;Немного рекламы этого проекта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Золотое правило CoffeeScript: &lt;strong&gt;"It's just Javascript"&lt;/strong&gt; &lt;em&gt;(это
    просто JavaScript)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Прямое преобразование кода в JavaScript&lt;/li&gt;
&lt;li&gt;Доступны абсолютно все JavaScript-библиотеки&lt;/li&gt;
&lt;li&gt;Никаких точек с запятой в конце каждой строки&lt;/li&gt;
&lt;li&gt;Структурирование кода на основе отступов, как в Python&lt;/li&gt;
&lt;li&gt;Объявление функций просто стрелочкой &lt;code&gt;-&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;При вызове методов даже скобки писать не обязательно&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Человеческое наследование: простое &lt;strong&gt;class MyClass extends
    MyParent&lt;/strong&gt;&amp;nbsp;превращается в довольно хитрую конструкцию с
    использованием прототипов и замыканий:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;MMyClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;__extends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyParent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__super__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Много укороченных команд ветвления кода (&lt;strong&gt;if&lt;/strong&gt;, &lt;strong&gt;switch,&lt;/strong&gt; циклы&amp;nbsp;и
    т.п.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;В целом код выходит раза в полтора-два короче и намного приятнее для
    глаз&lt;/li&gt;
&lt;li&gt;Консольный компилятор с функцией наблюдения за директориями&lt;/li&gt;
&lt;li&gt;Легко подключается как фильтр в Webassets&lt;/li&gt;
&lt;li&gt;Подробнее с примерами на &lt;a href="https://www.insight-it.ru/goto/834fa52/" rel="nofollow" target="_blank" title="http://coffeescript.org/"&gt;официальном сайте&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;В общем рекомендую :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="logicheskoe-razdelenie-koda"&gt;Логическое разделение кода&lt;/h3&gt;
&lt;p&gt;Если Вы сталкивались со сколько-либо сложным пользовательским
интерфейсом "на jQuery", то скорее всего не по наслышке понимаете откуда
взялось выражение &lt;strong&gt;"спагетти-код"&lt;/strong&gt;. В связи с событийной парадигмой
разработки браузерных приложений, очень часто JavaScript-код с
использованием jQuery или альтернатив превращается в так называемый
&lt;em&gt;"коллбек на коллбеке, коллбеком погоняет"&lt;/em&gt; (коллбек - транслит от
английского callback - обработчик события).&amp;nbsp;При отсутствии четкой
структуры такой код становится очень сложно поддерживать при его
увеличении в объемах. Но это не повод отказываться от jQuery - от
событий никуда не деться, и эта библиотека отлично справляется с
абстракций от особенностей их реализации в различных браузерах.&lt;/p&gt;
&lt;p&gt;На мой взгляд, одним из наиболее резонных способов решения (или
заблаговременного предотвращения) этой проблемы является использование в
разумных пределах &lt;a href="/tag/oop/"&gt;объектно-ориентированные&lt;/a&gt;&amp;nbsp;возможности
&lt;strong&gt;JavaScript&lt;/strong&gt; &lt;em&gt;(благо CoffeeScript это дело сильно упрощает)&lt;/em&gt;.
Соответственно, используемые классы можно разумно располагать в какой-то
иерархии с точки зрения наследования (для обеспечения DRY, don't repeat
yourself - "не повторяйся") и с точки зрения расположения в файловой
системе (с разложенными по папкам файлами работать намного проще, чем с
здоровенной вереницей обработчиков событий в одном файле).&lt;/p&gt;
&lt;p&gt;Собственно никто не мешает начать заворачивать код в классы на пустом
месте, но я позволю себе предложить немного более элегантное решение,
которое помимо организации кода пригодится нам и в дальнейшем. Подобно
серверным фреймворкам, для клиентских приложений есть библиотеки,
предоставляющие базовые классы для решения типичных задач:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Модель&lt;/strong&gt;&amp;nbsp;&lt;em&gt;(Model)&lt;/em&gt; - как и в традиционном MVC представляет собой
    класс, объект которого содержит локальную копию каких-то данных и
    предоставляет механизмы для её синхронизации с внешним хранилищем.
    Основное отличие от серверных моделей - хранилищем выступает не
    СУБД, а либо локальное хранилище браузера через HTML5, либо
    удаленный сервис через REST или другой интерфейс. Плюс так как они
    находятся вне "зоны доверия", то полученные от них данные нужно
    обязательно валидировать, фильтровать и проверять на серверной
    стороне, прежде чем что-либо с ними делать.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Представление&lt;/strong&gt; &lt;em&gt;(View)&lt;/em&gt; или &lt;strong&gt;контроллер&lt;/strong&gt; &lt;em&gt;(Controller)&lt;/em&gt; - тут,
    по моим впечатлениям, образовалась путаница и за обоими названиями в
    нашем контексте имеют ввиду примерно одно и то же. Объект такого
    класса следит за изменениями и событиями в связанных с ним моделях и
    элементах DOM, каким-либо образом на них реагируя. Таким образом
    большая часть кода, которая раньше была "вереницей обработчиков
    событий", оказывается методами этого класса. При этом базовый класс
    из библиотеки берет на себя нормальное поведение &lt;strong&gt;this&lt;/strong&gt;&amp;nbsp;и следит
    за тем, чтобы обработчики автоматически добавлялись на динамические
    созданные элементы DOM.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Маршрутизатор&lt;/strong&gt; &lt;em&gt;(Router)&lt;/em&gt;&amp;nbsp;- следит за состоянием адресной строки
    и позволяет обрабатывать изменения, понадобится для восстановления
    поведения браузера.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Коллекция&lt;/strong&gt; &lt;em&gt;(Collection)&lt;/em&gt; - отсортированный набор однотипных
    моделей, с которым можно работать как с единым целым.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="card blue lighten-4"&gt;
&lt;p&gt;&lt;div class="card-content"&gt;
Не стоит рассматривать эти абстракций как единственный верный способ
делать клиентские приложения, но при их использовании появляется хоть
какая-то логика и становится более-менее понятно где какой кусок кода
должен находиться и где его потом искать. Для абстракции особенностей
реализаций браузеров они по-прежнему полагаются на &lt;code&gt;$&lt;/code&gt; в виде
&lt;a href="https://www.insight-it.ru/goto/3b02d98c/" rel="nofollow" target="_blank" title="http://jquery.com/"&gt;jQuery&lt;/a&gt; или &lt;a href="https://www.insight-it.ru/goto/e6412e50/" rel="nofollow" target="_blank" title="http://zeptojs.com/"&gt;Zepto&lt;/a&gt;.
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Мне известны три библиотеки, предоставляющие большую часть изложенных
выше абстракций. Вкратце о каждой:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/e1e90fac/" rel="nofollow" target="_blank" title="http://documentcloud.github.com/backbone/"&gt;&lt;strong&gt;Backbone.js&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;-
    самая&amp;nbsp;широко распространенная из трех, используется во многих
    серьезных проектах.&amp;nbsp;Основана на библиотеке
    &lt;a href="https://www.insight-it.ru/goto/48609b39/" rel="nofollow" target="_blank" title="http://documentcloud.github.com/underscore/"&gt;Underscore.js&lt;/a&gt;,
    которая с одной стороны предоставляет массу удобных функций и
    шаблонизатор, но с другой стороны - не особо-то и часто они
    оказываются нужны.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/d7dc0253/" rel="nofollow" target="_blank" title="http://spinejs.com/"&gt;&lt;strong&gt;Spine.js&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;- библиотека по-моложе, которая
    очень похожа на Backbone.js, но написана на CoffeeScript и из-за
    отсутствия внешних зависимостей вышла компактнее. Отличия в основном
    в терминологии и деталях реализации.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/a115abb7/" rel="nofollow" target="_blank" title="http://knockoutjs.com/"&gt;&lt;strong&gt;Knockout.js&lt;/strong&gt;&lt;/a&gt; - эта
    библиотека&amp;nbsp;пропагандирует использование &lt;code&gt;data-*&lt;/code&gt; атрибутов из HTML5
    для хранения метаданных, которые как-то управляют изменениями
    тегов-владельцев при определенных событиях, практически забирая на
    себя роль представления. Концепция кажется мне мутноватой, так что
    лично для себя я её использование всерьез и не рассматривал никогда.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Когда в этой статье дело будет доходить до примеров кода, я буду
приводить их на основе &lt;strong&gt;Backbone.js&lt;/strong&gt;, так как в свое время я
остановился именно на ней. Почему? В основном из-за того, что она
используется в очень многих проектах и стоит за ней целая компания, а не
просто один разработчик, которому однажды может надоесть поддерживать
проект (как в случае с Spine.js). Но в глубине души я, конечно, надеюсь,
что однажды они уберут эту жесткую зависимость от Underscore.js, а то и
может быть тоже перепишут все на CoffeeScript.&lt;/p&gt;
&lt;p&gt;В целом я стараюсь изложить общую концепцию: те же принципы можно
реализовать и с использованием альтернатив, и с использованием
разрозненных библиотек, решающих более узкие задачи, и вообще с нуля,
самостоятельно занимаясь вопросами кроссбраузерности и прочих
особенностей современного Интернета. Последний путь, кстати, не
настолько уж и безумен, как кажется, крупные компании и интернет-проекты
обычно по нему и идут, если человеческие и финансовые ресурсы позволяют.&lt;/p&gt;
&lt;h2 id="obrabotchiki-sobytii_1"&gt;Обработчики событий&lt;/h2&gt;
&lt;p&gt;В предыдущем разделе мы прилично так отвлеклись от основной темы -
&lt;em&gt;интерактивных сайтов&lt;/em&gt;. Это было необходимо для того, чтобы достаточно
комплексное JavaScript-приложение в итоге оказалось поддерживаемым и
имело хоть какую-то структуру и логику.&lt;/p&gt;
&lt;p&gt;Напомню, то, что раньше было просто независимым обработчиком событий
становится методом представления (по терминологии Backbone.js). У
каждого представления создается "оглавление" методов-обработчиков в
атрибуте &lt;strong&gt;events&lt;/strong&gt;.&amp;nbsp;Наверное многим хотелось бы увидеть какой-то пример
кода, но так как статьями с примерами примитивных приложений на
Backbone.js пестрит весь Интернет, тратить на это время желания
совершенно никакого, сошлюсь на самый популярный: &lt;a href="https://www.insight-it.ru/goto/fbd5c000/" rel="nofollow" target="_blank" title="http://documentcloud.github.com/backbone/docs/todos.html"&gt;список задач
TODO&lt;/a&gt;, для
сравнения &lt;a href="https://www.insight-it.ru/goto/28094239/" rel="nofollow" target="_blank" title="https://github.com/maccman/spine.todos"&gt;то же самое на Spine.js&lt;/a&gt;.&amp;nbsp;К слову, при использовании &lt;em&gt;CoffeeScript&lt;/em&gt; использовать стандартный механизм
&lt;code&gt;Backbone.****.extend({ ... })&lt;/code&gt; не обязательно, &lt;code&gt;class MyClass extends Backbone.****&lt;/code&gt; прекрасно делает то же самое.&lt;/p&gt;
&lt;p&gt;По мне, так намного интереснее не какие именно события обрабатываются
(все равно 90% уникальны для проекта), а как их распределить по разным
представлениям. Обычно получается что-то в этом духе:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Пользовательское&lt;/strong&gt; представление будет модифицировать страницу в
    тех местах, где оно как-то связано с текущим пользователем: форма
    авторизации, надпись "Привет, ****!", кнопка выхода и пр.
    Вероятно, оно будет использовать &lt;em&gt;модель&lt;/em&gt; текущего пользователя или
    в тривиальных случаях просто самостоятельно работать с cookie
    сессии.&lt;/li&gt;
&lt;li&gt;Классы &lt;em&gt;модели&lt;/em&gt; и &lt;em&gt;представления&lt;/em&gt;, а вероятно и &lt;em&gt;коллекции&lt;/em&gt;,
    понадобятся каждой &lt;strong&gt;логической сущности&lt;/strong&gt;, которая каким-либо
    образом отражается в пользовательском интерфейсе. Это может быть что
    угодно, например задача в TODO-списке, статья, комментарий - все
    зависит от тематики проекта.&lt;/li&gt;
&lt;li&gt;Если &lt;strong&gt;навигация&lt;/strong&gt; по сайту каким-то образом динамически
    видоизменяется, то представление понадобится и для нее. Например,
    часто подсвечивают пункты в глобальной навигации на основе изменений
    в текущем адресе страницы.&lt;/li&gt;
&lt;li&gt;И, последний пункт, который собственно и относится к сегодняшней
    теме - одно представление будет общим для всего сайта и будет
    отвечать за его &lt;strong&gt;интерактивность&lt;/strong&gt;. Давайте его рассмотрим
    подробнее.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для отсутствия перезагрузок браузера внутри сайта, нам нужно
переопределить:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;События клика на ссылки: по содержимому атрибута &lt;code&gt;href&lt;/code&gt; нужно определить,
что ссылка внутренняя и вызвать "цепную реакцию" в других
представлениях, чтобы в итоге пользователь увидел то, что должен.&lt;/li&gt;
&lt;li&gt;При отправке формы есть два сценария:&lt;ul&gt;
&lt;li&gt;Обновляется связанная &lt;em&gt;модель&lt;/em&gt; и синхронизируется с сервером. В
таком сценарии при необходимости можно вообще скрыть кнопку отправки
и "автосохранять" изменения в модели.&lt;/li&gt;
&lt;li&gt;Связанной модели по каким-то причинам нет и нужно просто на основе
данных формы что-то сделать, например выполнить поиск по указанной в
форме фразе или отправить запрос на авторизацию.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Для отмены стандартной реакции браузера на события у jQuery есть два
основных механизма: &lt;code&gt;event.preventDefault()&lt;/code&gt; и &lt;code&gt;return false&lt;/code&gt;. В
данной ситуации (да и большинстве других), целесообразнее пользоваться
последним, так как если вдруг в коде обработчика окажется какая-то
ошибка, то пользователь просто увидит стандартную реакцию браузера, а не
окажется в ситуации "некликающихся ссылок" и "неотправляющихся форм".&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="vosstanovlenie-povedeniia-brauzera"&gt;Восстановление поведения браузера&lt;/h2&gt;
&lt;p&gt;В предыдущем разделе я даже не стал подробно останавливаться на том, как
сделать так "чтобы пользователь увидел то, что должен". Наверняка можно
придумать массу способов решения этой задачи, но единственный реально
применимый на практике - воспроизвести визуально то же самое, что
происходит при обычной&amp;nbsp;перезагрузке страницы.&lt;/p&gt;
&lt;p&gt;И первое, с чего стоит начать - с адресной строки, именно там должен
появиться тот адрес, который был в &lt;code&gt;href&lt;/code&gt; ссылки и action формы. Но на
самом деле проще сказать, чем сделать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Возможность просто полностью поменять текущий адрес в адресной
    строке из JavaScript без инициализации открытия страницы есть только
    в совсем свежих браузерах посредством &lt;strong&gt;HTML5 History API&lt;/strong&gt;
    (&lt;a href="https://www.insight-it.ru/goto/61b4e54f/" rel="nofollow" target="_blank" title="https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history#The_pushState().C2.A0method"&gt;pushState&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;В старых браузерах переходы между внутренними страницами сайта можно
    эмулировать через изменения якоря ссылки, который в URL идет после
    &lt;code&gt;#&lt;/code&gt; и обычно используется для "перелистывания" на середину
    HTML-документа. Для отслеживания таких изменений используется
    событие
    &lt;a href="https://www.insight-it.ru/goto/a35bb215/" rel="nofollow" target="_blank" title="https://developer.mozilla.org/en/DOM/window.onhashchange"&gt;onhashchange&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;В еще более старых браузерах это событие эмулируют разными трюками с
    iframe и setInterval.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Backbone.history.start()&lt;/code&gt;&amp;nbsp;берет на себя абстракцию изменений в
адресной строке, правда поддержку &lt;em&gt;pushState&lt;/em&gt; нужно явно включить в
аргументах. Заодно восстанавливается нормальное поведение кнопок "Назад"
и "Вперед" в браузере.&lt;/p&gt;
&lt;p&gt;Для обработки и создания событий, отражающихся в адресной строке, нужно
сделать подкласс &lt;strong&gt;Backbone.Router&lt;/strong&gt;. C ситуациями когда их имеет смысл
создать несколько, я не сталкивался. По аналогии с серверными
фреймворками в атрибуте &lt;strong&gt;routes&lt;/strong&gt;&amp;nbsp;задается соответствие паттернов
адресов к методам-обработчикам, которые будут выполниться при переходе.
В них вызываются необходимые изменения в коллекциях, моделях и
представлениях, чтобы привести в нужное состояние текущий документ.&lt;/p&gt;
&lt;p&gt;Для инициации "виртуального" перехода на новую внутреннюю страницу нужно
вызвать метод &lt;strong&gt;navigate&lt;/strong&gt; у нашего объекта-маршрутизатора, первым
аргументом передав её адрес без первого /, а вторым - настройки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;trigger&lt;/strong&gt; - вызывать ли обработчик из маршрутизатора?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;replace&lt;/strong&gt; - добавлять ли страницу, с которой мы уходим в историю
    браузера, чтобы можно было на нее вернуться при нажатии кнопки
    "назад"?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Таким образом, во внутренних ссылках мы используем нормальные
относительные URL, начинающиеся с /. По ним будут нормально ходить
роботы и браузеры без JavaScript. В обработчике кликов на них мы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;проверяем правда ли она внутренняя (начинается ли она с /);&lt;/li&gt;
&lt;li&gt;"отменяем" стандартный переход, вернув &lt;code&gt;false&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;вызываем &lt;code&gt;router.navigate(href.substring(1), {trigger: true})&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Осталась еще несколько атрибутов поведения браузера, которые необходимо
починить, чтобы визуально все выглядело "как обычно":&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Клик по ссылке с зажатым Shift должен открывать её &lt;em&gt;в новом окне&lt;/em&gt;, а
    с зажатым Ctrl или при клике средней кнопкой мыши - &lt;em&gt;в новой
    вкладке&lt;/em&gt;. Довольно не хитро делается на основе атрибутов
    объекта-события, который передает обработчику jQuery (button,
    shiftkey, metakey), для открытия окна или вкладки - window.open.&lt;/li&gt;
&lt;li&gt;Если пользователь сделал какое-то действие, а прореагировать на него
    мгновенно не получается (так как что-то грузится, вероятно) - нужно
    включить курсор ожидания, установив в CSS &lt;strong&gt;cursor: wait&lt;/strong&gt;, и,
    желательно, анимированный &lt;strong&gt;favicon.ico&lt;/strong&gt;. И, соответственно,
    вернуть все как было, когда страница примет нужный вид. Для смены
    favicon до сих пор пользуюсь каким-то довольно старым плагином к
    jQuery, который не особо шикарно, но все же работает. Его сайт,
    видимо, накрылся, так что продублировал:&amp;nbsp;&lt;a href="https://www.insight-it.ru/goto/d6f7fab3/" rel="nofollow" target="_blank" title="https://gist.github.com/2320740"&gt;https://gist.github.com/2320740&lt;/a&gt;, если кто знает более адекватные альтернативы - дайте знать в комментариях, пожалуйста, руки поискать все никак не доходят.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sinkhronizatsiia-sostoianiia"&gt;Синхронизация состояния&lt;/h2&gt;
&lt;p&gt;По-умолчанию Backbone.js предлагает хранить все состояние клиента в
моделях и синхронизировать его с серверным посредством реализации
простенького REST API на сервере
(&lt;a href="https://www.insight-it.ru/goto/e85f288a/" rel="nofollow" target="_blank" title="http://documentcloud.github.com/backbone/#Sync"&gt;подробнее&lt;/a&gt;), к
которому запросы отправляются посредством обычного &lt;code&gt;$.ajax&lt;/code&gt;. Чтобы
инициировать процесс нужно вручную вызвать у экземпляра модели метод
&lt;strong&gt;fetch&lt;/strong&gt;, чтобы обновить клиентское состояние данными с сервера, или
метод &lt;strong&gt;save&lt;/strong&gt;, для обратного процесса.&lt;/p&gt;
&lt;p&gt;Для многих приложений этого, в целом, достаточно. Но ограничение
очевидно - нет возможности мгновенно узнать, что на сервере что-то
изменилось. Чего-то близкого можно достичь вызовом &lt;strong&gt;fetch&lt;/strong&gt; раз в N
секунд для каждой модели, но если пользователей предполагается хоть
сколько-либо много, нагрузка на серверную часть будет неоправданно
велика.&lt;/p&gt;
&lt;p&gt;Резонным дополнением этой схемы является использование постоянного
соединения между клиентом и сервером для синхронизации их состояний.
Именно это мы и обсудим в следующей статье серии.&lt;/p&gt;
&lt;div class="card green"&gt;
&lt;p&gt;&lt;div class="card-content white-text"&gt;
Эта статья - вторая в &lt;a class="green-text text-lighten-4" href="https://www.insight-it.ru/interactive/"&gt;серии про Интерактивные сайты&lt;/a&gt;, автор - &lt;a class="green-text text-lighten-4" href="https://www.insight-it.ru/goto/b03d9116/" rel="nofollow" target="_blank" title="http://blinkov.ru"&gt;Иван&amp;nbsp;Блинков&lt;/a&gt;, основано на личном опыте.
До встречи &lt;a class="green-text text-lighten-4" href="/feed/"&gt;на страницах Insight IT&lt;/a&gt;!
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Fri, 06 Apr 2012 21:17:00 +0400</pubDate><guid>tag:www.insight-it.ru,2012-04-06:interactive/2012/klientskaya-chast-interaktivnogo-sajjta/</guid><category>AJAX</category><category>Backbone.js</category><category>CoffeeScript</category><category>JavaScript</category><category>JQuery</category><category>клиентская часть</category></item><item><title>Анонс серии статей: интерактивные сайты</title><link>https://www.insight-it.ru//interactive/2012/anons-serii-statejj-interaktivnye-sajjty/</link><description>&lt;p&gt;Интернет развивается огромными темпами. В борьбе за аудиторию крупные
интернет-компании поднимают стандарты качества веб-приложений на все
более и более высокий уровень. Одним из важнейших качеств современных
сайтов является &lt;strong&gt;интерактивность&lt;/strong&gt;, если раньше все они поголовно
представляли собой коллекцию статичных страниц, где можно что-то
почитать или посмотреть, то сегодня они - почти живой организм.&lt;/p&gt;
&lt;p&gt;Пользователи все больше привыкают узнавать о событиях и видеть реакцию
на свои действия мгновенно, не дожидаясь загрузок страниц и прочих
задержек. Раньше это было возможно только для обычных приложений, но с
сегодняшним уровнем технологий общаться с пользователем в реальном
времени можно и &lt;strong&gt;посредством браузера&lt;/strong&gt;, причем доступно это не только
интернет-гигантам, а практически любому интернет-проекту.&lt;/p&gt;
&lt;p&gt;За последний год &lt;em&gt;привнесение интерактивности в интернет-проекты&lt;/em&gt; -
пожалуй, одна из самых популярных тем, с которой ко мне &lt;a href="https://www.insight-it.ru/consulting/"&gt;обращаются за консультацией&lt;/a&gt;. В итоге я решил
не жадничать и поделиться с общественностью своими знаниями в этой
области, что в итоге должно вылиться в серию связанных статей
&lt;strong&gt;"Интерактивные сайты"&lt;/strong&gt;. В ней я хочу отразить практически пошаговую
инструкцию от А до Я для создания интерактивного интернет-приложения с
нуля или основываясь на существующем статичном проекте. Соответственно,
по ходу дела сделаю легко доступное оглавление по аналогии с
&lt;a href="https://www.insight-it.ru/highload/"&gt;архитектурой высоконагруженных интернет-проектов&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="orientirovochnye-temy-statei"&gt;Ориентировочные темы статей&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/arkhitektura-interaktivnykh-sajjtov/"&gt;Общая архитектура&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/klientskaya-chast-interaktivnogo-sajjta/"&gt;Организация клиентской части&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/postoyannoe-soedinenie-mezhdu-brauzerom-i-serverom/"&gt;Постоянное соединение между браузером и сервером&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/povtornoe-ispolzovanie-shablonov/"&gt;Повторное использование шаблонов&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/servernaya-chast-interaktivnogo-sajjta-i-potoki-soobshhenijj/"&gt;Серверная часть интерактивного сайта и потоки сообщений&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/interactive/2012/optimizaciya-interaktivnykh-sajjtov/"&gt;Оптимизация&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Основной упор будет сделан именно на общую концепцию и сведение всех
компонентов воедино, как на серверной стороне, так и на клиентской.
Количество изобретаемых велосипедов постараюсь свести к минимуму: где-то
будут просто рекомендации по использованию публично доступных
технологий, где-то - сравнительные обзоры. Специфики каких-либо
определенных типов проектов постараюсь избегать.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пожелания, предложения, советы и вопросы в комментариях к этому посту
очень приветствуются :)&lt;/strong&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Sun, 01 Apr 2012 17:43:00 +0400</pubDate><guid>tag:www.insight-it.ru,2012-04-01:interactive/2012/anons-serii-statejj-interaktivnye-sajjty/</guid><category>JavaScript</category><category>архитектура</category><category>интерактив</category><category>интернет-приложения</category><category>клиентская оптимизация</category><category>Масштабируемость</category><category>сайты</category><category>технологии</category></item><item><title>Добро пожаловать в Сказку! (вакансия закрыта)</title><link>https://www.insight-it.ru//vacancy/2011/dobro-pozhalovat-v-skazku-vakansiya/</link><description>&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансия более не актуальна&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Компания SKAZKA, российский разработчик и издатель
онлайн-игр, ищет опытного веб-разработчика на Python. Предлагается
работа в команде MMO-проекта "Королевство", а также
участие в разработке ряда новых игр (одна в активной разработке, а
другая проектируется).&lt;/p&gt;
&lt;h2 id="o-proekte"&gt;О проекте&lt;/h2&gt;
&lt;p&gt;Проект "Королевство" состоит из 2-х частей:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;непосредственно игра (сервер &amp;ndash; C+Python, клиент &amp;ndash; Flash)&lt;/li&gt;
&lt;li&gt;социальная сеть &amp;ndash; веб-часть проекта, содержащая все полагающиеся
    атрибуты соцсетей в реалиях игры (nginx, Python, Twisted, XSLT,
    memcached, PostgreSQL)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="obiazannosti"&gt;Обязанности&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Полная самостоятельная поддержка и разработка всех проектов компании
    со стороны веба&lt;/li&gt;
&lt;li&gt;Оптимизация существующего кода для увеличения производительности и
    уменьшения нагрузок&lt;/li&gt;
&lt;li&gt;Разработка модулей для существующего проекта&lt;/li&gt;
&lt;li&gt;Доработка функционала, фикс багов&lt;/li&gt;
&lt;li&gt;Интергация проектов с российскими и зарубежными соцсетями&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="trebovaniia-k-kandidatu"&gt;Требования к кандидату&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Уверенное знание Python&lt;/li&gt;
&lt;li&gt;Уверенное знание JavaScript&lt;/li&gt;
&lt;li&gt;Знание XSLT&lt;/li&gt;
&lt;li&gt;Умение разбираться в чужом коде&lt;/li&gt;
&lt;li&gt;Умение объективно оценивать собственные трудозатраты по той или иной
    задаче и укладываться в поставленные сроки&lt;/li&gt;
&lt;li&gt;Английский язык на уровне чтения технической документации&lt;/li&gt;
&lt;li&gt;Коммуникабельность, дисциплинированность и ответственность&lt;/li&gt;
&lt;li&gt;Приветствуется опыт работы над сложными/высоконагруженными
    web-проектами&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usloviia-raboty"&gt;Условия работы&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Полный рабочий день в офисе в Москве (пять минут пешком от метро
    Третьяковская)&lt;/li&gt;
&lt;li&gt;Работа над интересными, перспективными проектами&lt;/li&gt;
&lt;li&gt;Отличная команда единомышленников, каждый из которых является
    профессионалом в своей области&lt;/li&gt;
&lt;li&gt;Начало рабочего дня: с 10.00 до 12.00 (по желанию)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Зарплата: 50-100 тыс. руб. в месяц&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="kuda-pisat"&gt;Куда писать?&lt;/h2&gt;
&lt;div class="card orange darken-3"&gt;
&lt;p&gt;&lt;div class="card-content white-text center"&gt;
&lt;strong&gt;Вакансия более не актуальна&lt;/strong&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;P.S.: Если Вы не дотягиваете до требований, но в Сказку хочется - все
равно пишите, еще есть вакансия джуниора.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Mon, 14 Mar 2011 15:32:00 +0300</pubDate><guid>tag:www.insight-it.ru,2011-03-14:vacancy/2011/dobro-pozhalovat-v-skazku-vakansiya/</guid><category>nginx</category><category>Python</category><category>Twisted</category><category>XSLT</category><category>memcached</category><category>PostgreSQL</category><category>JavaScript</category></item><item><title>Comet</title><link>https://www.insight-it.ru//frontend/2008/comet/</link><description>&lt;p&gt;Уже приготовились мыть посуду? Что ж, придется Вас разочаровать, сегодня
речь пойдет вовсе не о моющем средстве, а об одноименной технологии.&lt;/p&gt;
&lt;p&gt;Comet представляет собой архитектуру веб-приложений, основной
особенностью которой является тот факт, что отправка данных от сервера к
клиенту (в роли которого обычно выступает браузер) не требует
какого-либо запроса данных со стороны клиента. Это позволяет
пользователям приложения более оперативно реагировать на возникающие на
сервере события и быть в курсе процесса работы приложения без
необходимости непрерывно опрашивать сервер с помощью веб-клиента.
&lt;!--more--&gt;
Реализация этой технологии, как не сложно догадаться, основывается на
JavaScript. Основной идеей является поддержание долговременных
HTTP-соединений с каждым клиентом приложения и отправка новых данных
клиентам с их помощью как только произошло их обновление или
возникновение на сервере. Этот принцип послужил основой для
альтернативных названий этой технологии: &lt;em&gt;Server-push&lt;/em&gt;, &lt;em&gt;Reverse AJAX&lt;/em&gt;.
В случае классического AJAX (о котором тоже стоило бы сначала написать
статейку, потом может быть соберусь) клиент асинхронно отправляет
серверу запрос на получение какой-либо конкретной информации. В Comet же
клиент с сервером как бы меняются ролями: инициатором передачи
информации является сервер, а не клиент. Что же это меняет? Самым
наглядным примером послужит реализация постоянного обновления какой-либо
информации в реальном времени:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Классическая модель отправки запросов.&lt;/strong&gt; Для решения задачи
    понадобится постоянно обновлять всю страницу целиком, вручную
    пользователем или альтернативными способами автоматически. Совсем не
    вариант, будет генерироваться огромное количество запросов к
    серверу, каждый из которых будет очень существеннен по объему.
    Большое количество одновременно работающих пользователей такое
    приложение явно не выдержит, да и доступность данных в реальном
    времени не обеспечит.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AJAX.&lt;/strong&gt; По сравнению с предыдущим вариантом AJAX предоставляет
    массу преимуществ: размер передаваемых данных существенно
    уменьшается, особенно если использовать в качестве формата данных не
    XML, а JSON. Но тем не менее необходимость регулярно отправлять
    запросы серверу для получения обновленной информации останется. С
    ростом количества пользователей будет расти и количество запросов,
    открытие и закрытие которых будет неуклонно генерировать нагрузку на
    сервер. Для снижения нагрузки можно попытаться увеличивать интервал
    между запросами, но это лишь временная мера, обладающая существенным
    недостатком - увеличение этого промежутка времени повлечет за собой
    рост задержек между обновлением информации на сервере и обновлением
    клиентской части приложения.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comet.&lt;/strong&gt; С каждым клиентом поддерживается постоянное
    HTTP-соединение, как только данные на сервере обновились - сервер
    сразу же отправляет по уже открытому соединению уведомление о
    необходимости провести изменения в клиентской части, это позволяет
    существенно сократить нагрузку на сервер и практически избавиться от
    задержек между обновлением данных на сервере и клиенте.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для написания серверной части приложения может использоваться
практически любой язык программирования, наиболее распространенным
решением, пожалуй, является Java Servlet, запущенный в каком-либо
контейнере - Apache TomCat, Jetty или Sun GlassFish. Для реализации
этого подхода к организации общения клиента с сервером написано
достаточно большое количество framework'ов и библиотек, наиболее полный
список, я думаю, можно найти в &lt;a href="https://www.insight-it.ru/goto/b28f61a7/" rel="nofollow" target="_blank" title="http://en.wikipedia.org/wiki/Comet_%28programming%29#Implementations"&gt;английской википедии&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Но и для Comet-приложений рано или поздно возникает вопрос
масштабируемости, так как традиционные HTTP-сервера создают новый поток
(thread) для обслуживания очередных нескольких очередных новых
соединений. Каждый поток в состоянии обрабатывать только небольшое
количество HTTP-соединений, а так как в случае с Comet соединения
находятся в открытом состоянии неопределенно долго, для каждых
нескольких новых пользователей веб-приложения приходится создавать новый
поток. Количество одновременно существующих потоков не безгранично, что
в один прекрасный момент приводит к существенному росту издержек,
связанных с созданием новых и управлением существующими потоками, а
также все чаще и чаще возникающим отказам потокам в предоставлении
серверу необходимых вычислительных. В таких ситуациях некоторые
пользователи встречаются с неприемлимыми задержками в работе приложения
или непредвиденными сообщениями об ошибках. Наиболее простым и в то же
время эффективным решением подобной проблемы является горизонтальное
масштабирование Comet-серверов с балансировкой нагрузки на программном
или аппаратном уровне.&lt;/p&gt;
&lt;p&gt;Если Вас заинтересовала эта тема - могу посоветовать взглянуть на пару
достаточно интересных статей, в котором более с практической точки
зрения описывается этот подход к построению приложений:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/2c5c0107/" rel="nofollow" target="_blank" title="http://www.ibm.com/developerworks/ru/library/j-jettydwr/"&gt;Создание масштабируемых Comet-приложений с использованием Jetty и Direct Web Remoting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.insight-it.ru/goto/4d14c647/" rel="nofollow" target="_blank" title="http://www.javaworld.com/javaworld/jw-03-2008/jw-03-asynchhttp.html"&gt;Asynchronous HTTP and Comet Architecture&lt;/a&gt;
    (eng.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Я же надеюсь написать статью более практической на направленности по
этой теме лишь в обозримом будущем, не пропустить этот момент Вам
поможет &lt;a href="/feed/"&gt;абонемент&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Wed, 26 Mar 2008 21:13:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-03-26:frontend/2008/comet/</guid><category>AJAX</category><category>Comet</category><category>HTTP</category><category>JavaScript</category><category>persistent</category><category>архитектура</category><category>информационные технологии</category></item><item><title>7 способов защитить свой интернет-ресурс от нежелательной информации</title><link>https://www.insight-it.ru//security/2008/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/</link><description>&lt;p&gt;В одном из предыдущих постов я поднял &lt;a href="https://www.insight-it.ru/security/2008/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/"&gt;тему о технологии под названием captcha&lt;/a&gt;, которая является одним из самых распространенных и эффективных способов борьбы с автоматическим заполнением интернет-ресурсов нежелательным контентом. В этом же посте хотелось бы развить начатый разговор повествованием о различных способах воплощения этой технологии в жизнь.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id="1-klassicheskii-variant-graficheskaia-realizatsiia"&gt;1. Классический вариант - графическая реализация&lt;/h3&gt;
&lt;p&gt;Самым популярным вариантом реализации является "графическая" captcha
(позволю себе "обращаться" к этому слову в женском роде, просто из-за
того, что по-моему оно так лучше звучит, не смотря на то, что по логике
все же стоило использовать "он", так как при дословном переводе
получилось бы слово "тест" с кучкой прилагательных
и определений). Она представляет собой изображение, содержащее чаще
всего какой-либо сильно искаженный текст или набор цифр, и перед
посетителем ставится задача воспроизведения в текстовом поле,
находящемся неподалеку, того что он/она видит на изображении.
Большинству людей не составит труда прочесть и набрать на клавиатуре
даже искаженный до неузнаваемости текст, а вот для программы данная
задача является как минимум нетривиальной.&lt;/p&gt;
&lt;p&gt;Существует некоторое количество алгоритмов (называются &lt;a href="/tag/ocr/"&gt;&lt;abbr title="Optical Character Recognition"&gt;OCR&lt;/abbr&gt;&lt;/a&gt;), позволяющих программе
пытаться понять что же за текст расположен на изображении. Эти алгоритмы
разрабатывались для вполне мирных целей - для оцифровки книг и любых
других напечатанных на бумаге документов. Но все же эти алгоритмы
предназначены для распознавания аккуратно написанного текста черным
шрифтом на белом фоне и являются плохо приспособленными для
распознавания &lt;a href="/tag/captcha/"&gt;captch'и&lt;/a&gt;. Но все же существует довольно
большое количество модификаций этих алгоритмов, приспособленных для
чтения даже искаженного текста.&lt;/p&gt;
&lt;p&gt;Казалось бы это существование таких алгоритмов делает бессмысленным
использованием такого рода "защиты", но на практике это далеко не так:
большинство из них пригодны только для распознавания только узкого
набора реализаций графических &lt;a href="/tag/captcha/"&gt;captch&lt;/a&gt;, особенно это
актуально для популярных готовых решений реализации этого типа защиты
находящимся в свободном доступе в сети Интернет, а также сервисов,
предоставляющих услуги по генерации такого рода изображений. Что делает
довольно актуальным написание собственной реализации графической
&lt;a href="/tag/captcha/"&gt;captch'и&lt;/a&gt; для появления уверенности в отсутствии готовой
модификации &lt;a href="/tag/ocr/"&gt;&lt;abbr title="Optical Character Recognition"&gt;OCR&lt;/abbr&gt;&lt;/a&gt; алгоритма, для преодоления используемой
преграды. Об этом и пойдет речь в &lt;a href="https://www.insight-it.ru/php/2008/zashhita-internet-resursov-v-kartinkax/"&gt;записи про собственноручную реализацию технологии CAPTCHA.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Но запись еще далека от завершения, ведь описанная выше графическая
реализация, не является единственной. Во-первых, стоило упомянуть пару
несколько реже используемые модификации визуальных тестов:&lt;/p&gt;
&lt;h3 id="2-sommon-sense"&gt;2. Сommon sense&lt;/h3&gt;
&lt;p&gt;Эта категория модификаций основывается на вопросах построенных на так
называемом &lt;em&gt;common sense&lt;/em&gt;, то есть на каких-то общеизвестных вещах,
очевидных для любого человека, но не поддающимся четкому осознаванию
программой с помощью какого-либо алгоритма. К сожалению, этот факт
вместе с тем порождает и основной недостаток этой категории проверок-
такой тест невозможно автоматически сгенерировать, что делает реализацию
существенно более трудоемкой и неэффективной, что собственно и
обуславливает редкость их применения на практике.&lt;/p&gt;
&lt;h3 id="3-matematicheskii-test"&gt;3. Математический тест&lt;/h3&gt;
&lt;p&gt;Помимо просто перенабирания некоторого набора цифр с изображения, авторы
captch'и могут попросить своего посетителя выполнить какую-либо
несложную операцию (например: &lt;code&gt;2 x 2 = ???&lt;/code&gt;). Но такого рода тесты также далеки от идеала, так как в подавляющем большинстве алгоритм их решения прост для безобразия - вполне достаточно бывает базового &lt;a href="/tag/ocr/"&gt;&lt;abbr title="Optical Character Recognition"&gt;OCR&lt;/abbr&gt;&lt;/a&gt; и реализации калькулятора внутри &lt;a href="/tag/crawler/"&gt;crawler&lt;/a&gt;'a, чтобы он смог преодолеть такого рода барьер.&lt;/p&gt;
&lt;h3 id="4-vybor-izobrazheniia"&gt;4. Выбор изображения&lt;/h3&gt;
&lt;p&gt;Хочется также упомянуть один из достаточно оригинальных вариантов
реализации, являющийся по сути вариацией на тему common sense captch'и,
который меня как минимум удивил, когда я его впервые увидел на сайте
одного из мобильных операторов рядом с формой для &lt;strong&gt;online&lt;/strong&gt; отправки SMS. Суть его заключалось в том, что предлагался набор небольших фотографий, из которых предлагалось выбрать 2-4 изображения обладающих каким-либо свойством, например являющимися живыми объектами. Помимо позитивненького оформления и симпатичных фотографий, чисто технически такой подход является достаточно эффективным и легко реализуемым, единственное предъявляемое к такой реализации требование - достаточно обширная база данных изображений.&lt;/p&gt;
&lt;h3 id="5-vykhod-za-ramki-standartov"&gt;5. Выход за рамки стандартов&lt;/h3&gt;
&lt;p&gt;Большинство вещей, предназначенных для массового использования, принято
делать по принципу "чем проще тем лучше". Обусловлено это тем, что
количество пользователей обратно пропорционально уровню требований, к
ним предъявляемых. Формы на интернет-страницах, как ни странно,
исключением из этого принципа не являются, что является причиной их
построения с использованием только базовых языков разметки -
&lt;a href="/tag/html/"&gt;HTML&lt;/a&gt;, &lt;a href="/tag/xhtml/"&gt;XHTML&lt;/a&gt; или в крайнем случае
&lt;a href="/tag/xml/"&gt;XML&lt;/a&gt;. Именно такую форму и ожидает увидеть spider, попадая на
страницу. Но если поступиться этим принципом - легко поставить программу
в тупиковое положение, задействовав какую-либо непривычную для нее
технологию. В качестве примера в голову приходит Flash-ролик вместо
изображения в &lt;em&gt;графическом&lt;/em&gt; варианте реализации.&lt;/p&gt;
&lt;p&gt;Этот способ является очень эффективным, но обладает существенными
недостатками, такими как, например, необходимость использования
современных браузеров с определенными plug-in'ами.&lt;/p&gt;
&lt;h3 id="6-skrytie-razmetki"&gt;6. Скрытие разметки&lt;/h3&gt;
&lt;p&gt;В качестве продолжения предыдущей мысли: &lt;em&gt;&lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;&lt;/em&gt;
предоставляет далеко не один способ скрыть внутри себя код разметки, что
позволяет сделать вид, что формы &lt;em&gt;как бы&lt;/em&gt; не существует (в основном
базирующиеся на обратимом шифровании), заставляя программу подумать "да
тут и заполнять-то нечего" и пройти мимо на какой-нибудь другой сайт.
Все бы хорошо, только посетители сайта с отключенным
&lt;em&gt;&lt;a href="/tag/javascript/"&gt;JavaScript&lt;/a&gt;&lt;/em&gt;'ом формы тоже не увидят...&lt;/p&gt;
&lt;h3 id="7-zvukovoe-voploshchenie"&gt;7. Звуковое воплощение&lt;/h3&gt;
&lt;p&gt;Как не трудно было заметить, что все варианты, которые я упомянул до
этого момента, так или иначе базировались на визуальном восприятии
информации. И вполне обосновано - для большинства людей зрение играет
роль основного чувства, но существуют и интернет-ресурсы, для которых
важен абсолютно каждый посетитель, в том числе и люди с ограниченными
способности, для которых стандартные проверки являются непреодолимыми.
Для такой категории людей были сделаны альтернативные варианты,
основывающиеся на таком чувстве, как слух. Суть же от этого изменилась:
посетителя просят набрать с клавиатуры нечто услышанное при
воспроизведении аудио-записи, либо ответить на какой-либо вопрос,
основывающийся на уже упомянутом принципе &lt;em&gt;common sense&lt;/em&gt; и заданный тоже
с помощью в аудио-файле.&lt;/p&gt;
&lt;p&gt;Вместо заключения хотелось бы предложить Вам &lt;a href="/feed/"&gt;подписаться на RSS этого блога&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Иван Блинков</dc:creator><pubDate>Thu, 03 Jan 2008 20:41:00 +0300</pubDate><guid>tag:www.insight-it.ru,2008-01-03:security/2008/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/</guid><category>captcha</category><category>common sense</category><category>JavaScript</category><category>OCR</category><category>online</category><category>защита интернет-ресурсов</category><category>изображение</category><category>классификация</category><category>проверка</category><category>реализация</category><category>технология</category><category>форма</category></item></channel></rss>