Herberth Amaral

Software development adventures

Archive for the ‘JavaScript’ tag

[jQuery para apressados] Modularizando sua aplicação com Module Pattern e jQuery

without comments

O module pattern é um padrão de projetos para JavaScript que permite que você use closures autoexecutáveis para criação de “classes” com “atributos privados”.

Calma que eu explico :0)

O JavaScript não possui meios de declarar uma variável como “protected” ou “private”, como você costuma ver em linguagens como Java, C# e C++. Como uma forma de “proteger” alguns objetos de acesso externo, desenvolveu-se uma técnica chamada “module pattern”, que tem o poder de encapsular e restringir o acesso a tais objetos.

Antes de irmos para o module pattern, de uma olhada numa função autoexecutável:

(function(){
    alert('olá, mundo!');
}) ();

Interessante, não? Eu estou criando uma função e executando-a ao mesmo tempo. Note que eu posso passar um parâmetro pra ela se for necessário:

(function(nome){
    alert('Olá, '+nome+'!'); // Olá, Herberth
}) ('Herberth');

O module pattern funciona do mesmo jeito:

var CarrinhoDeCompras = (function(){
  var itens = [];  // variável "privada". Não pode ser acessada externamente

   function hasItem(item)
   {
         return jQuery.inArray(item,itens)!=-1;
   }

   function addItem(item)
   {
         if(!hasItem(item))
         {
              itens.push(item);
         }
         else
         {
              alert('Opa! O item '+item+' já está selecionado');
         }
   }

   function removeItem(item)
   {
         var position = jQuery.inArray(item,itens);
          if(hasItem(item))
         {
              delete itens[position];
         }
         else
            alert('Opa, não temos o item '+item+' no carrinho de compras')
   }
    // retorna um objeto com o que será visível pro mundo
    // note que o array itens não está incluído
    return {removeItem:removeItem,addItem:addItem};
})();

//poderíamos utilizar o código acima da seguinte forma:


CarrinhoDeCompras.addItem('Livro');
CarrinhoDeCompras.addItem('Caneca');
CarrinhoDeCompras.addItem('Livro'); //Opa, o item Livro já está adicionado

CarrinhoDeCompras.removeItem('Livro'); // remove ok
CarrinhoDeCompras.removeItem('Livro'); // Opa, não temos o item Livro no carrinho de compras

// mas não poderiámos fazer algo assim:

CarrinhoDeCompras.itens.push('Camiseta');

Neste caso, eu estou retornando um objeto contendo a referências das funções que eu declarei dentro da minha função autoexecutável. Perceba que, em hipótese alguma, eu conseguiria acessar diretamente o conteúdo/valor do array itens, pois eu não tenho uma referência dele externamente.

Isto é algo importante, por dois motivos:

  1. Se você estiver num time de desenvolvimento e desenvolver um módulo utilizando o module pattern, o desenvolvedor que pegar o seu módulo para utilizar saberá o que ele pode e o que não pode acessar.
  2. Você previne que aquele engraçadinho que sabe usar o Firebug mexa nos seus objetos em tempo de execução.

Onde o jQuery entra nesta história?

O jQuery entra principalmente na parte em que começamos a trabalhar com eventos customizados. Estes eventos customizados podem funcionar como um meio de comunicação entre os módulos da aplicação, sem que um conheça necessariamente o outro. O que é necessário que cada módulo saiba é como utilizar os eventos.

Continuando o exemplo anterior:

var CarrinhoDeCompras = (function(){
  var itens = [];  // variável "privada". Não pode ser acessada externamente
   function hasItem(item)
   {
         return jQuery.inArray(item,itens)!=-1;
   }

   function addItem(item)
   {
         if(!hasItem(item))
         {
              itens.push(item);
         }
         else
         {
              alert('Opa! O item '+item+' já está selecionado');
         }
   }

   function removeItem(item)
   {
         var position = jQuery.inArray(item,itens);
          if(hasItem(item))
         {
              delete itens[position];
         }
         else
            alert('Opa, não temos o item '+item+' no carrinho de compras')
   }


   function finalizarCompras()
   {
        // dispara o evento "finalizaCompras"
        // quem estiver "ouvindo" este evento, receberá os itens como argumento
        $(document).trigger("finalizaCompras",itens);
   }

   function init() { } // algum código de inicialização
   
    // retorna um objeto com o que será visível pro mundo
    // note que o array itens não está incluído
    return {removeItem:removeItem,addItem:addItem,init:init};
})();


