Javascript
Princípios da linguagem e utilização de
              frameworks
Separação de
componentes
Unobtrusive
       Javascript
Separar a aplicação em três componentes
lógicos:
Unobtrusive
       Javascript
Separar a aplicação em três componentes
lógicos:

  Conteúdo (HTML)
Unobtrusive
       Javascript
Separar a aplicação em três componentes
lógicos:

  Conteúdo (HTML)

  Apresentação (CSS)
Unobtrusive
       Javascript
Separar a aplicação em três componentes
lógicos:

  Conteúdo (HTML)

  Apresentação (CSS)

  Comportamento (Javascript)
Como fazer isto?
Exemplo prático



<a href=”javascript:open(‘image.jpg’);” ...
Exemplo prático



                 A I L
                F
<a href=”javascript:open(‘image.jpg’);” ...
Exemplo prático



<a href=”#” onclick=”open(‘image.jpg’);” ...
Exemplo prático



                A I L
               F
<a href=”#” onclick=”open(‘image.jpg’);” ...
Exemplo prático


<a href=”image.jpg”
onclick=”open(‘image.jpg’); return false;” ...
Exemplo prático



                 A I L
                F
<a href=”image.jpg”
onclick=”open(‘image.jpg’); return false;” ...
Exemplo prático



<a href=”image.jpg” class=”lightbox” ...
Exemplo prático
Num ficheiro .js incluído na página...




 var links = document.getElementsByClassName(‘lightbox’);

 for (var i=0, len=links.length; i<len; i++) {

         links[i].addEventListener(‘click’, function(evt){

               open(this.href);

               evt.preventDefault();

         });

 }
Exemplo prático


                                      !
                                           var links =




                                   I N
                                           document.getElementsByClassName(‘lightbox’);


                                           for (var i=0, len=links.length; i<len; i++) {




                                 W
<a href=”image.jpg” class=”lightbox” ...
                                           links[i].addEventListener(‘click’, function(evt){


                                                    open(this.href);


                                                    evt.preventDefault


                                           });


                                           }
Na verdade...
Exemplo prático


                                         L
                                             var links =




                                       I
                                             document.getElementsByClassName(‘lig
                                             htbox’);




                                    FA
                                             for (var i=0, len=links.length; i<len; i+
                                             +) {
<a href=”image.jpg” class=”lightbox” ...
                                             links[i].addEventListener(‘click’,
                                             function(){


                                                      open(this.href);


                                             });


                                             }
Inconsistências nos
    browsers...
I can haz jQuery?




Frameworks to the
    rescue!
jQuery

$(document).ready(function(){
    $(‘a.lightbox’).click(function(){
        open(this.href);
    });
});



                                        http://jquery.com
Prototype.js

document.observe ( 'dom:loaded', function () {

     $$('a.prototype').each (function (el) {

     
     Event.observe (el, 'click', function () {

     
     
     open(this.href);

     
     });

     });
});




                                                        http://prototypejs.org
Frameworks

Abstraem métodos nativos do Javascript

Lidam com inconsistências em browsers

Aumentam as funcionalidades nativas da
linguagem
jQuery
Porquê?

Uma das frameworks mais populares na
actualidade

Facilmente extensível (plugins!)

Extremamente fácil de aprender
var jQuery


jQuery (ou $) é a função principal.

Este objecto global incorpora todas as
propriedades e métodos disponíveis na
framework
var jQuery


Quando utilizada como função, selecciona
elementos do DOM.

Utilizando uma sintaxe muito semelhante a
CSS
var jQuery

