Você ainda não sabe escrever JavaScript para aplicações Rails

Você ainda não sabe escrever JavaScript para aplicações Rails

Uma palestra com as principais tecnologias e técnicas utilizadas para escrever código JavaScript sano para diferentes tipos de aplicações. Uma viagem às antigas soluções Rails até as atuais e nem sempre suficientes jQuery UJS e Turbolinks. Aprenda sobre componentes auto-discoverable, comunicação através de eventos, modularização e gerência de dependências. Tudo isto sem deixar de fora alguns dos conceitos por trás dos principais frameworks MV* do mercado.

C5df370a883b65279af5a7ca94a5eed7?s=128

Jean Carlo Emer

August 29, 2014
Tweet

Transcript

  1. 4.
  2. 8.

    [...] é necessário ir ao passado para a compreensão de

    todos os questionamentos do tempo presente - Historiador Tiago Menta
  3. 12.

    <%  form_remote_tag  :url  =>  '/'  do  -­‐%>      

       <div><%=  submit_tag  'Save'  %></div>   <%  end  -­‐%> index.erb
  4. 13.

    <form action="/" method="post" onsubmit="
 new Ajax.Request('/', {asynchronous:true, 
 evalScripts:true, parameters:


    Form.serialize(this)}); return false;"> <input name="commit" type="submit" /> </form> index.html
  5. 15.

    <%=  observe_field(:local_estado_id,            :update  =>  "local_cidade_id",

               :url  =>  cidades_options_for_select_path,            :with  =>  "estado_id"  %> index.erb
  6. 16.

    <select  id="local_estado_id"                

       name="local[estado_id]"><!-­‐-­‐  -­‐-­‐></select>   ! <script  type="text/javascript">   //<![CDATA[      new  Form.Element.EventObserver('local_estado_id',         ! ! ! //]]>   </script> !@#$%^@!% index.html
  7. 20.

    update_page  do  |page|      page.insert_html  :bottom,  'list',    

           "<li>#{@item.name}</li>"      page.visual_effect  :highlight,   'list'   end controller/action.rb
  8. 22.

    new  Element.insert("list",            {  bottom:  "<li>Some

     item</li>"  });   new  Effect.Highlight("list"); response.js
  9. 24.

    JavaScript não deve estar no markup Código back-end não deve

    depender de biblioteca front-end. ♥ ♥
  10. 27.

    Rails 3.0 Fim das chamadas Ajax através de JavaScript inline

    e dos observers https://github.com/rails/prototype_legacy_helper
  11. 30.

    <%=  link_to  "Other  Site",  "url",         data:

     {  confirm:  "Are  you  sure?"  }  %> index.erb
  12. 35.

    Considere que o formulário também pode ser enviado sincronamente pelo

    usuário E se não executar o 
 JavaScript?
  13. 37.

    <%=  link_to  "Destroy",  "url",  
          

                   method:  :delete  %> index.erb
  14. 40.

    O usuário irá apenas ler a notícia, considere sempre utilizar

    formulários para este tipo de ação E se não executar o 
 JavaScript?
  15. 50.

    $('#photo_<%=  params[:id]  %>').remove(); destroy.js.erb photo.html <a  href="photo/2"      

       data-­‐method="delete"          data-­‐remote="true">Destroy</a>  
  16. 51.

    <%-­‐  if  @contact.errors.any?  %>      $('#contact-­‐modal').html('<%=   escape_javascript(render(partial:  'form'))

        )  %>');   <%-­‐  else  %>      $('#contact-­‐modal').html('<%=   !       !   $('#contact-­‐modal').append('<p  class="alert  
 alert-­‐success">Your  message  was  successfully  
 sent  </p>');      setTimeout("$('.close').click();",  2000);   <%-­‐  end  %> !@#$%^@!% create.js.erb
  17. 54.

    class  Counter      constructor:  (@min  =  0,  @max  =

     10e9)  -­‐>          @current  =  @min      next:  -­‐>          @current  =  Math.min(@max,  @current  +  1)      isFirst:  -­‐>          @current  <=  @min   ! class  CounterPlus  extends  Counter      goToLast:  -­‐>          @current  =  @max counter.coffee
  18. 55.

    function  Counter(min,  max)  {          this.min  =

     min  !=  null  ?  min  :  0;          this.max  =  max  !=  null  ?  max  :  10e9;          this.current  =  this.min;   }   ! Counter.prototype.next  =  function()  {          return  this.current  =  
       Math.min(this.max,  this.current  +  1)   }   ! Counter.prototype.isFirst  =  function()  {          return  this.current  <=  this.min   }   ! function  CounterPlus()  {   counter.js
  19. 56.

    ! Counter.prototype.isFirst  =  function()  {          return

     this.current  <=  this.min   }   ! function  CounterPlus()  {          Counter.apply(this,  arguments)   }   ! function  InheritCounter()  {}   InheritCounter.prototype  =  Counter.prototype   ! CounterPlus.prototype  =  new  InheritCounter()   CounterPlus.prototype.constructor  =  CounterPlus   ! CounterPlus.prototype.goToLast  =  function()  {          return  this.current  =  this.max   }
  20. 58.

    Não é por nada que o EcmaScript 6 usa o

    CoffeeScript como referência
  21. 63.

    RUBYCONF
 
 CONHEÇA OS PALESTRANTES PROMETE TRAZER NOVIDADES E ASSUNTOS

    PERTINENTES DA ÁREA Requisição Ajax pela página apontada no link
  22. 65.
  23. 66.

    A barra de endereços é atualizada e as páginas visitadas

    são armazenadas (voltar à uma página é imediato)
  24. 67.

    Assets devem ficar no <head> e precisam ser marcados para

    que modificações sejam monitoradas (e recarregada caso preciso)
  25. 71.

    Suporte para widgets do Facebook, Twitter, Google+, Google Analytics, AdSense

    e alguns mais http://reed.github.io/turbolinks-compatibility
  26. 73.

    A cada transição os events handlers e demais callbacks devem

    ser desativados para não interferir na performance
  27. 74.

    Código JavaScript pode ser executado na troca de páginas Widgets

    e add-ons funcionam de acordo depois de ajustados Memory leaks podem ser evitados ♥ ♥ ♥
  28. 75.

    O Turbolinks não permite que apenas porções da página sejam

    requisitadas (confira o jquery-pajax para isto)
  29. 76.

    Turbolinks funciona bem 
 em websites simples (como o 


    desta conferência) e forma uma 
 boa dupla com UJS
  30. 81.

    O JavaScript não possui sistema de módulos fazendo com que

    diferentes scripts compartilhem o mesmo escopo
  31. 82.

    file1.js file2.js Sem a criação de um escopo, as variáveis

    ficam expostas var  myVar  =  "bla"; alert(myVar);
  32. 83.

    (function  ()  {      var  data  =  {};  

       function  parser()  {            //  Code      }   })(); Immediately-Invoked Function Expression viabilizam a criação de escopos http://benalman.com/news/ 2010/11/immediately- invoked-function-expression
  33. 85.
  34. 86.

    App.modules.mediabox  =  (function  ()  {      var  data  =

     {};   !    return  {            data:  data,            parser:  //  ...      }   })(); Namespaces mediabox.js (namespace)
  35. 87.

    Module('modules.mediabox',  
    function  (Mediabox)  {        

     Mediabox.data  =  {};        Mediabox.parser  =  //  ...      }   ); Biblioteca de módulos do Nando Vieira http://simplesideias.com.br/ escrevendo-javascript-modular mediabox.js (Module.js)
  36. 88.

    define(      [          'jquery',  

             'util/counter'      ],      function  ($,  Counter)  {          //  ...                  return  {              Mediabox:  Mediabox,              //  ...          };      }
 ); mediabox.js (AMD) Módulos AMD que permitem indicação de dependências https://github.com/ jwhitley/requirejs-rails
  37. 89.

    Declaração de dependências Path do arquivo como identificador do módulo

    Assíncrono por natureza e adotado
 por jQuery e outras bibliotecas ♥ ♥ ♥
  38. 90.

    [...] it makes code easier to understand for others and

    yourself re-visting your own code - Chris Coyier
  39. 91.

    ES6 Modules e CommonJS Modules não possuem suporte adequado 


    ao Asset Pipeline (alguém se habilita?)
  40. 96.
  41. 99.

    main.js //  Setup  product  page   if  ($('body').is('.page-­‐product'))  {  

       $("[data-­‐draggable]").draggable()      $("[data-­‐comments]").comments()   }   ! //  Setup  checkout  page   if  ($('body').is('.page-­‐checkout'))  {      $("[data-­‐draggable]").draggable()      $("[data-­‐datepicker]").datepicker()   }
  42. 101.

    main.js //  Setup  product  page   if  ($('body').is('.page-­‐product'))  {  

       $("[data-­‐draggable]").draggable()      $("[data-­‐comments]").comments()   }   ! //  Setup  checkout  page   if  ($('body').is('.page-­‐checkout'))  {      $("[data-­‐draggable]").draggable()      $("[data-­‐datepicker]").datepicker()   }
  43. 105.

    define(function  ()  {      function  Mediabox(container)  {    

         //  ...      }      return  Mediabox;   }); Chamada do construtor
 com o container mediabox.js
  44. 108.

    Trabalhar com models que emitem eventos é trabalhoso e passível

    a erros (não entenda mal, Backbone.js) ♥
  45. 114.

    <div  ng-­‐controller="Basket">      <select  ng-­‐model="quantity"  
      

                 ng-­‐init="quantity=1">          <option>1</option><option>10</option>      </select>      <div>Valor:  R$  {{price()}}</div>   </div> index.html function  Basket($scope)  {          $scope.price  =  function  ()  {                  return  $scope.quantity  *  50;                              };   } main.js
  46. 119.

    <div  ng-­‐app="component">      <tabs>          <pane

     title="Date">              Date:  {{  '2012-­‐04-­‐01'  |  date:'fullDate'  }}          </pane>          <pane  title="Hello">              Hi!          </pane>      </tabs>   </div> Tags são mapeadas para templates e controllers
  47. 120.
  48. 121.
  49. 122.

    What’s wrong with Angular.js https://medium.com/este-js-framework/whats- wrong-with-angular-js-97b0a787f903 What I would recommend

    instead of Angular.js? https://medium.com/este-js-framework/what-i- would-recommend-instead-of-angular- js-62b057d8a9e
  50. 127.

    Estude sobre execução de código assíncrono com callbacks e promises

    https://speakerdeck.com/jcemer/controle-de- fluxo-com-execucao-assincrona 1.
  51. 128.

    Aceite que o JavaScript do front-end da sua aplicação pode

    dar tanto ou mais trabalho que o back-end 2.