var Services = (function(){
     
     function finalizarCompras(event,itens) // função "privada". Não pode ser acessada externamente
     {
          // envia os itens por AJAX e faz algum tratamento.
     }

     function init()
     {
           // "escuta" pelo evento finalizaCompras
           // quando o mesmo for disparado, a função finalizarCompras será executada
           // com os parâmetros do evento
           $(document).bind("finalizaCompras",finalizarCompras);
     }

     return {init:init};
})();


$(document).ready(function(){
     //inicializamos os módulos e colocamos os manipuladores de eventos.
     CarrinhoDeCompras.init();
     Services.init();
});

Whoa! Conseguimos desacoplar nossa aplicação utilizando eventos customizados.

Um módulo não conhece o outro, mas os mesmos se comunicam através de eventos. Note que a única coisa comum entre os módulos é o nome do evento utilizado para finalizar a compra.

Fazendo um paralelo com Programação Orientada a Objetos, os eventos seriam nossa Interface, neste caso.

Seria possível ainda, o módulo Service disparar um evento para avisar o CarrinhoDeCompras quando a transação for completada.

Interessante, não? :-)

Written by Herberth Amaral

July 22nd, 2010 at 6:58 am

[jQuery para apressados] Efeitos e animações avançadas

without comments

No post anterior, eu mostrei alguns efeitos e animações básicas que o jQuery oferece. Neste post eu vou mostrar algumas outras funcionalidades mais avançadas.

Encadeando efeitos

Os métodos de efeitos do jQuery permitem que você passe uma função de callback como argumento para serem executados assim que os efeito termine. Esta funcionalidade nos permite encadear efeitos:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('a').slideUp(1000,function() {  $(this).slideDown(1000) });
});
</script>

Você não precisa especificar o tempo de duração do evento: basta passar a função de callback para que a mesma seja executada ao final do evento. Esta estratégia funciona para os métodos $.hide, $.show, $.slideUp, $.slideDown, $.slideToggle, $.fadeIn,$.fadeOut e $.fadeToggle.

Animações customizadas com o $.animate

O jQuery faz as animações customizadas através das propriedades que você quer que ele anime, de uma duração (opcional), de uma função de animação (já pré-definida no jquery - opcional) e de um callback (também opcional) para ser executado quando a animação acabar. Um exemplo bem básico do .animate:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('a').animate({'font-size':'15px'});
});
</script>

O animate permite que você especifique a duração da animação e permite que você passe N propriedades para se animar:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('a').animate({'font-size':'15px','opacity':'0.4'},2000);
});
</script>
Como funções de 'easing', você pode utilizar as funções 'linear' e a 'swing', que são funções básicas. Alguns plugins, como o jQuery UI, permitem a animação de propriedades como a cor da fonte e outras funções de animação.O método $.animate é deveras complexo. Dê uma olhada nadocumentação oficial se você precisar de algo a mais.See ya! [inline][/inline]

Written by Herberth Amaral

July 21st, 2010 at 7:42 am

[jQuery para apressados] Efeitos e animações básicas

without comments

Apesar do jQuery ter uma enorme lista de plugins para efeitos, ele possui um framework básico de eventos que serve para 80-90% dos casos que eu vejo.

Métodos básicos

Os métodos básicos escondem e mostram elementos utilizando alguns efeitos. Dê uma olhada no método hide e no show:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('a').hover(function(){ $(this).hide(1000) })
             .mouseout(function(){ $(this).show(1000) } );
});
</script>
O que eu faço no código acima é aplicar duas funções, uma para quando o mouse estiver sobre um link (elemento 'a') e outra para quando o mouse sair de cima. Nas duas eu coloco a função hide e show com um argumento que diz pro jQuery quanto tempo que a animação deve durar.

Nota: estes métodos são "sobrecarregados". Se você não passar nenhum valor como argumento, o elemento será mostrado/escondido sem animações.

slideDown e slideUp

Esconde e mostra (respectivamente) elementos utilizando o efeito slide. O uso é simples:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('a').hover(function(){ $(this).slideUp() })
             .mouseout(function(){ $(this).slideDown() } );
});
</script>
Estes métodos também aceitam um argumento numérico que especifica a duração do evento.

fadeOut e fadeIn

Esconde e mostra (respectivamente) elementos ajustando a sua transparência até desaparecerem/aparecerem por completo. O uso é bem simples também:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
      $('a').hover(function(){ $(this).fadeOut() })
             .mouseout(function(){ $(this).fadeIn() } );
});
</script>
Assim como o slideUp e slideDown, eles também suportam um argumento numérico que especifica a duração do evento.

