Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
690 lines (600 sloc) 54.4 KB
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Пиши код]]></title>
<link href="http://bardt.github.com/atom.xml" rel="self"/>
<link href="http://bardt.github.com/"/>
<updated>2013-06-10T14:52:16+07:00</updated>
<id>http://bardt.github.com/</id>
<author>
<name><![CDATA[Роман "Bardt" Сальников]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Вертикальное расположение монитора]]></title>
<link href="http://bardt.github.com/blog/2013/04/02/viertikal%27noie-raspolozhieniie-monitora/"/>
<updated>2013-04-02T01:12:00+07:00</updated>
<id>http://bardt.github.com/blog/2013/04/02/viertikal&#8217;noie-raspolozhieniie-monitora</id>
<content type="html"><![CDATA[<p>Мне в руки попали два идентичных монитора NEC (1080p, LED, вроде бы 23&#8217;). Один из них в качестве эксперимента поставил вертикально. Теперь не понимаю, почему не сделал ничего подобного раньше.</p>
<p>Преимущества:</p>
<ol>
<li>Отлично подходит для чтения PDF. В горизонтальной ориентации лист не помещается на экране полностью, а после масштабирования текст становится слишком мелким. Вывод: отлично подходит для чтения документации.</li>
<li>Веб смотрится по-новому. Большая часть сайтов имеют фиксированную колонку контента или резиновую верстку; в обоих случаях ширины такого монитора, как у меня, достаточно, чтобы уместить контент без горизонтальной прокрутки и в то же время максимально утилизировать вертикальное пространство. При горизонтальной ориентации, если растянуть браузер на половину экрана, то горизонтального скролла редко удается избежать.</li>
<li>Вся конструкция из двух мониторов занимает меньше места на столе, а головой приходится мотать меньше.</li>
<li>Это просто круто выглядит.</li>
</ol>
<p>С редактированием кода еще не до конца разобрался. При растягивании редактора на всю высоту глаза разбегаются. Думаю, это дело привычки. Рекомендую попробовать всем, у кого есть такая возможность.</p>
<p>P.S.: Для OS X советую посмотреть в сторону <a href="http://www.irradiatedsoftware.com/sizeup/">SizeUp</a> и перемещать окна с клавиатуры, не хватаясь за мышь. Особенно удобно с учетом нестандартного расположения экранов.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Подходы к хорошему RESTful API]]></title>
<link href="http://bardt.github.com/blog/2013/01/17/podkhody-k-khoroshiemu-restful-api/"/>
<updated>2013-01-17T13:13:00+07:00</updated>
<id>http://bardt.github.com/blog/2013/01/17/podkhody-k-khoroshiemu-restful-api</id>
<content type="html"><![CDATA[<iframe src="http://www.slideshare.net/slideshow/embed_code/6052457" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe>
<p> <div style="margin-bottom:5px"> <strong> <a href="http://www.slideshare.net/landlessness/teach-a-dog-to-rest" title="Teach a Dog to REST" target="_blank">Teach a Dog to REST</a> </strong> from <strong><a href="http://www.slideshare.net/landlessness" target="_blank">landlessness</a></strong> </div></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Организуем CSS3 анимации с помощью LESS]]></title>
<link href="http://bardt.github.com/blog/2012/11/18/orghanizuiem-css3-animatsii-s-pomoshch%27iu-less/"/>
<updated>2012-11-18T19:40:00+07:00</updated>
<id>http://bardt.github.com/blog/2012/11/18/orghanizuiem-css3-animatsii-s-pomoshch&#8217;iu-less</id>
<content type="html"><![CDATA[<p>Времена меняются. Клиентская веб-разработка также не стоит на месте.</p>
<p>Изначально HTML-разметка должна была стать носителем логики построения документа, CSS отвечал за визуальное оформление, а JavaScript - за поведение. Но не все пошло по плану. В какой-то момент все смешалось: теперь разметка пишется под внешний вид, лишаясь значительной части семантики, а скриптами подменяются визуальные стили. Возьмите любое веб-приложение прошлых лет: почти все делается через JS, и как результат мы имеет кашу из HTML-кода, стилей, серверных запросов, и все это намешано в .js файлах.</p>
<!-- more -->
<p>Так не могло продолжаться вечно. Современные технологии позволяют во многом вернуть изначальные роли языкам разметки и программирования. JS обзаводится новыми API, HTML поддерживает семантические теги, а CSS3 - всем тем, что раньше было возможно реализовать только при помощи хитрых скриптов ил сложной разметки: тенями, масками, анимациями. Об анимациях как раз и пойдет речь ниже.</p>
<h2>Анимации</h2>
<p><a href="http://www.w3.org/TR/css3-animations/" title="W3C">Анимации CSS3</a> предоставляют возможности по плавному изменению свойств объекта, например, его прозрачности, размеров и т.д. Мы будем реализовывать простейшую анимацию циклического изменения свойства opacity объекта, обладающего классом .pulse. Это сымитирует его пульсацию - неплохой эффект для того, чтобы привлечь внимание пользователя.</p>
<p>В идеальном мире код для такой анимации мог бы выглядеть примерно так:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>@keyframes pulse {
</span><span class='line'> 0% { // В начальной точке
</span><span class='line'> opacity: 1; // прозрачность составит 1,
</span><span class='line'> }
</span><span class='line'> 100% { // а в конечной
</span><span class='line'> opacity: .4; // 0.4
</span><span class='line'> }
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>.pulse {
</span><span class='line'> animation-name: pulse; // Анимация pulse
</span><span class='line'> animation-iteration-count: infinite; // будет выполняться бесконечно
</span><span class='line'> animation-timing-function: ease-in; // и нелинейно.
</span><span class='line'> animation-duration: 1s; // По истечении 1 секунды
</span><span class='line'> animation-direction: alternative; // будет менять направление на противоположное.
</span><span class='line'>}
</span></code></pre></td></tr></table></div></figure>
<p>Выглядит неплохо, но все меняется, когда приходят они&#8230;</p>
<h2>Префиксы</h2>
<p>Наличие префиксов у свойств CSS в разных браузерах - это тот самый случай, когда теория расходится с практикой. Давайте посмотрим, как будет выглядеть приведенный выше лаконичный код в полевых условиях:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>@-moz-keyframes pulse {
</span><span class='line'> 0% {
</span><span class='line'> opacity: 1;
</span><span class='line'> }
</span><span class='line'> 100% {
</span><span class='line'> opacity: .4;
</span><span class='line'> }
</span><span class='line'>}
</span><span class='line'>@-webkit-keyframes pulse {
</span><span class='line'> 0% {
</span><span class='line'> opacity: 1;
</span><span class='line'> }
</span><span class='line'> 100% {
</span><span class='line'> opacity: .4;
</span><span class='line'> }
</span><span class='line'>}
</span><span class='line'>@keyframes pulse {
</span><span class='line'> 0% {
</span><span class='line'> opacity: 1;
</span><span class='line'> }
</span><span class='line'> 100% {
</span><span class='line'> opacity: .4;
</span><span class='line'> }
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>.pulse {
</span><span class='line'> -webkit-animation-name: pulse;
</span><span class='line'> -moz-animation-name: pulse;
</span><span class='line'> -ms-animation-name: pulse;
</span><span class='line'> -o-animation-name: pulse;
</span><span class='line'> animation-name: pulse;
</span><span class='line'> -webkit-animation-duration: 1s;
</span><span class='line'> -moz-animation-duration: 1s;
</span><span class='line'> -ms-animation-duration: 1s;
</span><span class='line'> -o-animation-duration: 1s;
</span><span class='line'> animation-duration: 1s;
</span><span class='line'> -webkit-animation-iteration-count: infinite;
</span><span class='line'> -moz-animation-iteration-count: infinite;
</span><span class='line'> -ms-animation-iteration-count: infinite;
</span><span class='line'> -o-animation-iteration-count: infinite;
</span><span class='line'> animation-iteration-count: infinite;
</span><span class='line'> -webkit-animation-direction: alternative;
</span><span class='line'> -moz-animation-direction: alternative;
</span><span class='line'> -ms-animation-direction: alternative;
</span><span class='line'> -o-animation-direction: alternative;
</span><span class='line'> animation-direction: alternative;
</span><span class='line'> -webkit-animation-timing-function: ease-in;
</span><span class='line'> -moz-animation-timing-function: ease-in;
</span><span class='line'> -ms-animation-timing-function: ease-in;
</span><span class='line'> -o-animation-timing-function: ease-in;
</span><span class='line'> animation-timing-function: ease-in;
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>
<p>Очевидно, что свою элегантность код потерял. Но это еще не все. Представим, что для разных элементов скорость анимации - <em>animation-duration</em> - должна быть различной. Можно описывать дополнительные классы, в которых переопределять необходимые свойства, но это повлечет за собой целый ворох кода на все случаи жизни, что само по себе не тру. А что тру?</p>
<h2>Реализация на LESS</h2>
<p>В своих проектах я использую <a href="http://lesscss.ru" title="LESS CSS по-русски">LESS CSS</a>. С помощью него не удастся сократить объем сгенерированного кода, но исходники станут заметно чище и читаемее.</p>
<p>Мы заменим класс .pulse из предыдущего примера более универсальным миксином (mixin), принимающим все значения свойств в качестве аргументов:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>.pulse-keyframes {
</span><span class='line'> 0% {
</span><span class='line'> opacity: 1;
</span><span class='line'> }
</span><span class='line'> 100% {
</span><span class='line'> opacity: .4;
</span><span class='line'> }
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>@-webkit-keyframes pulse {.pulse-keyframes;}
</span><span class='line'>@-moz-keyframes pulse {.pulse-keyframes;}
</span><span class='line'>@-ms-keyframes pulse {.pulse-keyframes;}
</span><span class='line'>@-o-keyframes pulse {.pulse-keyframes;}
</span><span class='line'>@keyframes pulse {.pulse-keyframes;}
</span><span class='line'>
</span><span class='line'>.animation(@name, @duration:500ms, @count:infinite, @direction:alternate, @function:ease-in) {
</span><span class='line'> -webkit-animation-name: @name;
</span><span class='line'> -moz-animation-name: @name;
</span><span class='line'> -ms-animation-name: @name;
</span><span class='line'> -o-animation-name: @name;
</span><span class='line'> animation-name: @name;
</span><span class='line'> -webkit-animation-duration: @duration;
</span><span class='line'> -moz-animation-duration: @duration;
</span><span class='line'> -ms-animation-duration: @duration;
</span><span class='line'> -o-animation-duration: @duration;
</span><span class='line'> animation-duration: @duration;
</span><span class='line'> -webkit-animation-iteration-count: @count;
</span><span class='line'> -moz-animation-iteration-count: @count;
</span><span class='line'> -ms-animation-iteration-count: @count;
</span><span class='line'> -o-animation-iteration-count: @count;
</span><span class='line'> animation-iteration-count: @count;
</span><span class='line'> -webkit-animation-direction: @direction;
</span><span class='line'> -moz-animation-direction: @direction;
</span><span class='line'> -ms-animation-direction: @direction;
</span><span class='line'> -o-animation-direction: @direction;
</span><span class='line'> animation-direction: @direction;
</span><span class='line'> -webkit-animation-timing-function: @function;
</span><span class='line'> -moz-animation-timing-function: @function;
</span><span class='line'> -ms-animation-timing-function: @function;
</span><span class='line'> -o-animation-timing-function: @function;
</span><span class='line'> animation-timing-function: @function;
</span><span class='line'>} </span></code></pre></td></tr></table></div></figure>
<p>Теперь вместо переписывания всех свойств с префиксами достаточно будет построить конструкцию вроде следующий:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>.pulse {
</span><span class='line'> .animation(@pulse, 1s);
</span><span class='line'>} </span></code></pre></td></tr></table></div></figure>
<p>Такой подход имеет следующие преимущества:</p>
<ol>
<li>Не нужно заботиться о постоянном переписывании всех свойств с префиксами. Да и помнить их уже не обязательно.</li>
<li>Достаточно передать значения, отличные от заданных по умолчанию.</li>
<li>Одна строчка кода отлично читается и из нее сразу становится понятно, что происходит.</li>
<li>Сгенерированный CSS будет содержать только класс <em>.pulse</em>, без промежуточного <em>.animation</em>.</li>
</ol>
<p>Но есть и недостатки. LESS устанавливает ограничения, в силу которых не получится упростить запись <em>@keyframes</em> с префиксами. В частности, имя свойства не может являться аргументом в миксине. Говорят, что <a href="http://sass-lang.com">SASS</a> более человечен в этом отношении, но сам я на него еще не перешел и знаю довольно плохо. Конструкция на нем могла бы выглядеть примерно так:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>.keyframes-mixin (@name, @frames) {
</span><span class='line'> @-webkit-keyframes @name {@frames}
</span><span class='line'> @-moz-keyframes @name {@frames}
</span><span class='line'> @-ms-keyframes @name {@frames}
</span><span class='line'> @-o-keyframes @name {@frames}
</span><span class='line'> @keyframes @name {@frames}
</span><span class='line'>}
</span></code></pre></td></tr></table></div></figure>
<p><strong>Мораль</strong>: завязывайте писать CSS руками со всеми префиксами, используйте препроцессоры.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Bardtastic Timer v0.1]]></title>
<link href="http://bardt.github.com/blog/2012/11/10/bardtastic-timer-v0-dot-1/"/>
<updated>2012-11-10T19:48:00+07:00</updated>
<id>http://bardt.github.com/blog/2012/11/10/bardtastic-timer-v0-dot-1</id>
<content type="html"><![CDATA[<p>Начать ведение блога я бы хотел с небольшого кусочка кода моего текущего проекта, который хорошо иллюстрирует некоторые хорошие (хотя, наверное, и плохие тоже) приемы в написании JavaScript кода.</p>
<p>Я оформил этот кусочек как небольшую <a href="https://github.com/bardt/bardtastic.timer.js">библиотечку на гитхабе</a>.</p>
<p><strong>Bardtastic Timer</strong> представляет собой замену <em>setTimeout</em> с функциями паузы, возобновления, а также отслеживания текущего времени.</p>
<!-- more -->
<p>Начнем с простого. Весь код библиотеки обворачивается самоисполняемой функцией. Это требуется для того, чтобы можно было использовать вместо <em>window</em> другой корневой элемент, например <em>App</em>, и не засорять глобальный контекст. Кстати, такая техника - стандарт де факто при разработке jQuery плагинов.</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">Bardtastic</span><span class="p">){</span>
</span><span class='line'> <span class="p">...</span>
</span><span class='line'><span class="p">})(</span><span class="nb">window</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>Внутри объявляем нашу функцию, которая будет служить конструктором объекта:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">Bardtastic</span><span class="p">.</span><span class="nx">Timer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">callback</span><span class="p">,</span> <span class="nx">time</span><span class="p">){</span>
</span><span class='line'> <span class="p">...</span>
</span><span class='line'> <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>В конце нужен <em>return this</em> для того, чтобы на выходе получить созданный объект, с которым мы собственно и будем совершать дальнейшие действия. В результате мы хотим использовать библиотеку примерно следующим способом:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">timer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Timer</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="nx">alert</span><span class="p">(</span><span class="s2">&quot;Hello, world!&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">},</span> <span class="mi">5000</span><span class="p">).</span><span class="nx">start</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'><span class="nx">timer</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
</span><span class='line'><span class="nx">timer</span><span class="p">.</span><span class="nx">resume</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>
<p>Далее идет немаловажный этап установки значений по умолчанию. Делается это как для более удобного использования функции, если она будет чаще всего вызываться с определенными аргументами, так и для того, чтобы у свойств всегда были хотя бы какие-нибудь значения (это поможет избежать внезапностей с <em>undefined</em> в коде и уменьшит число необходимых проверок).</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">Bardtastic</span><span class="p">.</span><span class="nx">Timer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">callback</span><span class="p">,</span> <span class="nx">time</span><span class="p">){</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">time</span> <span class="o">=</span> <span class="nx">time</span> <span class="o">||</span> <span class="mi">1000</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">callback</span> <span class="o">=</span> <span class="nx">callback</span> <span class="o">||</span> <span class="kd">function</span><span class="p">(){};</span>
</span><span class='line'>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">isPaused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">isRun</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">onTick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
</span><span class='line'> <span class="p">...</span>
</span><span class='line'> <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Эту технику я выцепил, если не изменяет память, из <a href="http://backbonejs.org/docs/backbone.html">исходников Backbone.js</a>, где зачастую используются еще более изощренные конструкции, вроде этого:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">(</span><span class="nx">value</span> <span class="o">||</span> <span class="p">(</span><span class="nx">value</span> <span class="o">=</span> <span class="s2">&quot;default&quot;</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>
<p>В данном случае, если <em>callback</em> не будет задан, или будет иметь значения, не проходящие проверку истинности (<em>null</em>, <em>NaN</em>, <em>undefined</em> и др.), то ему будет присвоена пустая функция.</p>
<p>Все значения мы присваиваем <em>this</em>, потому что в дальнейшем нам предстоит к ним обращаться и менять значения из методов.</p>
<p>Ну и напоследок, сохраняем ссылку на <em>this</em>:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">...</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">timer</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>
<p>Разные методы будут вызываться в разном контексте, а нам нужна гарантия, что всегда можно будет обратиться к самому объекту. Проиллюстрирую следующим примером:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">...</span>
</span><span class='line'><span class="k">this</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">time</span><span class="p">){</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span> <span class="o">=</span> <span class="nx">time</span> <span class="o">||</span> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span><span class="p">;</span>
</span><span class='line'> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">timeout</span><span class="p">);</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">time</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">finish</span><span class="p">();</span>
</span><span class='line'> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span> <span class="o">-=</span> <span class="mi">100</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">onTick</span><span class="p">();</span>
</span><span class='line'> <span class="p">},</span> <span class="mi">100</span><span class="p">);</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isRun</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isPaused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">timer</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'><span class="p">...</span>
</span></code></pre></td></tr></table></div></figure>
<p>Мы только что объявили первый метод нашего объекта. В нем также можно задать время, это нужно чтобы использовать метод <em>start()</em> одного и того же объекта многократно с разными значениями.</p>
<p>Суть метода проста:
1. Очищаем setInterval, который мог остаться от предыдущего вызова
2. Запускаем setInterval, который будет отсчитывать время, вызывать колбэк при каждом изменении времени и завершать таймер, когда время истечет.
3. Переключаем триггеры <em>isRun</em> и <em>isPaused</em>, по которым станем в дальнейшем определять состояние.</p>
<p>В конце метода возвращается timer, чтобы можно было выстраивать цепочки из методов, например:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">timer</span><span class="p">.</span><span class="nx">start</span><span class="p">(</span><span class="mi">1000</span><span class="p">).</span><span class="nx">pause</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>
<p>Аналогичным образом задаем остальные методы. Я не буду их подробно расписывать. Полный код библиотеки приведен ниже.</p>
<figure class='code'><figcaption><span>bardtastic.timer.js </span><a href='https://github.com/bardt/bardtastic.timer.js/blob/master/src/bardtastic.timer.js'>on GitHub</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">Bardtastic</span><span class="p">){</span>
</span><span class='line'> <span class="nx">Bardtastic</span><span class="p">.</span><span class="nx">Timer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">callback</span><span class="p">,</span> <span class="nx">time</span><span class="p">){</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">time</span> <span class="o">=</span> <span class="nx">time</span> <span class="o">||</span> <span class="mi">1000</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">callback</span> <span class="o">=</span> <span class="nx">callback</span> <span class="o">||</span> <span class="kd">function</span><span class="p">(){};</span>
</span><span class='line'>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">isPaused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">isRun</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">onTick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">var</span> <span class="nx">timer</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">time</span><span class="p">){</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span> <span class="o">=</span> <span class="nx">time</span> <span class="o">||</span> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span><span class="p">;</span>
</span><span class='line'> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">timeout</span><span class="p">);</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">time</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">finish</span><span class="p">();</span>
</span><span class='line'> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span> <span class="o">-=</span> <span class="mi">100</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">onTick</span><span class="p">();</span>
</span><span class='line'> <span class="p">},</span> <span class="mi">100</span><span class="p">);</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isRun</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isPaused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">timer</span><span class="p">;</span>
</span><span class='line'> <span class="p">};</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">resume</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">isPaused</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">timer</span><span class="p">;</span>
</span><span class='line'> <span class="p">};</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">pause</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">isRun</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">stop</span><span class="p">();</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isRun</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isPaused</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">timer</span><span class="p">;</span>
</span><span class='line'> <span class="p">};</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">stop</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="nx">clearInterval</span><span class="p">(</span><span class="nx">timer</span><span class="p">.</span><span class="nx">timeout</span><span class="p">);</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">timer</span><span class="p">;</span>
</span><span class='line'> <span class="p">};</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">finish</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">stop</span><span class="p">();</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isRun</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">isPaused</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">callback</span><span class="p">.</span><span class="nx">call</span><span class="p">();</span>
</span><span class='line'> <span class="p">};</span>
</span><span class='line'> <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">})(</span><span class="nb">window</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>Пример использования:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;number&quot;</span> <span class="na">placeholder=</span><span class="s">&quot;Enter time in milliseconds&quot;</span> <span class="na">id=</span><span class="s">&quot;time&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;button&quot;</span> <span class="na">value=</span><span class="s">&quot;Start&quot;</span> <span class="na">id=</span><span class="s">&quot;start&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;button&quot;</span> <span class="na">value=</span><span class="s">&quot;Pause&quot;</span> <span class="na">id=</span><span class="s">&quot;pause&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;button&quot;</span> <span class="na">value=</span><span class="s">&quot;Resume&quot;</span> <span class="na">id=</span><span class="s">&quot;resume&quot;</span><span class="nt">&gt;</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">timer</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;start&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">timeContainer</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;time&#39;</span><span class="p">);</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">time</span> <span class="o">=</span> <span class="nx">timeContainer</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
</span><span class='line'> <span class="nx">timer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Timer</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="nx">alert</span><span class="p">(</span><span class="s2">&quot;Timer finished!&quot;</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span> <span class="nx">time</span><span class="p">);</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">onTick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="nx">timeContainer</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">timer</span><span class="p">.</span><span class="nx">time</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nx">timer</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;pause&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">timer</span><span class="p">)</span> <span class="nx">timer</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;resume&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">timer</span><span class="p">)</span> <span class="nx">timer</span><span class="p">.</span><span class="nx">resume</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
</feed>