var el1 = $(“#um”);
// Retorna o elemento com o id #um


var el2 = $(‘ul.menu li a’);
// Retorna um array com todos os elementos a dentro de li que
estejam dentro do ul com a classe “menu”
var jQuery


Os elementos seleccionados herdam métodos e
propriedades da framework.

O jQuery permite “chaining”
var jQuery
$(“#um”).show().css({background: “red”, color: “white”});


$(“#um”).addClass(‘disappearing’).fadeOut(‘fast’);


$(“#um”).click(function(){
      $(this).text(‘mudei o meu texto!’).addClass(‘awesome’);
});
var jQuery


Quero usar jQuery com outra framework!!

Mas essa framework também utiliza $() como
função principal...
var jQuery


Utilizar jQuery.noConflict();

jQuery(‘#myElement’) ...
var jQuery


var $j = jQuery.noConflict();

$j(‘#myElement’) ...
Cuidados a ter?
Conhecer a
       linguagem!
Modelo de eventos
Conhecer a
        linguagem!
Modelo de eventos

Scope
Conhecer a
        linguagem!
Modelo de eventos

Scope

Closures
Conhecer a
        linguagem!
Modelo de eventos

Scope

Closures

Herança Prototipal
Modelo de
 Eventos
Event Capturing
            Elemento 1




     Elemento 2




           http://www.quirksmode.org/js/events_order.html
Event Bubbling
           Elemento 1




    Elemento 2




          http://www.quirksmode.org/js/events_order.html
Cancelar bubbling

function doSomething(e) {
    if (!e) var e = window.event;


    if (e.stopPropagation) {
        e.stopPropagation();
    } else {
        e.cancelBubble = true;
    }
}
Scope
O que é?

Define onde as variáveis e funções se
encontram acessíveis.

Uma variável ou função pode ter scope local
ou global

Num browser, a scope global refere-se ao
objecto window.
Scope Global


var coisa = “uma coisa”;

function ola() {

     return alert(“olá!”);

}
Scope local

function ola() {

     var msg = “Olá!”;

     return alert(msg);

}

alert(msg); // Retorna erro, variável “msg” não definida
A keyword “this”



Refere-se sempre ao owner da função
A keyword “this”


function ola() {

     // this == window

}
A keyword “this”

function ola() {

     ...

}

element.onclick = ola; // na função “ola”, this == element

element.addEventListener(‘click’, ola) // mesma coisa!
A keyword “this”

function ola() {

     ...

}

<element onclick=”ola();” />

// Função é apenas uma referência,

// this == window (!)
Closures
O que são?


Funções dentro de funções que utilizem
variáveis da sua função exterior criam closures
WTF?!?
Exemplo prático!
function ola(nome) {

     var texto = “Olá ” + nome, //var local

     alerta = function() { alert(texto); }

     return alerta;

}

var umAlerta = ola(“Bruno”);

umAlerta(); // Mostra “Olá Bruno!”
Outro exemplo
function addLinks () {

    for (var i=0, link; i<5; i++) {

    
    link = document.createElement("a");

    
    link.innerHTML = "Link " + i;

    
    link.onclick = function () {

    
    
    alert(i);

    
    };

    
    document.body.appendChild(link);

    }
}
window.onload = addLinks;
Outro exemplo
function addLinks () {

    for (var i=0, link; i<5; i++) {




                                   L

    
    link = document.createElement("a");




                               A I

    
    link.innerHTML = "Link " + i;




                              F

    
    link.onclick = function () {

    
    
    alert(i);

    
    };

    
    document.body.appendChild(link);

    }
}
window.onload = addLinks;
Outro exemplo
function addLinks () {


     for (var i=0, link; i<5; i++) {


     
    link = document.createElement("a");


     
    link.innerHTML = "Link " + i;


     
    link.onclick = function (i) {


     
    
       return function(){


     
    
       
   alert(i);


     
    
       }


     
    }(i);


     
    document.body.appendChild(link);


     }

}

window.onload = addLinks;
Problema!
var msg = ‘xpto153’;

$(‘a#awesomeLink’).click(function(){   #awesomeLink

      alert(msg);

});

msg = ‘zyvr62’;

$(‘a#otherLink’).click(function(){      #otherLink

      alert(msg);

});
Problema!
var msg = ‘xpto153’;        zyvr62
$(‘a#awesomeLink’).click(function(){   #awesomeLink

      alert(msg);

});

msg = ‘zyvr62’;
                            zyvr62
$(‘a#otherLink’).click(function(){      #otherLink

      alert(msg);

});
WTF?!?
Problema!

