Back home

AngularJs: Warsztaty - stopień 3

Środowisko

Start

Podpinanie js do html

Directive blokujący zaznaczanie i klikanie na element

<quote ws-unselectable>Copyright protected piece of thought</quote>
return {
  restrict: 'A',
  link: function postLink(scope, element, attrs) {
    element.bind('mousedown', function(e) {
      e.preventDefault();
    }); 
    element.bind('selectstart', function(e) {
      e.preventDefault();
    }); 
  }

Kontrolka w directive

<div ws-shortcut-input ws-label="Special key + 1"></div>
<div ws-shortcut-input ws-label="Special key + 2"></div>

Nieizolowane scopy

return {
  template: ': <input ng-model="number" />',
  restrict: 'A',
  link: function (scope, element, attrs)  {
    scope.label = attrs.wsLabel;
  }

Izolowane scopy

return {
  template: ': <input ng-model="number" />',
  restrict: 'A',
  scope: {
    label: '@wsLabel',
    number: '=ngModel'
  }

Zadanie 1: kontrolka dla filtru przedziału

<fieldset ws-interval min="20" max="40" ng-model="interval">
</fieldset>

Rozwiązanie 1

return {
  template: 'Min: <input type="range" max="siteJekyll::Drops::SiteDrop" min="content<h1 id="angularjs-warsztaty---stopień-2">AngularJs: Warsztaty - stopień 2</h1>
<h2 id="środowisko">Środowisko</h2>
<ul>
  <li>konsolowy git</li>
  <li>chrome/chromium</li>
  <li>korzystamy z <code class="language-plaintext highlighter-rouge">&lt;input type="range"&gt;</code></li>
  <li>powinien być slider tutaj: <input type="range" /></li>
  <li>lokalny serwer http - ciasteczka nie działają z file systemu</li>
</ul>

<h2 id="start">Start</h2>
<ul>
  <li>Treść slajdów: <a href="http://bit.ly/angular-workshop2">http://bit.ly/angular-workshop2</a></li>
  <li><code class="language-plaintext highlighter-rouge">git clone</code> <a href="https://github.com/marcin-wosinek/workshop-2.git">https://github.com/marcin-wosinek/workshop-2.git</a></li>
  <li>chrome:</li>
  <li>linux: chromium-browser –disable-web-security</li>
  <li>windows - skopiować link do chroma i edytować: “(originalny link) –disable-web-security”</li>
  <li><code class="language-plaintext highlighter-rouge">git config --global alias.tree "log --oneline --graph --decorate --all"</code></li>
</ul>

<h2 id="projekt">Projekt</h2>
<ul>
  <li>Książka kontaktów</li>
  <li>lista kontaktów</li>
  <li>strona osoby</li>
  <li>formularz edycji</li>
</ul>

<h2 id="indexhtml">index.html</h2>
<ul>
  <li>ng-view - ładujemy ścieżki</li>
  <li>underscore - użyteczne funkcje</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Add your site or application content here --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>

<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"components/angular/angular.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"components/underscore/underscore.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
</code></pre></div></div>

<h2 id="ścieżki">Ścieżki</h2>
<ul>
  <li>konfiguracja aplikacji</li>
  <li>definicja ścieżek</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$routeProvider</span>
  <span class="p">.</span><span class="nx">when</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">templateUrl</span><span class="p">:</span> <span class="dl">'</span><span class="s1">views/main.html</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">controller</span><span class="p">:</span> <span class="dl">'</span><span class="s1">MainCtrl</span><span class="dl">'</span>
  <span class="p">})</span>
  <span class="p">.</span><span class="nx">when</span><span class="p">(</span><span class="dl">'</span><span class="s1">/contact/:id</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">redirectTo</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/contact/:id/view</span><span class="dl">'</span>
  <span class="p">})</span>
</code></pre></div></div>

<h2 id="kontrolery">Kontrolery</h2>
<ul>
  <li>$routeParams</li>
  <li>contacts</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">ContactViewCtrl</span><span class="dl">'</span><span class="p">,</span>
      <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">$routeParams</span><span class="p">,</span> <span class="nx">contacts</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">contact</span> <span class="o">=</span> <span class="nx">contacts</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">$routeParams</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">$routeParams</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
  <span class="p">});</span>
</code></pre></div></div>

<h2 id="serwis-z-danymi">Serwis z danymi</h2>
<ul>
  <li>contacts</li>
  <li><a href="http://www.json-generator.com/">json-generator</a></li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">contacts</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">exampleContacts</span> <span class="o">=</span> <span class="p">[</span> <span class="p">...</span> <span class="p">];</span>

    <span class="c1">// Public API here</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">getAll</span><span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nx">exampleContacts</span><span class="p">;</span>
      <span class="p">},</span>
      <span class="na">get</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{}</span>
</code></pre></div></div>

<h2 id="underscore">Underscore</h2>
<ul>
  <li>użyteczne funkcje</li>
  <li><a href="http://underscorejs.org">dokumentacja</a></li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">evens</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">filter</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span> <span class="k">return</span> <span class="nx">num</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span> <span class="p">});</span>
<span class="c1">// =&gt; [2, 4, 6]</span>

<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">memo</span><span class="p">,</span> <span class="nx">num</span><span class="p">){</span> <span class="k">return</span> <span class="nx">memo</span> <span class="o">+</span> <span class="nx">num</span><span class="p">;</span> <span class="p">},</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// =&gt; 6</span>

<span class="nx">_</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">isNumber</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="struktura-plików">Struktura plików</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-1</code></li>
  <li>app/ zawiera wszystko, co jest potrzebne do dostarczenia aplikacji</li>
  <li>index.html - jedyny plik do użytku bezpośredniego</li>
  <li>view/ - templaty angulara</li>
  <li>styles/ - pliki css i nie skompilowany sass</li>
  <li>components/ - zewnętrzne komponenty</li>
  <li>scripts/ - js</li>
  <li>app.js - definicja modułu + konfiguracja</li>
  <li>test/ katalog z testami</li>
</ul>

<h2 id="yeoman">Yeoman</h2>
<ul>
  <li>narzędzie do wspierania workflowu developerskiego</li>
  <li>generator kodu</li>
</ul>

<h3 id="prezentacja">Prezentacja:</h3>
<ol>
  <li>Generowanie ścieżki</li>
  <li>Odpalenie serwera</li>
  <li>Automatyczne odświeżenie na zmianę</li>
</ol>

<ul>
  <li>pozwalają zmieniać dane z poziomu widoku</li>
  <li>wbudowane filtry</li>
</ul>

<h2 id="filtry">Filtry</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;p&gt;&lt;/p&gt;</span>

<span class="nt">&lt;p&gt;</span>Output: <span class="nt">&lt;/p&gt;</span>

<span class="nt">&lt;tr</span> <span class="na">ng-repeat=</span><span class="s">"friend in friends | filter:searchText"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/tr&gt;</span>
</code></pre></div></div>

<h2 id="pisanie-filtrów">Pisanie filtrów</h2>
<ul>
  <li>zwracamy przetworzony element</li>
  <li>przyjmujemy dowolną liczbę argumentów</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="dl">'</span><span class="s1">filterName</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">arg1</span><span class="p">,</span> <span class="nx">arg2</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="dl">'</span><span class="s1">between filter: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">input</span><span class="p">;</span>
    <span class="p">};</span>
  <span class="p">});</span>
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;li</span> <span class="na">ng-repeat=</span><span class="s">"element in list | filterName:value1:value2"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h2 id="angularforeach">angular.forEach</h2>
<ul>
  <li>pętla</li>
  <li>nie kopiuje danych stworzonych przez angulara (object.$someAngularStuff)</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>