Os métodos toggle

O toggle é um utilitário do jQuery que lhe permite mostrar/esconder elementos sem consultar se o mesmo está visível ou não. Ou seja, ao invés de fazer algo assim:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){

      $('h1').hover(function(){
           if( $('p:visible').length == 0) //nenhum p visível
               $('p').show()
           else
               $('p').hide()
       });

});
</script>
Você pode fazer algo assim:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){

      $('h1').hover(function(){
           $('p').toggle();
       });

});
</script>
O mais interessante é que os outros métodos de efeitos possuem uma 'versão toggle': slideToggle, fadeToggle. Estes eu deixo pra você testar :DNo próximo post eu vou falar sobre callbacks de efeitos, encadeamento de efeitos e efeitos avançados. See ya![inline][/inline]

Written by Herberth Amaral

July 20th, 2010 at 7:44 am

[jQuery para apressados] – Trabalhando com eventos customizados

without comments

Eventos customizados em JavaScript podem trazer algumas possibilidades legais: imagine que você tenha uma grande aplicação em JavaScript dividida em módulos. Você pode diminuir o acoplamento entre eles utilizando eventos customizados para comunicação inter-módulos. Neste post, eu vou mostrar como você pode aproveitar as facilidades do jQuery para uso de eventos customizados

Let's pull the $.trigger

O método trigger serve para lançar eventos e toma como parâmetro o nome do evento. Por exemplo:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
    $('form input[type=submit]').trigger('click');
});
</script>
O que isto vai fazer terá o mesmo efeito de um usuário clicando em todos os botões de submit de todos os formulários do documento: basicamente, irá disparar o evento "click" para todos os botões submit dos formulários.Você pode lançar os eventos padrões do jQuery somente chamando os métodos de atalho sem argumentos, por exemplo:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
   
   // mesma coisa de $('form input[type=submit]').trigger('click');
   $('form input[type=submit]').click();
});
</script>
Você ainda pode passar argumentos customizados para a função manipuladora do evento, como neste exemplo adaptado da documentação oficial do jQuery:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
    $('button[name=executeEvent]').bind('custom', function(event, param1, param2) {
      alert(param1 + "\n" + param2);
    });

    $('button[name=executeEvent]').trigger('custom', ['Evento', 'Customizado']);
});
</script>

Neste caso, já estamos fazendo uso de um evento customizado: você pode passar qualquer string como argumento do trigger e do bind e voilà, você tem um evento customizado! Vale notar que, o jQuery não possui métodos de atalho (como o $.click()) para eventos customizados, mas nada impede que você mesmo os crie.

Nota: No exemplo do botão acima, eu tive que colocar um bind para o evento click e dentro do evento click eu disparo o evento 'custom'. Isso não afeta o comportamento do evento customizado, apenas fiz assim para poder demonstrar melhor.

No próximo post farei uma introdução ao module pattern e mostrarei como você pode desacoplar sua aplicação JavaScript usando custom events. Até mais![inline][/inline]

Written by Herberth Amaral

July 19th, 2010 at 6:15 am

[jQuery para apressados] Tratamento básico de eventos

with 2 comments

Um evento é uma ação que geralmente é iniciada fora do escopo de um programa e que é manipulado por uma parte do códigod dentro do programa [Wikipedia]. Um evento pode ser o clique do usuário de um botão, o pressionar de uma tecla do teclado ou uma resposta de uma requisição do servidor.Dê uma olhada como você pode manipular um clique a um botão:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function()
{
     $('#enviarDados').click(function()
     {
           alert('Enviando dados...');
     });
});

</script>
O que você basicamente faz aí em cima é dizer pro jQuery: execute esta função que eu estou passando como argumento do método click quando o(s) elemento(s) que atendem ao seletor #enviarDados for clicado.Naturalmente, você pode separar um pouco mais as coisas:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

enviarDados = function()
{
    alert('Enviando dados');
}

$(document).ready(function()
{
     $('#enviarDados').click(enviarDados);
});

</script>
Além do click, o jQuery tem muitos outros métodos para tratamento de evento. Dentre eles se destacam:
  • hover - quando o mouse for passado sobre o elemento
  • blur - quando o elemento perder o foco
  • focus - quando o elemento de formulário ou link ganhar foco
  • change - quando um elemento de formulário for mudado
  • mousedown - quando clicarem (sem necessariamente "soltar" o mouse) sobre o elemento
  • mouseup - quando "soltarem" o mouse depois de clicado no elemento
  • E muitos outros

Usando o bind