A variável “msg” utilizada na closure é uma
referência.

Quando o seu valor muda durante a execução
da função pai, a referência é actualizada em
todas as closures onde existe.
Solução!
var msg = ‘xpto153’;

$(‘a#awesomeLink’).click(function(){

      var correctMsg = msg;

      alert(correctMsg);

});

msg = ‘zyvr62’;

$(‘a#otherLink’).click(function(){

      var correctMsg = msg;

      alert(correctMsg);

});
Solução!
var msg = ‘xpto153’;
                           xpto153
$(‘a#awesomeLink’).click(function(){
                                       #awesomeLink
      var correctMsg = msg;

      alert(msg);

});                         zyvr62
msg = ‘zyvr62’;
                                        #otherLink
$(‘a#otherLink’).click(function(){

      var correctMsg = msg;

      alert(msg);

});
Herança
Prototipal
O que é?


Modelo de herança de objectos

Todos os objectos de Javascript herdam
propriedades do tipo abstracto Object
Como utilizar?


Object.prototype.myFunction = function() {

     // Do something

}
Exemplo prático!

Object.prototype.toString = function () {


     var message = '';


     for (var prop in this) {


     
    message += 'property ' + prop + ' equals: ' + this[prop] + '.';


     }


     return message;

}
Exemplo prático!
var myObj = {

      a: “valor1”,

      b: “valor2”

};



alert(myObj);

// Mostra:

// “property a equals valor1. property b equals valor2.”
Herança prototipal


Mais informação?

http://javascript.crockford.com/
prototypal.html
The End!
Bruno Abrantes      http://brunoabrantes.com   http:/twitter.com/inf0rmer

Javascript - Princípios da linguagem e utilização de frameworks