<span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="dl">'</span><span class="s1">Value: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<h2 id="zadanie-1-filtr-przedziału">Zadanie 1: filtr przedziału</h2>
<ul>
  <li>filtr wybierający ludzi z odpowiedniego przedziału wieku</li>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-1</code></li>
  <li>użycie: app/views/showContacts.html +9</li>
  <li>implementacja: app/scripts/filters/between.js</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;tr</span> <span class="na">ng-repeat=</span><span class="s">"contact in contacts | between:'age':min:max"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h2 id="rozwiązanie-1">Rozwiązanie 1</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-1</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">min</span><span class="p">,</span> <span class="nx">max</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">angular</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">input</span><span class="p">))</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">toReturn</span> <span class="o">=</span> <span class="p">[];</span>

    <span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">min</span> <span class="o">&lt;=</span> <span class="nx">element</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="nx">element</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="nx">max</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">toReturn</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">});</span>

    <span class="k">return</span> <span class="nx">toReturn</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// is not array - just return unmodified and forget</span>
  <span class="k">return</span> <span class="nx">input</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h2 id="angular-11x">Angular 1.1.x</h2>
<ul>
  <li>w przeciwieństwie do 1.0.x - gałąź niestabilna</li>
  <li>w przeciągu kilku tygodni wyjdzie 1.2</li>
  <li>duży feature animacje</li>
</ul>

<h2 id="animacje">Animacje</h2>
<ul>
  <li>dyrektywy odpowiadają za zmianę DOM</li>
  <li>do wersji 1.1.4 nie było wsparcia dla animacji</li>
</ul>

<h2 id="nganimation">ngAnimation</h2>
<ul>
  <li>pozwala odpalać animacje na zmiana DOM:</li>
  <li>ng-repeat</li>
  <li>ng-include</li>
  <li>ng-hide</li>
  <li>ng-show</li>
  <li>Demo <a href="/http://www.nganimate.org/">http://www.nganimate.org</a></li>
</ul>

<h2 id="zadanie-2-zastosowanie-animacji">Zadanie 2: zastosowanie animacji</h2>
<ul>
  <li>animowanie zmiany wyświetlanych elementów</li>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-2</code></li>
  <li>implementacja: app/views/showContacts.html &amp; app/styles/main.css</li>
</ul>

<h2 id="rozwiązanie-2">Rozwiązanie 2</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-2</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;li</span> <span class="na">ng-animate=</span><span class="s">"'animate'"</span> <span class="na">ng-repeat=</span><span class="s">"contact in contacts | between:'age':min:max"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.animate-enter</span><span class="o">,</span>
<span class="nc">.animate-leave</span>
<span class="p">{</span>
  <span class="nl">-webkit-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-moz-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-ms-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-o-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
  <span class="nl">display</span><span class="p">:</span> <span class="nb">block</span><span class="p">;</span>
  <span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span>
  <span class="nl">text-overflow</span><span class="p">:</span> <span class="n">clip</span><span class="p">;</span>
  <span class="nl">white-space</span><span class="p">:</span><span class="nb">nowrap</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="cel-śledzenie-userów">Cel: śledzenie userów</h2>
<ul>
  <li>liczenie odwiedzin</li>
  <li>śledzenie aktywności</li>
</ul>

<h2 id="global-controller">Global controller</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-3</code></li>
  <li>pliki: app/index.html +26</li>
  <li>hack - na zawsze uruchamiany kontroler</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Before --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- After --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">ng-controller=</span><span class="s">"GlobalCtrl"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<h2 id="generator-uuid-universally-unique-identifier">Generator UUID (Universally unique identifier)</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-4</code></li>
  <li>pliki: app/scripts/services/wsUuidGenerator.js</li>
  <li>prawdopodobieństwo kolizji:</li>
  <li>miliard co sekundę: w 100 lat mamy 50%</li>
  <li>600 milionów dla każdego człowieka na ziemi: 50%</li>
  <li>ryzyko że uderzy mnie meteor w ciągu roku = kolizja przy kilku dziesiątkach bilionów UUID</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="dl">'</span><span class="s1">xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx</span><span class="dl">'</span>
  <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[</span><span class="sr">xy</span><span class="se">]</span><span class="sr">/g</span><span class="p">,</span> 
    <span class="kd">function</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span><span class="kd">var</span> <span class="nx">r</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="o">*</span><span class="mi">16</span><span class="o">|</span><span class="mi">0</span><span class="p">,</span><span class="nx">v</span><span class="o">=</span><span class="nx">c</span><span class="o">==</span><span class="dl">'</span><span class="s1">x</span><span class="dl">'</span><span class="p">?</span><span class="nx">r</span><span class="p">:</span><span class="nx">r</span><span class="o">&amp;</span><span class="mh">0x3</span><span class="o">|</span><span class="mh">0x8</span><span class="p">;</span><span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">);});</span>
</code></pre></div></div>

<h2 id="ciasteczka---cookies">Ciasteczka - cookies</h2>
<ul>
  <li>do 4 kb danych</li>
  <li>przesyłane z każdym requestem do serwera</li>
</ul>

<h2 id="zastosowanie">Zastosowanie</h2>
<ul>
  <li>śledzenie użytkowników/liczenie odwiedzin</li>
  <li><del>przechowywanie danych</del>: lepiej użyć <a href="http://dev.w3.org/html5/webstorage/">webstorage</a></li>
  <li>logowanie usera - dobrze zainteresować się tym <a href="http://witoldsz.github.io/angular-http-auth/">http://witoldsz.github.io/angular-http-auth/</a></li>
</ul>

<h2 id="cookies-w-angularze">Cookies w angularze</h2>
<ul>
  <li>ngCookies - dodatkowy plik do załadowania</li>
  <li>$cookies - serwis opakowujący użycie cookies</li>
</ul>

<h2 id="zadanie-3-tracking-cookies">Zadanie 3: tracking cookies</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-3</code></li>
  <li>implementacja: app/scripts/controllers/global.js</li>
  <li>jeśli nie ma trackingId na ciasteczku, ustawiamy je na nowo wygenerowany UUID</li>
</ul>

<h2 id="rozwiązanie-3">Rozwiązanie 3</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-3</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">GlobalCtrl</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">$cookies</span><span class="p">,</span> <span class="nx">wsUuidGenerator</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// if it's empty set trackingId on cookie to new created UUID</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">angular</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">$cookies</span><span class="p">.</span><span class="nx">trackingId</span><span class="p">))</span> <span class="p">{</span>
    <span class="nx">$cookies</span><span class="p">.</span><span class="nx">trackingId</span> <span class="o">=</span> <span class="nx">wsUuidGenerator</span><span class="p">.</span><span class="nx">createUuid</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<h2 id="directives">Directives</h2>
<ul>
  <li>rozszerzenia html</li>
  <li>formy użycia</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;span</span> <span class="na">my-dir=</span><span class="s">"exp"</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"my-dir: exp;"</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;my-dir&gt;&lt;/my-dir&gt;</span>
<span class="c">&lt;!-- directive: my-dir exp --&gt;</span>
</code></pre></div></div>

<h2 id="pisanie-directives">Pisanie directives</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-5</code></li>
  <li>plik: app/scripts/directives/ws-accept-cookies.js</li>
  <li>tak definiujemy, tak jak kontrolery, serwisy czy filtry</li>
  <li>properties zwracanego obiektu:</li>
  <li>template - html, który zastąpi zawartość</li>
  <li>restrict - ograniczenie użycia directive:</li>
  <li>E - element, tag</li>
  <li>A - atrybut</li>
  <li>C - klasa</li>
  <li>M - komentarz</li>
  <li>link - funkcja odpalana po podpięciu directive</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">wsAcceptCookies</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div&gt;&lt;/div&gt;</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">E</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">element</span><span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="dl">'</span><span class="s1">this is the wsAcceptCookies directive</span><span class="dl">'</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">};</span>
  <span class="p">});</span>
