
              <rss version="2.0">
              <channel>
                <title>Кумир святого Исидора</title>
                <link>http://it.nittis.ru</link>
                <description>изучаю новые аббревиатуры для резюме</description>
                <item>
                  <title>Nodejs. Первые шаги</title>
                  <link>http://it.nittis.ru/node-first-steps.html</link>
                  <description>&lt;p&gt;Одна из самых больших проблем с nodejs - это отсутствие актуальных материалов для тех, кто начинает изучение платформы. Многие статьи сильно устарели и в них встречаются упоминания о том, что nodejs не запускается под Windows, хотя это уже давно не так.&lt;/p&gt;

&lt;p&gt;Знакомство в nodejs требует одновременного изучения нескольких технологий и библиотек одновременно, для меня этот список выглядит примерно так (nodejs, express, mongodb, mongoose, asyncjs, mocha, jade vs haml, web sockets). Надо хотябы немного ознакомиться со всем этим, чтобы не изобретать собственные велосипеды на каждом шагу. Хотелось бы почитать что-нибудь связанное с общими подходами при организации кода в nodejs, модульном тестировании, изучить что-то более глубокое, чем одинаковые статьи-введения.&lt;/p&gt;

&lt;p&gt;В прошлой статье о ноде, я ссылался на пару статей с habrahabr и теперь я нашел ее продолжение на гитхаб, в которой есть третья часть &lt;a href=&quot;https://github.com/DavidKlassen/node-tutorial/wiki/Web-%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0-%D0%BD%D0%B0-node.js-%D0%B8-express&quot;&gt;Контроллер страниц&lt;/a&gt;. Она еще не дописана и не так интересна, как предыдущие две.&lt;/p&gt;

&lt;p&gt;Пенемногу ищу ответы на свои вопросы: &lt;a href=&quot;http://tjholowaychuk.com/post/759178288/jade-haml-killer-for-nodejs&quot;&gt;Jade - Haml killer for nodejs&lt;/a&gt; и &lt;a href=&quot;http://vschart.com/compare/jade-template-engin/vs/haml&quot;&gt;сравнительная таблица по этому же вопросу&lt;/a&gt;. Так как по умолчанию экспресс использует jade, то и я остановлюсь на нем.&lt;/p&gt;

&lt;p&gt;Вот и &lt;a href=&quot;https://vimeo.com/56166857&quot;&gt;видео про организацию кода&lt;/a&gt; подоспело. В оригинале оно называется &lt;strong&gt;Modular web applications with Node.js and Express&lt;/strong&gt;, а его автор TJ Holowaychuk - это создатель Express, Jade, Stylus, and Mocha (три кодовых слова из моего набора)&lt;/p&gt;

&lt;p&gt;В поисках нестарого видео по nodejs нашел парочку интересных источников (кончно же на английском), которыми спешу поделиться:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://net.tutsplus.com/tutorials/javascript-ajax/this-time-youll-learn-node-js/&quot;&gt;Node.js Step by Step&lt;/a&gt; - ссылка на первую (из пяти) часть руководства.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://nodetuts.com/&quot;&gt;Node Tuts&lt;/a&gt; - это совсем свежее творение, последняя часть (на данный момент их 8) датируется матром 2013 года. Его оглавлене выглядит заметно интереснее, потому и начну я с него.&lt;/p&gt;

&lt;p&gt;Первый эпизод, &lt;strong&gt;Introduction to Node&lt;/strong&gt;, не обманул моих ожданий, хотя и не продемонстрировал чего-то нового. Многие обзорные статьи по node содержат примерно ту же информацию. Большинстов из них этим и ограничивается, но в даном случае впереди еще 7 уроков и их названия обещают интересное содержание.&lt;/p&gt;

&lt;p&gt;С технической точки зрения, материал подготовлен очень хорошо. Параллельно с видео можно посмотреть текст урока с примерами кода. Текст помогает не только лучше понять особености программирования под ноду, но и упростить преодоление языкового барьера.&lt;/p&gt;

&lt;p&gt;В первом эпизоде автор расказывает об установке nodejs, и приводит пример создания веб-сервера &quot;Hello World&quot;. Он объясняет разницу между блокирующим и неблокирующим кодом, демонстрирует пример многопоточного асинхронного кода и рассказывает о событийной (event-driven) модели, которая используется в nodejs.&lt;/p&gt;

&lt;p&gt;В следующих постах непременно расскажу о других эпизодах руководства и поделюсь своими находками на пути изучения nodejs&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Sun, 05 May 2013 23:20:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/node-first-steps.html</guid>
                </item>
                <item>
                  <title>Знакомство с nodejs</title>
                  <link>http://it.nittis.ru/node-start.html</link>
                  <description>&lt;p&gt;На горизонте появился проект с nodejs на серверной строне. Я давно хотел приступить к изучению этой технолгии и теперь мне совершенно точно не отвертеться. Пожалуй, начну.&lt;/p&gt;