Notas do Editor

  • #10 Link n&amp;#xE3;o tem um href v&amp;#xE1;lido Search Engines n&amp;#xE3;o seguem o link Link n&amp;#xE3;o funciona sem Javascript
  • #11 Melhor... Utiliza um event handler para executar JS href continua sem levar a lado nenhum!
  • #12 Melhor... Utiliza um event handler para executar JS href continua sem levar a lado nenhum!
  • #13 Ainda Melhor... Utilizadores sem JS conseguem ver a imagem return false impede o browser de seguir o link
  • #14 Mas JS inline n&amp;#xE3;o &amp;#xE9; grande ideia. Dif&amp;#xED;cil de manter
  • #19 Microsoft utiliza modelo de eventos propriet&amp;#xE1;rio Existem preocupa&amp;#xE7;&amp;#xF5;es cross-browser getElementsByClassName n&amp;#xE3;o tem implementa&amp;#xE7;&amp;#xE3;o nativa em muitos browsers
  • #30 Chaining acontece quando um m&amp;#xE9;todo ou propriedade retorna de novo o elemento original, para que este possa invocar novos m&amp;#xE9;todos ou aceder a novas propriedades
  • #33 noConflict() liberta o controlo da vari&amp;#xE1;vel $
  • #34 para n&amp;#xE3;o ter de escrever sempre jQuery() podemos atribuir o noConflict a outra var
  • #36 Uma framework n&amp;#xE3;o &amp;#xE9; um substituto para o JS Apesar de serem f&amp;#xE1;ceis de utilizar, uma fraca compreens&amp;#xE3;o da linguagem pode tornar a sua utiliza&amp;#xE7;&amp;#xE3;o um inferno!
  • #37 Uma framework n&amp;#xE3;o &amp;#xE9; um substituto para o JS Apesar de serem f&amp;#xE1;ceis de utilizar, uma fraca compreens&amp;#xE3;o da linguagem pode tornar a sua utiliza&amp;#xE7;&amp;#xE3;o um inferno!
  • #38 Uma framework n&amp;#xE3;o &amp;#xE9; um substituto para o JS Apesar de serem f&amp;#xE1;ceis de utilizar, uma fraca compreens&amp;#xE3;o da linguagem pode tornar a sua utiliza&amp;#xE7;&amp;#xE3;o um inferno!
  • #39 Uma framework n&amp;#xE3;o &amp;#xE9; um substituto para o JS Apesar de serem f&amp;#xE1;ceis de utilizar, uma fraca compreens&amp;#xE3;o da linguagem pode tornar a sua utiliza&amp;#xE7;&amp;#xE3;o um inferno!
  • #46 A vari&amp;#xE1;vel e fun&amp;#xE7;&amp;#xE3;o ficam afectas ao objecto window.
  • #47 A var msg est&amp;#xE1; dentro o scope da fun&amp;#xE7;&amp;#xE3;o, ou seja, s&amp;#xF3; existe dentro do Activation Object da fun&amp;#xE7;&amp;#xE3;o, e &amp;#xE9; destru&amp;#xED;da quando a fun&amp;#xE7;&amp;#xE3;o &amp;#xE9; interpretada.
  • #49 O owner da fun&amp;#xE7;&amp;#xE3;o &amp;#xE9; o objecto global
  • #50 O registo de eventos tradicional copia a fun&amp;#xE7;&amp;#xE3;o para o m&amp;#xE9;todo onclick do objecto &amp;#x201C;element&amp;#x201D;, e portanto o this refere-se agora ao elemento
  • #51 Fun&amp;#xE7;&amp;#xE3;o &amp;#xE9; passada por refer&amp;#xEA;ncia e portanto &amp;#xE9; executada no seu contexto original
  • #55 Ao contr&amp;#xE1;rio do que acontece normalmente, &amp;#xE9; mantida viva uma refer&amp;#xEA;ncia &amp;#xE0; var &amp;#x201C;texto&amp;#x201D; a fun&amp;#xE7;&amp;#xE3;o &amp;#x201C;alerta&amp;#x201D; cria uma closure lembra-se do &amp;#xFA;ltimo valor da var &amp;#x201C;texto&amp;#x201D;
  • #57 Ao clicar nos diferentes links, todos mostram a mensagem &amp;#x201C;5&amp;#x201D; A vari&amp;#xE1;vel
  • #58 Dentro da fun&amp;#xE7;&amp;#xE3;o onclick &amp;#xE9; criada uma closure A fun&amp;#xE7;&amp;#xE3;o passada ao evento &amp;#x201C;onclick&amp;#x201D; &amp;#xE9; auto-executada na altura da atribui&amp;#xE7;&amp;#xE3;o e passa como argumento o valor de &amp;#x201C;i&amp;#x201D; naquele momento do loop
  • #63 A vari&amp;#xE1;vel correctMsg s&amp;#xF3; existe na scope da fun&amp;#xE7;&amp;#xE3;o em closure. No momento da sua declara&amp;#xE7;&amp;#xE3;o, o valor de &amp;#x201C;msg&amp;#x201D; &amp;#xE9; copiado para &amp;#x201C;correctMsg&amp;#x201D;
  • #67 Como todos os objectos herdam m&amp;#xE9;todos do objecto abstracto &amp;#x201C;Object&amp;#x201D;, a fun&amp;#xE7;&amp;#xE3;o &amp;#x201C;myFunction&amp;#x201D; passa a estar imediatamente dispon&amp;#xED;vel em todos os objectos criados.
  • #68 &amp;#xC9; tamb&amp;#xE9;m poss&amp;#xED;vel redefinir fun&amp;#xE7;&amp;#xF5;es. Neste caso estamos a melhorar a fun&amp;#xE7;&amp;#xE3;o nativa toString para mostrar nomes de propriedades de um objecto e seus valores
  • #69 &amp;#xC9; tamb&amp;#xE9;m poss&amp;#xED;vel redefinir fun&amp;#xE7;&amp;#xF5;es. Neste caso estamos a melhorar a fun&amp;#xE7;&amp;#xE3;o nativa toString para mostrar nomes de propriedades de um objecto e seus valores
  • #71 D&amp;#xFA;vidas?