</code></pre></div></div>

<h2 id="ngtransclude">ngTransclude</h2>
<ul>
  <li>pozwala na wstawienie oryginalnej zawartości tagu wewnątrz templatu</li>
  <li>wymaga transclude: true</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
  <span class="nl">transclude</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
  <span class="nx">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div ng-transclude&gt;&lt;/div&gt;</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="zadanie-4-template-dla-ws-accept-cookies">Zadanie 4: template dla ws-accept-cookies</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-4</code></li>
  <li>przykład użycia: app/index.htm +27</li>
  <li>implementacja: app/scripts/directives/ws-accept-cookies.js</li>
  <li>to, co jest oryginalnie wewnatrz tagu, chcemy mieć wciąż w directive + chcemy mieć guzik accept</li>
</ul>

<h2 id="rozwiązanie-4">Rozwiązanie 4</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-4</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="p">{</span>
    <span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div ng-transclude&gt;&lt;/div&gt;</span><span class="dl">'</span> <span class="o">+</span>
              <span class="dl">'</span><span class="s1">&lt;button&gt;Akceptuje&lt;/button&gt;</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">transclude</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
    <span class="na">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span> <span class="p">{</span>
  <span class="p">}</span>
</code></pre></div></div>

<h2 id="linking-function">Linking function</h2>
<ul>
  <li>miejsce na logikę directive</li>
  <li>argumenty - kolejność jest istotna:</li>
  <li>scope - zakres. W najprostszym przypadku dzielony ze światem zewnętrznym</li>
  <li>element - element jQuery lub jqLite, do którego podpinany logikę</li>
  <li>attrs - obiekt z atrybutami na elemencie, do którego się wpinamy</li>
</ul>

<h2 id="zadanie-5-ws-accept-cookies---implementacja-chowania">Zadanie 5: ws-accept-cookies - implementacja chowania</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-5</code></li>
  <li>dodanie obsługi kliknięcia guzika akceptuj</li>
  <li>ukrywanie elementu, jesli ciasteczka były już zaakceptowane</li>
</ul>

<h2 id="rozwiązanie-5">Rozwiązanie 5</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-5</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span>  <span class="p">{</span>
    <span class="c1">// accept button logic</span>
    <span class="nx">scope</span><span class="p">.</span><span class="nx">accept</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
      <span class="nx">$cookies</span><span class="p">.</span><span class="nx">accepted</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">true</span><span class="dl">'</span><span class="p">;</span>
      <span class="nx">element</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">display</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">};</span>

    <span class="c1">// hide element if cookies are already accepted</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">$cookies</span><span class="p">.</span><span class="nx">accepted</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">element</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">display</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
</code></pre></div></div>

<h2 id="podsumowanie">Podsumowanie</h2>
<ul>
  <li>pisanie filtrów?</li>
  <li>animacje?</li>
  <li>pisanie dyrektyw?</li>
  <li>ngCookies? - session cookies</li>
</ul>

<h2 id="materiały-do-nauki">Materiały do nauki</h2>
<ul>
  <li><a href="http://egghead.io/">http://egghead.io/</a> epizod 10 - 21</li>
  <li><a href="http://www.nganimate.org/">http://www.nganimate.org/</a></li>
</ul>

<h2 id="co-na-następnych-warsztatach">Co na następnych warsztatach?</h2>
<ul>
  <li>dyrektywy - dokończenie</li>
  <li>unit testy &amp; TDD we frontendzie</li>
  <li>warte uwagi projekty:</li>
  <li>angular-ui</li>
  <li>angular-bootstrap</li>
</ul>

<h2 id="stay-tuned">Stay tuned</h2>
<ul>
  <li><a href="http://geekgirlscarrots.pl/category/spotkania/poznan/">GeekCarrots Poznań</a></li>
  <li><a href="http://akai.org.pl/">Akai</a></li>
  <li><a href="https://plus.google.com/110191013153077917985/posts">GDG Poznań</a></li>
  <li><a href="http://www.meetup.com/Hacking-Poznan/">Hacking-Poznan</a></li>
</ul>
" ng-model="model.min"> ' +
      ' <br> Max: <input type="range" max="siteJekyll::Drops::SiteDrop" min="content<h1 id="angularjs-warsztaty---stopień-2">AngularJs: Warsztaty - stopień 2</h1>
<h2 id="środowisko">Środowisko</h2>
<ul>
  <li>konsolowy git</li>
  <li>chrome/chromium</li>
  <li>korzystamy z <code class="language-plaintext highlighter-rouge">&lt;input type="range"&gt;</code></li>
  <li>powinien być slider tutaj: <input type="range" /></li>
  <li>lokalny serwer http - ciasteczka nie działają z file systemu</li>
</ul>

<h2 id="start">Start</h2>
<ul>
  <li>Treść slajdów: <a href="http://bit.ly/angular-workshop2">http://bit.ly/angular-workshop2</a></li>
  <li><code class="language-plaintext highlighter-rouge">git clone</code> <a href="https://github.com/marcin-wosinek/workshop-2.git">https://github.com/marcin-wosinek/workshop-2.git</a></li>
  <li>chrome:</li>
  <li>linux: chromium-browser –disable-web-security</li>
  <li>windows - skopiować link do chroma i edytować: “(originalny link) –disable-web-security”</li>
  <li><code class="language-plaintext highlighter-rouge">git config --global alias.tree "log --oneline --graph --decorate --all"</code></li>
</ul>

<h2 id="projekt">Projekt</h2>
<ul>
  <li>Książka kontaktów</li>
  <li>lista kontaktów</li>
  <li>strona osoby</li>
  <li>formularz edycji</li>
</ul>

<h2 id="indexhtml">index.html</h2>
<ul>
  <li>ng-view - ładujemy ścieżki</li>
  <li>underscore - użyteczne funkcje</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Add your site or application content here --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>

<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"components/angular/angular.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"components/underscore/underscore.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
</code></pre></div></div>

<h2 id="ścieżki">Ścieżki</h2>
<ul>
  <li>konfiguracja aplikacji</li>
  <li>definicja ścieżek</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$routeProvider</span>
  <span class="p">.</span><span class="nx">when</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">templateUrl</span><span class="p">:</span> <span class="dl">'</span><span class="s1">views/main.html</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">controller</span><span class="p">:</span> <span class="dl">'</span><span class="s1">MainCtrl</span><span class="dl">'</span>
  <span class="p">})</span>
  <span class="p">.</span><span class="nx">when</span><span class="p">(</span><span class="dl">'</span><span class="s1">/contact/:id</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">redirectTo</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/contact/:id/view</span><span class="dl">'</span>
  <span class="p">})</span>
</code></pre></div></div>

<h2 id="kontrolery">Kontrolery</h2>
<ul>
  <li>$routeParams</li>
  <li>contacts</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">ContactViewCtrl</span><span class="dl">'</span><span class="p">,</span>
      <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">$routeParams</span><span class="p">,</span> <span class="nx">contacts</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">contact</span> <span class="o">=</span> <span class="nx">contacts</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">$routeParams</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">$routeParams</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
  <span class="p">});</span>
</code></pre></div></div>

<h2 id="serwis-z-danymi">Serwis z danymi</h2>
<ul>
  <li>contacts</li>
  <li><a href="http://www.json-generator.com/">json-generator</a></li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">contacts</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">exampleContacts</span> <span class="o">=</span> <span class="p">[</span> <span class="p">...</span> <span class="p">];</span>

    <span class="c1">// Public API here</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">getAll</span><span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nx">exampleContacts</span><span class="p">;</span>
      <span class="p">},</span>
      <span class="na">get</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{}</span>
</code></pre></div></div>