&lt;p&gt;Не стану рассказывать о том, как найти nodejs с помощью google, но упомяну те статьи и сайты, которые буду использовать в процессе обучения. Первый поисковый запрос &lt;strong&gt;&quot;запуск express на nodejs&quot;&lt;/strong&gt; привел меня на хабр &lt;a href=&quot;http://habrahabr.ru/post/146983/&quot;&gt;Web-разработка на node.js и express. Изучаем node.js на практике&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Полезная привычка: &lt;strong&gt;начал что-то новое - заведи репозиторий на битбакет&lt;/strong&gt;.&lt;/em&gt; Я предпочитаю mercurial из-за большей, по сравнению с git, дружелюбности.&lt;/p&gt;

&lt;p&gt;Установка express&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g express&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Создание тестового приложения&lt;/p&gt;

&lt;p&gt;&lt;code&gt;express test
cd test
npm install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;В итоге имеем проект почти на 2 мегабайта и содержащий 730 файлов. Запуск приложения&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;На этом полезная часть хабра-статьи для меня закончилась, оставив на последок ссылку на книгу &lt;a href=&quot;http://www.nodebeginner.ru/&quot;&gt;Node.js для начинающих&lt;/a&gt;. Во второй части статьи &lt;a href=&quot;http://habrahabr.ru/post/158185/&quot;&gt;Web разработка на node.js и express. Глава 2 — тестирование приложения&lt;/a&gt; автор еще раз рассказывает о создании приложения и ипользовании git, а потом переходит к TDD.&lt;/p&gt;

&lt;p&gt;Unit-тесты - это моя мечта. Однаждя я пробовал программировать с их использованием и это было действительно полезно, особенно в те моменты когда требовалось изменить что-то, от чего зависит половина модулей приложения. В моем нынешнем рабочем проекте нет автоматизированных тестов и потому я вынужден придумывать патчи. За два для до релиза, мне не хватает смелости исправить некоторые архитектурные решения, просто потому, что я не могу предсказать, как это скажется на компанентах, написанных моими коллегами.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;application-name&quot;,
  &quot;version&quot;: &quot;0.0.1&quot;,
  &quot;private&quot;: true,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node app.js&quot;
  },
  &quot;dependencies&quot;: {
    &quot;express&quot;: &quot;3.2.0&quot;,
    &quot;jade&quot;: &quot;*&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;mocha&quot;: &quot;*&quot;,
    &quot;should&quot;: &quot;*&quot;,
    &quot;supertest&quot;: &quot;*&quot;
  }
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;После изменения package.json вызываю npm install для загрузки библиотек для тестирования (попробую взять последние версии). Примеры тестов можно найти в статье, на которую я сослался выше, здесь же приведу только команду для их запуска.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node_modules\.bin\_mocha --require should --reporter spec&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Следующий шаг - установка mongodb и запуск базы данных&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C:\mongodb\bin\mongod.exe --dbpath C:\mongodb\data&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Порт БД - 27017, Веб-интерфейс - 28017&lt;/p&gt;