Todos os métodos acima descritos são métodos "atalho" e todos eles utilizam o método bind para mapear eventos. Ele possui uma argumento extra que eu gosto de utilizar de vez em quando: a passagem de dados para o tratador do evento. Exemplo:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

enviarDados = function(event)
{
    var dados = event.data;
    alert('Enviando dados. Dados enviados:'+dados);
}

$(document).ready(function()
{
     $('#enviarDados').bind('click','Dado que vai para a função que trata o evento',enviarDados);
});

</script>
De vez em quando, precisamos remover tratadores de eventos de alguns elementos. Isso é feito com o método unbind:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

enviarDados = function(event)
{
    var dados = event.data;
    alert('Enviando dados. Dados enviados:'+dados);
    $(this).unbind('click');
}

$(document).ready(function()
{
     $('#enviarDados').bind('click','Dado que vai para a função que trata o evento',enviarDados);
});

</script>
Note a palavra chave this na função que trata o evento: neste contexto, ela simboliza o elemento que sofreu o evento (no nosso caso, o elemento que contém o id="enviarDados")O que eu fiz acima foi remover o tratamento do evento 'click' para o elemento que foi clicado. Neste caso, o tratamento deste evento irá acontecer somente uma vez. Se eu chamasse o método unbind sem nenhum argumento, eu removeria todos os eventos atrelados a ele:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

enviarDados = function(event)
{
    var dados = event.data;
    alert('Enviando dados. Dados enviados:'+dados);
    $(this).unbind(); //remove todos os eventos
}

$(document).ready(function()
{
     $('#enviarDados').bind('click','Dado que vai para a função que trata o evento',enviarDados);
});

</script>
Você ainda pode remover somente uma das funções que tratam um determinado evento. Suponhamos que você, por qualquer motivo, tenha mais de uma função tratando o mesmo evento no mesmo elemento e quer remover somente uma função: há um terceiro argumento no unbind que permite remover somente uma função:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
enviarDados = function(event)
{
    var dados = event.data;
    alert('Enviando dados. Dados enviados:'+dados);
    $(this).unbind('click',enviarDados); // remove o tratamento do evento click pela função
                                                    // enviarDados
}

$(document).ready(function()
{
     $('#enviarDados').bind('click','Dado que vai para a função que trata o evento',enviarDados);
});

</script>
Legal, né? :DAmanhã falarei sobre tratamento avançado de eventos e eventos customizados. See ya!

Written by Herberth Amaral

July 16th, 2010 at 6:45 am

[jQuery para apressados] – Entendendo seletores

with 2 comments

Uma das especialidades do jQuery é selecionar um conjunto de elementos e aplicar algum dos seu métodos sobre eles. "Seletores" são formas de você selecionar um ou mais elementos dentro do seu documento HTML com o intuito de aplicar algum método do jQuery sobre ele. Por exemplo:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function)
{
    $('a').hide(); //seleciona todos os links e os esconde
});
</script>
O código acima é fictício, mas seve para ilustrar. No jQuery, 90% (ou mais) do que você faz o tempo inteiro é selecionar um elemento e fazer alguma coisa com ele.Os seletores do jQuery são bem poderosos. Dê uma olhada nestes exemplos:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function)
{
    $('table a').hide(); //seleciona todos os links dentro de tabelas e os esconde
   
    $('input[name=email]').val(''); //seleciona todos os inputs que tenham a
                                             //propriedade name=email e apaga seus respectivos conteúdos
   
    $('#content').show(); //seleciona o elemento com o id content e o exibe
    $('div.item').remove(); //seleciona todas as divs que possuem a classe item e as remove
    $('.item').remove(); //seleciona todos os elementos com a classe item e os remove
   
    $('.item:first').slideUp(); //seleciona o primeiro elemento com a classe
                                      //item e aplica uma animação para faze-lo desaparecer
   
    $('div:eq(5) a.marcado[rel^=bookmark]').slideDown(); // seleciona todos os links
                     // em que o atributo rel que comecem com bookmark e que tenham
                     // a classe marcado e que estejam dentro da quinta div dentro do
                     //documento e aplica uma animação para o(s) link(s) aparecer(em)
});
</script>
Como mostrado acima, você pode selecionar elementos pela sua tag, classe, id, propriedade e posição. Achou poderoso? Espere só até ver a documentação oficial de todos os seletores do jQuery! :D

Live example! Teste aqui mesmo alguns seletores!

$.slideUp();

[inline][/inline]

Written by Herberth Amaral

July 15th, 2010 at 8:11 am