<h2 id="underscore">Underscore</h2>
<ul>
  <li>użyteczne funkcje</li>
  <li><a href="http://underscorejs.org">dokumentacja</a></li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">evens</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">filter</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span> <span class="k">return</span> <span class="nx">num</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span> <span class="p">});</span>
<span class="c1">// =&gt; [2, 4, 6]</span>

<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">memo</span><span class="p">,</span> <span class="nx">num</span><span class="p">){</span> <span class="k">return</span> <span class="nx">memo</span> <span class="o">+</span> <span class="nx">num</span><span class="p">;</span> <span class="p">},</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// =&gt; 6</span>

<span class="nx">_</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">isNumber</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="struktura-plików">Struktura plików</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-1</code></li>
  <li>app/ zawiera wszystko, co jest potrzebne do dostarczenia aplikacji</li>
  <li>index.html - jedyny plik do użytku bezpośredniego</li>
  <li>view/ - templaty angulara</li>
  <li>styles/ - pliki css i nie skompilowany sass</li>
  <li>components/ - zewnętrzne komponenty</li>
  <li>scripts/ - js</li>
  <li>app.js - definicja modułu + konfiguracja</li>
  <li>test/ katalog z testami</li>
</ul>

<h2 id="yeoman">Yeoman</h2>
<ul>
  <li>narzędzie do wspierania workflowu developerskiego</li>
  <li>generator kodu</li>
</ul>

<h3 id="prezentacja">Prezentacja:</h3>
<ol>
  <li>Generowanie ścieżki</li>
  <li>Odpalenie serwera</li>
  <li>Automatyczne odświeżenie na zmianę</li>
</ol>

<ul>
  <li>pozwalają zmieniać dane z poziomu widoku</li>
  <li>wbudowane filtry</li>
</ul>

<h2 id="filtry">Filtry</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;p&gt;&lt;/p&gt;</span>

<span class="nt">&lt;p&gt;</span>Output: <span class="nt">&lt;/p&gt;</span>

<span class="nt">&lt;tr</span> <span class="na">ng-repeat=</span><span class="s">"friend in friends | filter:searchText"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/tr&gt;</span>
</code></pre></div></div>

<h2 id="pisanie-filtrów">Pisanie filtrów</h2>
<ul>
  <li>zwracamy przetworzony element</li>
  <li>przyjmujemy dowolną liczbę argumentów</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="dl">'</span><span class="s1">filterName</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">arg1</span><span class="p">,</span> <span class="nx">arg2</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="dl">'</span><span class="s1">between filter: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">input</span><span class="p">;</span>
    <span class="p">};</span>
  <span class="p">});</span>
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;li</span> <span class="na">ng-repeat=</span><span class="s">"element in list | filterName:value1:value2"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h2 id="angularforeach">angular.forEach</h2>
<ul>
  <li>pętla</li>
  <li>nie kopiuje danych stworzonych przez angulara (object.$someAngularStuff)</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>

<span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="dl">'</span><span class="s1">Value: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<h2 id="zadanie-1-filtr-przedziału">Zadanie 1: filtr przedziału</h2>
<ul>
  <li>filtr wybierający ludzi z odpowiedniego przedziału wieku</li>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-1</code></li>
  <li>użycie: app/views/showContacts.html +9</li>
  <li>implementacja: app/scripts/filters/between.js</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;tr</span> <span class="na">ng-repeat=</span><span class="s">"contact in contacts | between:'age':min:max"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h2 id="rozwiązanie-1">Rozwiązanie 1</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-1</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">min</span><span class="p">,</span> <span class="nx">max</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">angular</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">input</span><span class="p">))</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">toReturn</span> <span class="o">=</span> <span class="p">[];</span>

    <span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">min</span> <span class="o">&lt;=</span> <span class="nx">element</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="nx">element</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="nx">max</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">toReturn</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">});</span>

    <span class="k">return</span> <span class="nx">toReturn</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// is not array - just return unmodified and forget</span>
  <span class="k">return</span> <span class="nx">input</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h2 id="angular-11x">Angular 1.1.x</h2>
<ul>
  <li>w przeciwieństwie do 1.0.x - gałąź niestabilna</li>
  <li>w przeciągu kilku tygodni wyjdzie 1.2</li>
  <li>duży feature animacje</li>
</ul>

<h2 id="animacje">Animacje</h2>
<ul>
  <li>dyrektywy odpowiadają za zmianę DOM</li>
  <li>do wersji 1.1.4 nie było wsparcia dla animacji</li>
</ul>

<h2 id="nganimation">ngAnimation</h2>
<ul>
  <li>pozwala odpalać animacje na zmiana DOM:</li>
  <li>ng-repeat</li>
  <li>ng-include</li>
  <li>ng-hide</li>
  <li>ng-show</li>
  <li>Demo <a href="/http://www.nganimate.org/">http://www.nganimate.org</a></li>
</ul>

<h2 id="zadanie-2-zastosowanie-animacji">Zadanie 2: zastosowanie animacji</h2>
<ul>
  <li>animowanie zmiany wyświetlanych elementów</li>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-2</code></li>
  <li>implementacja: app/views/showContacts.html &amp; app/styles/main.css</li>
</ul>