&lt;p&gt;Несколько команд для работы с MongoDB в качевтве сервиса Windows&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C:\mongodb\bin\mongod.exe --config C:\mongodb\mongod.cfg --install
net start MongoDB
net stop MongoDB
C:\mongodb\bin\mongod.exe --remove&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Пытаюсь перейти от псевдотестов к чему-нибудь более реальному. Пока получается, что-то такое - код:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
module.exports = db;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Сам тест:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;var db = require(__dirname + '/../db');
describe('Database', function()
{
  describe('connection', function()
  {
    it('should opened w/o errors', function(done)
    {
      db.once('open', function callback ()
      {
        done();
      });
    })
  })
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Вызов функции done означает успешное завершение теста, в противном случае будет сгенерировано сообщение об ошибке. Самы простой способ испробовать это на собственном опыте - остановить сервер базы данных. Осталось понять, насколько такой тест может быть полезен, проверят ли он что-то действительно важное или является еще одним сферическим конем?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://habrahabr.ru/post/165017/&quot;&gt;Подборка библиотек для nodejs&lt;/a&gt;&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Thu, 02 May 2013 14:33:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/node-start.html</guid>
                </item>
                <item>
                  <title>Объединение ячеек в xlsx при использовании OpenTBS</title>
                  <link>http://it.nittis.ru/opentbs-xlsx-merge-cells.html</link>
                  <description>
&lt;p&gt;Что-то давно я ничего не писал о PHP, к которому приходится обращаться все реже из-за моей нынешней любви к javascript. Однако, некоторые задачи попрежнему тяжело реализовать на клиенте и потому приходится вспоминать о серверных технологиях. В очередной раз мне потребовалось сгенерировать отчет в excel, точнее заполнить существующую форму данными.&lt;/p&gt;

&lt;p&gt;Первначальное решение с помощью Excel.Automation требует наличия на каждой клиентской машине и грозит потенциальными проблемами с версиями MS Office. В поисках решения, я стал поглядывать в сторону шаблонных генераторов и не нашел практически ничего. Тут-то на глаза мне попался проект &lt;a href='http://www.tinybutstrong.com/'&gt;TBS&lt;/a&gt;, который с помощью своего плагина &lt;a href='http://www.tinybutstrong.com/plugins/opentbs/tbs_plugin_opentbs.html'&gt;OpenTBS&lt;/a&gt; обещал мне золотые горы, в виде, генерации документов OpenXML (в том числе и xlsx) на основе шаблона.&lt;/p&gt;

&lt;p&gt;Он действительно это умеет! При этом количесво кода, который нужно написать совсем невелико, в отличие от PHPExcel. Внешний вид полей задается небосредственно в шаблоне xslx-документа. Синтаксис полей в шаблоне прост и понятен. Ура!!! Лучше всего возможности OpenTBS демонстрируется на этой &lt;a href='http://www.tinybutstrong.com/plugins/opentbs/demo/demo.html'&gt;демо странице&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Но! Куда же без этого. Плагин не имеет средств для построчного объединения ячеек при выводе списков и потому его пришлось немного доработать напильником, расширив шаблон параметром merge и написав для него соответсвующий обработчик. Теперь поле, для которого необходимо выполнить объединение должно задаваться примерно вот так:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;[a.num;block=row;ope=xlsxMerge;merge=7:A:M]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;В качестве значения merge испольуется строка с тремя параметрами base:start:end, где base - номер первой строки списка, start и end - начальный и конечный индесы объединения. Пример выше указывает, что необходимо объеденить ячейки A7:M7, A8:M8, A9:M9 и так далее, пока в выводимом списке есть значения.&lt;/p&gt;

&lt;p&gt;Для запуска необходимо выполнить команду Merge Cells, которой я расширил плагин OpenTBS.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;  $template = 'template.xlsx';
  if(!file_exists($template))
  {
    echo &quot;file $template not found&quot;;
  }
  $TBS-&gt;LoadTemplate($template);
  $TBS-&gt;PlugIn(OPENTBS_SELECT_SHEET, 1);
  $TBS-&gt;MergeBlock('a', $data);
  $TBS-&gt;PlugIn(OPENTBS_MERGE_CELLS);
  $filename = &quot;output.xlsx&quot;;
  $TBS-&gt;Show(OPENTBS_FILE+TBS_EXIT, $filename);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Модифицированная версия плагина и пример его использования доступны на GitHub &lt;a href='https://github.com/VladimirRybakov/OpenTBS'&gt;OpenTBS with cells merge for xlsx&lt;/a&gt;&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Thu, 01 Nov 2012 17:28:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/opentbs-xlsx-merge-cells.html</guid>
                </item>
                <item>
                  <title>IT Дайджест #1</title>
                  <link>http://it.nittis.ru/it-digest-1.html</link>
                  <description>
&lt;p&gt;Посещаемость блога понемногу растет, но как-то уж очень медленно. Для того чтобы увеличить её ещё немного - хочу попробовать посты-дайджесты. Таким образом хочу поделиться теми интересными статьями, которые попались мне на глаза, да и ссылки сохранить для последующего использования.&lt;/p&gt; 
                                                                                                   
&lt;h3&gt;1. Node.js + Chromium = AppJS: один из перспективных вариантов второго шага эволюции веборазработчика&lt;/h3&gt;

&lt;p&gt;Ох, как близка мне &lt;a href='http://habrahabr.ru/post/153013/'&gt;эта тема&lt;/a&gt;, потому как сам ковыряю связку &lt;a href='mfc-cef-javascript.html'&gt;MFC + Chromium&lt;/a&gt;, да и node.js хочется попробовать уже давно.&lt;/p&gt;

&lt;h3&gt;2. Динамическое подключение Javascript на Javascript&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://www.activewidgets.com/javascript.forum.6114.43/dynamic-load-javascript-from-javascript.html'&gt;Решение этой задачи&lt;/a&gt;, конечно же, тривиальное, но почему-то сразу не пришло в голову. Чтобы не гуглить его в следующий раз, сохраню в собственном блоге&lt;/p&gt;

&lt;p&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'snip.js';
document.getElementsByTagName('head')[0].appendChild(script);
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;h3&gt;3. Стратегия для технического интервью&lt;/h3&gt;

&lt;p&gt;Переодически у меня возникает мысль о том, что однажды наша маленькая компания начнет расти и тогда я буду &lt;a href='http://habrahabr.ru/company/luxoft/blog/152505/'&gt;проводить интервью при поиске новых программистов&lt;/a&gt;. А может мне самому придется поменять рабочее место, и я буду готовиться к собеседованию, как соискатель.&lt;/p&gt;

&lt;h3&gt;4. Включение чего угодно по HTTP без заморочек c OpenWRT&lt;/h3&gt;

&lt;p&gt;Чувствую себя безруким уродом, после прочтения &lt;a href='http://habrahabr.ru/post/151982/'&gt;подобных статей&lt;/a&gt;. Остается надежда на то, что подрастающие сыновья заставят меня исправиться.&lt;/p&gt;

&lt;h3&gt;5. Pandoc - универсальный конвертер документов.&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://johnmacfarlane.net/pandoc/index.html'&gt;Pandoc&lt;/a&gt; это швейцарский нож, который помогает конвертировать различные текстовые форматы друг в друга. Документы предстваленные в markdown, reStructuredText, textile, HTML, DocBook, или LaTeX можно конвертировать в:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML форматы: XHTML, HTML5, а так же HTML слайд-шоу с использованием Slidy, Slideous, S5, или DZSlides&lt;/li&gt;
&lt;li&gt;Форматы текстовых процессоров: Microsoft Word docx, OpenOffice/LibreOffice ODT, OpenDocument XML&lt;/li&gt;
&lt;li&gt;Электронные книги: EPUB&lt;/li&gt;
&lt;li&gt;Форматы документации: DocBook, GNU TexInfo, Groff man pages
&lt;/li&gt;
&lt;li&gt;TeX: LaTeX, ConTeXt, LaTeX Beamer slides&lt;/li&gt;
&lt;li&gt;PDF через LaTeX&lt;/li&gt;
&lt;li&gt;Текстовые форматы разметки: Markdown, reStructuredText, AsciiDoc, MediaWiki markup, Emacs Org-Mode, Textile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pandoc распознает расширенный синтаксис markdown, включая мета-данные документа (заголовок, автор, дата), колонтитулы, таблицы, списки, индексыб перечеркнутый текст, выделенные блоки кода с подсветкой синтаксиса, умные кавычки и прочее. При необходимости использовать строгий markdown все расширения можно отключить.&lt;/p&gt;

&lt;p&gt;Описание обещает столько вкусного, что я хочу использовать этот инструмент не только для генерации .docx в одном из текущих проектов, но и для написания статей в блоге (сейчас я пишу их в текстовом редакторе, при необходимости вставляя html-разметку)&lt;/p&gt;

&lt;h3&gt;6. Лучшее с хабра&lt;/h3&gt;

&lt;p&gt;Частенько я не успеваю читать хабр, хотя на нем действительно много хороших и полезных статаей, о чем свидетельствует и содержимое этого дайджеста. Чтобы не упустить самые лучшие статьи хабра можно использовать вот &lt;a href='http://habrafilter.ru'&gt;этот фильтр&lt;/a&gt;, который поможет отобрать несколько самых популярных статей в течение дня.&lt;/p&gt;

&lt;h3&gt;7. Инструкция начинающего разработчика игр&lt;/h3&gt;

&lt;p&gt;Статья рассказывает о том, &lt;a href='http://habrahabr.ru/post/153933/'&gt;почему не надо писать игры&lt;/a&gt;. Иногда я все еще подумываю об этом, но пока все мои начинания сводятся к созданию концепции. Скорее я отважусь на создание своей настолки - пока есть интересная механика, но никак не придумаю какими же тварями населить игру.&lt;/p&gt;

&lt;h3&gt;P.S.&lt;/h3&gt;

&lt;p&gt;Первоначально я предполагал, что в дайджесте будет дюжина новостей. Но выпуск первого номера уже затянулся больше, чем на неделю. Потому, осановлюсь на  семи.&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Wed, 10 Oct 2012 21:38:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/it-digest-1.html</guid>
                </item>
                <item>
                  <title>Динамические CSS стили в knockout</title>
                  <link>http://it.nittis.ru/knockoutjs-dynamic-css.html</link>
                  <description>
&lt;p&gt;В knockoutjs достаточно удобная система шаблонизации, которая, кроме всего прочего, позволяет использовать вложенные шаблоны. В последний раз я столкнулся с ними, когда делал некоторое подобие CRUD на javascript. Кроме всего прочего мне потребовалась устанавливать стили тем элементам, которые создавались с помощью шаблонов. Причем информация о внешнем виде редактора и его полей хранится в прототипе конструктора.&lt;/p&gt;

&lt;p&gt;В поисках решения я наткнулся на блог, который предлагает вот такое решение для динамического назначения стилей - &lt;a href='http://variouslines.blogspot.com/2012/08/how-to-use-computed-observable-in.html'&gt;How to use a computed observable in KnockoutJS CSS binding&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;На его основе я сделал небольшой, пример, который показывает код в действии&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;function viewModel() {
    var self = this,
        defs = {
            name: &quot;base&quot;,
            color: false,
            background: false,
            bold: true
        }
        ko.mapping.fromJS(defs, {}, self);

    self.style = ko.computed(function() {
        return {
            red: self.color(),
            yellow: self.background(),
            bold: self.bold()
        };
    })
};

$(function() {
    vm = new viewModel();
    ko.applyBindings(vm);
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href='http://jsfiddle.net/nittis/P46Pd/'&gt;Демо на jsfiddle&lt;/a&gt;&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Fri, 21 Sep 2012 16:56:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/knockoutjs-dynamic-css.html</guid>
                </item>
                <item>
                  <title>Loginza. Проблема с авторизацией с вКонтакте</title>
                  <link>http://it.nittis.ru/loginza-in-trouble.html</link>
                  <description>
&lt;p&gt;Проблемы у loginz'ы со входом в Контакт подтвердились. И скорость их решения заставляет задуматься о поиске альтернативы, например, &lt;a href='https://ulogin.ru/constructor.html'&gt;uLogin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ниже приведен комментарий от службы поддержки, yandex, которым в настоящее время принадлежит loginza.&lt;/p&gt;

&lt;div style=&quot;margin: 8px; padding: 8px; background: #ffd&quot;&gt;
&lt;p&gt;&lt;i&gt;Приношу свои извинения за задержку с ответом.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Проблема связана с тем, что сервис Вконтакте неожиданно и без предупреждения изменили собственную документацию, поэтому возникла проблема с авторизациями не только у сервиса Loginza, но и у других сайтов. Мы работаем над проблемой с нашей стороны, постараемся решить её в ближайшее время.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Желание яндекса оперативно решить проблему радует, но судя по сообщениям на &lt;a href='http://feedback.loginza.ru/problem/details/id/11618'&gt;странице&lt;/a&gt; с обсуждением проблемы (Выдаёт ошибку: sign validation Invalid session or session signature) такая канитель продолжается уже неделю. Похоже, что яндекс не знает, как извлечь прибыль из логинзы и потому решил похоронить сервис. Я не верю, что изменение API со стороны контакта требует титанических усилий для исправления ошибки.&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Tue, 18 Sep 2012 10:06:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/loginza-in-trouble.html</guid>
                </item>
                <item>
                  <title>knockoutjs. Интеграция chosen</title>
                  <link>http://it.nittis.ru/knockoutjs-n-chosen.html</link>
                  <description>
&lt;p&gt;Для меня навсегда останется загадкой, почему разработчики браузеров не потрудились создать красивый выпадающий списко select. К счастью, есть плагин chosen, который успещно заменяет стандартные списки. Именно о его интеграции knockoutjs и пойдет речь.&lt;/p&gt;

&lt;p&gt;Прежде, чем изобретать собственный велосипед я обратился к всезнающему (и потому пугающему) гуглу и нашел тех, кто уже сталкивался с подобной проблемой &lt;a href='https://github.com/harvesthq/chosen/issues/604'&gt;Does not work with Knockout.js&lt;/a&gt; и её решение. Там же можно найти ссылку на &lt;a href='http://jsfiddle.net/jearles/eJsEN/14/'&gt;рабочий пример&lt;/a&gt;, однако не сложно убедиться, что он не работает, достаточно для первого списка так же указать knockout.binding chosen&lt;/p&gt;

&lt;p&gt;Итак, нужно создать &lt;a href='knockoutjs-custom-binding.html'&gt;custom binding&lt;/a&gt;, который позволит использовать привязку данных knockoutjs и интерфейс chosen. После нескольких попыток у меня получилось следующее&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;ko.bindingHandlers.chosen =
{
  init: function(element)
  {
    $(element).addClass('chzn-select');
    $(element).chosen();
  },
  update: function(element)
  {
    $(element).trigger('liszt:updated');
  }
};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Для вызова использовался вот такой код&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;data-bind=&quot;options: items,
           optionsText: 'name',
           optionsCaption: 'Select item...',
           value: selectedItem,
           chosen: {}&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Однако код не заработал, так как мне было нужно, потому что не обновлялось привязанное значение при изменении значения в списке. Стоило убрать вызов chosen и все работало, как часы. Но каждая попытка использовать плагин снова приводила к неудаче, selectedItem не изменял своекл значения.&lt;/p&gt;

&lt;p&gt;Оказалось, что knockout не устанавливает атрибут value, а без него chosen не отличет один элемент от другого и потому не посылает сообщение о новом значении селектора. Решить проблему со стороны knockout не получилось и потому пришлось править файл chosen.jquery.js&lt;/p&gt;

&lt;p&gt;Потребовалось изменить лишь одну строку, отключив проверку на изменение value в методе Chosen.prototype.result_select&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;//if (this.is_multiple || this.form_field_jq.val() !== this.current_value)
        {
          this.form_field_jq.trigger(&quot;change&quot;, {
            'selected': this.form_field.options[item.options_index].value
          });
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Посмотреть, как все это работает можно на &lt;a href='http://jsfiddle.net/nittis/gzUtU/'&gt;jsFiddle&lt;/a&gt;&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Tue, 18 Sep 2012 00:02:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/knockoutjs-n-chosen.html</guid>
                </item>
                <item>
                  <title>Отладка mod_rewrite</title>
                  <link>http://it.nittis.ru/debug-mod-rewrite.html</link>
                  <description>
&lt;p&gt;Каждый раз работа с .htaccess и mod_rewrite становится для меня испытанием. Я не так часто сталкиваюсь с ними и потому мои знания несколько разрозненны, да и логи, которые предлагается использовать в качестве средства отладки доступны далеко не всегда. Уже несколько раз я сталкивался с ситуацией, когда .htaccess переставал работать при переносе файлов с локальной машины на сервер.&lt;/p&gt;

&lt;p&gt;Включение логов для mod_rewrite&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;IfModule mod_rewrite.c&amp;gt;
RewriteLog &quot;/home/rob4/www/logs/rewrite.log&quot;
RewriteLogLevel 3
&amp;lt;/IfModule&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Недавно наткнулся на &lt;a href='http://www.latenightpc.com/blog/archives/2007/09/05/a-couple-ways-to-debug-mod_rewrite'&gt;статью&lt;/a&gt;, которая предлагает использовать возможности самого mod_rewrite для отладки&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RewriteCond %{QUERY_STRING} !vardump
RewriteRule (.*) %{REQUEST_URI}?vardump=1&amp;r=%{REQUEST_URI} [R=302,L,QSA]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Все запросы будут обработаны этим правилом и для каждого из них сервер выполнит редирект, выведя в строке запроса необходимые параметры. В данном случае get-переменная r - будет содержать запрос (REQUEST_URI). Аналогичным образом можно вывести другие переменные.&lt;/p&gt;

&lt;p&gt;Переменная vardump используется для того, чтобы избежать зацикливания mod_rewrite и гарантировать, что правлио будет использовано лишь однажды, для каждого запроса.&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Sat, 08 Sep 2012 09:16:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/debug-mod-rewrite.html</guid>
                </item>
                <item>
                  <title>JavaScript. Отмена прехода к предыдущей странице при нажатии Backspace</title>
                  <link>http://it.nittis.ru/disable-back-in-ie.html</link>
                  <description>
&lt;p&gt;Последний раз я писал в блог месяц назад - в последний день июля. С тех пор я побывал в отпуске и снова успел устать, с головой окунувшись в работу. Которой, как обычно, больше, чем я когда-либо смогу сделать. Считая проекты, в которые я вовлечен, я сбился, когда закончались пальцы на руке. Удручает, что совсем не остается времени на собственные задумки, вновь отложены в сторону &lt;a href='http://it.nittis.ru/tag-money-page1.html'&gt;учет личных финансов&lt;/a&gt; и &lt;a href='http://it.nittis.ru/tag-gtd-page1.html'&gt;GTD&lt;/a&gt;. Я вернусь к ним. Позже. Наверно.&lt;/p&gt;

&lt;p&gt;Я думаю, так происходит из-за отсутствия быстрого результата. Хочется очень кортоких проектов в противовес тому, что приходится делать на работе - когда разработка программы длится месяцами. Попробую сосредоточиться (в очередной раз) на каких-то вещах, которые мне действительно интересны. Надеюсь, что в сферу моих нынешних увлечений попадет и этот блог.&lt;/p&gt;

&lt;p&gt;Я же пишу код почти каждый день, так почему не могу выдать несколько мыслей по этому поводу на станицах блога. Может от того, что боюсь написать банальщину?Может потому, что объяснить десятичасовой поиск ошибки, не представляется возможным, без подробного описания проекта? Может быть из-за лени?&lt;/p&gt;

&lt;p&gt;Я попробую снова что-то изменить? Если не пытаться, то уж точно ничего не получиться.&lt;/p&gt;

&lt;p&gt;К делу:&lt;/p&gt;

&lt;p&gt;Я многократно писал о своей любви к &lt;a href='http://it.nittis.ru/tag-html-interface-page1.html'&gt;веб-интерфейсу&lt;/a&gt; даже в обычных приложениях. Потому приходится решать проблемы свойственные браузерам. Например, Internet Explorer обладает неприятной особеннойстью переходить к предыдущей странице, при нажатии кнопки Backspace. Причем это происходит даже в том случае, когда фокус находится в поле ввода (input) или textarea. Гугл помог отыскать &lt;a href='http://dev.ektron.com/forum.aspx?g=posts&amp;t=19188'&gt;решение&lt;/a&gt; для этой проблемы, которое я не хочу потеряти и потому публикую здесь.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;function killBackSpace(e)
{
  e = e ? e : window.event;
  var t = e.target ? e.target : e.srcElement ? e.srcElement : null;
  if(t &amp;&amp; t.tagName &amp;&amp; (t.type &amp;&amp; /(password)|(text)|(file)/.test(t.type.toLowerCase()))
  || t.tagName.toLowerCase() == 'textarea')
  {
    return true;
  }
  var k = e.keyCode ? e.keyCode : e.which ? e.which : null;
  if (k == 8)
  {
    if (e.preventDefault)
    {
      e.preventDefault();
    }
    return false;
  };
  return true;
};

if(typeof document.addEventListener!='undefined')
{
  document.addEventListener('keydown', killBackSpace, false);
}
else if(typeof document.attachEvent!='undefined')
{
  document.attachEvent('onkeydown', killBackSpace);
}
else
{
  if(document.onkeydown!=null)
  {
    var oldOnkeydown=document.onkeydown;
    document.onkeydown=function(e)
    {
      oldOnkeydown(e);
      killBackSpace(e);
    };
  }
  else
  {
    document.onkeydown=killBackSpace;
  }
}
&lt;/code&gt;&lt;/pre&gt;
</description>
                  <author> ()</author>
                  <pubDate>Fri, 31 Aug 2012 22:56:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/disable-back-in-ie.html</guid>
                </item>
                <item>
                  <title>jsFiddle. Тестирование JSONP</title>
                  <link>http://it.nittis.ru/jsfiddle-jsonp-echo.html</link>
                  <description>
&lt;p&gt;Я - консерватор. Это не самое лучшее качество для программиста из-за стремительного изменения технологий в IT. Чтобы угнаться за ними, надо как можно чаще использовать новинки. Я же, больше года тянул с тем, чтобы попробовать jQuery, долго изобретал собственный велосипед, убеждая себя и других, что knockoutjs не подойдет для нашего проекта. Теперь стараюсь наверстать упущенное и потому знакомлюсь, с TDD, XP, юнит-тестированием и прочими IT-новинками, открывая для себя технологии, которые для других программистов уже стали привычными инструментами.&lt;/p&gt;

&lt;p&gt;Чтобы избавиться от большого количества тестовых страничек, разбросанных по моему HDD, я решил ближе познакомиться с jsFiddle. Непременно наделаю себе базовых проектов на все случаи жизни и буду активно ими пользоваться. Лучше всего изучать что-то на конкретном примере и мой выбор пал на JSONP, протокол, который, в скором времени, понадобится в одном из моих проектов, для кросс-доменной передачи запросов.&lt;/p&gt;

&lt;p&gt;Вот &lt;a href='http://jsfiddle.net/nittis/qySmJ/'&gt;результат моих экспериментов&lt;/a&gt;, во время которых я познакомился с тем, как jQuery взаимодействует с echo-сервисом jsFiddle и написал свой собственный echo-script на php&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;var data = {
      json: ko.toJSON({
          id: 12345,
          name: 'Legion',
          isReal: true
      }),
      delay: 1
    },
    vm = {
        json: ko.observable('json'),
        onJSON: function() {
            $.ajax({
                type: 'post',
                url: '/echo/json/',
                dataType: 'json',
                data: data,
                success: function(js) {
                    vm.json(ko.toJSON(js) + ' ' + (new Date()).getTime());
                }
            });
        },
        jsonp: ko.observable('jsonp'),
        onJSONP: function() {
            $.ajax(
            jsonpData);
        },
        nittis: ko.observable('nittis'),
        onNittis: function() {
            $.ajax(
            nittisData);
        }
    },
    jsonpData = {
        type: 'post',
        url: 'http://jsfiddle.net/echo/jsonp/',
        dataType: 'jsonp',
        data: data,
        success: function(js) {
            vm.jsonp(js.json + ' ' + js._);
        }
    },
    nittisData = {};

$.extend(nittisData, jsonpData);
nittisData.success = function(js) {
    vm.nittis(js.json + ' ' + js._);
};
nittisData.url = 'http://it.nittis.ru/jsonp.echo.php';

ko.applyBindings(vm);&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;  extract($_GET);
  $arr['json'] = $json;
  $arr['_'] = $_;
  $out = json_encode($arr); 
  $out = &quot;$callback($out);&quot;;
  echo $out;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Программирование должно быть веселым занятием, чтобы приносить не только деньги, но и удовольствие. jsFiddle определенно делает работу веселее.&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Mon, 30 Jul 2012 17:37:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/jsfiddle-jsonp-echo.html</guid>
                </item>
                <item>
                  <title>Knockout JS. Плагин mapping</title>
                  <link>http://it.nittis.ru/knockoutjs-mapping.html</link>
                  <description>
&lt;p&gt;Никак не могу проснуться сегодня. Попробую сделать это с помощью небольшой статьи для блога. Сегодня я возвращаюсь к описанию knockout.js и хочу рассказать о замечательной плагине mapping. Плагин настолько хорош, что только он удостоился ссылки с официального сайта knockoutjs.com&lt;/p&gt;

&lt;p&gt;&lt;a href='http://knockoutjs.com/documentation/plugins-mapping.html'&gt;Плагин mapping&lt;/a&gt; испольуется для создания knockout-модели на основе javascript-модели и, естественно, для обратного преобразования. Очень часто плагин используется для преобразования данных полученых с сервера от backend-приложения.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;//пример создания модели на основе полученных данных
var viewModel = ko.mapping.fromJS(data);
...
//обновление модели
ko.mapping.fromJS(data, {}, viewModel);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Все свойства объекта data будет пребразованы в observable или observableArray, в зависимости от своего типа.&lt;/p&gt; 

&lt;p&gt;Для обратного преобразования модели в объект используется функция &lt;b&gt;ko.mapping.toJS&lt;/b&gt;. При этом в полученном объекте будут присутствовать только те свойства, которые были в исходном объекте при вызове &lt;b&gt;ko.mapping.fromJS&lt;/b&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;  var data = {id: '1', name: 'Ann'};
  var model = ko.mapping.fromJS(data);
  model.job = 'Pretty girl';
  console.log(typeof(model.job)); // &gt;&gt; string
  var js = ko.mapping.toJS(model);
  console.log(typeof(js.job)); // &gt;&gt; undefined&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Advanced usage&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://knockoutjs.com/documentation/plugins-mapping.html'&gt;В оригинальном документе&lt;/a&gt; можно найти подробное описание всех настроек преобразования с примерами. Я же лишь упомяну о них, чтобы сосавить представление о возможностях плагина.&lt;/p&gt;

&lt;p&gt;Опция &lt;b&gt;update&lt;/b&gt; позволяет определить функцию, которая будет вызвана, если свойство с определенным именем уже существует в обновляемом объекте.&lt;/p&gt;

&lt;p&gt;С помощью опции &lt;b&gt;ignore&lt;/b&gt; можно указать имена свойств, которые не должны обрабатываться при формировании модели.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;include&lt;/b&gt; позволяет дополнить список свойств, которые будут использоваться при обратном преобразовании с помощью функции &lt;b&gt;ko.mapping.toJS&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;copy&lt;/b&gt; задает список свойств, которые должны быть скопированы при формировании модели без изменений. То есть они не будут преобразованы в observable или observableArray&lt;/p&gt;

&lt;p&gt;При преобразовании вложенных массивов для каждого из них можно задать несколько опций&lt;/p&gt;

&lt;p&gt;&lt;b&gt;keys&lt;/b&gt; - определяет ключевое поле. При обновлении модели объекты с одинаковым значеним ключа будут обновляться, а не создаваться вновь, что позволит сохранить уже существующие связи.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;create&lt;/b&gt; - позволяет определить функцию, которая будет вызвана при обработке каждого элемента массива. Её можно использовать, для вызова функции-конструктора и создания объектов нужного типа.&lt;/p&gt;

&lt;h3&gt;Пример&lt;/h3&gt;

&lt;p&gt;В своем проекте по учету линых финансов, я использую плагин mapping для сохранения и загрузки информации о счетах. Вот как выглядят функции загрузки и сохранения.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;account.prototype.save = function()
{
  return this.ajax('save', ko.mapping.toJS(this));
};

account.prototype.load = function()
{
  var self = this;
  var promise = this.ajax('load', {})
    .done(function()
    {
      var json = this;
      var mapping = 
      {
        'transfers' : 
        {
          create: function(options)
          {
            return transfer(options.data);
          }
        }
      }
      ko.mapping.fromJS(json[getType(self)], mapping, self);
    });
  return promise;    
};&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Функция ajax() отправляет асинхронный запрос на сервер, который, в случае опреации load возаращает данные завернутые в JSON. В полученном объекте, хранится массив transfers, содержащий информацию обо всех движениях средств по счету.&lt;/p&gt;

&lt;p&gt;Функция transfer, которая вызывается для обработки элементов массива - это функция конструктор, которая выглядит примерно вот так:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;
function transfer(data)
{
  if(!(this instanceof transfer))
  {
    return new transfer(data)
  }
  var self = this; 

  var defs = 
  {
    id: getKey(),
    date: round((new Date()).getTime() / 1000, 0), /* fix for php */ 
    sum: 0.0,
    from: 0, 
    to: 0
  };

  $.extend(defs, data);

  ko.mapping.fromJS(defs, {}, self);

  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;На github этот код можно обнаружить в &lt;a href='https://github.com/VladimirRybakov/money/commit/bfec7a7de4cd7e489356b0cff04fd89050f0ac22'&gt;этой ревизии&lt;/a&gt;&lt;/p&gt;
</description>
                  <author> ()</author>
                  <pubDate>Fri, 27 Jul 2012 11:51:00 GMT</pubDate>
                  <guid>http://it.nittis.ru/knockoutjs-mapping.html</guid>
                </item>
              </channel>
              </rss>