<h2 id="rozwiązanie-2">Rozwiązanie 2</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-2</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;li</span> <span class="na">ng-animate=</span><span class="s">"'animate'"</span> <span class="na">ng-repeat=</span><span class="s">"contact in contacts | between:'age':min:max"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.animate-enter</span><span class="o">,</span>
<span class="nc">.animate-leave</span>
<span class="p">{</span>
  <span class="nl">-webkit-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-moz-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-ms-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-o-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
  <span class="nl">display</span><span class="p">:</span> <span class="nb">block</span><span class="p">;</span>
  <span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span>
  <span class="nl">text-overflow</span><span class="p">:</span> <span class="n">clip</span><span class="p">;</span>
  <span class="nl">white-space</span><span class="p">:</span><span class="nb">nowrap</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="cel-śledzenie-userów">Cel: śledzenie userów</h2>
<ul>
  <li>liczenie odwiedzin</li>
  <li>śledzenie aktywności</li>
</ul>

<h2 id="global-controller">Global controller</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-3</code></li>
  <li>pliki: app/index.html +26</li>
  <li>hack - na zawsze uruchamiany kontroler</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Before --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- After --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">ng-controller=</span><span class="s">"GlobalCtrl"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<h2 id="generator-uuid-universally-unique-identifier">Generator UUID (Universally unique identifier)</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-4</code></li>
  <li>pliki: app/scripts/services/wsUuidGenerator.js</li>
  <li>prawdopodobieństwo kolizji:</li>
  <li>miliard co sekundę: w 100 lat mamy 50%</li>
  <li>600 milionów dla każdego człowieka na ziemi: 50%</li>
  <li>ryzyko że uderzy mnie meteor w ciągu roku = kolizja przy kilku dziesiątkach bilionów UUID</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="dl">'</span><span class="s1">xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx</span><span class="dl">'</span>
  <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[</span><span class="sr">xy</span><span class="se">]</span><span class="sr">/g</span><span class="p">,</span> 
    <span class="kd">function</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span><span class="kd">var</span> <span class="nx">r</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="o">*</span><span class="mi">16</span><span class="o">|</span><span class="mi">0</span><span class="p">,</span><span class="nx">v</span><span class="o">=</span><span class="nx">c</span><span class="o">==</span><span class="dl">'</span><span class="s1">x</span><span class="dl">'</span><span class="p">?</span><span class="nx">r</span><span class="p">:</span><span class="nx">r</span><span class="o">&amp;</span><span class="mh">0x3</span><span class="o">|</span><span class="mh">0x8</span><span class="p">;</span><span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">);});</span>
</code></pre></div></div>

<h2 id="ciasteczka---cookies">Ciasteczka - cookies</h2>
<ul>
  <li>do 4 kb danych</li>
  <li>przesyłane z każdym requestem do serwera</li>
</ul>

<h2 id="zastosowanie">Zastosowanie</h2>
<ul>
  <li>śledzenie użytkowników/liczenie odwiedzin</li>
  <li><del>przechowywanie danych</del>: lepiej użyć <a href="http://dev.w3.org/html5/webstorage/">webstorage</a></li>
  <li>logowanie usera - dobrze zainteresować się tym <a href="http://witoldsz.github.io/angular-http-auth/">http://witoldsz.github.io/angular-http-auth/</a></li>
</ul>

<h2 id="cookies-w-angularze">Cookies w angularze</h2>
<ul>
  <li>ngCookies - dodatkowy plik do załadowania</li>
  <li>$cookies - serwis opakowujący użycie cookies</li>
</ul>

<h2 id="zadanie-3-tracking-cookies">Zadanie 3: tracking cookies</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-3</code></li>
  <li>implementacja: app/scripts/controllers/global.js</li>
  <li>jeśli nie ma trackingId na ciasteczku, ustawiamy je na nowo wygenerowany UUID</li>
</ul>

<h2 id="rozwiązanie-3">Rozwiązanie 3</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-3</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">GlobalCtrl</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">$cookies</span><span class="p">,</span> <span class="nx">wsUuidGenerator</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// if it's empty set trackingId on cookie to new created UUID</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">angular</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">$cookies</span><span class="p">.</span><span class="nx">trackingId</span><span class="p">))</span> <span class="p">{</span>
    <span class="nx">$cookies</span><span class="p">.</span><span class="nx">trackingId</span> <span class="o">=</span> <span class="nx">wsUuidGenerator</span><span class="p">.</span><span class="nx">createUuid</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<h2 id="directives">Directives</h2>
<ul>
  <li>rozszerzenia html</li>
  <li>formy użycia</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;span</span> <span class="na">my-dir=</span><span class="s">"exp"</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"my-dir: exp;"</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;my-dir&gt;&lt;/my-dir&gt;</span>
<span class="c">&lt;!-- directive: my-dir exp --&gt;</span>
</code></pre></div></div>

<h2 id="pisanie-directives">Pisanie directives</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-5</code></li>
  <li>plik: app/scripts/directives/ws-accept-cookies.js</li>
  <li>tak definiujemy, tak jak kontrolery, serwisy czy filtry</li>
  <li>properties zwracanego obiektu:</li>
  <li>template - html, który zastąpi zawartość</li>
  <li>restrict - ograniczenie użycia directive:</li>
  <li>E - element, tag</li>
  <li>A - atrybut</li>
  <li>C - klasa</li>
  <li>M - komentarz</li>
  <li>link - funkcja odpalana po podpięciu directive</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">wsAcceptCookies</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div&gt;&lt;/div&gt;</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">E</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">element</span><span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="dl">'</span><span class="s1">this is the wsAcceptCookies directive</span><span class="dl">'</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">};</span>
  <span class="p">});</span>
</code></pre></div></div>

<h2 id="ngtransclude">ngTransclude</h2>
<ul>
  <li>pozwala na wstawienie oryginalnej zawartości tagu wewnątrz templatu</li>
  <li>wymaga transclude: true</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
  <span class="nl">transclude</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
  <span class="nx">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div ng-transclude&gt;&lt;/div&gt;</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="zadanie-4-template-dla-ws-accept-cookies">Zadanie 4: template dla ws-accept-cookies</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-4</code></li>
  <li>przykład użycia: app/index.htm +27</li>
  <li>implementacja: app/scripts/directives/ws-accept-cookies.js</li>
  <li>to, co jest oryginalnie wewnatrz tagu, chcemy mieć wciąż w directive + chcemy mieć guzik accept</li>
</ul>

<h2 id="rozwiązanie-4">Rozwiązanie 4</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-4</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="p">{</span>
    <span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div ng-transclude&gt;&lt;/div&gt;</span><span class="dl">'</span> <span class="o">+</span>
              <span class="dl">'</span><span class="s1">&lt;button&gt;Akceptuje&lt;/button&gt;</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">transclude</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
    <span class="na">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span> <span class="p">{</span>
  <span class="p">}</span>
</code></pre></div></div>

<h2 id="linking-function">Linking function</h2>
<ul>
  <li>miejsce na logikę directive</li>
  <li>argumenty - kolejność jest istotna:</li>
  <li>scope - zakres. W najprostszym przypadku dzielony ze światem zewnętrznym</li>
  <li>element - element jQuery lub jqLite, do którego podpinany logikę</li>
  <li>attrs - obiekt z atrybutami na elemencie, do którego się wpinamy</li>
</ul>

<h2 id="zadanie-5-ws-accept-cookies---implementacja-chowania">Zadanie 5: ws-accept-cookies - implementacja chowania</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-5</code></li>
  <li>dodanie obsługi kliknięcia guzika akceptuj</li>
  <li>ukrywanie elementu, jesli ciasteczka były już zaakceptowane</li>
</ul>

<h2 id="rozwiązanie-5">Rozwiązanie 5</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-5</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span>  <span class="p">{</span>
    <span class="c1">// accept button logic</span>
    <span class="nx">scope</span><span class="p">.</span><span class="nx">accept</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
      <span class="nx">$cookies</span><span class="p">.</span><span class="nx">accepted</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">true</span><span class="dl">'</span><span class="p">;</span>
      <span class="nx">element</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">display</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">};</span>

    <span class="c1">// hide element if cookies are already accepted</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">$cookies</span><span class="p">.</span><span class="nx">accepted</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">element</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">display</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
</code></pre></div></div>

<h2 id="podsumowanie">Podsumowanie</h2>
<ul>
  <li>pisanie filtrów?</li>
  <li>animacje?</li>
  <li>pisanie dyrektyw?</li>
  <li>ngCookies? - session cookies</li>
</ul>

<h2 id="materiały-do-nauki">Materiały do nauki</h2>
<ul>
  <li><a href="http://egghead.io/">http://egghead.io/</a> epizod 10 - 21</li>
  <li><a href="http://www.nganimate.org/">http://www.nganimate.org/</a></li>
</ul>

<h2 id="co-na-następnych-warsztatach">Co na następnych warsztatach?</h2>
<ul>
  <li>dyrektywy - dokończenie</li>
  <li>unit testy &amp; TDD we frontendzie</li>
  <li>warte uwagi projekty:</li>
  <li>angular-ui</li>
  <li>angular-bootstrap</li>
</ul>

<h2 id="stay-tuned">Stay tuned</h2>
<ul>
  <li><a href="http://geekgirlscarrots.pl/category/spotkania/poznan/">GeekCarrots Poznań</a></li>
  <li><a href="http://akai.org.pl/">Akai</a></li>
  <li><a href="https://plus.google.com/110191013153077917985/posts">GDG Poznań</a></li>
  <li><a href="http://www.meetup.com/Hacking-Poznan/">Hacking-Poznan</a></li>
</ul>
" ng-model="model.max"> ',
    scope: {
    min: '@',
    max: '@',
    model: '=ngModel'
  },
  restrict: 'A',
  link: function (scope, element, attrs) {
    scope.model = {
      min: scope.min,
      max: scope.max
    };
  }

Hack

template: 'Min: <input type="range" max="" min="content<h1 id="angularjs-warsztaty---stopień-2">AngularJs: Warsztaty - stopień 2</h1>
<h2 id="środowisko">Środowisko</h2>
<ul>
  <li>konsolowy git</li>
  <li>chrome/chromium</li>
  <li>korzystamy z <code class="language-plaintext highlighter-rouge">&lt;input type="range"&gt;</code></li>
  <li>powinien być slider tutaj: <input type="range" /></li>
  <li>lokalny serwer http - ciasteczka nie działają z file systemu</li>
</ul>

<h2 id="start">Start</h2>
<ul>
  <li>Treść slajdów: <a href="http://bit.ly/angular-workshop2">http://bit.ly/angular-workshop2</a></li>
  <li><code class="language-plaintext highlighter-rouge">git clone</code> <a href="https://github.com/marcin-wosinek/workshop-2.git">https://github.com/marcin-wosinek/workshop-2.git</a></li>
  <li>chrome:</li>
  <li>linux: chromium-browser –disable-web-security</li>
  <li>windows - skopiować link do chroma i edytować: “(originalny link) –disable-web-security”</li>
  <li><code class="language-plaintext highlighter-rouge">git config --global alias.tree "log --oneline --graph --decorate --all"</code></li>
</ul>

<h2 id="projekt">Projekt</h2>
<ul>
  <li>Książka kontaktów</li>
  <li>lista kontaktów</li>
  <li>strona osoby</li>
  <li>formularz edycji</li>
</ul>

<h2 id="indexhtml">index.html</h2>
<ul>
  <li>ng-view - ładujemy ścieżki</li>
  <li>underscore - użyteczne funkcje</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Add your site or application content here --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>

<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"components/angular/angular.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"components/underscore/underscore.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
</code></pre></div></div>

<h2 id="ścieżki">Ścieżki</h2>
<ul>
  <li>konfiguracja aplikacji</li>
  <li>definicja ścieżek</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$routeProvider</span>
  <span class="p">.</span><span class="nx">when</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">templateUrl</span><span class="p">:</span> <span class="dl">'</span><span class="s1">views/main.html</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">controller</span><span class="p">:</span> <span class="dl">'</span><span class="s1">MainCtrl</span><span class="dl">'</span>
  <span class="p">})</span>
  <span class="p">.</span><span class="nx">when</span><span class="p">(</span><span class="dl">'</span><span class="s1">/contact/:id</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">redirectTo</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/contact/:id/view</span><span class="dl">'</span>
  <span class="p">})</span>
</code></pre></div></div>

<h2 id="kontrolery">Kontrolery</h2>
<ul>
  <li>$routeParams</li>
  <li>contacts</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">ContactViewCtrl</span><span class="dl">'</span><span class="p">,</span>
      <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">$routeParams</span><span class="p">,</span> <span class="nx">contacts</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">contact</span> <span class="o">=</span> <span class="nx">contacts</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">$routeParams</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
    <span class="nx">$scope</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">$routeParams</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
  <span class="p">});</span>
</code></pre></div></div>

<h2 id="serwis-z-danymi">Serwis z danymi</h2>
<ul>
  <li>contacts</li>
  <li><a href="http://www.json-generator.com/">json-generator</a></li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">contacts</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">exampleContacts</span> <span class="o">=</span> <span class="p">[</span> <span class="p">...</span> <span class="p">];</span>

    <span class="c1">// Public API here</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">getAll</span><span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nx">exampleContacts</span><span class="p">;</span>
      <span class="p">},</span>
      <span class="na">get</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{}</span>
</code></pre></div></div>

<h2 id="underscore">Underscore</h2>
<ul>
  <li>użyteczne funkcje</li>
  <li><a href="http://underscorejs.org">dokumentacja</a></li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">evens</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">filter</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span> <span class="k">return</span> <span class="nx">num</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span> <span class="p">});</span>
<span class="c1">// =&gt; [2, 4, 6]</span>

<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">memo</span><span class="p">,</span> <span class="nx">num</span><span class="p">){</span> <span class="k">return</span> <span class="nx">memo</span> <span class="o">+</span> <span class="nx">num</span><span class="p">;</span> <span class="p">},</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// =&gt; 6</span>

<span class="nx">_</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">isNumber</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="struktura-plików">Struktura plików</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-1</code></li>
  <li>app/ zawiera wszystko, co jest potrzebne do dostarczenia aplikacji</li>
  <li>index.html - jedyny plik do użytku bezpośredniego</li>
  <li>view/ - templaty angulara</li>
  <li>styles/ - pliki css i nie skompilowany sass</li>
  <li>components/ - zewnętrzne komponenty</li>
  <li>scripts/ - js</li>
  <li>app.js - definicja modułu + konfiguracja</li>
  <li>test/ katalog z testami</li>
</ul>

<h2 id="yeoman">Yeoman</h2>
<ul>
  <li>narzędzie do wspierania workflowu developerskiego</li>
  <li>generator kodu</li>
</ul>

<h3 id="prezentacja">Prezentacja:</h3>
<ol>
  <li>Generowanie ścieżki</li>
  <li>Odpalenie serwera</li>
  <li>Automatyczne odświeżenie na zmianę</li>
</ol>

<ul>
  <li>pozwalają zmieniać dane z poziomu widoku</li>
  <li>wbudowane filtry</li>
</ul>

<h2 id="filtry">Filtry</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;p&gt;&lt;/p&gt;</span>

<span class="nt">&lt;p&gt;</span>Output: <span class="nt">&lt;/p&gt;</span>

<span class="nt">&lt;tr</span> <span class="na">ng-repeat=</span><span class="s">"friend in friends | filter:searchText"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/tr&gt;</span>
</code></pre></div></div>

<h2 id="pisanie-filtrów">Pisanie filtrów</h2>
<ul>
  <li>zwracamy przetworzony element</li>
  <li>przyjmujemy dowolną liczbę argumentów</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="dl">'</span><span class="s1">filterName</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">arg1</span><span class="p">,</span> <span class="nx">arg2</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="dl">'</span><span class="s1">between filter: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">input</span><span class="p">;</span>
    <span class="p">};</span>
  <span class="p">});</span>
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;li</span> <span class="na">ng-repeat=</span><span class="s">"element in list | filterName:value1:value2"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h2 id="angularforeach">angular.forEach</h2>
<ul>
  <li>pętla</li>
  <li>nie kopiuje danych stworzonych przez angulara (object.$someAngularStuff)</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>

<span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="dl">'</span><span class="s1">Value: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<h2 id="zadanie-1-filtr-przedziału">Zadanie 1: filtr przedziału</h2>
<ul>
  <li>filtr wybierający ludzi z odpowiedniego przedziału wieku</li>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-1</code></li>
  <li>użycie: app/views/showContacts.html +9</li>
  <li>implementacja: app/scripts/filters/between.js</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;tr</span> <span class="na">ng-repeat=</span><span class="s">"contact in contacts | between:'age':min:max"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h2 id="rozwiązanie-1">Rozwiązanie 1</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-1</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">min</span><span class="p">,</span> <span class="nx">max</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">angular</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">input</span><span class="p">))</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">toReturn</span> <span class="o">=</span> <span class="p">[];</span>

    <span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="nx">min</span> <span class="o">&lt;=</span> <span class="nx">element</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="nx">element</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="nx">max</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">toReturn</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">});</span>

    <span class="k">return</span> <span class="nx">toReturn</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// is not array - just return unmodified and forget</span>
  <span class="k">return</span> <span class="nx">input</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<h2 id="angular-11x">Angular 1.1.x</h2>
<ul>
  <li>w przeciwieństwie do 1.0.x - gałąź niestabilna</li>
  <li>w przeciągu kilku tygodni wyjdzie 1.2</li>
  <li>duży feature animacje</li>
</ul>

<h2 id="animacje">Animacje</h2>
<ul>
  <li>dyrektywy odpowiadają za zmianę DOM</li>
  <li>do wersji 1.1.4 nie było wsparcia dla animacji</li>
</ul>

<h2 id="nganimation">ngAnimation</h2>
<ul>
  <li>pozwala odpalać animacje na zmiana DOM:</li>
  <li>ng-repeat</li>
  <li>ng-include</li>
  <li>ng-hide</li>
  <li>ng-show</li>
  <li>Demo <a href="/http://www.nganimate.org/">http://www.nganimate.org</a></li>
</ul>

<h2 id="zadanie-2-zastosowanie-animacji">Zadanie 2: zastosowanie animacji</h2>
<ul>
  <li>animowanie zmiany wyświetlanych elementów</li>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-2</code></li>
  <li>implementacja: app/views/showContacts.html &amp; app/styles/main.css</li>
</ul>

<h2 id="rozwiązanie-2">Rozwiązanie 2</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-2</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;li</span> <span class="na">ng-animate=</span><span class="s">"'animate'"</span> <span class="na">ng-repeat=</span><span class="s">"contact in contacts | between:'age':min:max"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.animate-enter</span><span class="o">,</span>
<span class="nc">.animate-leave</span>
<span class="p">{</span>
  <span class="nl">-webkit-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-moz-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-ms-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">-o-transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">transition</span><span class="p">:</span> <span class="m">400ms</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">0.250</span><span class="p">,</span> <span class="m">0.250</span><span class="p">,</span> <span class="m">0.750</span><span class="p">,</span> <span class="m">0.750</span><span class="p">)</span> <span class="n">all</span><span class="p">;</span>
  <span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
  <span class="nl">display</span><span class="p">:</span> <span class="nb">block</span><span class="p">;</span>
  <span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span>
  <span class="nl">text-overflow</span><span class="p">:</span> <span class="n">clip</span><span class="p">;</span>
  <span class="nl">white-space</span><span class="p">:</span><span class="nb">nowrap</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="cel-śledzenie-userów">Cel: śledzenie userów</h2>
<ul>
  <li>liczenie odwiedzin</li>
  <li>śledzenie aktywności</li>
</ul>

<h2 id="global-controller">Global controller</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-3</code></li>
  <li>pliki: app/index.html +26</li>
  <li>hack - na zawsze uruchamiany kontroler</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Before --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>
</code></pre></div></div>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- After --&gt;</span>
<span class="nt">&lt;div</span> <span class="na">ng-controller=</span><span class="s">"GlobalCtrl"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="na">ng-view</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<h2 id="generator-uuid-universally-unique-identifier">Generator UUID (Universally unique identifier)</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-4</code></li>
  <li>pliki: app/scripts/services/wsUuidGenerator.js</li>
  <li>prawdopodobieństwo kolizji:</li>
  <li>miliard co sekundę: w 100 lat mamy 50%</li>
  <li>600 milionów dla każdego człowieka na ziemi: 50%</li>
  <li>ryzyko że uderzy mnie meteor w ciągu roku = kolizja przy kilku dziesiątkach bilionów UUID</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="dl">'</span><span class="s1">xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx</span><span class="dl">'</span>
  <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[</span><span class="sr">xy</span><span class="se">]</span><span class="sr">/g</span><span class="p">,</span> 
    <span class="kd">function</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span><span class="kd">var</span> <span class="nx">r</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="o">*</span><span class="mi">16</span><span class="o">|</span><span class="mi">0</span><span class="p">,</span><span class="nx">v</span><span class="o">=</span><span class="nx">c</span><span class="o">==</span><span class="dl">'</span><span class="s1">x</span><span class="dl">'</span><span class="p">?</span><span class="nx">r</span><span class="p">:</span><span class="nx">r</span><span class="o">&amp;</span><span class="mh">0x3</span><span class="o">|</span><span class="mh">0x8</span><span class="p">;</span><span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">);});</span>
</code></pre></div></div>

<h2 id="ciasteczka---cookies">Ciasteczka - cookies</h2>
<ul>
  <li>do 4 kb danych</li>
  <li>przesyłane z każdym requestem do serwera</li>
</ul>

<h2 id="zastosowanie">Zastosowanie</h2>
<ul>
  <li>śledzenie użytkowników/liczenie odwiedzin</li>
  <li><del>przechowywanie danych</del>: lepiej użyć <a href="http://dev.w3.org/html5/webstorage/">webstorage</a></li>
  <li>logowanie usera - dobrze zainteresować się tym <a href="http://witoldsz.github.io/angular-http-auth/">http://witoldsz.github.io/angular-http-auth/</a></li>
</ul>

<h2 id="cookies-w-angularze">Cookies w angularze</h2>
<ul>
  <li>ngCookies - dodatkowy plik do załadowania</li>
  <li>$cookies - serwis opakowujący użycie cookies</li>
</ul>

<h2 id="zadanie-3-tracking-cookies">Zadanie 3: tracking cookies</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-3</code></li>
  <li>implementacja: app/scripts/controllers/global.js</li>
  <li>jeśli nie ma trackingId na ciasteczku, ustawiamy je na nowo wygenerowany UUID</li>
</ul>

<h2 id="rozwiązanie-3">Rozwiązanie 3</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-3</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">GlobalCtrl</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">$cookies</span><span class="p">,</span> <span class="nx">wsUuidGenerator</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// if it's empty set trackingId on cookie to new created UUID</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">angular</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">$cookies</span><span class="p">.</span><span class="nx">trackingId</span><span class="p">))</span> <span class="p">{</span>
    <span class="nx">$cookies</span><span class="p">.</span><span class="nx">trackingId</span> <span class="o">=</span> <span class="nx">wsUuidGenerator</span><span class="p">.</span><span class="nx">createUuid</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<h2 id="directives">Directives</h2>
<ul>
  <li>rozszerzenia html</li>
  <li>formy użycia</li>
</ul>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;span</span> <span class="na">my-dir=</span><span class="s">"exp"</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"my-dir: exp;"</span><span class="nt">&gt;&lt;/span&gt;</span>
<span class="nt">&lt;my-dir&gt;&lt;/my-dir&gt;</span>
<span class="c">&lt;!-- directive: my-dir exp --&gt;</span>
</code></pre></div></div>

<h2 id="pisanie-directives">Pisanie directives</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout slide-5</code></li>
  <li>plik: app/scripts/directives/ws-accept-cookies.js</li>
  <li>tak definiujemy, tak jak kontrolery, serwisy czy filtry</li>
  <li>properties zwracanego obiektu:</li>
  <li>template - html, który zastąpi zawartość</li>
  <li>restrict - ograniczenie użycia directive:</li>
  <li>E - element, tag</li>
  <li>A - atrybut</li>
  <li>C - klasa</li>
  <li>M - komentarz</li>
  <li>link - funkcja odpalana po podpięciu directive</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">workshop2App</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">wsAcceptCookies</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">{</span>
      <span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div&gt;&lt;/div&gt;</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">E</span><span class="dl">'</span><span class="p">,</span>
      <span class="na">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">element</span><span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="dl">'</span><span class="s1">this is the wsAcceptCookies directive</span><span class="dl">'</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">};</span>
  <span class="p">});</span>
</code></pre></div></div>

<h2 id="ngtransclude">ngTransclude</h2>
<ul>
  <li>pozwala na wstawienie oryginalnej zawartości tagu wewnątrz templatu</li>
  <li>wymaga transclude: true</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
  <span class="nl">transclude</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
  <span class="nx">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div ng-transclude&gt;&lt;/div&gt;</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="zadanie-4-template-dla-ws-accept-cookies">Zadanie 4: template dla ws-accept-cookies</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-4</code></li>
  <li>przykład użycia: app/index.htm +27</li>
  <li>implementacja: app/scripts/directives/ws-accept-cookies.js</li>
  <li>to, co jest oryginalnie wewnatrz tagu, chcemy mieć wciąż w directive + chcemy mieć guzik accept</li>
</ul>

<h2 id="rozwiązanie-4">Rozwiązanie 4</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-4</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="p">{</span>
    <span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&lt;div ng-transclude&gt;&lt;/div&gt;</span><span class="dl">'</span> <span class="o">+</span>
              <span class="dl">'</span><span class="s1">&lt;button&gt;Akceptuje&lt;/button&gt;</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">A</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">transclude</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
    <span class="na">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span> <span class="p">{</span>
  <span class="p">}</span>
</code></pre></div></div>

<h2 id="linking-function">Linking function</h2>
<ul>
  <li>miejsce na logikę directive</li>
  <li>argumenty - kolejność jest istotna:</li>
  <li>scope - zakres. W najprostszym przypadku dzielony ze światem zewnętrznym</li>
  <li>element - element jQuery lub jqLite, do którego podpinany logikę</li>
  <li>attrs - obiekt z atrybutami na elemencie, do którego się wpinamy</li>
</ul>

<h2 id="zadanie-5-ws-accept-cookies---implementacja-chowania">Zadanie 5: ws-accept-cookies - implementacja chowania</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git checkout todo-5</code></li>
  <li>dodanie obsługi kliknięcia guzika akceptuj</li>
  <li>ukrywanie elementu, jesli ciasteczka były już zaakceptowane</li>
</ul>

<h2 id="rozwiązanie-5">Rozwiązanie 5</h2>
<ul>
  <li><code class="language-plaintext highlighter-rouge">git add .</code></li>
  <li><code class="language-plaintext highlighter-rouge">git commit -m '(commit message)'</code></li>
  <li><code class="language-plaintext highlighter-rouge">git checkout done-5</code></li>
  <li>Pytania?</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">link</span><span class="p">:</span> <span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">element</span><span class="p">,</span> <span class="nx">attrs</span><span class="p">)</span>  <span class="p">{</span>
    <span class="c1">// accept button logic</span>
    <span class="nx">scope</span><span class="p">.</span><span class="nx">accept</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
      <span class="nx">$cookies</span><span class="p">.</span><span class="nx">accepted</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">true</span><span class="dl">'</span><span class="p">;</span>
      <span class="nx">element</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">display</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">};</span>

    <span class="c1">// hide element if cookies are already accepted</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">$cookies</span><span class="p">.</span><span class="nx">accepted</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">element</span><span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="dl">'</span><span class="s1">display</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
</code></pre></div></div>

<h2 id="podsumowanie">Podsumowanie</h2>
<ul>
  <li>pisanie filtrów?</li>
  <li>animacje?</li>
  <li>pisanie dyrektyw?</li>
  <li>ngCookies? - session cookies</li>
</ul>

<h2 id="materiały-do-nauki">Materiały do nauki</h2>
<ul>
  <li><a href="http://egghead.io/">http://egghead.io/</a> epizod 10 - 21</li>
  <li><a href="http://www.nganimate.org/">http://www.nganimate.org/</a></li>
</ul>

<h2 id="co-na-następnych-warsztatach">Co na następnych warsztatach?</h2>
<ul>
  <li>dyrektywy - dokończenie</li>
  <li>unit testy &amp; TDD we frontendzie</li>
  <li>warte uwagi projekty:</li>
  <li>angular-ui</li>
  <li>angular-bootstrap</li>
</ul>

<h2 id="stay-tuned">Stay tuned</h2>
<ul>
  <li><a href="http://geekgirlscarrots.pl/category/spotkania/poznan/">GeekCarrots Poznań</a></li>
  <li><a href="http://akai.org.pl/">Akai</a></li>
  <li><a href="https://plus.google.com/110191013153077917985/posts">GDG Poznań</a></li>
  <li><a href="http://www.meetup.com/Hacking-Poznan/">Hacking-Poznan</a></li>
</ul>
" ng-model="model.min"> ' +
          ' <br> Max: <input type="range" max="siteJekyll::Drops::SiteDrop" min="" ng-model="model.max"> '

Testy

Piramida testów

Unit testy - idea

Mocks & stubs

Dependecy injection

// Dependecy injection
function ContactEditCtrl ($scope, $routeParams, contacts) {
  $scope.contact = contacts.get($routeParams.id);
  $scope.id = $routeParams.id;
}
// Dependecy 'calling'
function ContactEditCtrl () {
  var $scope = ScopeFactory.getNewScope(),
    $routeParams = RouteParams.getSingleton(),
    contacts = new Contacts();

  $scope.contact = contacts.get($routeParams.id);
  $scope.id = $routeParams.id;
}

Jasmine

Jasmine - składnia

describe("Jasmine", function() {
  it("is aware that true === true", function() {
    expect(true).toBe(true);
  });

  it("is aware that false !== true", function() {
    expect(false).not.toBe(true);
  });
});

Jasmine - matchery (asercje)

// Defaults
expect(a.foo).toBeDefined();
expect(message).toMatch(/bar/);
expect(a).toBe(true);
expect(a).toEqual(12);
expect(pi).toBeGreaterThan(e);

// Jasmine matchers
expect(function).toBeFunction();
expect(string).toBeString();
expect(array).toBeArray();

Jasmine - mokowanie

spyOn(foo, 'setBar').andCallThrough();
foo.setBar(42);
expect(foo.setBar).toHaveBeenCalled();
expect(foo.setBar).toHaveBeenCalledWith(42);

var standAloneSpy = jasmine.createSpy('standAloneSpy').andReturn(11);

Unit testy - Angular

Angular - testowanie controlera

$controller('GlobalCtrl', {
  $scope: scope});

Zadanie 2 - unit testy controlera

Rozwiązanie 2a

beforeEach(inject(function ($controller, $rootScope) {
  scope = $rootScope.$new();
  cookies = {};
  wsUuidGenerator = {
    createUuid: jasmine.createSpy('createUuid').andReturn('341')
  };

  GlobalCtrl = $controller('GlobalCtrl', {
    $scope: scope,
    $cookies: cookies,
    wsUuidGenerator: wsUuidGenerator
  });
}));

it('should setup cookies', function () {
  expect(cookies.trackingId).toEqual('341');
});

Zadanie 2b - naiwna implementacja

Rozwiązanie 2b

$cookies.trackingId = '341';

Refaktoring testu

init = function () {
  GlobalCtrl = $controller('GlobalCtrl', {
    $scope: scope,
    $cookies: cookies,
    wsUuidGenerator: wsUuidGenerator
  });
};

Zadanie 2c

Rozwiązanie 2c

expect(wsUuidGenerator.createUuid).toHaveBeenCalled();

Naiwna implementacja

wsUuidGenerator.createUuid();
$cookies.trackingId = '341';

Zadanie 2d

Rozwiązanie 2d

// check for some other value   
wsUuidGenerator.createUuid.andReturn('111');
init();
expect(cookies.trackingId).toEqual('111');

Pokryty testami kod

$cookies.trackingId = wsUuidGenerator.createUuid();

Zadanie 2e

Rozwiązanie 2e

// should not override existing cookie value
wsUuidGenerator.createUuid.andReturn('111');
init();
expect(cookies.trackingId).toEqual('341');

Pokryty testami kod

if (!angular.isString($cookies.trackingId)) {
  $cookies.trackingId = wsUuidGenerator.createUuid();
}

Angular - testowanie serwisu

module(function($provide) {
  $provide.value('ServiceA', ServiceAMock);
  $provide.value('ServiceB', ServiceBMock);
});

inject(function(_ServiceInTest_) {
  ServiceInTest = _ServiceInTest_;
});

Przykład testów service

beforeEach(function () {
  module(function($provide) {
    $provide.value('$resource', _resource);
  });

  inject(function(_contacts_) {
    contacts = _contacts_;
  });
});

it('should implement getAll', function () {
  expect(ContactsResource.query).not.toHaveBeenCalled();
  var returned = contacts.getAll();
  expect(ContactsResource.query).toHaveBeenCalled();
  expect(returned).toEqual('queryTest');
});

Podsumowanie

Stay tuned