Vous êtes sur la page 1sur 110

Fundamentos de jQuery (jQuery Fundamentals)

Rebecca Murphey [http://www.rebeccamurphey.com]

Fundamentos de jQuery (jQuery Fundamentals)


Rebecca Murphey [http://www.rebeccamurphey.com] Herberth Amaral (traduo e reviso), Elvis Luciano Guimares (traduo e reviso), Diego Guimares (traduo), Diego Caxito (traduo), Luciana Balieiro (reviso), Washington Botelho (reviso), Giovani Generali (reviso) Copyright 2010
Licensed by Rebecca Murphey under the Creative Commons Attribution-Share Alike 3.0 United States license [http://creativecommons.org/licenses/ by-sa/3.0/us/]. You are free to copy, distribute, transmit, and remix this work, provided you attribute the work to Rebecca Murphey as the original author and reference the GitHub repository for the work [http://github.com/rmurphey/jqfundamentals]. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. Any of the above conditions can be waived if you get permission from the copyright holder. For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to the license [http://creativecommons.org/licenses/by-sa/3.0/us/].

ndice
1. Bem vindo ..................................................................................................................... 1 Obtendo o cdigo ....................................................................................................... 1 Software ................................................................................................................... 1 Adicionando JavaScript sua pgina ............................................................................. 1 Debugando JavaScript ................................................................................................. 2 Exerccios ................................................................................................................. 2 Convenes usadas neste livro. ..................................................................................... 2 Material de referncia ................................................................................................. 3 I. JavaScript 101 ................................................................................................................ 4 2. O Bsico de JavaScript ............................................................................................ 5 Introduo ......................................................................................................... 5 O Bsico de sintaxe ............................................................................................ 5 Operadores ........................................................................................................ 5 Operadores Bsicos ..................................................................................... 5 Operaes sobre nmeros & Strings ............................................................... 6 Operadores lgicos ..................................................................................... 6 Operadores de comparao ........................................................................... 7 Cdigo condicional ............................................................................................. 7 Coisas Verdadeiras e Falsas ......................................................................... 8 Associao Condicional de Variveis Com o Operador Ternrio .......................... 9 Declarao Switch ...................................................................................... 9 Laos .............................................................................................................. 10 O lao for ................................................................................................ 10 O lao while ............................................................................................ 11 O lao do-while ........................................................................................ 11 Parando e continuando ............................................................................... 12 Palavras Reservadas .......................................................................................... 12 Arrays ............................................................................................................. 14 Objetos ........................................................................................................... 15 Funes ........................................................................................................... 16 Usando funes ........................................................................................ 16 Funes annimas autoexecutveis ............................................................... 17 Funes como argumento ........................................................................... 17 Testando Tipo .................................................................................................. 18 Escopo ............................................................................................................ 18 Closures .......................................................................................................... 20 II. jQuery: Conceitos bsicos .............................................................................................. 22 3. O bsico de jQuery ............................................................................................... 23 $(document).ready() .......................................................................................... 23 Selecionando elementos ..................................................................................... 23 Minha seleo contm algum elemento? ........................................................ 25 Salvando selees ..................................................................................... 25 Refinando & Filtrando Selees .................................................................. 26 Seletores relacionados formulrios ............................................................. 26 Trabalhando com selees .................................................................................. 27 Encadeamento .......................................................................................... 27 Getters & Setters ...................................................................................... 28 CSS, Styling, & Dimenses ................................................................................ 28 Usando classes do CSS para estilos .............................................................. 28 Dimenses ............................................................................................... 29 Atributos ......................................................................................................... 29

iii

Fundamentos de jQuery (jQuery Fundamentals) Travessia ......................................................................................................... Manipulando elementos ..................................................................................... Obtendo e Definindo informaes sobre elementos .......................................... Movendo, copiando e removendo elementos. ................................................. Criando novos elementos ........................................................................... Manipulando atributos ............................................................................... Exerccios ........................................................................................................ Selecionando ............................................................................................ Atravessamento ........................................................................................ Manipulando ............................................................................................ Ncleo do jQuery .................................................................................................. $ vs $() ........................................................................................................ Mtodos Utilitrios ........................................................................................... Verificando tipos .............................................................................................. Mtodos de Dados ............................................................................................ Deteco de Navegador & Funcionalidades ........................................................... Evitando Conflitos com Outras Bibliotecas ............................................................ Eventos ............................................................................................................... Introduo ....................................................................................................... Conectando Eventos a Elementos ........................................................................ Conectando Eventos para Executar Apenas uma vez ........................................ Desconectando Eventos .............................................................................. Usando Namespaces com Eventos ............................................................... Por Dentro da Funo Manipuladora de Evento ...................................................... Disparando Eventos ........................................................................................... Aumentando a Performance com Delegao de Evento ............................................ Desvinculando Eventos Delegados ............................................................... Auxiliares de Eventos ........................................................................................ $.fn.hover .......................................................................................... $.fn.toggle ........................................................................................ Exerccios ........................................................................................................ Criando uma dica de Input ......................................................................... Adicionando navegao por abas ................................................................. Efeitos ................................................................................................................. Viso Geral ..................................................................................................... Efeitos Embutidos ............................................................................................. Mudando a Durao de Efeitos Embutidos .................................................... Fazendo algo quando um Efeito tiver Terminado ............................................ Efeitos customizados com $.fn.animate .......................................................... Easing ..................................................................................................... Controlando efeitos ........................................................................................... Exerccios ........................................................................................................ Mostrando texto oculto .............................................................................. Criando menus dropdown ........................................................................... Crie um slideshow .................................................................................... Ajax .................................................................................................................... Introduo ....................................................................................................... Conceitos Chave ............................................................................................... GET vs. POST ......................................................................................... Tipos de dados ......................................................................................... A de assncrono ..................................................................................... Regra da mesma origem e JSONP ............................................................... Ajax e o Firebug ...................................................................................... Mtodos do jQuery relacionados ao Ajax .............................................................. 30 30 31 31 33 34 34 34 35 35 36 36 36 37 38 39 39 40 40 40 40 41 41 41 42 42 43 43 43 44 44 44 44 46 46 46 46 47 47 48 48 49 49 49 49 50 50 50 50 50 51 51 51 52

4.

5.

6.

7.

iv

Fundamentos de jQuery (jQuery Fundamentals) $.ajax ...................................................................................................... Mtodos de convenincia ........................................................................... $.fn.load ............................................................................................ Ajax e formulrios ............................................................................................ Trabalhando com JSONP ................................................................................... Eventos do Ajax ............................................................................................... Exerccios ........................................................................................................ Carregar contedo externo .......................................................................... Carregando contedo usando JSON .............................................................. 8. Plugins ................................................................................................................ O que exatamente um plugin? .......................................................................... Como criar um plugin bsico .............................................................................. Procurando & Avaliando Plugins ......................................................................... Escrevendo Plugins ........................................................................................... Escrevendo plugins com estado utilizando a fbrica de widgets do jQuery UI ............... Adicionando mtodos a um Widget .............................................................. Trabalhando com Opes de Widget ............................................................ Adicionando Callbacks .............................................................................. Limpando ................................................................................................ Concluso ................................................................................................ Exerccios ........................................................................................................ Fazendo uma tabela ordenvel ..................................................................... Escreva um plugin para listrar tabelas ........................................................... III. Tpicos Avanados ...................................................................................................... Esta seo um trabalho em andamento ....................................................................... 9. Melhores prticas para performance .......................................................................... Armazene o length em loops .............................................................................. Adicione novo contedo fora de um loop .............................................................. Mantenha as coisas DRY ................................................................................... Cuidado com funes annimas .......................................................................... Otimize seletores .............................................................................................. Seletores baseados em ID ........................................................................... Especificidade .......................................................................................... Evite o seletor universal ............................................................................. Use Delegao de Evento ................................................................................... Desanexe elementos para trabalhar com eles .......................................................... Use folhas de estilo para mudar o CSS em vrios elementos ..................................... Use $.data ao invs de $.fn.data ................................................................ No faa nada quando no tiver elementos ............................................................ Definio de Varivel ........................................................................................ Condicionais .................................................................................................... No trate o jQuery como uma Caixa Preta ............................................................. 10. Organizao de cdigo ......................................................................................... Viso Geral ..................................................................................................... Conceitos Chave ....................................................................................... Encapsulamento ................................................................................................ O literal objeto ......................................................................................... O Module Pattern ..................................................................................... Gerenciando dependncias .................................................................................. Obtendo o RequireJS ................................................................................. Utilizando o RequireJS com jQuery ............................................................. Criando mdulos reusveis com RequireJS .................................................... Otimizando seu cdigo: A ferramenta de build do RequireJS ............................. Exerccios ........................................................................................................ 52 54 55 56 56 57 57 57 58 59 59 59 61 61 64 65 67 68 70 70 71 71 71 72 73 74 74 74 74 75 76 76 76 76 77 77 77 78 78 78 79 79 80 80 80 80 80 84 87 87 87 88 90 91

Fundamentos de jQuery (jQuery Fundamentals) Crie um mdulo Portlet ............................................................................. 11. Eventos Customizados .......................................................................................... Introduo Eventos Customizados ..................................................................... Uma aplicao de amostra .......................................................................... 91 92 92 94

vi

Lista de Exemplos
1.1. Um exemplo de JavaScript inline .................................................................................... 1 1.2. Um exemplo de incluso de JavaScript externo .................................................................. 1 1.3. Exemplo de um exemplo ............................................................................................... 3 2.1. Uma simples declarao de varivel ................................................................................ 5 2.2. Espaos em branco no interferem fora das aspas. .............................................................. 5 2.3. Parnteses indicam precedncia ....................................................................................... 5 2.4. Tabulao melhora a leitura, mas no tem significado especial .............................................. 5 2.5. Concatenao ............................................................................................................... 5 2.6. Multiplicao e diviso .................................................................................................. 5 2.7. Incrementando e decrementando ..................................................................................... 6 2.8. Adio vs. Concatenao ............................................................................................... 6 2.9. Forando uma string atuar como um nmero ..................................................................... 6 2.10. Forando uma string a atuar como um nmero (usando o operador unrio de adio) ................ 6 2.11. Os operadores lgicos AND e OR ................................................................................. 6 2.12. Operadores de comparao ........................................................................................... 7 2.13. Controle de fluxo ........................................................................................................ 8 2.14. Valores que so avaliados como true ........................................................................... 8 2.15. Valores que so avaliados como false ......................................................................... 8 2.16. O operador ternrio ..................................................................................................... 9 2.17. Uma declarao switch ................................................................................................ 9 2.18. Laos ...................................................................................................................... 10 2.19. Um lao for tpico .................................................................................................. 11 2.20. Um lao while tpico ............................................................................................... 11 2.21. Um lao while com uma condio e incremento combinado ............................................ 11 2.22. Um lao do-while ................................................................................................. 12 2.23. Parando um lao ....................................................................................................... 12 2.24. Pulando para a prxima iterao de um loop .................................................................. 12 2.25. Um array simples ...................................................................................................... 14 2.26. Acessando os itens do array pelo ndice ........................................................................ 15 2.27. Testando o tamanho de um array ................................................................................. 15 2.28. Mudando o valor de um item do array .......................................................................... 15 2.29. Adicionando elementos em um array ............................................................................ 15 2.30. Trabalhando com arrays ............................................................................................. 15 2.31. Criando um "literal objeto" ......................................................................................... 15 2.32. Declarao de Funo ................................................................................................ 16 2.33. Expresso de Funo Nomeada .................................................................................... 16 2.34. Uma funo simples .................................................................................................. 16 2.35. Uma funo que retorna um valor ................................................................................ 16 2.36. Uma funo que retorna outra funo ........................................................................... 17 2.37. Uma funo annima auto-executvel ........................................................................... 17 2.38. Passando uma funo annima como argumento ............................................................. 17 2.39. Passando uma funo nomeada como argumento ............................................................ 17 2.40. Testando o tipo de vrias variveis ............................................................................... 18 2.41. Funes tem acesso a variveis definidas num mesmo escopo ............................................ 19 2.42. Cdigo fora do escopo em que uma varivel foi definida no tem acesso varivel. ............... 19 2.43. Variveis com o mesmo nome podem existir em escopos diferentes com valores diferentes. 19 ..... 2.44. Funes podem "ver" mudanas em valores de variveis depois que a funo definida .......... 20 2.45. Insanidade do Escopo ................................................................................................ 20 2.46. Como bloquear no valor de i? .................................................................................... 21 2.47. Bloqueando no valor de i com uma closure ................................................................... 21 3.1. Um bloco $(document).ready() ...................................................................................... 23

vii

Fundamentos de jQuery (jQuery Fundamentals) 3.2. Atalho para $(document).ready() ................................................................................... 3.3. Passando uma funo nomeada ao invs de uma annima ................................................... 3.4. Selecionando elementos por ID ..................................................................................... 3.5. Selecionando elementos pelo nome da classe ................................................................... 3.6. Selecionando elementos por atributo .............................................................................. 3.7. Selecionando elementos atravs da composio de seletores CSS ......................................... 3.8. Pseudo-seletores ......................................................................................................... 3.9. Testando se uma seleo contm elementos. .................................................................... 3.10. Armazenando selees em variveis ............................................................................. 3.11. Refinando selees .................................................................................................... 3.12. Usando pseudo-seletores relacionados formulrios ........................................................ 3.13. Encadeamento .......................................................................................................... 3.14. Formatando cdigo encadeado ..................................................................................... 3.15. Restaurando sua seleo original usando $.fn.end ....................................................... 3.16. O mtodo $.fn.html usado como setter .................................................................... 3.17. O mtodo html usado como getter ................................................................................ 3.18. Pegando propriedades CSS ......................................................................................... 3.19. Setando propriedades CSS .......................................................................................... 3.20. Trabalhando com classes ............................................................................................ 3.21. Mtodos bsicos de dimenses .................................................................................... 3.22. Definindo atributos .................................................................................................... 3.23. Obtendo atributos ...................................................................................................... 3.24. Movendo pelo DOM usando mtodos de travessia. .......................................................... 3.25. Iterando sobre uma seleo ......................................................................................... 3.26. Mudando o HTML de um elemento. ............................................................................. 3.27. Movendo elementos usando outras formas ..................................................................... 3.28. Fazendo uma cpia de um elemento ............................................................................. 3.29. Criando novos elementos ............................................................................................ 3.30. Criando um novo elemento com um objeto atributo ......................................................... 3.31. Inserindo um novo elemento na pgina ......................................................................... 3.32. Criando e adicionando um elemento pgina ao mesmo tempo .......................................... 3.33. Manipulando um nico atributo ................................................................................... 3.34. Manipulando mltiplos atributos .................................................................................. 3.35. Usando uma funo para determinar um novo valor de atributo .......................................... 4.1. Verificando o tipo de um valor arbitrrio ........................................................................ 4.2. Armazenando e recuperando dados relacionados a um elemento .......................................... 4.3. Armazenando um relacionamento entre elementos usando $.fn.data ................................ 4.4. Colocando jQuery em modo no-conflict .......................................................................... 4.5. Usando o $ dentro de uma funo annima auto-executada ................................................. 5.1. Vinculando Eventos Usando um Mtodo de Convenincia .................................................. 5.2. Vinculando eventos usando o mtodo $.fn.bind .......................................................... 5.3. Vinculando eventos usando o mtodo $.fn.bind com dados ........................................... 5.4. Trocando manipuladores usando o mtodo $.fn.one ...................................................... 5.5. Desconectando todos os manipuladores de clique em uma seleo ........................................ 5.6. Desconectando um manipulador de clique especfico ......................................................... 5.7. Usando Namespaces com eventos .................................................................................. 5.8. Impedindo um link de ser seguindo ................................................................................ 5.9. Disparando um evento do jeito certo .............................................................................. 5.10. Delegao de Evento usando $.fn.delegate ............................................................ 5.11. Delegao de Evento usando $.fn.live .................................................................... 5.12. Desvinculando eventos delegados ................................................................................. 5.13. A funo auxiliar hover ............................................................................................. 5.14. A funo auxiliar toggle ............................................................................................. 6.1. Um uso bsico de um efeito embutido ............................................................................ 23 23 23 23 24 24 24 25 26 26 27 27 27 27 28 28 28 28 29 29 29 30 30 30 31 32 32 33 33 33 33 34 34 34 38 38 38 39 39 40 40 40 41 41 41 41 42 42 43 43 43 44 44 46

viii

Fundamentos de jQuery (jQuery Fundamentals) 6.2. Configurando a durao de um efeito ............................................................................. 6.3. Acrescentando definies de velocidade customizadas ao jQuery.fx.speeds ................... 6.4. Executando cdigo quando uma animao tiver completado ................................................ 6.5. Executa uma callback mesmo se no houver elementos para animar ..................................... 6.6. Efeitos customizados com $.fn.animate .................................................................... 6.7. Easing por propriedade ................................................................................................ 7.1. Usando o mtodo core $.ajax ........................................................................................ 7.2. Usando os mtodos de convenincia do jQuery ................................................................ 7.3. Usando o $.fn.load para popular um elemento ............................................................ 7.4. Usando o $.fn.load para popular um elemento baseado no seletor ................................... 7.5. Transformando os dados de um formulrio em uma string de requisio ................................ 7.6. Criando um array de objetos contendo dados do formulrio. ............................................... 7.7. Usando YQL e JSONP ................................................................................................ 7.8. Configurando um indicador de carregamento usando eventos do Ajax ................................... 8.1. Criando um plugin para adicionar e remover uma classe no hover ........................................ 8.2. O Padro de Desenvolvimento de Plugins do Mike Alsup ................................................... 8.3. Um plugin simples, stateful utilizando a fbrica de widgets do jQuery UI. ............................. 8.4. Passando opes para um Widget .................................................................................. 8.5. Setando opes padro para um Widget .......................................................................... 8.6. Criando mtodos para um Widget .................................................................................. 8.7. Chamando mtodos numa instncia do plugin .................................................................. 8.8. Respondendo quando a opo setada ........................................................................... 8.9. Provendo callbacks para extenso do usurio ................................................................... 8.10. Vinculando eventos do Widget .................................................................................. 8.11. Adicionando um mtodo destroy um Widget ............................................................... 10.1. Um literal objeto ....................................................................................................... 10.2. Usando um literal de objeto numa funcionalidade do jQuery ............................................. 10.3. O module pattern ...................................................................................................... 10.4. Usando o module patterns numa funcionalidade do jQuery ................................................ 10.5. Utilizando o RequireJS: Um exemplo simples ................................................................ 10.6. Um simples arquivo JavaScript com dependncias .......................................................... 10.7. Definindo um mdulo do RequireJS que no tem dependncias ......................................... 10.8. Definindo um mdulo do RequireJS com dependncias .................................................... 10.9. Definindo um mdulo do RequireJS que retorna uma funo ............................................. 10.10. Um arquivo de configurao de build do RequireJS ....................................................... 46 47 47 47 48 48 53 55 56 56 56 56 57 57 62 63 64 65 65 66 67 67 68 69 70 81 83 84 86 87 88 89 89 89 90

ix

Captulo 1. Bem vindo


jQuery est se tornando rapidamente uma habilidade fundamental para desenvolvedores de interface. O objetivo deste livro prover uma viso geral do jQuery, uma biblioteca para JavaScript; quando voc terminar com este livro, voc dever conseguir completar tarefas bsicas usando jQuery, e conseguir uma base slida se continuar estudando. Este livro foi feito para servir de material para ser usado em sala de aula, mas pode servir para estudo individual. Esta uma aula prtica. Ns vamos usar um pouco de tempo para cobrir conceitos, e ento voc ter a chance de trabalhar num exerccio relacionado ao conceito. Alguns dos exerccios podem parecer triviais; outros podem ser assustadores. Em ambos os casos, no h problema; o objetivo simplesmente fazer voc ficar confortvel com problemas comuns que voc ir resolver no uso do jQuery. As solues de exemplo para todos os exerccios esto inclusos no cdigo de amostra.

Obtendo o cdigo
O cdigo que iremos usar neste livro est num repositrio do Github [http://github.com/rmurphey/ jqfundamentals]. Voc pode baixar um arquivo .zip ou .tar contendo o cdigo e ento descompact-lo para usar no seu servidor. Se voc souber usar o git, voc ser bem vindo para clonar ou 'forkar' o repositrio.

Software
Voc precisar das seguintes ferramentas para aproveitar as aulas ao mximo: O navegador Firefox A extenso Firebug para o Firefox Um editor de textos Para as partes com Ajax: um servidor local (como o MAMP ou WAMP), ou um cliente FTP ou SSH para acessar um servidor remoto.

Adicionando JavaScript sua pgina


JavaScript pode ser includo inline ou incluindo um arquivo externo atravs de uma tag script. A ordem em que voc inclui o JavaScript muito importante: as dependncias precisam ser includas antes do script que depende dela. Para o bem da performance da pgina, o JavaScript deve ser colocado o mais prximo possvel do fim do seu HTML. Mltiplos arquivos JavaScript devem ser combinados para uso em produo.

Exemplo 1.1. Um exemplo de JavaScript inline


<script> console.log('olah'); </script>

Exemplo 1.2. Um exemplo de incluso de JavaScript externo


<script src='/js/jquery.js'></script>

Bem vindo

Debugando JavaScript
Uma ferramenta de debugging essencial para desenvolvimento em JavaScript. O Firefox prov um debugger atravs da extenso Firebug; Chrome e Safari possuem consoles embutidos. Cada console oferece: Editores para testar JavaScript. Um inspetor para analisar o cdigo gerado da sua pgina Um visualizador de rede ou recursos, para examinar as requisies de rede Quando voc estiver escrevendo cdigo em JavaScript, voc pode usar os seguintes mtodos para enviar mensagens ao console: console.log() para enviar mensagens de log console.dir() para registrar um objeto navegvel no log console.warn() para registrar avisos (warnings) no log console.error() para registrar mensagens de erro no log Outros mtodos para console esto disponveis, apesar deles terem uma diferena em cada navegador. Os consoles tambm tem a habilidade de setar breakpoints e observar expresses no seu cdigo para propsitos de debug.

Exerccios
A maioria dos captulos no livro so concludos com um ou mais exerccios. Para alguns exerccios, voc poder trabalhar diretamente no Firebug; para outros, voc precisar incluir outros scripts depois da tag de script do jQuery nos exerccios individuais. Em alguns casos, voc precisar consultar a documentao do jQuery para concluir um exerccio, pois, por praticidade, no cobriremos todas as informaes que so relevantes no livro. O jQuery uma biblioteca grande, e aprender a encontrar respostas na documentao uma parte importante no processo. Aqui vo algumas sugestes para combater estes problemas: Primeiro, tenha certeza que voc entende completamente o problema que voc ir pedir por soluo. Depois, descubra quais elementos voc precisar acessar para conseguir resolver o problema e determine como voc ir conseguir estes elementos. Use o Firebug para verificar se voc est obtendo os elementos que est procurando. Por ltimo, descrubra o que voc precisa fazer com os elementos para resolver o problema. Pode ser til escrever comentrios explicando o que voc ir fazer antes de tentar escrever cdigo. No tenha medo de errar! No tente fazer seu cdigo ficar perfeito de incio! Errar e experimentar solues parte do aprendizado da biblioteca, e voc ser um melhor desenvolvedor com isso. Exemplos de solues para estes exerccios esto localizados no dir /solutions no cdigo de exemplo.

Convenes usadas neste livro.


Mtodos que podem ser chamados em objetos jQuery sero referenciados como $.fn.methodName. Mtodos que existem no namespace do jQuery mas no podem ser chamados em objetos jQuery sero

Bem vindo

referidos como $.methodName. Se no fizer muito sentido para voc, no se preocupe - ficar mais claro medida que voc avanar no livro.

Exemplo 1.3. Exemplo de um exemplo


// exemplos de cdigo sero parecidos com isto Comentrios iro aparecer assim.

Nota
Notas sob um tpico ir aparecer assim.

Material de referncia
H muitos artigos e posts de blog por a que falam de alguma forma de jQuery. Alguns so fenomenais; outros so certamente errados. Quando voc ler um artigo sobre jQuery, tenha certeza que est falando sobre a mesma verso que voc est usando e resista tentao de somente copiar e colar - leve um tempo para entender o cdigo no artigo. Aqui vo alguns excelentes recursos para usar durante seu aprendizado em jQuery. O mais importante de todos o cdigo fonte do jQuery: ele contm, em forma de cdigo, a documentao completa da biblioteca. No uma caixa preta - seu conhecimento sobre a biblioteca crescer exponencialmente se voc gastar um tempo visitando-o agora e novamente - e eu recomendo fortemente que voc favorite-o no seu navegador e visite-o com frequncia. O cdigo fonte do jQuery [http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js] A documentao do jQuery [http://api.jquery.com] O frum do jQuery [http://forum.jquery.com/] Favoritos no Delicious [http://delicious.com/rdmey/jquery-class] Canal IRC #jquery na Freenode [http://docs.jquery.com/Discussion#Chat_.2F_IRC_Channel]

Parte I. JavaScript 101

Captulo 2. O Bsico de JavaScript


Introduo
jQuery construdo sobre JavaScript, uma linguagem rica e expressiva por si s. Esta sesso cobre os conceitos bsicos de JavaScript, assim como algumas pegadinhas que aparecem com freqncia para pessoas que ainda no usaram JavaScript. Por enquanto, para pessoas sem experincia em programao, at mesmo para aquelas que j programam em outras linguagens, podem se beneficiar ao aprender um pouco sobre algumas particularidades de JavaScript. Se voc est interessado em aprender mais sobre a linguagem JavaScript, eu recomento fortemente o livro JavaScript: The Good Parts do Douglas Crockford.

O Bsico de sintaxe
Entendendo declaraes, nomes de variveis, espao, e outras sintaxes bsicas do JavaScript.

Exemplo 2.1. Uma simples declarao de varivel


var foo = 'ola mundo';

Exemplo 2.2. Espaos em branco no interferem fora das aspas.


var foo = 'ol mundo';

Exemplo 2.3. Parnteses indicam precedncia


2 * 3 + 5; 2 * (3 + 5); // retorna 11; multiplicao acontece antes // retorna 16; adio acontece primeiro

Exemplo 2.4. Tabulao melhora a leitura, mas no tem significado especial


var foo = function() { console.log('ol'); };

Operadores
Operadores Bsicos
Operadores bsicos permitem que voc manipule valores.

Exemplo 2.5. Concatenao


var foo = 'ol'; var bar = 'mundo'; console.log(foo + ' ' + bar); // 'ol mundo'

Exemplo 2.6. Multiplicao e diviso


2 * 3; 2 / 3;

O Bsico de JavaScript

Exemplo 2.7. Incrementando e decrementando


var i = 1; var j = ++i; var k = i++; // pr-incremento: j igual a 2; i igual a 2 // ps-incremento: k igual a 2; i igual a 3

Operaes sobre nmeros & Strings


Em JavaScript, nmeros e strings ocasionalmente iro se comportar de formas inesperadas.

Exemplo 2.8. Adio vs. Concatenao


var foo = 1; var bar = '2'; console.log(foo + bar); // 12. uh oh

Exemplo 2.9. Forando uma string atuar como um nmero


var foo = 1; var bar = '2'; // converte string para numero console.log(foo + Number(bar)); O construtor Number, quando chamado como funo (como no exemplo acima), ter o efeito de mudar seu argumento para um nmero. Voc pode tambm usar o operador unrio de adio, que faz a mesma coisa:

Exemplo 2.10. Forando uma string a atuar como um nmero (usando o operador unrio de adio)
console.log(foo + +bar);

Operadores lgicos
Operadores lgicos permitem que voc teste uma srie de operadores usando as operaes lgicas AND e OR.

Exemplo 2.11. Os operadores lgicos AND e OR


var foo = 1; var bar = 0; var baz = 2; foo || bar; bar || foo; foo && bar; foo && baz; baz && foo; // retorna 1, que verdadeiro // retorna 1, que verdadeiro // retorna 0, que falso // retorna 2, que verdadeiro // retorna 1, que verdadeiro

O Bsico de JavaScript

Apesar de no estar claro pelo exemplo, o operador || retorna o valor do primeiro operador verdadeiro, ou, em casos em que nenhum operador seja verdadeiro, ele ir retornar o ltimo dos operandos. O operador && retorna o valor do primeiro operando falso, ou o valor do ltimo operador se ambos operadores forem verdadeiros. Tenha certeza de consultar Coisas Verdadeiras e Falsas para maiores detalhes sobre quais valores so avaliados como true e quais so avaliados como false.

Nota
Algumas vezes, voc ver alguns desenvolvedores usando estes operadores lgicos para controle de fluxo ao invs de utilizar o if. Por exemplo: // faz alguma coisa com foo se foo for verdadeiro foo && doSomething(foo); // seta bar para baz se baz verdadeiro; // seno for verdadeiro, seta-o para retornar // o valor de createBar() var bar = baz || createBar(); Este estilo elegante e agradevelmente curto; por isso, pode ser difcil ler, especialmente por iniciantes. Eu o mostro aqui para que voc possa reconhec-lo no cdigo que voc l, mas eu no recomendo o uso at que voc esteja extremamente confortvel com o que isto significa e como voc espera que se comporte.

Operadores de comparao
Operadores de comparao permite testar quando valores so equivalentes ou quando so idnticos.

Exemplo 2.12. Operadores de comparao


var var var var foo bar baz bim = = = = 1; 0; '1'; 2; // retorna false // retorna true // retorna true; cuidado! // retorna false // retorna true // retorna true

foo == bar; foo != bar; foo == baz;

foo === baz; foo !== baz; foo === parseInt(baz); foo > bim; bim > baz; foo <= baz;

// retorna false // retorna true // retorna true

Cdigo condicional
Algumas vezes voc s ir querer executar um bloco de cdigo sob certas condies. Controle de fluxo atravs dos blocos if e else - permite que voc execute uma parte do cdigo em certas condies.

O Bsico de JavaScript

Exemplo 2.13. Controle de fluxo


var foo = true; var bar = false; if (bar) { // este cdigo nunca ser executado console.log('hello!'); } if (bar) { // este cdigo no ir executar } else { if (foo) { // este cdigo ir executar } else { // este cdigo poder ser executado se foo e bar forem ambos falsos. } }

Nota
As chaves no so estritamente necessrias quando voc tem blocos if com uma s linha, porm, se forem usados consistentemente, mesmo que no sejam estritamente requeridos, eles podem fazer seu cdigo ficar mais legvel. Esteja atento para no definir funes com o mesmo nome vrias vezes dentro de blocos de cdigo if/ else, seno pode haver resultados inesperados.

Coisas Verdadeiras e Falsas


De forma a usar o controle de fluxo com sucesso, importante entender quais tipos de valores so "verdadeiros" e quais tipos de valores so "falsos". Algumas vezes, valores que parecem ser avaliados de uma forma, so avaliados de outra.

Exemplo 2.14. Valores que so avaliados como true


'0'; 'qualquer string'; []; // um array vazio {}; // um objeto vazio 1; // qualquer nmero diferente de zero

Exemplo 2.15. Valores que so avaliados como false


0; ''; // uma string vazia NaN; // Varivel "not-a-number" do JavaScript null; undefined; // seja cuidadoso -- undefined pode ser redefinido!

O Bsico de JavaScript

Associao Condicional de Variveis Com o Operador Ternrio


Algumas vezes voc precisar colocar um valor numa varivel dependendo de uma condio. Voc poderia usar uma declarao if/else, mas em muitos casos, o operador ternrio mais conveniente. [Definition: O operador ternrio testa uma condio; se a condio for verdadeira, ele retorna um valor correto, seno retorna um valor diferente.]

Exemplo 2.16. O operador ternrio


// seta foo pra 1 se bar for verdadeiro; // seno, seta foo para 0 var foo = bar ? 1 : 0; Enquanto o operador ternrio pode ser usado sem associao do valor de retorno para uma varivel, isto geralmente desencorajado.

Declarao Switch
Ao invs de usar uma srie de blocos if/else if/else, algumas vezes pode ser til usar a declarao switch. [Definition: Declaraes Switch olham o valor da varivel ou expresso e executa blocos de cdigo diferentes dependendo do valor.]

Exemplo 2.17. Uma declarao switch


switch (foo) { case 'bar': alert('o valor bar -- yay!'); break; case 'baz': alert('boo baz :('); break; default: alert('todo o resto est ok'); break; } As declaraes Switch de alguma forma favorecem o JavaScript, pois frequentemente o mesmo comportamento pode ser obtido atravs da criao de um objeto que tem um maior potencial para reuso, teste, etc. Por exemplo: var stuffToDo = { 'bar' : function() { alert('o valor bar -- yay!'); }, 'baz' : function() { alert('boo baz :(');

O Bsico de JavaScript

}, 'default' : function() { alert('todo o resto est ok'); } }; if (stuffToDo[foo]) { stuffToDo[foo](); } else { stuffToDo['default'](); } Ns daremos uma olhada mais profunda em objetos mais a frente neste captulo.

Laos
Laos permitem que voc execute um bloco de cdigo por um certo nmero de vezes.

Exemplo 2.18. Laos


// loga 'tentativa 0', 'tentativa 1', ..., 'tentativa 4' for (var i=0; i<5; i++) { console.log('tentativa ' + i); } Note que em Exemplo 2.18, Laos mesmo que usemos a palavra chave var antes do nome da varivel i, o escopo da varivel i no alterado para o bloco do lao. Ns iremos discutir sobre escopo com mais profundidade mais a frente neste captulo.

O lao for
O lao for constitudo de quatro declaraes e possui a seguinte estrutura: for ([inicializao]; [condio]; [incremento]) [corpoDoLao] A declarao inicializao executada somente uma vez, antes do loop iniciar. Ela lhe d uma oportunidade de preparar ou declarar qualquer varivel. A declarao condio executada antes de cada iterao, e o seu valor de retorno decide se o loop continua ou no. Se a declarao condicional for interpretada como um valor falso, o lao para de ser executado. A declarao incremento executada no fim de cada iterao e lhe d a oportunidade de mudar o estado de variveis importantes. Tipicamente, isso ir envolver o incremento ou decremento de um contador e assim fazer com que o loop sempre chegue ao seu fim. A declarao corpoDoLao o que executado em cada iterao. Ele pode conter o que voc quiser. Tipicamente, voc ter mltiplas declaraes que precisam ser executadas e portanto voc ir coloc-las dentro de um bloco de cdigo ({...}). Este um uso tpico para o lao for:

10

O Bsico de JavaScript

Exemplo 2.19. Um lao for tpico


for (var i = 0, limit = 100; i < limit; i++) { // Este bloco ser executado 100 vezes console.log('Estou em ' + i); // Nota: o ltimo log ser: "Estou em 99" }

O lao while
O lao while similar a uma declao if, exceto que seu corpo continuar executando at que a condio seja interpretada como falso. while ([condio]) [corpoDoLao] Este um lao while tpico:

Exemplo 2.20. Um lao while tpico


var i = 0; while (i < 100) { // Este bloco ser executado 100 vezes console.log('Estou em ' + i); i++; // incrementa i } Voc ir perceber que ns temos que incrementar o contador dentro do corpo do lao. possvel combinar o incremento e a condio, desse jeito:

Exemplo 2.21. Um lao while com uma condio e incremento combinado


var i = -1; while (++i < 100) { // Este bloco ser executado 100 vezes console.log('Estou em ' + i); } Perceba que ns estamos iniciando em -1 e usando o incremento prefixo (++i).

O lao do-while
quase a mesma coisa do lao while, exceto pelo fato que o corpo do lao executado pelo menos uma vez antes da condio ser testada. do [corpoDoLao] while ([condio]) Este um exemplo de cdigo com do-while:

11

O Bsico de JavaScript

Exemplo 2.22. Um lao do-while


do { // Mesmo que a condio seja interpretada como false // este corpo do lao ainda ser executado uma vez alert('Ol!'); } while (false); Estes tipos de laos so relativamente raros, pois poucas situaes requerem um lao que execute cegamente um bloco de cdigo ao menos uma vez. Independentemente, bom ficar sabendo disso.

Parando e continuando
Geralmente, um loop termina porque a declarao condicional no interpretada como verdadeira, mas possvel parar um lao dentro do corpo do mesmo utilizando a declarao break.

Exemplo 2.23. Parando um lao


for (var i = 0; i < 10; i++) { if (algumaCoisa) { break; } } Voc tambm pode desejar continuar o lao sem executar o resto do seu corpo. Isso feito usando a declarao continue.

Exemplo 2.24. Pulando para a prxima iterao de um loop


for (var i = 0; i < 10; i++) { if (algumaCoisa) { continue; } // A declarao seguinte somente ser executada se // a condio 'algumaCoisa' for falsa console.log('Cheguei at aqui'); }

Palavras Reservadas
JavaScript possui um nmero de palavras reservadas, ou palavras que tm significado especial na linguagem. Voc deve evitar usar estas palavras em seu cdigo, exceto quando voc as usar com seu significado desejado. break case

12

O Bsico de JavaScript

catch continue default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with abstract boolean byte char class const debugger

13

O Bsico de JavaScript

double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile

Arrays
Arrays so listas de valores indexadas por zero. Eles so uma forma til de armazenar um conjunto de itens relacionados do mesmo tipo (como strings), apesar que na realidade, um array pode incluir mltiplos tipos de itens, incluindo outros arrays.

Exemplo 2.25. Um array simples


var meuArray = [ 'Ol', 'Mundo' ];

14

O Bsico de JavaScript

Exemplo 2.26. Acessando os itens do array pelo ndice


var meuArray = [ 'ola', 'mundo', 'foo', 'bar' ]; console.log(meuArray[3]); // loga 'bar'

Exemplo 2.27. Testando o tamanho de um array


var meuArray = [ 'ol', 'mundo' ]; console.log(meuArray.length); // loga 2

Exemplo 2.28. Mudando o valor de um item do array


var meuArray = [ 'ol', 'mundo' ]; meuArray[1] = 'mudado'; Enquanto possvel mudar o valor de um item do array como mostrado no Exemplo 2.28, Mudando o valor de um item do array, geralmente no recomendado.

Exemplo 2.29. Adicionando elementos em um array


var meuArray = [ 'ol', 'mundo' ]; meuArray.push('novo');

Exemplo 2.30. Trabalhando com arrays


var meuArray = [ 'h', 'e', 'l', 'l', 'o' ]; var minhaString = meuArray.join(''); // 'hello' var meuSplit = minhaString.split(''); // [ 'h', 'e', 'l', 'l', 'o' ]

Objetos
Objetos contm um ou mais pares chave-valor. A poro chave pode ser qualquer string. A poro valor pode ser qualquer tipo de valor: um nmero, uma string, um array, uma funo ou at um outro objeto. [Definition: Quando um desses valores uma funo, chamado de mtodo do objeto.] Seno, elas so chamadas de propriedades. Na prtica, quase tudo em JavaScript um objeto arrays, funes nmeros e at strings - e todos eles possuem propriedades e mtodos.

Exemplo 2.31. Criando um "literal objeto"


var myObject = { sayHello : function() { console.log('ol'); }, myName : 'Rebecca' }; myObject.sayHello(); console.log(myObject.myName); // loga 'ol' // loga 'Rebecca'

15

O Bsico de JavaScript

Nota
Ao criar literais objeto, voc deve notar que a poro chave de cada par chave-valor pode ser escrito como qualquer identificador vlido em JavaScript, uma string (entre aspas) ou um nmero: var myObject = { validIdentifier: 123, 'some string': 456, 99999: 789 }; Literais objeto podem ser extremamente teis para organizao de cdigo; para mais informaes leia Using Objects to Organize Your Code [http://blog.rebeccamurphey.com/2009/10/15/using-objects-toorganize-your-code/] de Rebecca Murphey.

Funes
Funes contm blocos de cdigo que precisam ser executados repetidamente. As funes podem ter zero ou mais argumentos, e podem opcionalmente retornar um valor. Funes podem ser criadas em uma srie de formas:

Exemplo 2.32. Declarao de Funo


function foo() { /* faz alguma coisa */ }

Exemplo 2.33. Expresso de Funo Nomeada


var foo = function() { /* faz alguma coisa */ } Eu prefiro a expresso de funo nomeada para definir o nome da funo por algumas questes tcnicas [http://yura.thinkweb2.com/named-function-expressions/]. Voc provavelmente ver ambos os mtodos usados em cdigo JavaScript de outros.

Usando funes
Exemplo 2.34. Uma funo simples
var greet = function(person, greeting) { var text = greeting + ', ' + person; console.log(text); };

greet('Rebecca', 'Ol');

Exemplo 2.35. Uma funo que retorna um valor


var greet = function(person, greeting) { var text = greeting + ', ' + person; return text; }; console.log(greet('Rebecca','Ol'));

16

O Bsico de JavaScript

Exemplo 2.36. Uma funo que retorna outra funo


var greet = function(person, greeting) { var text = greeting + ', ' + person; return function() { console.log(text); }; };

var greeting = greet('Rebecca', 'Ol'); greeting();

Funes annimas autoexecutveis


Um padro comum em JavaScript a funo annima autoexecutvel. Este padro cria uma funo e a executa imediatamente. Este padro extremamente til para casos onde voc quer evitar poluir o namespace global com seu cdigo -- nenhuma varivel declarada dentro da funo visvel fora dele.

Exemplo 2.37. Uma funo annima auto-executvel


(function(){ var foo = 'Ol mundo'; })();

console.log(foo);

// undefined!

Funes como argumento


Em JavaScript, funes so "cidados de primeira classe" -- eles podem ser atribudos a variveis ou passados para outras funes como argumentos. Passar funes como argumento um idioma extremamente comum em jQuery.

Exemplo 2.38. Passando uma funo annima como argumento


var myFn = function(fn) { var result = fn(); console.log(result); }; myFn(function() { return 'ol mundo'; }); // loga 'ol mundo'

Exemplo 2.39. Passando uma funo nomeada como argumento


var myFn = function(fn) { var result = fn(); console.log(result); }; var myOtherFn = function() { return 'ol mundo'; }; myFn(myOtherFn); // loga 'ol mundo'

17

O Bsico de JavaScript

Testando Tipo
JavaScript oferece um meio de testar o "tipo" de uma varivel. Entretanto, o resultado pode ser confuso -- por exemplo, o tipo de um Array "objeto". uma prtica comum usar o operador typeof ao tentar determinar o tipo de um valor especfico.

Exemplo 2.40. Testando o tipo de vrias variveis


var myFunction = function() { console.log('ol'); }; var myObject = { foo : 'bar' }; var myArray = [ 'a', 'b', 'c' ]; var myString = 'ol'; var myNumber = 3; typeof typeof typeof typeof typeof myFunction; myObject; myArray; myString; myNumber; // // // // // retorna retorna retorna retorna retorna 'function' 'object' 'object' -- cuidado! 'string'; 'number'

typeof null;

// retorna 'object' -- cuidado!

if (myArray.push && myArray.slice && myArray.join) { // provavelmente um array // (isso chamado de "duck typing") } if (Object.prototype.toString.call(myArray) === '[object Array]') { // Definitivamente um array! // Isso largamente considerado como a forma mais robusta para // determinar se um valor especfico um Array. } O jQuery oferece mtodos utilitrios para ajudar voc determinar o tipo de um valor arbitrrio. Estes mtodos sero mostrados depois.

Escopo
"Escopo" refere-se a variveis que esto disponveis em um pedao do cdigo em um determinado tempo. A falta de entendimento de escopo pode levar a experincias de debugging frustrantes. Quando uma varivel declarada dentro de uma funo usando a palavra chave var, ela a nica disponvel para o cdigo dentro daquela funo -- cdigo fora desta funo no podem acessar a varivel. Por outro lado, funes definidas dentro daquela funo ter acesso varivel declarada.

18

O Bsico de JavaScript

Alm disso, variveis que so declaradas dentro de uma funo sem o cdigo var no so locais para a funo -- JavaScript ir atravessar a cadeia do escopo para indicar onde a varivel foi definida anteriormente. Se a varivel no foi previamente definida, ela ser definida no escopo global, onde podem acontecer consequencias extremamente inesperadas;

Exemplo 2.41. Funes tem acesso a variveis definidas num mesmo escopo
var foo = 'ol'; var sayHello = function() { console.log(foo); }; sayHello(); console.log(foo); // loga 'ol' // tambm loga 'ol'

Exemplo 2.42. Cdigo fora do escopo em que uma varivel foi definida no tem acesso varivel.
var sayHello = function() { var foo = 'ol'; console.log(foo); }; sayHello(); console.log(foo); // loga 'ol' // no loga nada

Exemplo 2.43. Variveis com o mesmo nome podem existir em escopos diferentes com valores diferentes.
var foo = 'mundo'; var sayHello = function() { var foo = 'ol'; console.log(foo); }; sayHello(); console.log(foo); // loga 'ol' // loga 'mundo'

19

O Bsico de JavaScript

Exemplo 2.44. Funes podem "ver" mudanas em valores de variveis depois que a funo definida
var myFunction = function() { var foo = 'ol'; var myFn = function() { console.log(foo); }; foo = 'mundo'; return myFn; }; var f = myFunction(); f(); // loga 'mundo' -- uh oh

Exemplo 2.45. Insanidade do Escopo


// uma funo annima auto-executvel (function() { var baz = 1; var bim = function() { alert(baz); }; bar = function() { alert(baz); }; })(); console.log(baz); bar(); // // // // // // baz no definido fora da funo fora da funo annima foi declarada com var; alm disso, definida no mesmo escopo de baz, a baz mesmo que outro cdigo fora dela

bar definida porque ela no porque ela foi ela tem acesso no tenha

bim();

// bim no est definido fora da funo annima, // ento isto ir resultar em um erro

Closures
Closures so uma extenso do conceito de escopo funes tm acesso a variveis que esto disponveis no escopo onde a funo foi criada. Se isso confuso, no se preocupe: closures so geralmente entendidas melhor atravs de um exemplo. No Exemplo 2.44, Funes podem "ver" mudanas em valores de variveis depois que a funo definida ns vimos como as funes tm acesso para modificar valores de variveis. O mesmo tipo de comportamento existe com funes definidas dentro de laos -- a funo "v" a mudana no valor da varivel mesmo depois que a funo foi definida, resultando em todos os cliques alertando 5.

20

O Bsico de JavaScript

Exemplo 2.46. Como bloquear no valor de i?


/* isso no se comportar como ns quisermos; */ /* todo clique ir alertar 5 */ for (var i=0; i<5; i++) { $('<p>click me</p>').appendTo('body').click(function() { alert(i); }); }

Exemplo 2.47. Bloqueando no valor de i com uma closure


/* conserto: fecha o valor de i dentro de createFuncion, ento ela no ir mudar var createFunction = function(i) { return function() { alert(i); }; }; for (var i=0; i<5; i++) { $('p').appendTo('body').click(createFunction(i)); }

21

Parte II. jQuery: Conceitos bsicos

Captulo 3. O bsico de jQuery


$(document).ready()
Voc no pode manipular a pgina com segurana at o documento estar "pronto" (ready). O jQuery detecta o estado de prontido para voc; o cdigo incluido dentro de $(document).ready() somente ir rodar depois que a pgina estiver pronta executar o cdigo JavaScript.

Exemplo 3.1. Um bloco $(document).ready()


$(document).ready(function() { console.log('pronto!'); }); H um atalho para $(document).ready() que voc ver algumas vezes; entretando, eu no recomendo us-lo se voc estiver escrevendo cdigo que pessoas que no tm experincia com jQuery poder ver.

Exemplo 3.2. Atalho para $(document).ready()


$(function() { console.log('pronto!'); }); Voc ainda pode passar uma funo nomeada para $(document).ready() ao invs de passar uma funo annima.

Exemplo 3.3. Passando uma funo nomeada ao invs de uma annima


function readyFn() { // cdigo para executar quando o documento estiver pronto }

$(document).ready(readyFn);

Selecionando elementos
O conceito mais bsico do jQuery "selecionar alguns elementos e fazer alguma coisa com eles." O jQuery suporta a maioria dos seletores CSS3, assim como alguns seletores no-padro. Para uma referncia completa de seletores, visite http://api.jquery.com/category/selectors/. A seguir, alguns exemplos de tcnicas comuns de seleo.

Exemplo 3.4. Selecionando elementos por ID


$('#myId'); // lembre-se que os IDs devem ser nicos por pgina

Exemplo 3.5. Selecionando elementos pelo nome da classe

$('div.myClass'); // h um aumento de performance se voc especificar o tipo de ele

23

O bsico de jQuery

Exemplo 3.6. Selecionando elementos por atributo


$('input[name=first_name]'); // cuidado, isto pode ser muito lento

Exemplo 3.7. Selecionando elementos atravs da composio de seletores CSS


$('#contents ul.people li');

Exemplo 3.8. Pseudo-seletores


$('a.external:first'); $('tr:odd'); $('#myForm :input'); // selecione todos os elementos input num formulrio $('div:visible'); $('div:gt(2)'); // todos exceto as trs primeiras divs $('div:animated'); // todas as divs com animao

Nota
Quando voc usa os pseudos-seletores :visible e :hidden, o jQuery testa a visibilidade atual do elemento, no os atributos visibility ou display do CSS - ou seja, ele olha se a altura e a largura fsica do elemento na pgina so ambas maiores que zero. No entanto, este teste no funciona com elementos <tr>; neste caso, o jQuery faz a verificao da propriedade display do CSS, e considera um elemento como oculto se sua propriedade display for none. Elementos que no forem adicionados no DOM sero sempre considerados ocultos, mesmo que o CSS que os afetam torn-los visveis. (Consulte a seo de Manipulao mais adiante neste captulo para aprender como criar e adicionar elementos ao DOM). Para referncia, aqui est o cdigo que jQuery usa para determinar se um elemento visvel ou oculto, com os comentrios adicionados para maior esclarecimento: jQuery.expr.filters.hidden = function( elem ) { var width = elem.offsetWidth, height = elem.offsetHeight, skip = elem.nodeName.toLowerCase() === "tr"; // o elemento tem 0 de altura e 0 de largura e no uma <tr>? return width === 0 && height === 0 && !skip ? // ento deve estar escondido true : // mas se o elemento tiver largura e altura e no for uma <tr> width > 0 && height > 0 && !skip ? // ento deve estar visvel false : // se chamos aqui, o elemento tem largura // e altura, mas tambm uma <tr>, // ento verifica a propriedade display para // decidir se ele est escondido jQuery.curCSS(elem, "display") === "none"; };

24

O bsico de jQuery

jQuery.expr.filters.visible = function( elem ) { return !jQuery.expr.filters.hidden( elem ); };

Escolhendo seletores Escolher bons seletores uma forma de melhorar a performance do seu JavaScript. Uma pequena especificidade - por exemplo, incluir um elemento como div quando selecionar elementos pelo nome da classe - pode ir por um longo caminho. Geralmente, sempre que voc puder dar ao jQuery alguma dica sobre onde ele pode esperar encontrar o que voc estiver procurando, voc deve dar. Por outro lado, muita especificidade pode no ser muito bom. Um seletor como #myTable thead tr th.special um desperdcio se um seletor como #myTable th.special lhe dar o que voc precisa. O jQuery oferece muitos seletores baseados em atributo, permitindo que voc selecione elementos baseados no contedo de atributos arbitrrios usando expresses regulares simplificadas. // encontre todos elementos <a>s em que o atributo // rel termine com "thinger" $("a[rel$='thinger']"); Se por um lado estes seletores podem ser bem teis, eles tambm podem ser extremamente lerdos - Uma vez eu escrevi um seletor baseado em atributos que travou minha pgina por mltiplos segundos. Sempre que possvel, faa suas selees usando IDs, nomes de classe e nomes de tags. Quer saber mais? Paul Irish tem uma excelente apresentao sobre melhorar a performance do JavaScript [http://paulirish.com/perf], com vrios slides focando especificamente em performace de seletores.

Minha seleo contm algum elemento?


Uma vez que voc fez uma seleo, voc ir querer saber se h algo para trabalhar com ela. Voc talvez se sinta tentado a fazer algo assim: if ($('div.foo')) { ... } Isso no ir funcionar. Quando voc faz uma seleo usando $(), um objeto sempre retornado, e objetos sempre so tratados como true. Mesmo se sua seleo no tiver nenhum elemento, o cdigo dentro do if vai executar do mesmo jeito. Ao invs disso, voc precisa testar a propriedade length da seleo, que diz a voc quantos elementos foram selecionados. Se a resposta for 0, a propriedade length ser interpretada como falso quando usada como um valor booleano.

Exemplo 3.9. Testando se uma seleo contm elementos.


if ($('div.foo').length) { ... }

Salvando selees
Toda vez que voc faz uma seleo, um monte de cdigo executado, e o jQuery no faz caching de selees para voc. Se voc fez uma seleo que voc talvez precise fazer novamente, voc deve salvar a seleo numa varivel ao invs de fazer a seleo vrias vezes.

25

O bsico de jQuery

Exemplo 3.10. Armazenando selees em variveis


var $divs = $('div');

Nota
No Exemplo 3.10, Armazenando selees em variveis, o nome da varivel comea com um sinal de dlar. Ao invs de outras linguagens, no h nada especial sobre o sinal de dlar em JavaScript -- apenas outro caracter. Ns o usamos para indicar que a varavel contm um objeto jQuery. Esta prtica -- um tipo de Notao Hngara [http://en.wikipedia.org/wiki/ Hungarian_notation] -- meramente uma conveno, e no obrigatria. Uma vez que voc armazenou sua seleo, voc pode chamar os mtodos do jQuery na varivel que voc armazenou, da mesma forma que voc faria na seleo original.

Nota
Uma seleo somente obtm os elementos que esto na pgina quando voc faz a seleo. Se voc adicionar elementos na pgina depois, voc ter que repetir a seleo ou ento adicion-la seleo armazenada na varivel. Selees armazenadas no atualizam automaticamente quando o DOM muda.

Refinando & Filtrando Selees


Algumas vezes voc tem uma seleo que contm mais do que voc quer; neste caso, voc talvez queira refinar sua seleo. O jQuery oferece vrios mtodos para voc obter exatamente o que precisa.

Exemplo 3.11. Refinando selees


$('div.foo').has('p'); $('h1').not('.bar'); $('ul li').filter('.current'); $('ul li').first(); $('ul li').eq(5); // // // // //

o elemento div.foo que contm <p>'s elementos h1 que no tm a classe bar itens de listas no-ordenadas com a classe curre somente o primeiro item da lista no ordenada o sexto item da lista

Seletores relacionados formulrios


O jQuery oferece vrios pseudo-seletores que lhe ajudam a encontrar elementos nos seus formulrios; estes so especialmente teis porque pode ser difcil distinguir entre elementos form baseados no seu estado ou tipo usando seletores CSS padro. :button :checkbox :checked :disabled :enabled :file :image Seleciona elementos do tipo <button> e elementos com type="button" Seleciona inputs com type="checkbox" Seleciona inputs selecionados Seleciona elementos de formulrio desabilitados Seleciona elementos de formulrio habilitados Seleciona inputs com type="file" Seleciona inputs com type="image"

26

O bsico de jQuery

:input :password :radio :reset :selected :submit :text

Seleciona <input>, <textarea>, e elementos <select> Seleciona inputs com type="password" Seleciona inputs com type="radio" Seleciona inputs com type="reset" Seleciona inputs que esto selecionados Seleciona inputs com type="submit" Seleciona inputs com type="text"

Exemplo 3.12. Usando pseudo-seletores relacionados formulrios


$("#myForm :input'); // obtm todos os elementos que aceitam entrada de dados

Trabalhando com selees


Uma vez que voc tem uma seleo, voc pode chamar mtodos nela. Mtodos geralmente vm em duas formas diferentes: getters e setters. Getters retornam uma propriedade do primeiro elemento selecionado; setters ajustam (setam) uma propriedade em todos os elementos selecionados

Encadeamento
Se voc chamar um mtodo numa seleo e este mtodo retornar um objeto jQuery, voc pode continuar a chamar mtodos do jQuery sem precisar pausar com um ponto-e-vrgula.

Exemplo 3.13. Encadeamento


$('#content').find('h3').eq(2).html('o novo texto do terceiro h3!'); Se voc estiver escrevendo uma cadeia que inclui vrios passos, voc (e a pessoa que vir depois de voc) talvez ache seu cdigo mais legvel se voc quebrar o cdigo em vrias linhas.

Exemplo 3.14. Formatando cdigo encadeado


$('#content') .find('h3') .eq(2) .html('novo texto do terceiro h3!'); Se voc mudar sua seleo no meio de uma cadeia, o jQuery prov o mtodo $.fn.end para voc voltar para sua seleo original.

Exemplo 3.15. Restaurando sua seleo original usando $.fn.end


$('#content') .find('h3') .eq(2) .html('novo texto para o terceiro h3!') .end() // restaura a seleo para todos h3 em #context .eq(0) .html('novo texto para o primeiro h3!');

27

O bsico de jQuery

Nota
Encadeamento um recurso extraordinariamente poderoso, e muitas bibliotecas adotaram-no desde que o jQuery o tornou popular. Entretando, deve ser usado com cuidado. Encadeamentos extensos podem deixar o cdigo extremamente difcil de debugar ou modificar. No h uma regra que diz o quo grande uma cadeia deve ser -- mas saiba que fcil fazer baguna

Getters & Setters


O jQuery sobrecarrega seus mtodos, ento o mtodo usado para setar um valor geralmente tem o mesmo nome do mtodo usado para obter um valor. [Definition: Quando um mtodo usado para setar um valor, ele chamado de setter]. [Definition: Quando um mtodo usado para pegar (ou ler) um valor, ele chamado de getter]. Os setters afetam todos os elementos na seleo; getters obtm o valor requisitado somente do primeiro elemento na seleo.

Exemplo 3.16. O mtodo $.fn.html usado como setter


$('h1').html('ol mundo');

Exemplo 3.17. O mtodo html usado como getter


$('h1').html(); Os setters retornam um objeto jQuery, permitindo que voc continue chamando mtodos jQuery na sua seleo; getters retornam o que eles foram pedidos para retornar, o que significa que voc no pode continuar chamando mtodos jQuery no valor retornado pelo getter.

CSS, Styling, & Dimenses


O jQuery possui uma forma bem prtica para pegar e setar propriedades CSS dos elementos.

Nota
Propriedades CSS que normalmente incluem um hfen, precisam ser acessadas no estilo camel case em JavaScript. Por exemplo, a propriedade CSS font-size expressada como fontSize em JavaScript.

Exemplo 3.18. Pegando propriedades CSS


$('h1').css('fontSize'); // retorna uma string, como "19px"

Exemplo 3.19. Setando propriedades CSS

$('h1').css('fontSize', '100px'); // setando uma propriedade individual $('h1').css({ 'fontSize' : '100px', 'color' : 'red' }); // setando mltiplas propri Note o estilo do argumento que usamos na segunda linha -- um objeto que contm mltiplas propriedades. Este um jeito comum de passar mltiplos argumentos para uma funo, e muitos setters do jQuery aceitam objetos para setar mltiplos valores de uma s vez.

Usando classes do CSS para estilos


Como um getter, o mtodo $.fn.css til; Entretanto, ele geralmente deve ser evitado como um setter em cdigo de produo, pois voc no quer informao de apresentao no seu JavaScript. Ao invs disso,

28

O bsico de jQuery

escreva regras CSS para classes que descrevam os vrios estados visuais, e ento mude a classe no elemento que voc quer afetar.

Exemplo 3.20. Trabalhando com classes


var $h1 = $('h1'); $h1.addClass('big'); $h1.removeClass('big'); $h1.toggleClass('big'); if ($h1.hasClass('big')) { ... } Classes tambm podem ser teis para armazenar informaes de estado de um elemento, como indicar se um elemento est selecionado, por exemplo.

Dimenses
O jQuery oferece uma variedade de mtodos para obter e modificar informaes sobre dimenses e posies de um elemento. O cdigo do Exemplo 3.21, Mtodos bsicos de dimenses somente uma introduo muito curta sobre as funcionalidades de dimenses do jQuery; para detalhes completos sobre os mtodos de dimenso do jQuery, visite http://api.jquery.com/category/dimensions/.

Exemplo 3.21. Mtodos bsicos de dimenses


$('h1').width('50px'); $('h1').width(); $('h1').height('50px'); $('h1').height(); $('h1').position(); // seta a largura de todos os elementos h1 // obtm a largura do primeiro h1 // seta a altura de todos os elementos h1 // obtm a altura do primeiro h1 // retorna um objeto contendo informaes // sobre a posio do primeiro h1 relativo // a seu pai

Atributos
Atributos de elementos podem conter informaes teis para sua aplicao, ento importante saber como set-los e obt-los. O mtodo $.fn.attr atua como getter e setter. Assim como o mtodo $.fn.css, $.fn.attr atuando como setter, pode aceitar tanto uma chave e um valor ou um objeto contendo um ou mais pares chave/valor.

Exemplo 3.22. Definindo atributos


$('a').attr('href', 'todosMeusHrefsSaoOMesmoAgora.html'); $('a').attr({ 'title' : 'todos os ttulos so os mesmos tambm!', 'href' : 'algoNovo.html' });

29

O bsico de jQuery

Agora, ns quebramos o objeto em mltiplas linhas. Lembre-se, espaos no importam em JavaScript, ento voc deve se sentir livre para us-lo do jeito que quiser para fazer seu cdigo ficar mais legvel! Depois, voc pode usar uma ferramenta de minificao para remover espaos desnecessrios para seu cdigo de produo.

Exemplo 3.23. Obtendo atributos


$('a').attr('href'); // retorna o href do primeiro elemento <a> do documento

Travessia
Uma vez que voc tem uma seleo do jQuery, voc pode encontrar outros elementos usando sua seleo como ponto de incio. Para documentao completa dos mtodos de travessia do jQuery, visite http://api.jquery.com/category/ traversing/.

Nota
Seja cuidadoso com travessias de longas distncias nos seus documentos -- travessias complexas torna imperativo que a estrutura do seu documento permanea a mesma, uma dificuldade estabilidade, mesmo se voc for o responsvel por criar toda a aplicao desde o servidor at o cliente. Travessias de um ou dois passos so legais, mas geralmente voc ir querer evitar travessias que levem voc de um container para outro.

Exemplo 3.24. Movendo pelo DOM usando mtodos de travessia.


$('h1').next('p'); $('div:visible').parent(); $('input[name=first_name]').closest('form'); $('#myList').children(); $('li.selected').siblings(); Voc tambm pode iterar sobre uma seleo usando $.fn.each. Este mtodo itera sobre todos os elementos numa seleo e executa uma funo para cada um. A funo recebe como argumento um ndice com o elemento atual e com o prprio elemento DOM. Dentro da funo, o elemento DOM tambm est disponvel como this por padro.

Exemplo 3.25. Iterando sobre uma seleo


$('#myList li').each(function(idx, el) { console.log( 'O elemento ' + idx + 'tem o seguinte html: ' + $(el).html() ); });

Manipulando elementos
Uma vez que voc fez uma seleo, a diverso comea. Voc pode mudar, mover, remover e clonar elementos. Voc ainda pode criar novos elementos atravs de uma sintaxe simples

30

O bsico de jQuery

Para uma referncia completa dos mtodos de manipulao do jQuery, visite http://api.jquery.com/ category/manipulation/.

Obtendo e Definindo informaes sobre elementos


H um certo nmero de formas que voc pode mudar um elemento existente. Dentre as tarefas mais comuns que voc ir fazer mudar o HTML interno ou o atributo de um elemento. O jQuery oferece mtodos simples e cross-navegador para estes tipos de manipulao. Voc ainda pode obter informaes sobre elementos usando muitos dos mesmos mtodos nas suas formas de getter. Ns veremos exemplos destes mtodos durante esta seo, mas especificamente, aqui vo alguns poucos mtodos que voc pode usar para obter e definir informao sobre elementos.

Nota
Mudar coisas em elementos trivial, mas lembre-se que a mudana ir afetar todos os elementos na seleo, ento se voc quiser mudar um elemento, esteja certo de especific-lo em sua seleo antes de chamar o mtodo setter

Nota
Quando os mtodos atuam como getters, eles geralmente s trabalham no primeiro elemento da seleo e eles no retornam um objeto jQuery, portanto voc no pode encadear mtodos adicionais a eles. Uma exceo notvel $.fn.text; como mencionado acima, ele obtm o texto para todos os elementos da seleo $.fn.html $.fn.text $.fn.attr $.fn.width $.fn.height $.fn.position $.fn.val Obtm ou seta o contedo html. Obtm ou seta os contedos de texto; HTML ser removido. Obtm ou seta o valor do atributo fornecido. Obtm ou seta a largura em pixels do primeiro elemento na seleo como um inteiro. Obtm ou seta a altura em pixels do primeiro elemento na seleo. Obtm um objeto com a informao de posio do primeiro elemento na seleo, relativo a seu primeiro ancestral (pai). Este somente um getter. Obtm ou seta o valor de elementos de formulrios.

Exemplo 3.26. Mudando o HTML de um elemento.


$('#myDiv p:first') .html('Primeiro pargrafo <strong>novo</strong>!');

Movendo, copiando e removendo elementos.


H uma variedade de formas de mover elementos pelo DOM; geralmente, h duas abordagens: Coloque o(s) elemento(s) selecionado(s) relativo outro elemento Coloque um elemento relativo ao(s) elemento(s) selecionado(s) Por exemplo, o jQuery fornece $.fn.insertAfter e $.fn.after. O mtodo $.fn.insertAfter coloca o(s) elemento(s) selecionado(s) depois do elemento que voc passou como argumento; o mtodo $.fn.after coloca o elemento passado como argumento depois do elemento

31

O bsico de jQuery

selecionado. Vrios outros mtodos seguem este padro: $.fn.insertBefore e $.fn.before; $.fn.appendTo e $.fn.append; e $.fn.prependTo e $.fn.prepend. O mtodo que faz mais sentido para voc depender de quais elementos voc j selecionou e quais voc precisar armazenar uma referncia para os elementos que voc est adicionando na pgina. Se voc precisar armazenar uma referncia, voc sempre ir querer fazer pela primeira forma -- colocando os elementos selecionados relativos outro elemento -- de forma que ele retorne o(s) elemento(s) que voc est colocando. Neste caso, os mtodos $.fn.insertAfter, $.fn.insertBefore, $.fn.appendTo, e $.fn.prependTo sero suas ferramentas para escolha.

Exemplo 3.27. Movendo elementos usando outras formas


// faz o primeiro item da lista se tornar o ltimo var $li = $('#myList li:first').appendTo('#myList'); // outra forma de resolver o mesmo problema $('#myList').append($('#myList li:first')); // perceba que no tem como acessar o item // da lista que movemos, pois ele retorna // a prpria lista

Clonando elementos
Quando voc usa mtodos como $.fn.appendTo, voc est movendo o elemento; porm, algumas vezes voc ir querer fazer uma cpia do elemento. Neste caso, voc precisar usar $.fn.clone primeiro.

Exemplo 3.28. Fazendo uma cpia de um elemento


// copia o primeiro item da lista para o fim $('#myList li:first').clone().appendTo('#myList');

Nota
Se voc precisa copiar dados e eventos relacionados, esteja certo de passar true como um argumento para $.fn.clone.

Removendo elementos
H duas formas de remover elementos da pgina: $.fn.remove e $.fn.detach. Voc ir usar $.fn.remove quando voc quiser remover a seleo permanentemente da pgina; enquanto o mtodo retorna os elementos removidos, estes elementos no tero seus eventos e dados associados a ele se voc retorn-los pgina. Se voc precisa que os dados e eventos persistam, voc ir usar $.fn.detach. Da mesma forma que $.fn.remove, ele retorna uma seleo, mas tambm mantm os dados e os eventos associados com a seleo para que voc possa restaurar a seleo para a pgina no futuro.

Nota
O mtodo $.fn.detach extremamente til se voc estiver fazendo uma manipulao pesada um elemento. Neste caso, bom aplicar um $.fn.detach no elemento da pgina, trabalhar no seu prprio cdigo, e ento restaur-lo pgina quando voc terminar. Isto evita que voc faa "toques ao DOM" caros enquanto mantm os dados e eventos do elemento.

32

O bsico de jQuery

Se voc quer deixar um elemento na pgina mas simplesmente quer remover seu contedo, voc pode usar $.fn.empty para retirar o HTML interno do elemento.

Criando novos elementos


O jQuery oferece uma forma elegante e trivial para criar novos elementos usando o mesmo mtodo $() que voc usava para selees.

Exemplo 3.29. Criando novos elementos


$('<p>Este um novo pargrafo</p>'); $('<li class="new">novo item de lista</li>');

Exemplo 3.30. Criando um novo elemento com um objeto atributo


$('<a/>', { html : 'Este um link <strong>new</strong>', 'class' : 'new', href : 'foo.html' }); Perceba que no objeto de atributos ns incluimos como segundo argumento a propriedade class entre aspas, enquanto as propriedades html e href no. Geralmente, nomes de propriedades no precisam estar entre aspas a no ser que elas sejam palavras reservadas (como a class neste caso) Quando voc cria um novo elemento, ele no adicionado imediatamente pgina. H vrias formas de adicionar um elemento pgina uma vez que ele esteja criado.

Exemplo 3.31. Inserindo um novo elemento na pgina


var $myNewElement = $('<p>Novo elemento</p>'); $myNewElement.appendTo('#content'); $myNewElement.insertAfter('ul:last'); // isto ir remover p de #content! $('ul').last().after($myNewElement.clone()); // clona o p, portanto temos 2 agora Estritamente falando, voc no precisa armazenar o elemento criado numa varivel -- voc pode simplesmente chamar o mtodo para adicion-lo diretamente depois do $(). Entretanto, a maior parte do tempo voc precisar de uma referncia ao elemento que voc adicionou para que voc no o selecione depois. Voc ainda pode criar um elemento ao mesmo tempo que voc o adiciona pgina, mas note que neste caso voc no obtm a referncia do novo objeto criado.

Exemplo 3.32. Criando e adicionando um elemento pgina ao mesmo tempo


$('ul').append('<li>item de lista</li>');

Nota
A sintaxe para adicionar novos elementos pgina to fcil que tentador esquecer que h um enorme custo de performance por adicionar ao DOM repetidas vezes. Se voc est adicionando muitos elementos ao mesmo container, voc ir concatenar todo html numa nica string e ento adicionar a string ao container ao invs de ir adicionando um elemento de cada vez. Voc pode

33

O bsico de jQuery

usar um array para colocar todas os pedaos juntos e ento aplicar um join nele em uma nica string para adicionar ao container. var myItems = [], $myList = $('#myList'); for (var i=0; i<100; i++) { myItems.push('<li>item ' + i + '</li>'); } $myList.append(myItems.join(''));

Manipulando atributos
Os recursos de manipulao de atributos do jQuery so muitos. Mudanas bsicas so simples, mas o mtodo $.fn.attr tambm permite manipulaes mais complexas.

Exemplo 3.33. Manipulando um nico atributo


$('#myDiv a:first').attr('href', 'novoDestino.html');

Exemplo 3.34. Manipulando mltiplos atributos


$('#myDiv a:first').attr({ href : 'novoDestino.html', rel : 'super-special' });

Exemplo 3.35. Usando uma funo para determinar um novo valor de atributo
$('#myDiv a:first').attr({ rel : 'super-special', href : function() { return '/new/' + $(this).attr('href'); } }); $('#myDiv a:first').attr('href', function() { return '/new/' + $(this).attr('href'); });

Exerccios
Selecionando
Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ sandbox.js ou trabalhe no Firebug para fazer o seguinte: 1. Selecione todos os elementos DIV que tm a classe "module". 2. Escreva trs seletores que voc pode usar para obter o terceiro item na lista no-ordenada #myList. Qual o melhor para se usar? Por qu? 3. Selecione o label para o input de busca usando um seletor de atributo.

34

O bsico de jQuery

4. Encontre quantos elementos na pgina esto escondidos (dica: .length). 5. Encontre quantos elementos na pgina tm um atributo alt. 6. Selecione todas as linhas mpares no corpo de uma tabela.

Atravessamento
Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ sandbox.js ou trabalhe no Firebug para fazer o seguinte: 1. Selecione todos os elementos de imagem na pgina; logue o atributo alt de cada imagem. 2. Selecione a caixa de texto de busca, ento atravesse para o form e adicione uma classe nele. 3. Selecione o item de lista dentro de #myList que possui uma classe "current" e remova esta classe dele; adicione uma classe "current" no prximo item de lista. 4. Selecione o elemento select dentro de #specials; atravesse para o boto de submit. 5. Selecione o primeiro item de lista no elemento #slideshow; adicione a classe "current" a ele e ento adicione a classe "disabled" para seus elementos sibling.

Manipulando
Abra o arquivo/exercises/index.html no seu navegador. Utilize o arquivo /exercises/js/ sandbox.js ou use o Firebug para realizar o seguinte: 1. Adicione cinco novos itens de lista no fim da lista no ordenada #myList. Dica: for (var i = 0; i<5; i++) { ... } 2. Remova os itens mpares 3. Adicione outro h2 e outro pargrafo ltima div.module 4. Adicione outra opo para o elemento select; d ao option o valor "Quarta-Feira". 5. Adicione uma nova div.module pgina depois da ltima; coloque uma cpia de uma das imagens existentes dentro dela.

35

Captulo 4. Ncleo do jQuery


$ vs $()
At agora, estivemos lidando inteiramente com mtodos que so chamados em um objeto jQuery. Por exemplo: $('h1').remove(); A maioria dos mtodos jQuery chamada em objetos jQuery como mostrado acima; esses mtodos so considerados parte do namespace $.fn, ou o prottipo do jQuery, e so melhor imaginados como mtodos do objeto jQuery. No entanto, h vrios mtodos que no atuam em uma seleo; esses mtodos so considerados parte do namespace jQuery, e so melhor imaginados como mtodos do ncleo do jQuery. Esta distino pode ser incrivelmente confusa para os novos usurios do jQuery. Aqui est o que voc precisa se lembrar: Mtodos chamados em selees do jQuery esto no namespace $.fn, e automaticamente recebem e retornam a seleo como est. Mtodos no namespace $ geralmente so mtodos do tipo utilitrio, e no funcionam em selees; no so passados quaisquer argumentos automaticamente para eles, e seu valor de retorno variar. H alguns casos onde mtodos de objeto e mtodos do ncleo tem os mesmos nomes, tal como $.each e $.fn.each. Nesses casos, seja extremamente cuidadoso(a) ao ler a documentao para que voc explore o mtodo correto.

Mtodos Utilitrios
jQuery oferece diversos mtodos utilitrios no namespace $. Estes mtodos so teis para realizar tarefas rotineiras de programao. Abaixo esto exemplos de alguns dos mtodos utilitrios; para uma referncia completa sobre mtodos utilitrios do jQuery, visite http://api.jquery.com/category/utilities/. $.trim Remove espaos em branco esquerda e direita. $.trim(' muitos espaos em branco extras // returns 'muitos espaos em branco extras' $.each Itera sobre arrays e objetos. $.each([ 'foo', 'bar', 'baz' ], function(idx, val) { console.log('elemento ' + idx + ' ' + val); }); $.each({ foo : 'bar', baz : 'bim' }, function(k, v) { console.log(k + ' : ' + v); }); ');

Nota
H tambm um mtodo $.fn.each, que usado para iterar sobre uma seleo de elementos.

36

Ncleo do jQuery

$.inArray

Retorna o ndice de um valor em um array, ou -1 se o valor no estiver no array. var meuArray = [ 1, 2, 3, 5 ]; if ($.inArray(4, meuArray) !== -1) { console.log('encontrei!'); }

$.extend

Muda as propriedades do primeiro objeto usando as propriedades dos objetos subsequentes. var primeiroObjeto = { foo : 'bar', a : 'b' }; var segundoObjeto = { foo : 'baz' }; var novoObjeto = $.extend(primeiroObjeto, segundoObjeto); console.log(primeiroObjeto.foo); // 'baz' console.log(novoObjeto.foo); // 'baz' Se voc no quer mudar nenhum dos objetos que passa para o $.extend, passe um objeto vazio como primeiro argumento. var primeiroObjeto = { foo : 'bar', a : 'b' }; var segundoObjeto = { foo : 'baz' }; var novoObjeto = $.extend({}, primeiroObjeto, segundoObjeto); console.log(primeiroObjeto.foo); // 'bar' console.log(novoObjeto.foo); // 'baz'

$.proxy

Retorna uma funo que sempre ser executada no escopo fornecido isto , seta o significado do this dentro da funo passada ao segundo argumento. var minhaFuncao = function() { console.log(this); }; var meuObjeto = { foo : 'bar' }; minhaFuncao(); // loga o objeto window var minhaFuncaoComProxy = $.proxy(minhaFuncao, meuObjeto); minhaFuncaoComProxy(); // loga o objeto meuObjeto Se voc tiver um objeto com mtodos, pode passar o objeto e o nome do mtodo para retornar uma funo que sempre ser executada no escopo do objeto. var meuObjeto = { minhaFn : function() { console.log(this); } }; $('#foo').click(meuObjeto.minhaFn); // loga o elemento DOM #foo $('#foo').click($.proxy(meuObjeto, 'minhaFn')); // loga meuObjeto

Verificando tipos
Como mencionado na seo "O Bsico do jQuery", jQuery oferece alguns mtodos utilitrios para determinar o tipo de um valor especfico.

37

Ncleo do jQuery

Exemplo 4.1. Verificando o tipo de um valor arbitrrio


var meuValor = [1, 2, 3]; // Usando o operador typeof do JavaScript para testar tipos primitivos typeof meuValor == 'string'; // false typeof meuValor == 'number'; // false typeof meuValor == 'undefined'; // false typeof meuValor == 'boolean'; // false // Usando o operador de igualdade estrita para verificar null meuValor === null; // false // Usando os mtodos do jQuery para verificar tipos no primitivos jQuery.isFunction(meuValor); // false jQuery.isPlainObject(meuValor); // false jQuery.isArray(meuValor); // true

Mtodos de Dados
Assim que seu trabalho com o jQuery avana, voc descobrir com frequncia que h dados sobre um elemento que voc quer armazenar com o elemento. Em JavaScript puro, voc pode fazer isso adicionando uma propriedade ao elemento do DOM, mas voc ter que lidar com memory leaks em alguns navegadores. jQuery ofere um jeito simples de armazenar dados relacionados a um elemento, e gerencia os problemas de memria para voc.

Exemplo 4.2. Armazenando e recuperando dados relacionados a um elemento


$('#meuDiv').data('nomeChave', { foo : 'bar' }); $('#meuDiv').data('nomeChave'); // { foo : 'bar' } Voc pode armazenar qualquer tipo de dados em um elemento, e difcil expressar a importncia disto quando voc est desenvolvendo uma aplicao complexa. Para os fins deste curso, usaremos $.fn.data na maioria das vezes para armazenar referncias a outros elementos. Por exemplo, podemos querer estabelecer um relacionamento entre um item de lista e um div que est dentro dele. Poderamos estabelecer este relacionamento cada vez que interagimos com o item de lista, mas uma soluo melhor seria estabelecer o relacionamento uma vez, e ento armazenar um ponteiro para o div no item de lista usando $.fn.data:

Exemplo 4.3. Armazenando um relacionamento entre elementos usando $.fn.data


$('#minhaLista li').each(function() { var $li = $(this), $div = $li.find('div.content'); $li.data('contentDiv', $div); }); // depois no temos que procurar o div de novo; // podemos apenas l-lo dos dados do item de lista var $primeiroLi = $('#minhaLista li:first'); $primeiroLi.data('contentDiv').html('novo contedo');

38

Ncleo do jQuery

Alm de passar um nico par chave-valor para $.fn.data para armazenar dados, voc pode passar um objeto contento um ou mais pares.

Deteco de Navegador & Funcionalidades


Embora o jQuery elimine a maioria das peculiaridades dos navegadores, h ainda ocasies quando seu cdigo precisa saber sobre o ambiente do navegador. jQuery oferece o objeto $.support, assim como o objeto obsoleto $.browser, para este propsito. Para uma documentao completa sobre esses objetos, visite http://api.jquery.com/jQuery.support/ e http:// api.jquery.com/jQuery.browser/. O objeto $.support dedicado a determinar quais funcionalidades um navegador suporta; recomendado como um mtodo mais prova de futuro de customizar seu JavaScript para diferentes ambientes de navegador. O objeto $.browser foi substitudo em favor do objeto $.support, mas no ser removido do jQuery to cedo. Ele fornece deteco direta de verso e marca do navegador.

Evitando Conflitos com Outras Bibliotecas


Se voc est usando outra biblioteca JavaScript que usa a varivel $, voc pode cair em conflitos com o jQuery. Para evitar esses conflitos, voc precisa colocar o jQuery em modo no-conflict (sem conflito) imediatamente depois que ele carregado na pgina e antes que voc tente usar o jQuery em sua pgina. Quando voc coloca o jQuery em modo no-conflict, tem a opo de atribuir um nome de varivel para substituir a $.

Exemplo 4.4. Colocando jQuery em modo no-conflict


<script src="prototype.js"></script> <script src="jquery.js"></script> <script>var $j = jQuery.noConflict();</script> Voc pode continuar a usar o $ padro envolvendo seu cdigo em uma funo annima auto-executada; este o modelo padro para criao de plugin, onde o autor no saber se uma outra biblioteca estar usando o $.

Exemplo 4.5. Usando o $ dentro de uma funo annima auto-executada


<script src="prototype.js"></script> <script src="jquery.js"></script> <script> jQuery.noConflict(); (function($) { // seu cdigo aqui, usando o $ })(jQuery); </script>

39

Captulo 5. Eventos
Introduo
jQuery fornece mtodos simples para anexar manipuladores de eventos (event handlers) em selees. Quando um evento ocorre, a funo fornecida executada. Dentro da funo, this refere-se ao elemento que foi clicado. Para detalhes sobre eventos do jQuery, visite http://api.jquery.com/category/events/. A funo manipuladora de evento pode receber um objeto de evento. Este objeto pode ser usado para determinar a natureza do evento, e para impedir o comportamento padro do evento. Para detalhes sobre o objeto de evento, visite http://api.jquery.com/category/events/event-object/.

Conectando Eventos a Elementos


jQuery oferece mtodos de convenincia para a maioria dos eventos comuns, e estes so os mtodos que voc ver sendo usados com mais frequncia. Estes mtodos -- incluindo $.fn.click, $.fn.focus, $.fn.blur, $.fn.change, etc. -- so atalhos para o mtodo $.fn.bind do jQuery. O mtodo bind til para vincular a mesma funo a mltiplos eventos, e tambm usado quando voc quer fornecer dados para o manipulador de eventos, ou quando voc est trabalhando com eventos personalizados.

Exemplo 5.1. Vinculando Eventos Usando um Mtodo de Convenincia


$('p').click(function() { console.log('clique'); });

Exemplo 5.2. Vinculando eventos usando o mtodo $.fn.bind


$('p').bind('click', function() { console.log('clique'); });

Exemplo 5.3. Vinculando eventos usando o mtodo $.fn.bind com dados


$('input').bind( 'click change', // anexa mltiplos eventos { foo : 'bar' }, // passa dados function(eventObject) { console.log(eventObject.type, eventObject.data); // loga o tipo de evento, e ento { foo : 'bar' } } );

Conectando Eventos para Executar Apenas uma vez


Algumas vezes voc precisa que um handler especfico execute apenas uma vez -- depois disso, voc pode querer que nenhum handler execute, ou pode querer que um handler diferente execute. jQuery fornece o mtodo $.fn.one para este propsito.

40

Eventos

Exemplo 5.4. Trocando manipuladores usando o mtodo $.fn.one


$('p').one('click', function() { $(this).click(function() { console.log('Voc clicou nisto antes!'); }); }); O mtodo $.fn.one especialmente til se voc precisa fazer alguma configurao complicada na primeira vez que um elemento clicado, mas no nas vezes subsequentes.

Desconectando Eventos
Para desconectar um manipulador de evento, voc usa o mtodo $.fn.unbind e passa o tipo de evento para desatar. Se voc anexou uma funo nomeada para o evento, ento pode isolar a desconexo para essa funo nomeada passando-a como o segundo argumento.

Exemplo 5.5. Desconectando todos os manipuladores de clique em uma seleo


$('p').unbind('click');

Exemplo 5.6. Desconectando um manipulador de clique especfico


var foo = function() { console.log('foo'); }; var bar = function() { console.log('bar'); }; $('p').bind('click', foo).bind('click', bar); $('p').unbind('click', bar); // foo ainda est ligado ao evento de clique

Usando Namespaces com Eventos


Para aplicaes complexas e para plugins que voc compartilha com outros, pode ser til usar um namespace para seus eventos de forma que voc no desconecte sem querer eventos sobre os quais voc no conhece ou no poderia conhecer.

Exemplo 5.7. Usando Namespaces com eventos


$('p').bind('click.meuNamespace', function() { /* ... */ }); $('p').unbind('click.meuNamespace'); $('p').unbind('.meuNamespace'); // desconecta todos os eventos no namespace

Por Dentro da Funo Manipuladora de Evento


Como mencionado na introduo, a funo manipuladora de evento recebe um objeto de evento, que contm muitas propriedades e mtodos. O objeto de evento mais comumente usado para impedir a ao padro do evento atravs do mtodo preventDefault. Contudo, o objeto de evento contm vrios outros mtodos e propriedades teis, incluindo: pageX, pageY type which data A posio do mouse no momento em que o evento ocorreu, relativa ao canto superior esquerdo da pgina. O tipo do evento (por ex. "click"). O boto ou tecla que foi pressionado(a). Quaisquer dados que foram passados quando o evento foi anexado.

41

Eventos

target preventDefault() stopPropagation()

O elemento do DOM que iniciou o evento. Impede a ao padro do evento (por ex. seguir um link). Impede o evento de se propagar (bubble up) para os outros elementos.

Alm do objeto de evento, a funo manipuladora de evento tambm tem acesso ao elemento do DOM no qual o evento foi anexado atravs da palavra-chave this. Para transformar um elemento do DOM em um objeto jQuery no qual podemos usar mtodos do jQuery, simplesmente fazemos $(this), frequentemente seguindo este idioma: var $this = $(this);

Exemplo 5.8. Impedindo um link de ser seguindo


$('a').click(function(e) { var $this = $(this); if ($this.attr('href').match('mau')) { e.preventDefault(); $this.addClass('mau'); } });

Disparando Eventos
jQuery fornece um mtodo de disparar os eventos ligados a um elemento sem qualquer interao do usurio atravs do mtodo $.fn.trigger. Enquanto este mtodo tem seus usos, ele no deve ser usado simplesmente para chamar uma funo que foi ligada como um tratador de clique. Ao invs disso, voc deve armazenar a funo que voc quer chamar em uma varivel, e passar o nome da varivel quando fizer sua ligao. Ento voc pode chamar a prpria funo sempre que quiser, sem a necessidade do $.fn.trigger.

Exemplo 5.9. Disparando um evento do jeito certo


var foo = function(e) { if (e) { console.log(e); } else { console.log('isto no vem de um evento!'); } };

$('p').click(foo); foo(); // ao invs de $('p').trigger('click')

Aumentando a Performance com Delegao de Evento


Voc frequentemente usar o jQuery para adicionar novos elementos a pgina, e quando o faz, pode precisar anexar eventos a esses novos elementos -- eventos que voc j anexou a elementos similares que

42

Eventos

estavam na pgina originalmente. Ao invs de repetir a ligao de evento toda vez que adicionar elementos pgina, voc pode usar delegao de evento. Com delegao de evento voc anexa seu evento ao elemento container, e ento quando o evento ocorre, voc verifica em qual elemento contido ele ocorreu. Se isto soa complicado, por sorte o jQuery facilita com seus mtodos $.fn.live e $.fn.delegate. Enquanto a maioria das pessoas descobre a delegao de evento ao lidar com elementos adicionados na pgina depois, isso tem alguns benefcios de performance mesmo se voc nunca adiciona mais elementos para a pgina. O tempo requerido para ligar eventos a centenas de elementos individuais no-trivial; se voc tem um grande conjunto de elementos, deve considerar a delegao de eventos relacionados a um elemento container.

Nota
O mtodo $.fn.live foi introduzido no jQuery 1.3, e na poca apenas certos tipos de eventos eram suportados. Com o jQuery 1.4.2, o mtodo $.fn.delegate est disponvel, e o mtodo preferencial.

Exemplo 5.10. Delegao de Evento usando $.fn.delegate


$('#minhaListaNaoOrdenada').delegate('li', 'click', function(e) { var $meuItemDeLista = $(this); // ... });

Exemplo 5.11. Delegao de Evento usando $.fn.live


$('#minhaListaNaoOrdenada li').live('click', function(e) { var $meuItemDeLista = $(this); // ... });

Desvinculando Eventos Delegados


Se voc precisa remover eventos delegados, no pode simplesmente usar unbind neles. Ao invs disso, use $.fn.undelegate para eventos conectados com $.fn.delegate, e $.fn.die para eventos conectados com $.fn.live. Assim como com bind, voc pode opcionalmente passar o nome da funo ligada ao evento.

Exemplo 5.12. Desvinculando eventos delegados


$('#minhaListaNaoOrdenada').undelegate('li', 'click'); $('#minhaListaNaoOrdenada li').die('click');

Auxiliares de Eventos
jQuery oferece duas funes auxiliares relacionadas a eventos que economizam algumas teclas digitadas.

$.fn.hover
O mtodo $.fn.hover deixa voc passar uma ou duas funes para serem executadas quando os eventos mouseenter e mouseleave ocorrem em um elemento. Se voc passar uma funo, ela ser executada para ambos os eventos; se passar duas funes, a primeira ser executada para mouseenter, e a segunda ser executada para mouseleave.

43

Eventos

Nota
Antes do jQuery 1.4, o mtodo $.fn.hover exigia duas funes.

Exemplo 5.13. A funo auxiliar hover


$('#menu li').hover(function() { $(this).toggleClass('hover'); });

$.fn.toggle
Assim como $.fn.hover, o mtodo $.fn.toggle recebe duas ou mais funes; cada vez que o evento ocorre, a prxima funo na lista chamada. Geralmente, $.fn.toggle usado apenas com duas funes, mas tecnicamente voc pode usar tantas quantas desejar.

Exemplo 5.14. A funo auxiliar toggle


$('p.expander').toggle( function() { $(this).prev().addClass('open'); }, function() { $(this).prev().removeClass('open'); } );

Exerccios
Criando uma dica de Input
Abra o arquivo /exercises/index.html no seu navegador. Use o arquivo /exercises/js/ inputHint.js ou trabalhe no Firebug. Sua tarefa usar o texto do label para o input da busca para criar um texto de "hint" para o input da busca. Os passos so os seguintes: 1. Sete o valor do input de busca para o texto do elemento label 2. Adicione uma classe "hint" ao input de busca 3. Remova o elemento label 4. Faa um Bind do evento focus no input de busca que remove o texto de hint e a classe "hint". 5. Faa um bind do evento blur para o input de busca que restaura o texto de hint e a classe "hint" se nenhum texto for informado. Quais outras consideraes poderiam haver se voc estivesse criando esta funcionalidade para um site real?

Adicionando navegao por abas


Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ tabs.js. Sua tarefa criar uma navegao por abas para os dois elementos div.module. Para fazer isto:

44

Eventos

1. Esconda todos os modules. 2. Crie uma lista no-ordenada antes do primeiro mdulo. 3. Itere sobre os mdulos usando $.fn.each. Para cada mdulo, use o texto para o elemento h2 como o texto para um item da lista. 4. Crie um bind do evento click no item de lista que: Exiba o mdulo relacionado e esconda qualquer outro mdulo. Adicione uma classe "current" para o item de lista clicado. Remova a classe "current" do outro item de lista. 5. Por ltimo, mostre a primeira tabela.

45

Captulo 6. Efeitos
Viso Geral
jQuery torna trivial adicionar efeitos simples a sua pgina. Efeitos podem usar configuraes embutidas, ou fornecer uma durao customizada. Voc pode tambm criar animaes customizadas de propriedades CSS arbitrrias. Para detalhes completos sobre efeitos do jQuery, visite http://api.jquery.com/category/effects/.

Efeitos Embutidos
Efeitos frequentemente usados esto embutidos no jQuery como mtodos: $.fn.show $.fn.hide $.fn.fadeIn $.fn.fadeOut $.fn.slideDown $.fn.slideUp $.fn.slideToggle Mostra o elemento selecionado. Esconde o elemente selecionado. Anima a opacidade dos elementos selecionados para 100%. Anima a opacidade dos elementos selecionados para 0%. Mostra os elementos selecionados com um deslizamento vertical. Esconde os elementos selecionados com um deslizamento vertical. Mostra ou esconde os elementos selecionados com um deslizamento vertical, dependendo se os elementos atualmente esto visveis.

Exemplo 6.1. Um uso bsico de um efeito embutido


$('h1').show();

Mudando a Durao de Efeitos Embutidos


Com exceo de $.fn.show e $.fn.hide, todos os mtodos embutidos so animados ao longo de 400ms por padro. Mudar a durao de um efeito simples.

Exemplo 6.2. Configurando a durao de um efeito


$('h1').fadeIn(300); $('h1').fadeOut('slow'); // fade in durante 300ms // usando uma definio de durao nativa

jQuery.fx.speeds
jQuery tem um objeto em jQuery.fx.speeds que contm a velocidade padro, assim como as configuraes para "slow" e "fast". velocidades: {

46

Efeitos

slow: 600, fast: 200, // Velocidade padro _default: 400 } possvel sobrescrever ou adicionar a este objeto. Por exemplo, voc pode querer mudar a durao padro dos efeitos, ou pode querer criar suas prprias velocidades de efeitos.

Exemplo 6.3. Acrescentando definies de velocidade customizadas ao jQuery.fx.speeds


jQuery.fx.speeds.blazing = 100; jQuery.fx.speeds.turtle = 2000;

Fazendo algo quando um Efeito tiver Terminado


Frequentemente, voc ir querer executar algum cdigo uma vez que uma animao tenha terminado -se voc execut-lo antes que a animao tenha terminado, ele pode afetar a qualidade da animao, ou pode remover elementos que so parte da animao. [Definition: Funes de callback fornecem um jeito de registrar seu interesse em um evento que acontecer no futuro.] Neste caso, o evento que estaremos respondendo a concluso da animao. Dentro da funo de callback, a palavra-chave this refere-se ao elemento no qual o efeito foi chamado; como se estivssemos dentro de funes de manipulao de eventos, podemos transform-lo em um objeto jQuery via $(this).

Exemplo 6.4. Executando cdigo quando uma animao tiver completado


$('div.old').fadeOut(300, function() { $(this).remove(); }); Note que se sua seleo no retorna nenhum elemento, seu callback nunca ser executado! Voc pode resolver este problema testando se sua seleo retornou algum elemento; se no, voc pode s executar a callback imediatamente.

Exemplo 6.5. Executa uma callback mesmo se no houver elementos para animar
var $thing = $('#naoexistente'); var cb = function() { console.log('pronto!'); }; if ($thing.length) { $thing.fadeIn(300, cb); } else { cb(); }

Efeitos customizados com $.fn.animate


jQuery torna possvel animar propriedades CSS arbitrrias atravs do mtodo $.fn.animate. O mtodo $.fn.animate deixa voc animar para um valor definido ou para um valor relativo ao valor atual.

47

Efeitos

Exemplo 6.6. Efeitos customizados com $.fn.animate


$('div.funtimes').animate( { left : "+=50", opacity : 0.25 }, 300, // durao function() { console.log('pronto!'); // callback });

Nota
Propriedades relacionadas a cor no podem ser animadas com $.fn.animate usando jQuery de forma convencional. Animaes de cor podem ser facilmente efetuadas incluindo o plugin de cor [http://plugins.jquery.com/files/jquery.color.js.txt]. Discutiremos o uso de plugins depois no livro.

Easing
[Definition: Easing descreve a maneira na qual um efeito ocorre -- se a taxa de variao constante, ou varia com a durao da animao.] jQuery inclui apenas dois mtodos de easing: swing and linear. Se voc quer transies mais naturais em suas animaes, vrios plugins de easing esto disponveis. A partir do jQuery 1.4, possvel fazer easing por propriedade ao usar o mtodo $.fn.animate.

Exemplo 6.7. Easing por propriedade


$('div.funtimes').animate( { left : [ "+=50", "swing ], opacity : [ 0.25, "linear" ] }, 300 ); Para mais detalhes sobre opes de easing, veja http://api.jquery.com/animate/.

Controlando efeitos
jQuery fornece vrias ferramentas para controlar animaes. $.fn.stop $.fn.delay Pra animaes atualmente sendo executadas nos elementos selecionados. Espera um nmero de milissegundos especificado antes de executar a prxima animao. $('h1').show(300).delay(1000).hide(300); jQuery.fx.off Se este valor for true, no haver transio para as animaes; os elementos sero imediatamente setados para o estado alvo final em vez disso. Isto pode ser especialmente til ao lidar com navegadores antigos; voc pode querer fornecer a opo para seus usurios.

48

Efeitos

Exerccios
Mostrando texto oculto
Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ blog.js. Sua tarefa adicionar alguma interatividade seo de blog na pgina. A especificao para a funcionalidade a seguinte: O pargrafo de excerpt deve deslizar para baixo (slideDown) ao clicar na headline dentro da div #blog. O pargrafo de excerpt deve deslizar para baixo ao clicar na sua headline, e os outros excerpts devem deslizar para cima (slideUp). Dica: no se esquea do seletor :visible!

Criando menus dropdown


Abra o arquivo /exercises/index.htmlno seu navegador. Use o arquivo /exercises/js/ navigation.js. Sua tarefa adicionar menus dropdown navegao principal no topo da pgina. Passar o mouse sobre um item no menu principal deve mostrar os itens do submenu, se houver. Tirar o mouse de cima do item deve esconder todos os itens do submenu. Para fazer este exerccio, use o mtodo $.fn.hover para adicionar e remover uma classe dos itens do submenu para controlar quando ele ser visvel ou invisvel. (O arquivo em /exercises/css/ styles.css inclui a classe "hover" para este propsito.)

Crie um slideshow
Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ slideshow.js. Sua tarefa pegar HTML puro e melhor-lo com JavaScript adicionando um slideshow. 1. Mova o elemeto #slideshow para o topo do corpo. 2. Escreva o cdigo para navegar em torno dos itens da lista dentro do elemento; Exiba um com fadeIn, mostre-o por alguns segundos e ento faa o desaparecer com o fadeOut e faa o prximo aparecer com o fadeIn. 3. Quando voc chegar ao final da lista, comece denovo do incio. Para um desafio extra, crie uma rea de navegao debaixo do slideshow que mostra quantas imagens existem e quais imagens voc est vendo agora. (Dica: $.fn.prevAll ser util para isto.)

49

Captulo 7. Ajax
Introduo
O mtodo XMLHttpRequest permite que navegadores se comuniquem com o servidor sem precisar recarregar a pgina. Este mtodo, tambm conhecido como Ajax (Asynchronous JavaScript and XML JavaScript Assncrono e XML), permite ter experincias ricas e interativas nas pginas web. Requisies Ajax so disparadas por cdigo JavaScript; seu cdigo envia uma requisio a uma URL, e quando recebe uma resposta, uma funo de callback pode ser acionada para trat-la. Pelo motivo da requisio ser assncrona, o resto do seu cdigo continur executando enquanto a requisio processada, sendo assim, imperativo que um callback seja usado para lidar com a resposta. O jQuery prov suporte Ajax que abstrai as dolorosas diferenas entre navegadores. Ele oferece mtodos completos como o $.ajax(), e alguns mtodos de convenincia como $.get(), $.getScript(), $.getJSON(), $.post() e $().load(). A maior parte das aplicaes jQuery no usam XML apesar do nome "Ajax"; ao invs disso, elas transportam HTML puro ou JSON (JavaScript Object Notation - Notao de Objeto do JavaScript). Em geral, Ajax no funciona atravs de domnios diferentes. As excees so servios que fornecem suporte ao JSONP (JSON com padding), que permite uma limitada funcionalidade entre domnios.

Conceitos Chave
O uso apropriado de mtodos relacionados ao Ajax requer o conhecimento de alguns conceitos-chave.

GET vs. POST


Os mtodos mais comuns para enviar uma requisio ao servidor so o GET e o POST. importante entender a aplicao apropriada para cada um. O mtodo GET deve ser usado para operaes no-destrutivas - ou seja, operaes que voc apenas esteja "pegando" dados do servidor, sem modificar nenhum dado no servidor. Por exemplo, uma consulta para fazer uma busca pode ser uma requisio GET. Requisies GET podem ser cacheadas pelo navegador, que pode levar a comportamentos imprevisveis se voc no tomar cuidado. Requisies GET geralmente enviam todos os seus dados na string de requisio. O mtodo POST deve ser usado para operaes destrutivas - ou seja, operaes onde voc muda dados no servidor. Por exemplo, um usurio salvando o post de um blog deve ser uma requisio POST. Requisies POST geralmente no so cacheadas pelo navegador; uma string de requisio pode fazer parte da URL, mas os dados tendem a ser enviados separadamente como uma requisio POST.

Tipos de dados
O jQuery geralmente requer alguma instruo a respeito do tipo de dados que voc espera obter com uma requisio Ajax; em alguns casos, o tipo de dado especificado no nome do mtodo e em outros casos fornecido como parte do objeto de configurao. H vrias opes: texto html Para transportar strings simples Para transportar blocos de HTML para serem colocados na pgina

50

Ajax

script json

Para adicionar um novo script pgina Para transportar dados formatados no estilo JSON, que pode incluir strings, arrays e objetos

Nota
No jQuery 1.4, se os dados JSON enviados pelo seu servidor no estiverem propriamente formatados, a requisio pode falhar silenciosamente. D uma olhada em http://json.org para detalhes sobre formatao correta do JSON, mas como regra geral, use mtodos j prontos da linguagem usada no servidor para gerar JSON sem erros de sintaxe. jsonp xml Para transportar dados JSON de outro domnio. Para transporte de dados em um XML

Eu sou um forte proponente no uso de JSON na maioria dos casos, de forma que ele prov a maior flexibilidade. especialmente til para enviar HTML e dados ao mesmo tempo.

A de assncrono
A assincronicidade do Ajax pega muitos novos usurios do jQuery desprevinidos. Pelo fato das chamadas Ajax serem assncronas por padro, a resposta no estar disponvvel imediatamente. Respostas s podem ser manipuladas por um callback. Ento, por exemplo, o cdigo seguinte no ir funcionar: $.get('foo.php'); console.log(response); Ao invs disso, ns temos que passar um funo callback para nossa requisio; Este callback ser executado quando a requisio for realizada com sucesso, e neste ponto que poderemos acessar os dados que ela retornou, se houver algum. $.get('foo.php', function(response) { console.log(response); });

Regra da mesma origem e JSONP


Em geral, as requisies Ajax so limitadas ao mesmo protocolo (http ou https), a mesma porta, e ao mesmo domnio da pgina que est fazendo a requisio. Estas limitaes no se aplicam a scripts que so carregados pelos mtodos Ajax do jQuery. As outras excees so requisies direcionadas a um servio JSONP em outro domnio. No caso do JSONP, o provedor do servio tem que concordar em responder a sua requisio com um script que pode ser carregado dentro da mesma pgina usando uma tag <script>, assim evitando a limitao da mesma origem; este script ter os dados que voc requisitou encapsulado em uma funo de callback que voc especificou.

Ajax e o Firebug
O Firebug (ou o Webkit Inspector no Chrome ou Safari) uma ferramenta indispensvel para trabalhar com requisies Ajax. Voc pode ver as requisies Ajax no mesmo instante que elas acontecem na tab Console do Firebug (e no painel Resources > XHR do Webkit Inspector), e voc pode clicar numa requisio para expand-la e ver os detalhes como os headers de requisio, de resposta, contedo e mais. Se alguma coisa no estiver acontecendo como esperado com uma requisio Ajax, este o primeiro lugar para ver o que est acontecendo de errado.

51

Ajax

Mtodos do jQuery relacionados ao Ajax


Enquanto o jQuery oferece muitos mtodos convenientes relacionados ao Ajax, o corao de todos eles o mtodo $.ajax e entend-lo imperativo. Ns vamos revis-lo primeiro e ento dar uma olhada rpida nos mtodos de convenincia. Eu geralmente uso o mtodo $.ajax e no uso os mtodos de convenincia. Como voc poder ver, ele fornece recursos que os mtodos de convenincia no oferecem e sua sintaxe mais facilmente inteligvel, na minha opinio.

$.ajax
O mtodo core $.ajax uma forma simples e poderosa de criar requisies Ajax. Ele utiliza um objeto de configurao que contm todas as instrues que o jQuery precisa para completar a requisio. O mtodo $.ajax particularmente til porque ele oferece a habilidade de especificar callbacks de sucesso e falha. H tambm a possibilidade de pegar um objeto de configurao definido separadamente, fazendo que seja fcil escrever cdigo reutilizvel. Para documentao completa das opes de configurao, visite http:// api.jquery.com/jQuery.ajax/.

52

Ajax

Exemplo 7.1. Usando o mtodo core $.ajax


$.ajax({ // a URL para requisio url : 'post.php', // Os dados a serem enviados // (sero convertidos em uma string de requisio) data : { id : 123 }, // se esta uma requisio POST ou GET method : 'GET', // o tipo de dados que ns esperamos dataType : 'json', // cdigo a ser executado se a requisio // for executada com sucesso; a resposta // passada para a funo success : function(json) { $('<h1/>').text(json.title).appendTo('body'); $('<div class="content"/>') .html(json.html).appendTo('body'); }, // cdigo a ser executado se a requisio // falhar. A requisio bruta e os cdigos // de status so passados para funo error : function(xhr, status) { alert('Desculpa, aconteceu um problema!'); }, // Cdigo a ser executado independetemente // do sucesso ou falha complete : function(xhr, status) { alert('A requisio est completa!'); } });

Nota
Uma nota a respeito da configurao dataType: se o servidor enviar dados que esto num formato diferente que voc especificou, seu cdigo poder falhar, e a razo nem sempre ser clara, por que o cdigo de resposta HTTP no ir mostrar um erro. Quando estiver trabalhando com requisies Ajax, tenha certeza que o servidor est retornando os dados com o formato que voc especificou e verifique se o header Content-type est de acordo com o tipo de dados. Por exemplo, para dados JSON, o header Content-type deve ser application/json.

Opes do $.ajax
H vrias, vrias opes para o mtodo $.ajax, que parte do seu poder. Para uma lista completa de opes, visite http://api.jquery.com/jQuery.ajax/; aqui vo algumas opes que voc ir usar frequentemente:

53

Ajax

async

Configure para false se a requisio deve ser enviada de forma sncrona. O padro true. Perceba que se voc configurar esta opo para falso, sua requisio bloquear a execuo de outro cdigo at que a resposta seja recebida. Usado se a resposta disponvel for cachevel. O padro true para todos os tipos de dados, exceto "script" e "jsonp". Quando setado para falso, a URL simplesmente ter um parmetro a mais anexado a ela para evitar o cache. Uma funo callback para executar quando a requisio estiver completa, independetemente de sucesso ou falha. A funo recebe o objeto bruto da requisio e o texto de status da mesma. O escopo em que a funo callback deve executar (ou seja, o que this ir significar dentro da(s) funo(es) callback). Por padro, this dentro das funes callback refere ao objeto originalmente passado para $.ajax. Os dados a serem enviados para o servidor. Isto pode ser tanto um objeto quanto uma string de requisio, como foo=bar&baz=bim. O tipo de dado que voc espera do servidor. Por padro, o jQuery ir olhar o MIME type da resposta se nenhum tipo de dados for especificado. Uma funo callback para ser executa se a requisio resultar em um erro. A funo recebe o objeto bruto de requisio e o texto de status da requisio. O nome da funo de callback para enviar na string de requisio quando estiver fazendo uma requisio JSONP. O padro "callback". Uma funo de callback para ser executada se a requisio tiver xito. A funo recebe os dados de resposta (convertidos para um objeto JavaScript se o tipo de dados for JSON), e o texto de status da requisio e o objeto bruto da requisio. O tempo em milisegundos a se esperar antes de considerar que a reqsuisio falhou. Configure para true para usar o tipo de serializao param em verses anteriores ao jQuery 1.4. Para detalhes, veja: http://api.jquery.com/jQuery.param/. O tipo da requisio, "POST" ou "GET". O padro "GET". Outros tipos de requisies, como "PUT" e "DELETE" podem ser utilizados, mas eles talvez no sejam suportados por todos os navegadores. A URL para requisio.

cache

complete

context

data

dataType

error

jsonp

success

timeout traditional

type

url

A opo url a nica propriedade obrigatria do objeto de configurao do mtodo $.ajax; todas as outras propriedades so opcionais.

Mtodos de convenincia
Se voc no precisa da configurao extensiva do $.ajax, e voc no se preocupa sobre manipulao de erros, as funes de convenicia providas pelo jQuery podem ser uma forma til e lapidada para executar requisies Ajax. Estes mtodos so somente "encapsulamentos" em torno do mtodo $.ajax, e simplesmente pr setam algumas das opes no mtodo $.ajax. Os mtodos de convenincia providos pelo jQuery so:

54

Ajax

$.get $.post $.getScript $.getJSON

Executa uma requisio GET para a URL informada. Executa uma requisio POST para a URL informada. Adiciona um script pgina. Executa uma requisio GET com expectativa de retorno de um JSON.

Em cada caso, os mtodos pegam os seguintes argumentos, em ordem: url data A URL para requisio. Obrigatrio. Os dados para serem enviados para o servidor. Opcional. Pode ser tanto um objeto quanto uma string de requisio, como foo=bar&baz=bim.

Nota
Esta opo no vlida para $.getScript. callback de successo Uma funo de callback para executar se a requisio for executada com sucesso. Opcional. A funo recebe os dados de resposta (convertidos para um objeto JavaScript se o tipo de dados for JSON), assim como o texto de status e o objeto bruto da requisio. O tipo de dados que voc espera de retorno do servidor. Opcional.

tipo de dados

Nota
Esta opo s aplicvel para mtodos que ainda no especificaram o tipo de dados no seu nome.

Exemplo 7.2. Usando os mtodos de convenincia do jQuery


// pega um texto puro ou html $.get('/users.php', { userId : 1234 }, function(resp) { console.log(resp); }); // adiciona um script na pgina, e ento executa uma funo // definida nele $.getScript('/static/js/myScript.js', function() { functionFromMyScript(); }); // pega dados formatados em JSON do servidor $.getJSON('/details.php', function(resp) { $.each(resp, function(k, v) { console.log(k + ' : ' + v); }); });

$.fn.load
O mtodo $.fn.load nico dentre os mtodos de Ajax do jQuery que chamado em uma seleo. O mtodo $.fn.load pega o HTML de uma URL, e usa o HTML retornado para popular o(s) elemento(s)

55

Ajax

selecionados. Em adio URL informada, voc ainda pode informar um seletor; o jQuery ir pegar somente o elemento correspondente do HTML retornado.

Exemplo 7.3. Usando o $.fn.load para popular um elemento


$('#newContent').load('/foo.html');

Exemplo 7.4. Usando o $.fn.load para popular um elemento baseado no seletor


$('#newContent').load('/foo.html #myDiv h1:first', function(html) { alert('Contedo atualizado!'); });

Ajax e formulrios
As funcionalidades de Ajax do jQuery podem ser especialmente teis ao lidar com formulrios. O jQuery Form Plugin [http://jquery.malsup.com/form/] uma ferramenta bem testada para adicionar funcionalidades de Ajax nos formulrios e voc deve us-lo para manipular formulrios com Ajax ao invs de usar sua prpria soluo para alguma coisa mais complexa. Mas ainda h dois mtodos do jQuery relacionados processamento de formulrios que voc deve conhecer: $.fn.serialize e $.fn.serializeArray.

Exemplo 7.5. Transformando os dados de um formulrio em uma string de requisio


$('#myForm').serialize(); // cria uma estrutura como esta: name=campo1&value=123

Exemplo 7.6. Criando um array de objetos contendo dados do formulrio.


$('#myForm').serializeArray(); // cria uma estrutura como esta: [ { name : 'campo1', value : 123 }, { name : 'campo2', value : 'ol mundo!' } ]

Trabalhando com JSONP


O advento do JSONP -- essencialmente um hack consensual para cross-site scripting -- abriu a porta para mashups de contedo bem poderosos. Muitos sites provem servios JSONP, permitindo que voc acesse o contedo deles atravs de uma API pr-definida. Uma boa fonte de dados formatados em JSONP o Yahoo! Query Language [http://developer.yahoo.com/yql/console/], que ns iremos usar no prximo exemplo para pegar notcias a respeito de gatos.

56

Ajax

Exemplo 7.7. Usando YQL e JSONP


$.ajax({ url : 'http://query.yahooapis.com/v1/public/yql', // o nome do parmetro de callback, // como especificado pelo servio do YQL jsonp : 'callback', // fala para o jQuery que estamos esperando JSONP dataType : 'jsonp', // fala para o YQL o que ns queremos e que queremos em JSON data : { q : 'select title,abstract,url from search.news where query="gato"', format : 'json' }, // trabalha com a resposta success : function(response) { console.log(response); } }); O jQuery manipula todos os aspectos complexos por trs do JSONP -- tudo que ns temos que fazer falar para o jQuery o nome do callback JSONP especificado pelo YQL ("callback" neste caso), e todo o processo se parece com uma requisio Ajax normal.

Eventos do Ajax
Frequentemente, voc ir querer fazer algo depois que uma requisio Ajax inicia ou termina, como exibir ou mostrar um indicador de carregamento. Ao invs de definir este comportamento dentro de cada requisio Ajax, voc pode associar eventos do Ajax elementos da mesma forma que voc associa outros eventos. Para uma lista completa de de eventos do Ajax, visite http://docs.jquery.com/Ajax_Events.

Exemplo 7.8. Configurando um indicador de carregamento usando eventos do Ajax


$('#loading_indicator') .ajaxStart(function() { $(this).show(); }) .ajaxStop(function() { $(this).hide(); });

Exerccios
Carregar contedo externo
Abra o arquivo /exercises/index.htmlno seu navegador. Use o arquivo /exercises/js/ load.js. Sua tarefa carregar o contedo de um item de blog quando um usurio clicar no ttulo do item. 1. Crie uma div alvo depois da headline para cada post do blog e armazene uma referncia para ela na headline usando $.fn.data. 2. Crie um bind do evento click na headline que ir usar o mtodo $.fn.load para carregar o contedo apropriado de /exercises/data/blog.html dentro da div alvo. No se esquea de prevenir a ao padro do evento click.

57

Ajax

Perceba que cada headline do blog em index.html inclui um link para o post. Voc precisar aproveitar o href daquele link para obter o contedo de blog.html. Uma vez que voc tem o href, esta uma forma de process-lo num ID que voc pode usar como seletor em $.fn.load: var href = 'blog.html#post1'; var tempArray = href.split('#'); var id = '#' + tempArray[1]; Lembre-se de fazer uso liberal de console.log para ter certeza que voc est no caminho correto!

Carregando contedo usando JSON


Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ specials.js. Sua tarefa mostrar os detalhes do usurio para um dado dia quando o usurio seleciona um dia no menu dropdown de seleo. 1. Anexe uma div alvo depois do formulrio que est dentro do elemento #specials; este ser o lugar onde voc colocar informaes sobre o especial uma vez que voc recebeu a resposta do servidor. 2. Faa um bind no evento change do elemento select; quando o usurio mudar a seleo, envie uma requisio Ajax para /exercises/data/specials.json. 3. Quando a requisio retornar um resposta, use o valor que o usurio selecionou no select (dica: $.fn.val) para procurar informaes sobre o especial na resposta JSON. 4. Adicione algum HTML sobre o especial na div alvo que voc criou. 5. Por ltimo, pelo fato do form ter Ajax habilitado, retire o boto submit do form. Perceba que ns estamos carregando o JSON todas as vezes que o usurio muda a seleo. Como podemos mudar o cdigo para que uma requisio s seja feita uma nica vez e ento usarmos a resposta cacheada quando o usurio modificar a caixa de seleo?

58

Captulo 8. Plugins
O que exatamente um plugin?
Um plugin do jQuery simplesmente um novo mtodo que ns usamos para extender o prottipo de objeto do jQuery. Atravs da extenso do prottipo, voc permite que todos os objetos do jQuery herdem quaisquer mtodos que voc adicionar. Como estabelecido, sempre que voc chama jQuery() voc est criando um novo objeto do jQuery, com todos os mtodos herdados. A idia de um plugin fazer alguma coisa com uma coleo de elementos. Voc pode considerar que cada mtodo que vem com o core do jQuery seja um plugin, como fadeOut ou addClass. Voc pode fazer seus prprios plugins e us-los privadamente no seu cdigo ou voc pode liber-lo para comunidade. H milhares de plugins para o jQuery disponveis online. A barreira para criar um plugin prprio to pequena que voc desejar fazer um logo "de cara"!

Como criar um plugin bsico


A notao para criar um novo plugin a seguinte: (function($){ $.fn.myNewPlugin = function() { return this.each(function(){ // faz alguma coisa }); }; }(jQuery)); Mas no se deixe confundir. O objetivo de um plugin do jQuery extender o prottipo do objeto do jQuery, e isso o que est acontecendo nesta linha: $.fn.myNewPlugin = function() { //... Ns encapsulamos esta associao numa funo imediatamente invocada: (function($){ //... }(jQuery)); Isso possui o efeito de criar um escopo "privado" que nos permite extender o jQuery usando o smbolo de dlar sem ter o risco de ter o dlar sobrescrito por outra biblioteca. Ento nosso verdadeiro plugin, at agora, este: $.fn.myNewPlugin = function() { return this.each(function(){ // faz alguma coisa }); }; A palavra chave this dentro do novo plugin refere-se ao objeto jQuery em que o plugin est sendo chamado.

59

Plugins

var somejQueryObject = $('#something'); $.fn.myNewPlugin = function() { alert(this === somejQueryObject); }; somejQueryObject.myNewPlugin(); // alerta 'true' Seu objeto jQuery tpico conter referncias para qualquer nmero de elementos DOM, e esse o porqu que objetos jQuery so geralmente referenciados colees. Ento, para fazer algo com uma coleo, ns precisamos iterar sobre ela, que mais facilmente feito utilizando o mtodo each() do jQuery: $.fn.myNewPlugin = function() { return this.each(function(){ }); }; O mtodo each() do jQuery, assim como a maioria dos outros mtodos, retornam um objeto jQuery, permitindo-nos assim que possamos saber e adorar o 'encadeamento' ($(...).css().attr()...). Ns no gostaramos de quebrar esta conveno, ento ns retornamos o objeto this. Neste loop, voc poder fazer o que voc quiser com cada elemento. Este um exemplo de um pequeno plugin utilizando uma das tcnicas que ns discutimos: (function($){ $.fn.showLinkLocation = function() { return this.filter('a').each(function(){ $(this).append( ' (' + $(this).attr('href') + ')' ); }); }; }(jQuery)); // Exemplo de uso: $('a').showLinkLocation(); Este prtico plugin atravessa todas as ncoras na coleo e anexa o atributo href entre parnteses. <!-- antes do plugin ser chamado: --> <a href="page.html">Foo</a> <!-- Depois que o plugin foi chamado: --> <a href="page.html">Foo (page.html)</a> Nosso plugin pode ser otimizado: (function($){ $.fn.showLinkLocation = function() { return this.filter('a').append(function(){ return ' (' + this.href + ')'; }); };

60

Plugins

}(jQuery)); Ns estamos utilizando a capacidade de aceitao de um callback do mtodo append, e o valor de retorno deste callback ir determinar o que ser aplicado a cada elemento na coleo. Perceba tambm que ns no estamos usando o mtodo attr para obter o atributo href, pois a API do DOM nativa nos d um acesso facilitado atravs da propriedade href. Este um outro exemplo de plugin. Este no requer que ns faamos uma iterao sobre todos os elementos com o mtodo each()., Ao invs disso, ns simplesmente iremos delegar para outros mtodo do jQuery diretamente: (function($){ $.fn.fadeInAndAddClass = function(duration, className) { return this.fadeIn(duration, function(){ $(this).addClass(className); }); }; }(jQuery)); // Exemplo de uso: $('a').fadeInAndAddClass(400, 'finishedFading');

Procurando & Avaliando Plugins


Os plugins extendem funcionalidades bsicas do jQuery, e um dos aspectos mais celebrados da biblioteca seu extensivo ecossistema de plugins. De ordenao de tabelas validao de formulrio e autocompletamento ... se h uma necessidade para algo, h boas chances que algum j tenha escrito um plugin para isso. A qualidade dos plugins do jQuery varia muito. Muitos plugins so extensivamente testados e bem mantidos, mas outros so porcamente criados e ento ignorados. Mais do que algumas falhas para seguir as melhores prticas. O Google seu melhor recurso inicial para localizao de plugins, embora o time do jQuery esteja trabalhando em um repositrio de plugin melhorado. Uma vez que voc identificou algumas opes atravs de uma busca do Google, voc pode querer consultar a lista de emails do jQuery ou o canal de IRC #jquery para obter informaes de outros. Quando estiver procurando por um plugin para preencher uma necessidade, faa seu trabalho de casa. Tenha certeza que o plugin bem documentado, e veja se o autor prov vrios exemplos do seu uso. Tenha cuidado com plugins que fazem muito mais do que voc precisa; eles podem acabar adicionando um overhead substancial sua pgina. Para mais dicas sobre como identificar um plugin ruim, leia Signs of a poorly written jQuery plugin [http://remysharp.com/2010/06/03/signs-of-a-poorly-written-jquery-plugin/] do Remy Sharp. Uma vez que voc escolhe um plugin, voc precisar adicion-lo sua pgina. Baixe o plugin, descompacte-o se necessrio, coloque-o no diretrio da sua aplicao e ento inclua o plugin na sua pgina usando uma tag script (depois que voc incluir o jQuery).

Escrevendo Plugins
Algumas vezes voc quer que uma pequena funcionalidade esteja disponvel pelo seu cdigo; por exemplo, talvez voc queira que um simples mtodo possa ser chamado para executar uma srie de operaes sobre uma seleo do jQuery. Neste caso, voc pode querer escrever um plugin.

61

Plugins

A maioria dos plugins do jQuery so simplesmente mtodos criados no namespace $.fn. O jQuery garante que um mtodo chamado num objeto jQuery possa acessar aquele objeto jQuery como this dentro do mtodo. Em retorno, seu plugin precisa garantir que ele retorna o mesmo objeto que ele recebeu, a menos que o contrrio seja explicitamente documentado. Este um exemplo de um plugin simples:

Exemplo 8.1. Criando um plugin para adicionar e remover uma classe no hover
// definindo o plugin (function($){ $.fn.hoverClass = function(c) { return this.hover( function() { $(this).toggleClass(c); } ); }; }(jQuery); // utilizando o plugin $('li').hoverClass('hover'); Para mais informaes sobre desenvolvimento de plugins, leia o post essencial do Mike Alsup's, A Plugin Development Pattern [http://www.learningjquery.com/2007/10/a-plugin-development-pattern]. Nele, ele cria um plugin chamado $.fn.hilight, que prov suporte para o plugin de metadados se ele estiver presente e prov um mtodo centralizado para configurao central e opes de instncia para o plugin.

62

Plugins

Exemplo 8.2. O Padro de Desenvolvimento de Plugins do Mike Alsup


// // cria a closure // (function($) { // // definio do plugin // $.fn.hilight = function(options) { debug(this); // constri as opes principais antes da iterao com elemento var opts = $.extend({}, $.fn.hilight.defaults, options); // itera e reformata cada elemento encontrado return this.each(function() { $this = $(this); // constri opes especficas do elemento var o = $.meta ? $.extend({}, opts, $this.data()) : opts; // atualiza estilos do elemento $this.css({ backgroundColor: o.background, color: o.foreground }); var markup = $this.html(); // chama nossa funo de formatao markup = $.fn.hilight.format(markup); $this.html(markup); }); }; // // funo privada para debugging // function debug($obj) { if (window.console && window.console.log) window.console.log('hilight selection count: ' + $obj.size()); }; // // define e expe nossa funo de formatao // $.fn.hilight.format = function(txt) { return '<strong>' + txt + '</strong>'; }; // // padres do plugin // $.fn.hilight.defaults = { foreground: 'red', background: 'yellow' }; // // fim da closure // })(jQuery);

63

Plugins

Escrevendo plugins com estado utilizando a fbrica de widgets do jQuery UI


Nota
Esta seo baseada, com permisso, no post de blog Building Stateful jQuery Plugins [http:// blog.nemikor.com/2010/05/15/building-stateful-jquery-plugins/] de Scott Gonzalez. Enquanto a maioria dos plugins para jQuery so stateless - isto , ns os chamamos num elemento e isso a extenso de nossa interao com o plugin - h um grande conjunto de funcionalidades que no se encaixam no padro bsico de plugins. Como forma de preencher esta lacula, o jQuery UI implementa um sistema de plugin mais avanado. O novo sistema gerencia estado, permite mltiplas funes sendo expostas atravs de um plugin simples, e prov vrios pontos de extenso. Este sistema chamado de fbrica de widgets e exposto como jQuery.widget e faz parte do jQuery UI 1.8; entretanto, pode ser usado independentemente do jQuery UI. Para demonstrar as capacidades da fbrica de widget, ns iremos fazer um simples plugin para barra de progresso. Para iniciar, ns iremos criar uma barra de progresso que nos permite especificar o progresso uma s vez. Como podemos ver abaixo, isso pode ser feito atravs da chamada jQuery.widget com dois parmetros: o nome do plugin a ser criado e um literal objeto contendo funes para dar suporte ao nosso plugin. Quando nosso plugin for chamado, ele ir criar uma nova instncia do plugin e todas as funes sero executadas dentro do contexto desta instncia. Isso diferente de um plugin padro do jQuery em duas formas importantes. Primeiro, o contexto um objeto, no um elemento do DOM. Segundo, o contexto sempre um objeto, nunca uma coleo.

Exemplo 8.3. Um plugin simples, stateful utilizando a fbrica de widgets do jQuery UI.
$.widget("nmk.progressbar", { _create: function() { var progress = this.options.value + "%"; this.element .addClass("progressbar") .text(progress); } }); O nome do plugin precisa conter um namespace; neste caso ns usamos o namespace nmk. H uma limitao que namespaces tm que ter exatamente um nvel de profundidade - isto , ns no podemos usar um namespace como nmk.foo. Ns podemos tambm ver que a fbrica de widgets nos deu duas propriedades. this.element um objeto jQuery contendo exatamente um elemento. Se nosso plugin chamado num objeto do jQuery contendo mtiplos elementos, uma instncia nova ser criada para cada elemento e cada instncia ter seu prprio this.element. A segunda propriedade, this.options, um hash contendo pares chave/valor para todas as nossas opes do plugin. Estas opes podem ser passadas para nosso plugin como mostrado aqui.

64

Plugins

Nota
No nosso exemplo, ns usamos o namespace nmk. O namespace ui reservado para plugins oficiais do jQuery UI. Quando fizer seus prprios plugins, voc deve criar seu prprio namespace. Isso deixa claro de onde o plugin veio e se ele faz parte de uma coleo maior.

Exemplo 8.4. Passando opes para um Widget


$("<div></div>") .appendTo( "body" ) .progressbar({ value: 20 }); Quando ns chamamos jQuery.widget, ele estende o jQuery adicionando um mtodo em jQuery.fn (da mesma forma que ns criamos um plugin padro). O nome da funo que ele adiciona baseado no nome que voc passa para o jQuery.widget, sem o namespace; no nosso caso ele ir criar jQuery.fn.progressbar. As opes passadas para nosso plugins esto em this.options, dentro de nossa instncia do plugin. Como mostrado abaixo, ns podemos especificar valores padro para qualquer uma das nossas opes. Quando estiver projetando sua API, voc deve perceber o caso mais comum para seu plugin de modo que voc possa setar valores padro e fazer todas as opes verdadeiramente opcionais.

Exemplo 8.5. Setando opes padro para um Widget


$.widget("nmk.progressbar", { // opes padro options: { value: 0 }, _create: function() { var progress = this.options.value + "%"; this.element .addClass( "progressbar" ) .text( progress ); } });

Adicionando mtodos a um Widget


Agora que ns podemos inicializar nossa barra de progresso, ns iremos adicionar a habilidade de executar aes atravs da chamada de mtodos na instncia do nosso plugin. Para definir um mtodo do plugin ns simplesmente inclumos a funo num literal objeto que ns passamos para jQuery.widget. Ns tambm podemos definir mtodos privados se adicionarmos um underscore ("_") antes do nome da funo.

65

Plugins

Exemplo 8.6. Criando mtodos para um Widget


$.widget("nmk.progressbar", { options: { value: 0 }, _create: function() { var progress = this.options.value + "%"; this.element .addClass("progressbar") .text(progress); }, // cria um mtodo pblico value: function(value) { // nenhum valor passado, atuando como um getter if (value === undefined) { return this.options.value; // valor passado, atuando como um setter } else { this.options.value = this._constrain(value); var progress = this.options.value + "%"; this.element.text(progress); } }, // criando um mtodo privado _constrain: function(value) { if (value > 100) { value = 100; } if (value < 0) { value = 0; } return value; } }); Para chamar um mtodo numa instncia do plugin, voc precisa passar o nome do mtodo para o plugin do jQuery. Se voc estiver chamando um mtodo que aceita parmetros, voc simplemente passa estes parmetros depois do nome do mtodo.

66

Plugins

Exemplo 8.7. Chamando mtodos numa instncia do plugin


var bar = $("<div></div>") .appendTo("body") .progressbar({ value: 20 }); // pega o valor atual alert(bar.progressbar("value")); // atualiza o valor bar.progressbar("value", 50); // pega o valor atual denovo alert(bar.progressbar("value"));

Nota
Executar mtodos atravs da passagem do nome do mesmo para a mesma funo do jQuery que foi usada para inicializar o plugin pode parecer estranho. Isso feito para previnir a poluio do namespace do jQuery enquanto mantm a habilidade de encadear chamadas de mtodos.

Trabalhando com Opes de Widget


Um dos mtodos que automaticamente disponvel para nosso plugin o mtodo option. O mtodo option permite que voc obtenha e defina opes depois da inicializao. Este mtodo funciona exatamente como os mtodos css e attr do jQuery: voc pode passar somente o nome para us-lo como um getter, um nome e um valor para us-lo com um setter nico, ou um hash de pares nome/valor para setar mltiplos valores. Quando usado como um getter, o plugin ir retornar o valor atual da opo que corresponde ao nome que foi passado. Quando usado como um setter, o mtodo _setOption do plugin ser chamado para cada opo que estiver sendo setada. Ns podemos especificar um mtodo _setOption no nosso plugin para reagir a mudanas de opo.

Exemplo 8.8. Respondendo quando a opo setada


$.widget("nmk.progressbar", { options: { value: 0 }, _create: function() { this.element.addClass("progressbar"); this._update(); }, _setOption: function(key, value) { this.options[key] = value; this._update(); }, _update: function() { var progress = this.options.value + "%"; this.element.text(progress); } });

67

Plugins

Adicionando Callbacks
Uma das formas mais fceis de fazer seu plugin estensvel adicionar callbacks para que os usurios possam reagir quando o estado do plugin mudar. Ns podemos ver abaixo como adicionar um callback nossa barra de progresso para enviar um sinal quando a barra de progresso chegar 100%. O mtodo _trigger requer trs parmetros: o nome do callback, um objeto de evento nativo que iniciou o callback, e um hash de dados relevantes para o evento. O nome do callback o nico parmetro requerido, mas os outros podem ser muito teis para usurios que querem implementar funcionalidades customizadas no topo do seu plugin. Por exemplo, se ns construssemos um plugin arrastvel, ns poderamos passar o evento mouseover nativo quando dispararmos o callback de arrastar; Isso permitiria que usurios reagissem ao arraste baseado nas coordenadas x/y providas pelo objeto do evento.

Exemplo 8.9. Provendo callbacks para extenso do usurio


$.widget("nmk.progressbar", { options: { value: 0 }, _create: function() { this.element.addClass("progressbar"); this._update(); }, _setOption: function(key, value) { this.options[key] = value; this._update(); }, _update: function() { var progress = this.options.value + "%"; this.element.text(progress); if (this.options.value == 100) { this._trigger("complete", null, { value: 100 }); } } }); Funes de callback so essencialmente opes adicionais, ento voc pode obter e set-las como qualquer outra opo. Quando um callback executado, um evento correspondente executado tambm. O tipo do evento determinado pela concatenao do nome do plugin e do nome do callback. O callback e o evento recebem os mesmos dois parmetros: um objeto evento e um hash dos dados relevantes para o evento, como veremos a seguir. Se seu plugin tem funcionalidade que voc deseja permitir que o usurio previna, a melhor forma de suportar isso criando callbacks cancelveis. Usurios podem cancelar um callback, ou seu evento associado, da mesma forma que eles cancelam qualquer evento nativo: chamando event.preventDefault() ou usando return false. Se o usurio cancelar o callback, o mtodo _trigger ir retornar falso para que voc implemente a funcionalidade apropriada dentro do seu plugin.

68

Plugins

Exemplo 8.10. Vinculando eventos do Widget

var bar = $("<div></div>") .appendTo("body") .progressbar({ complete: function(event, data) { alert( "Callbacks so timos!" ); } }) .bind("progressbarcomplete", function(event, data) { alert("Eventos borbulham e suportam muitos manipuladores para extrema flexi alert("O valor da barra de progresso " + data.value); }); bar.progressbar("option", "value", 100); A Fbrica de Widget: Nos Bastidores Quando voc chama jQuery.widget, ele cria uma funo construtora para seu plugin e seta o literal objeto que voc passou como prottipo para suas instncias do plugin. Todas as funcionalidades que so automaticamente adicionadas a seu plugin vem de um prottipo base de widget, que definido como jQuery.Widget.prototype. Quando uma instncia do plugin criada, ela armazenada no elemento DOM original utilizando jQuery.data, com o plugin tendo o mesmo nome da chave. Pelo fato da instncia do plugin estar diretamente ligada ao elemento DOM, voc pode acessar a instncia do plugin diretamente ao invs de ir ao mtodo exposto do plugin. Isso permitir que voc chame mtodos diretamente na instncia do plugin ao invs de passar nomes de mtodos como strings e tambm lhe dar acesso direto s propriedades do plugin. var bar = $("<div></div>") .appendTo("body") .progressbar() .data("progressbar"); // chama um mtodo diretamente na instncia do plugin bar.option("value", 50); // acessa propriedades na instncia do plugin alert(bar.options.value); Um dos maiores benefcios de ter um construtor e um prottipo para um plugin a facilidade de estend-lo. Podemos modificar o comportamento de todas as instncias do nosso plugin adicionando ou modificando mtodos no prottipo do plugin. Por exemplo, se quisssemos adicionar um mtodo nossa barra de progresso para resetar o progresso para 0%, ns poderamos adicionar este mtodo ao prottipo e ele estaria instantaneamente disponvel para ser chamado em qualquer instncia do plugin. $.nmk.progressbar.prototype.reset = function() { this._setOption("value", 0); };

69

Plugins

Limpando
Em alguns casos, faz sentido permitir usurios aplicar seu plugin e desaplic-lo depois. Voc pode fazer isso pelo mtodo destroy. Dentro do mtodo destroy, voc deve desfazer qualquer coisa que seu plugin possa ter feito desde o incio. O mtodo destroy automaticamente chamado se o elemento que a instncia do seu plugin est amarrado removido do DOM, para que isso seja usado para coleo de lixo (garbage collection). O mtodo destroy padro remove a ligao entre o elemento DOM e a instncia do plugin, ento importante chamar a funo destroy base dentro do destroy do seu plugin.

Exemplo 8.11. Adicionando um mtodo destroy um Widget


$.widget( "nmk.progressbar", { options: { value: 0 }, _create: function() { this.element.addClass("progressbar"); this._update(); }, _setOption: function(key, value) { this.options[key] = value; this._update(); }, _update: function() { var progress = this.options.value + "%"; this.element.text(progress); if (this.options.value == 100) { this._trigger("complete", null, { value: 100 }); } }, destroy: function() { this.element .removeClass("progressbar") .text(""); // chama funo destroy base $.Widget.prototype.destroy.call(this); } });

Concluso
A fbrica de widget o nico jeito de criar plugins com estado. H alguns poucos modelos diferentes que podem ser usados e cada um tem suas vantagens e desvantagens. A fbrica de widget resolve muitos dos problemas comuns para voc e pode melhorar muito a produtividade e tambm melhora bastante o reuso de cdigo, fazendo com que funcione bem para o jQuery UI e para outros plugins com estado.

70

Plugins

Exerccios
Fazendo uma tabela ordenvel
Para este exerccio, sua tarefa identificar, baixar, e implementar um plugin para ordenamento de tabela na pgina index.html. Quando terminar, todas as colunas da tabela na pgina devem ser ordenveis.

Escreva um plugin para listrar tabelas


Abra o arquivo/exercises/index.html no seu navegador. Use o arquivo /exercises/js/ stripe.js. Sua tarefa escrever um plugin chamado "stripe" que voc possa chamar em qualquer elemento table. Quando o plugin for chamado no elemento table, ele deve modificar as cores das linhas mpares no corpo da tabela para uma cor especificada pelo usurio. $('#myTable').stripe('#cccccc'); No se esquea de retornar a tabela para que outros mtodos possam ser encadeados depois do plugin!

71

Parte III. Tpicos Avanados

Esta seo um trabalho em andamento


Por favor, visite http://github.com/rmurphey/jqfundamentals para contribuir!

73

Captulo 9. Melhores prticas para performance


Este captulo cobre um nmero de melhores prticas de jQuery e JavaScript, sem uma ordem particular. Muitas das melhores prticas neste captulo so baseadas na apresentao Anti-padres do jQuery para performance [http://paulirish.com/perf] por Paul Irish.

Armazene o length em loops


Em um loop, no acesse a propriedade length de um array todo tempo; armazene-o em outra varivel antes de manipul-lo. var myLength = myArray.length; for (var i = 0; i < myLength; i++) { // faz alguma coisa }

Adicione novo contedo fora de um loop


Tocar o DOM tem um custo; se voc estiver adicionando muitos elementos ao DOM, faa tudo de uma vez, no um de cada vez. // isto ruim $.each(myArray, function(i, item) { var newListItem = '<li>' + item + '</li>'; $('#ballers').append(newListItem); }); // melhor: faa isso var frag = document.createDocumentFragment(); $.each(myArray, function(i, item) { var newListItem = '<li>' + item + '</li>'; frag.appendChild(newListItem); }); $('#ballers')[0].appendChild(frag); // ou isso var myHtml = ''; $.each(myArray, function(i, item) { html += '<li>' + item + '</li>'; }); $('#ballers').html(myHtml);

Mantenha as coisas DRY


Don't repeat yourself; se voc estiver se repetindo, voc est fazendo errado. 74

Melhores prticas para performance

// RUIM if ($eventfade.data('currently') != 'showing') { $eventfade.stop(); } if ($eventhover.data('currently') != 'showing') { $eventhover.stop(); } if ($spans.data('currently') != 'showing') { $spans.stop(); } // BOM!! var $elems = [$eventfade, $eventhover, $spans]; $.each($elems, function(i,elem) { if (elem.data('currently') != 'showing') { elem.stop(); } });

Cuidado com funes annimas


Funes annimas em todo lugar so dolorosas. Elas so difceis de debugar, manter, testar ou reusar. Ao invs disso, utilize um literal objeto para organizar e nomear seus manipuladores e callbacks. // RUIM $(document).ready(function() { $('#magic').click(function(e) { $('#yayeffects').slideUp(function() { // ... }); }); $('#happiness').load(url + ' #unicorns', function() { // ... }); }); // MELHOR var PI = { onReady : function() { $('#magic').click(PI.candyMtn); $('#happiness').load(PI.url + ' #unicorns', PI.unicornCb); }, candyMtn : function(e) { $('#yayeffects').slideUp(PI.slideCb); }, slideCb : function() { ... }, unicornCb : function() { ... }

75

Melhores prticas para performance

}; $(document).ready(PI.onReady);

Otimize seletores
Otimizao de seletores menos importante do que costumava ser, pois mais navegadores implementam document.querySelectorAll() e a carga de selecionamento muda do jQuery para o navegador. Entretanto, ainda h algumas dicas para se manter em mente.

Seletores baseados em ID
Comear seu seletor com um ID sempre melhor. // rpido $('#container div.robotarm'); // super-rpido $('#container').find('div.robotarm'); A abordagem $.fn.find mais rpida pois a primeira seleo manipulada sem passar pelo engine de seleo do Sizzle - selees s com ID so manipuladas usando document.getElementById(), que extremamente rpido, pois nativo para o navegador.

Especificidade
Seja especfico no lado direito do seu seletor, e menos especfico no esquerdo. // no otimizado $('div.data .gonzalez'); // otimizado $('.data td.gonzalez'); Use tag .class se possvel no seu seletor mais a direita, e somente tag ou .class na esquerda. Evite especificidade excessiva. $('.data table.attendees td.gonzalez'); // melhor: remova o meio se possvel $('.data td.gonzalez'); Um DOM "magro" tambm ajuda a melhorar a performance do seletor, pois a engine de seleo possui poucas camadas para atravessar quando estiver procurando por um elemento.

Evite o seletor universal


Selees que especificam ou deixam implcito que uma combinao pode ser encontrada em qualquer lugar pode ser muito lenta. $('.buttons > *'); // extremamente caro $('.buttons').children(); // muito melhor

76

Melhores prticas para performance

$('.gender :radio'); // seleo universo implcita $('.gender *:radio'); // mesma coisa, explcito agora $('.gender input:radio'); // muito melhor

Use Delegao de Evento


Delegao de evento permite que voc delegue um manipulador de evento a um elemento container (uma lista no-ordenada, por exemplo) ao invs de mltiplos elementos contidos (uma lista de itens, por exemplo). O jQuery torna isso fcil com $.fn.live e $.fn.delegate. Sempre que possvel, voc deve usar $.fn.delegate ao invs de $.fn.live, de forma que isso elimina a necessidade de uma seleo desnecessria e seu contexto explcito (vs. o contexto de $.fn.live do document) reduz a sobrecarga por aproximadamente 80%. Em adio aos benefcios de performance, delegao de eventos tambm permite que voc adicione novos elementos contidos a sua pgina sem ter que re-delegar os manipuladores de eventos para eles quando so necessrios. // ruim (se houver muitos itens de lista) $('li.trigger').click(handlerFn); // melhor: delegao de eventos com $.fn.live $('li.trigger').live('click', handlerFn); // melhor ainda: delegao de eventos com $.fn.delegate // permite que voc especifique um contexto facilmente $('#myList').delegate('li.trigger', 'click', handlerFn);

Desanexe elementos para trabalhar com eles


O DOM lento; voc quer evitar a manipulao o tanto quanto possvel. O jQuery introduziu o $.fn.detach na verso 1.4 para ajudar a solucionar este problema, permitindo que voc remova um elemento do DOM enquanto trabalha com o mesmo. var $table = $('#myTable'); var $parent = table.parent(); $table.detach(); // ... adiciona um bocado de linhas tabela $parent.append(table);

Use folhas de estilo para mudar o CSS em vrios elementos


Se voc estiver mudando o CSS de mais de 20 elementos utilizando $.fn.css, considere adicionar uma tag de estilo pgina para uma melhoria de performance de aproximadamente 60%. // tudo certo para at 20 elementos, lento depois disso $('a.swedberg').css('color', '#asd123'); $('<style type="text/css">a.swedberg { color : #asd123 }</style>') .appendTo('head');

77

Melhores prticas para performance

Use $.data ao invs de $.fn.data


Usando $.data em um elemento DOM ao invs de chamar $.fn.data numa seleo do jQuery pode ser at 10 vezes mais rpido. Tenha certeza que voc entendeu a diferena entre um elemento do DOM e uma seleo do jQuery antes de fazer isso. // regular $(elem).data(key,value);

// 10x mais rpido $.data(elem,key,value);

No faa nada quando no tiver elementos


O jQuery no dir a voc que voc est tentando executar um monte de cdigo numa seleo vazia - ele vai proceder como se nada estivesse errado. sua responsabilidade verificar se sua seleo contm alguns elementos. // RUIM: executa trs funes // antes de perceber que no a nada a se fazer com // a seleo $('#nosuchthing').slideUp(); // MELHOR var $mySelection = $('#nosuchthing'); if ($mySelection.length) { mySelection.slideUp(); } // MELHOR AINDA: adiciona um plugin doOnce jQuery.fn.doOnce = function(func){ this.length && func.apply(this); return this; }

$('li.cartitems').doOnce(function(){ // faa com ajax! \o/ }); Este guia especialmente aplicvel para UI widgets do jQuery, que possuem muita sobrecarga mesmo quando a seleo no contm elementos.

Definio de Varivel
Variveis podem ser definidas em uma declarao ao invs de vrias. // velho & preso

78

Melhores prticas para performance

var test = 1; var test2 = function() { ... }; var test3 = test2(test); // nova onda var test = 1, test2 = function() { ... }, test3 = test2(test); Em funes auto-executveis, podem ser puladas todas as definies de variveis. (function(foo, bar) { ... })(1, 2);

Condicionais
// forma antiga if (type == 'foo' || type == 'bar') { ... } // melhor if (/^(foo|bar)$/.test(type)) { ... } // procura por literal objeto if (({ foo : 1, bar : 1 })[type]) { ... }

No trate o jQuery como uma Caixa Preta


Use os fontes como sua documentao favorite http://bit.ly/jqsource e v a ela frequentemente.

79

Captulo 10. Organizao de cdigo


Viso Geral
Quando voc vai alm de adicionar melhorias simples em seu website com jQuery e comea a desenvolver aplicaes client-side completas, voc precisa considerar como organizar seu cdigo. Neste captulo, ns iremos dar uma olhada em vrios padres para organizao de cdigo que voc pode utilizar em usa aplicao com jQuery e explorar o gerenciador de dependncias e sistema de build RequireJS.

Conceitos Chave
Antes de irmos para os padres de organizao de cdigo, importante entender alguns conceitos que so comuns a todos bons padres de organizao de cdigo. Seu cdigo deve ser dividido em unidades de funcionalidade - mdulos, servios, etc. Evite a tentao de ter todo seu cdigo em um enorme bloco dentro do $(document).ready(). No se repita. Identifique similaridades entre pedaos de funcionalidade e use tcnicas de herana para evitar cdigo repetitivo. Apesar da natureza centrada no DOM do jQuery, aplicaes em JavaScript no so s sobre o DOM. Lembre-se que no so todas as funcionalidades que necessitam - ou devem - ter uma representao no DOM. Unidades de funcionalidade devem ser fracamente acopladas [http://en.wikipedia.org/wiki/ Loose_coupling] uma unidade de funcionalidade deve conseguir existir por si s, e a comunicao entre unidades devem ser manipuladas atravs de um sistema de mensagens, como eventos customizados ou pub/sub. Evite comunicao direta entre unidades de funcionalidade sempre que possvel. Unidades de funcionalidade devem ser divididas em pequenos mtodos que fazem exatamente uma s coisa. Se seus mtodos so maiores que algumas linhas, voc deve considerar uma refatorao. Opes de configurao para suas unidades de funcionalidade - URLS, strings, timeouts, etc. - devem ser informadas em propriedades ou em um objeto de configurao, no espalhadas atravs do cdigo. O conceito de baixo acoplamento pode ser especialmente problemtico para desenvolvedores fazendo sua primeira investida em aplicaes complexas, ento preste ateno nisso quando voc estiver comeando.

Encapsulamento
O primeiro passo para organizao de cdigo separar as partes de sua aplicao em peas distintas; algumas vezes, mesmo este esforo suficiente para ceder

O literal objeto
Um literal objeto talvez a forma mais simples de encapsular cdigo relacionado. Ele no oferece nenhuma privacidade para propriedades ou mtodos, mas til para eliminar funes annimas do seu cdigo, centralizar opes de configurao e facilitar o caminho para o reuso e refatorao.

80

Organizao de cdigo

Exemplo 10.1. Um literal objeto


var myFeature = { myProperty : 'ol', myMethod : function() { console.log(myFeature.myProperty); }, init : function(settings) { myFeature.settings = settings; }, readSettings : function() { console.log(myFeature.settings); } }; myFeature.myProperty; // 'ol' myFeature.myMethod(); // loga 'ol' myFeature.init({ foo : 'bar' }); myFeature.readSettings(); // loga { foo : 'bar' } O literal objeto acima simplesmente um objeto associado a uma varivel. O objeto tem uma propriedade e vrios mtodos. Todas as propriedades e mtodos so pblicas, ento qualquer parte da sua aplicao pode ver as propriedades e chamar mtodos no objeto. Enquanto h um mtodo init. no h nada requerendo que ele seja chamado antes do objeto estar funcional. Como aplicaramos este padro no cdigo com jQuery? Vamos dizer que ns temos este cdigo escrito no estilo tradicional do jQuery: // carrega algum contedo ao clicar num item da lista // utilizando o ID do item da lista e esconde o contedo // em itens de lista similares $(document).ready(function() { $('#myFeature li') .append('<div/>') .click(function() { var $this = $(this); var $div = $this.find('div'); $div.load('foo.php?item=' + $this.attr('id'), function() { $div.show(); $this.siblings() .find('div').hide(); } ); }); }); Se isso for estender nossa aplicao, deixar como est pode ser legal. Por outro lado, se esse for um pedao de uma aplicao maior, ns temos que manter esta funcionalidade separada da funcionalidade no relacionada. Talvez ns ainda queiramos mover a URL para fora do cdigo e dentro de uma rea de

81

Organizao de cdigo

configurao. Por ltimo, ns talvez precisaremos quebrar o encadeamento de mtodos para ficar mais fcil modificar pedaos de funcionalidade depois.

82

var myFeature = { init : function(settings) { Organizao de cdigo myFeature.config = { $items : $('#myFeature li'), $container : $('<div class="container"></div>'), Exemplo 10.2.urlBase um'/foo.php?item=' Usando : literal de objeto numa funcionalidade do jQuery }; // permite a sobreposio da configurao padro $.extend(myFeature.config, settings); myFeature.setup(); }, setup : function() { myFeature.config.$items .each(myFeature.createContainer) .click(myFeature.showItem); }, createContainer : function() { var $i = $(this), $c = myFeature.config.$container.clone() .appendTo($i); $i.data('container', $c); }, buildUrl : function() { return myFeature.config.urlBase + myFeature.$currentItem.attr('id'); }, showItem : function() { var myFeature.$currentItem = $(this); myFeature.getContent(myFeature.showContent); }, getContent : function(callback) { var url = myFeature.buildUrl(); myFeature.$currentItem .data('container').load(url, callback); }, showContent : function() { myFeature.$currentItem .data('container').show(); myFeature.hideContent(); }, hideContent : function() { myFeature.$currentItem.siblings() .each(function() { $(this).data('container').hide(); }); } }; $(document).ready(myFeature.init);

83

Organizao de cdigo

A primeira coisa que voc ir perceber que esta abordagem obviamente muito maior que a original novamente, se isso for estender nossa aplicao, o uso do literal objeto no ir fazer sentido algum. Embora assumindo que no vai estender nossa aplicao, ns ganhamos vrias coisas: Ns quebramos nossas funcionalidaes em mtodos pequenos; no futuro, se ns precisarmos mudar como o contedo mostrado, claro onde ns iremos mudar. No cdigo original, este passo muito mais difcil para se localizar. Ns eliminamos o uso de funes annimas. Ns movemos as opes de configurao para fora do corpo do cdigo e colocamos em uma localizao central. Ns eliminamos as restries do encadeamento, fazendo o cdigo mais refatorvel, modificvel e rearranjvel. Para funcionalidades no triviais, literais de objeto so uma clara melhora sobre o longo pedao de cdigo dentro do bloco $(document).ready(), de forma nos leva a pensar sobre pedaos de funcionalidade. Entretanto, eles no so muito mais avanados do que ter um monte de declaraes de funes dentro do bloco $(document).ready().

O Module Pattern
O module pattern supera algumas das limitaes do literal objeto, oferecendo privacidade para variveis e funes enquanto expe uma API pblica se assim for necessrio.

Exemplo 10.3. O module pattern


var featureCreator = function() { var privateThing = 'segredo', publicThing = 'no segredo', changePrivateThing = function() { privateThing = 'super secreto'; }, sayPrivateThing = function() { console.log(privateThing); changePrivateThing(); }; return { publicThing : publicThing, sayPrivateThing : sayPrivateThing } }; var feature = featureCreator(); feature.publicThing; // 'no segredo' feature.sayPrivateThing(); // loga 'segredo' e muda o valor de // privateThing No exemplo acima, ns criamos uma funo featureCreator que retorna um objeto. Dentro da funo, ns definimos algumas variveis. Pelo fato das variveis estarem definidas dentro da funo, ns no temos

84

Organizao de cdigo

acesso ela fora da funo, a no ser que ns coloquemos no objeto de retorno. Isto significa que nenhum cdigo externo da funo tem acesso varivel privateThing ou a funo changePrivateThing. Entretando, sayPrivateThing tem acesso a privateThing e changePrivateThing, por causa que ambas foram definidas no mesmo escopo de sayPrivateThing. Este padro poderoso pois, da mesma forma que voc pode obter os nomes de variveis, ele pode dar a voc variveis privadas e funes enquanto expe uma API limitada consistindo das propriedades retornadas dos objetos e mtodos. Abaixo temos uma verso revisada do exemplo anterior, mostrando como poderamos criar a mesma funcionalidade utilizando o module pattern e somente expondo um mtodo pblico do mdulo, showItemByIndex().

85

Organizao de cdigo

$(document).ready(function() { Exemplo 10.4. Usando o module patterns var myFeature = (function() {

numa funcionalidade do jQuery

var $items = $('#myFeature li'), $container = $('<div class="container"></div>'), $currentItem, urlBase = '/foo.php?item=', createContainer = function() { var $i = $(this), $c = $container.clone().appendTo($i); $i.data('container', $c); }, buildUrl = function() { return urlBase + $currentItem.attr('id'); }, showItem = function() { var $currentItem = $(this); getContent(showContent); }, showItemByIndex = function(idx) { $.proxy(showItem, $items.get(idx)); }, getContent = function(callback) { $currentItem.data('container').load(buildUrl(), callback); }, showContent = function() { $currentItem.data('container').show(); hideContent(); }, hideContent = function() { $currentItem.siblings() .each(function() { $(this).data('container').hide(); }); }; config.$items .each(createContainer) .click(showItem); return { showItemByIndex : showItemByIndex }; })(); myFeature.showItemByIndex(0); });

86

Organizao de cdigo

Gerenciando dependncias
Nota
Esta seo fortemente baseada na excelente documentao do RequireJS disponvel em http:// requirejs.org/docs/jquery.html, e usada com permisso do autor do RequireJS, James Burke. Quando um projeto alcana um determinado tamanho, gerenciar mdulos de scripts comea a ficar complicado. Voc precisa ter certeza da seqncia correta dos scripts e voc comea a pensar seriamente em combinar scripts em um nico arquivo, para que somente uma ou um nmero pequeno de requisies sejam feitas para carregar os scripts. Voc pode tambm carregar cdigo assim que necessrio, depois que a pgina carregar. O RequireJS uma ferramenta para gerenciamento de dependncias feita pelo James Burke e pode lhe ajudar a gerenciar mdulos de scripts, carreg-los na ordem correta e tornar fcil a combinao de scripts mais tarde atravs de uma ferramenta prpria de otimizao, sem necessidade de alterar seu cdigo de marcao. Ele tambm lhe fornece um meio fcil de carregar os scripts depois da pgina ter carregado, permitindo que voc distribua o tamanho do download atravs do tempo. O RequireJS tem um sistema de mdulos que permite que voc defina mdulos com escopo bem definido, mas voc no precisa seguir o sistema para obter os benefcios do gerenciamento de dependncias e otimizaes em tempo de build. Com o tempo, se voc comear a criar cdigo mais modular que precisa ser reutilizado em algumas outras partes, o formato de mdulo do RequireJS torna fcil escrever cdigo encapsulado que pode ser carregado sob demanda. Ele pode crescer com sua aplicao, particularmente se voc deseja incorporar strings de internacionalizao (i18n), para que seu projeto funcione em lnguas diferentes, ou carregar algumas strings HTML e ter certeza que estas strings esto disponveis antes de executar o cdigo, ou mesmo usar servicos JSONP como dependncias.

Obtendo o RequireJS
A forma mais fcil de usar o RequireJS com jQuery baixando um build do jQuery que j tem o RequireJS embutido [http://requirejs.org/docs/download.html]. Este build exclui pores do RequireJS que duplicam funcionalidades do jQuery. Voc tambm pode achar til baixar um projeto jQuery de amostra que utiliza o RequireJS [http://requirejs.org/docs/release/0.11.0/jquery-require-sample.zip].

Utilizando o RequireJS com jQuery


Utilizar o RequireJS na sua pgina simples: inclua o jQuery que tenha o RequireJS embutido e depois faa a requisio dos arquivos da sua aplicao. O exemplo a seguir assume que o jQuery e seus outros scripts estejam todos no diretrio scripts/.

Exemplo 10.5. Utilizando o RequireJS: Um exemplo simples


<!DOCTYPE html> <html> <head> <title>jQuery+RequireJS Sample Page</title> <script src="scripts/require-jquery.js"></script> <script>require(["app"]);</script> </head> <body> <h1>jQuery+RequireJS Sample Page</h1> </body> </html>

87

Organizao de cdigo

A chamada require(["app"]) fala para o RequireJS carregar o arquivo scripts/app.js. O RequireJS ir carregar todas as dependncias que passada para o require() sem a extenso .js do mesmo diretrio do require-jquery.js, apesar que isto pode ser configurado para se comportar de forma diferente. Se voc se sentir mais confortvel ao especificar o caminho completo, voc pode fazer o seguinte: <script>require(["scripts/app.js"]);</script> O que h em app.js? Outra chamada para o require.js carregar todos os scripts que voc precisa e todo trabalho inicial que voc quer para a pgina. Neste exemplo, o script app.js carrega dois plugins, jquery.alpha.js e jquery.beta.js (no o nome real dos plugins, somente um exemplo). Os plugins devem estar no mesmo diretrio do require-jquery.js:

Exemplo 10.6. Um simples arquivo JavaScript com dependncias


require(["jquery.alpha", "jquery.beta"], function() { //os plugins jquery.alpha.js e jquery.beta.js foram carregados. $(function() { $('body').alpha().beta(); }); });

Criando mdulos reusveis com RequireJS


RequireJS torna fcil a definio de mdulos reusveis via require.def(). Um mdulo RequireJS pode ter dependncias que podem ser usadas para definir um mdulo e um mdulo RequireJS pode retornar um valor - um objeto, uma funo, o que for - que pode ser consumido por outros mdulos. Se seu mdulo no tiver nenhuma dependncia, ento simplesmente especifique o nome do mdulo como primeiro argumento do require.def(). O segundo argumento somente um literal objeto que define as propriedades do mdulo. Por exemplo:

88

Organizao de cdigo

Exemplo 10.7. Definindo um mdulo do RequireJS que no tem dependncias


require.def("my/simpleshirt", { color: "black", size: "unisize" } ); Este exemplo seria melhor armazenado no arquivo my/simpleshirt.js. Se seu mdulo possui dependncias, voc pode especific-las como segundo argumento para require.def() (como um array) e ento passar uma funo como terceiro argumento. A funo ser chamada para definir o mdulo quando todas as dependncias tiverem sido carregadas. A funo recebe os valores retornados pelas dependncias como seus argumentos. (na mesma ordem que elas so requeridas no array), e a funo deve retornar um objeto que define o mdulo.

Exemplo 10.8. Definindo um mdulo do RequireJS com dependncias


require.def("my/shirt", ["my/cart", "my/inventory"], function(cart, inventory) { //retorna um objeto para definir o mdulo "my/shirt". return { color: "blue", size: "large" addToCart: function() { inventory.decrement(this); cart.add(this); } } } ); Neste exemplo, um mdulo my/shirt criado. Ele depende de my/cart e my/inventory. No disco, os arquivos so estruturados assim: my/cart.js my/inventory.js my/shirt.js A funo que define my/shirt no chamada at que os mdulos my/cart e my/inventory sejam carregados, e a funo recebe os mdulos como argumentos cart e inventory. A ordem dos argumentos da funo precisam combinar com a ordem em que as dependncias foram requiridas no array de dependncias. O objeto retornado pela chamada da funo define o mdulo my/shirt. Por definir os mdulos dessa forma, my/shirt no existe como um objeto global. Mdulos que definem globais so explicitamente desencorajados, ento mltiplas verses de um mdulo podem existir na pgina ao mesmo tempo. Mdulos no precisam retornar objetos; qualquer retorno vlido a partir de uma funo permitido.

Exemplo 10.9. Definindo um mdulo do RequireJS que retorna uma funo


require.def("my/title", ["my/dependency1", "my/dependency2"], function(dep1, dep2) { //retorna uma funo para definir "my/title". Ele obtm ou muda //o ttulo da janela. return function(title) { return title ? (window.title = title) : window.title; } } ); Somente um mdulo deve ser requerido por arquivo JavaScript.

89

Organizao de cdigo

Otimizando seu cdigo: A ferramenta de build do RequireJS


Uma vez que voc incorporou o RequireJS para gerenciamento de dependncia, sua pgina est configurada para ser otimizada bem facilmente. Baixe o cdigo fonte do RequireJS e coloque onde voc quiser, preferencialmente em um lugar fora da sua rea de desenvolvimento. Para os propsitos deste exemplo, o fonte do RequireJS colocado num diretrio irmo do webapp, que contm a pgina HTML e o diretrio de scripts com todos os scripts. Estrutura completa do diretrio: requirejs/ (utilizado pelas ferramentas de build) webapp/app.html webapp/scripts/app.js webapp/scripts/require-jquery.js webapp/scripts/jquery.alpha.js webapp/scripts/jquery.beta.js Ento, nos diretrios de scripts que tem o require-jquery.js e app.js, crie um arquivo chamado app.build.js com o seguinte contedo:

Exemplo 10.10. Um arquivo de configurao de build do RequireJS


{ appDir: "../", baseUrl: "scripts/", dir: "../../webapp-build", //Comente a linha de otimizao (optimize) se voc quer //o cdigo minificado pelo Compilador Closure Compiler utilizando //o modo de otimizao "simple" optimize: "none", modules: [ { name: "app" } ] } Para usar a ferramenta de build, voc precisa do Java 6 instalado. O Compilador Closure usado para o passo de minificao do JavaScript (se optimize: "none" estiver comentado), e requer o Java 6. Para iniciar o buid, v no diretrio webapp/scripts, e execute o seguinte comando: # sistemas no-windows ../../requirejs/build/build.sh app.build.js # sistemas windows ..\..\requirejs\build\build.bat app.build.js Agora, no diretrio webapp-build, app.js ter o contedo de app.js, jquery.alpha.js e jquery.beta.js numa s linha. Ento, se voc carregar o arquivo app.html no diretrio webapp-build, voc no dever ver nenhuma requisio de rede para jquery.alpha.js e jquery.beta.js.

90

Organizao de cdigo

Exerccios
Crie um mdulo Portlet
Abra o arquivo /exercises/portlets.html em seu navegador. Use o arquivo /exercises/ js/portlets.js. Sua tarefa criar um funo criadora de portlet que utilize o module pattern, fazendo que o seguinte cdigo funcione: var myPortlet = Portlet({ title : 'Curry', source : 'data/html/curry.html', initialState : 'aberto' // ou 'fechado' }); myPortlet.$element.appendTo('body'); Cada portlet deve ser uma div com um ttulo, uma rea de contedo, um boto para abrir/fechar o portlet, um boto para remover o portlet, e um boto para atualizar o portlet. O portlet retornado pela funo Portlet deve ter a seguinte API pblica: myPortlet.open(); // fora o estado aberto myPortlet.close(); // fora o estado fechado myPortlet.toggle(); // inverte o estado aberto/fechado myPortlet.refresh(); // atualiza o contedo myPortlet.destroy(); // remove o portlet da pgina myPortlet.setSource('data/html/onions.html'); // muda a fonte

91

Captulo 11. Eventos Customizados


Introduo Eventos Customizados
Ns todos estamos familiares com eventos bsicos - click, mouseover, focus, blur, submit, etc. - estes que ns podemos usar para interaes entre o usurio e o navegador. Eventos customizados abrem um mundo completamente novo de programao orientada a eventos. Neste captulo, ns iremos utilizar o sistema de eventos customizados do jQuery para fazer uma aplicao de busca simples no Twitter. Pode ser difcil primeira instncia entender por que voc iria querer utilizar eventos customizados, quando os eventos j prontos parecem satisfazer bem suas necessidades. Acontece que eventos customizados oferecem um jeito completamente novo de pensar sobre JavaScript orientado a eventos. Ao invs de focar no elemento que dispara uma ao, eventos customizados colocam o holoforte no elemento em ao. Isso traz muitos benefcios, incluindo: Comportamentos do elemento alvo podem ser facilmente disparados por elementos diferentes utilizando o mesmo cdigo. Comportamentos podem ser disparados atravs de elementos-alvo mltiplos e similares de uma vez. Comportamentos podem ser mais facilmente associados com o elemento alvo no cdigo, tornando o cdigo mais fcil de ler e manter. Por que voc deveria se importar? Um exemplo provavelmente a melhor forma de explicar. Suponha que voc tenha uma lmpada num quarto na casa. A lmpada est ligada e ela controlada por dois switches de trs vias e um clapper: <div class="room" id="kitchen"> <div class="lightbulb on"></div> <div class="switch"></div> <div class="switch"></div> <div class="clapper"></div> </div> O estado da lmpada ir mudar disparando o clapper ou mesmo os switches. Os switches e o clapper no se importam em qual estado a lmpada est; eles somente querem mudar o estado. Sem eventos customizados, voc talvez poderia escrever algo assim: $('.switch, .clapper').click(function() { var $light = $(this).parent().find('.lightbulb'); if ($light.hasClass('on')) { $light.removeClass('on').addClass('off'); } else { $light.removeClass('off').addClass('on'); } }); Com eventos customizados, seu cdigo pode ficar parecido com este: $('.lightbulb').bind('changeState', function(e) { var $light = $(this); if ($light.hasClass('on')) { $light.removeClass('on').addClass('off');

92

Eventos Customizados

} else { $light.removeClass('off').addClass('on'); } }); $('.switch, .clapper').click(function() { $(this).parent().find('.lightbulb').trigger('changeState'); }); Este ltimo pedao de cdigo no l essas coisas, mas algo importante aconteceu: ns movemos o comportamento da lmpada para a lmpada, e ficamos longe dos switches e do clapper. Vamos tornar nosso exemplo um pouco mais interessante. Ns vamos adicionar outro quarto nossa casa, junto com o switch mestre, como mostrado a seguir: <div class="room" id="kitchen"> <div class="lightbulb on"></div> <div class="switch"></div> <div class="switch"></div> <div class="clapper"></div> </div> <div class="room" id="bedroom"> <div class="lightbulb on"></div> <div class="switch"></div> <div class="switch"></div> <div class="clapper"></div> </div> <div id="master_switch"></div> Se h vrias luzes na casa, ns queremos que o switch mestre desligue todas as luzes; de outra forma, ns queremos todas as luzes acesas. Para fazer isso, ns iremos adicionar dois ou mais eventos customizados s lmpadas: turnOn e turnOff. Ns iremos fazer uso deles no evento customizado changeState, e usar alguma lgica para decidir qual que o switch mestre vai disparar: $('.lightbulb') .bind('changeState', function(e) { var $light = $(this); if ($light.hasClass('on')) { $light.trigger('turnOff'); } else { $light.trigger('turnOn'); } }) .bind('turnOn', function(e) { $(this).removeClass('off').addClass('on'); }) .bind('turnOff', function(e) { $(this).removeClass('off').addClass('on'); }); $('.switch, .clapper').click(function() { $(this).parent().find('.lightbulb').trigger('changeState'); }); $('#master_switch').click(function() {

93

Eventos Customizados

if ($('.lightbulb.on').length) { $('.lightbulb').trigger('turnOff'); } else { $('.lightbulb').trigger('turnOn'); } }); Note como o comportamento do switch mestre est vinculado ao switch mestre; O comportamento de uma lmpada pertence s lmpadas.

Nota
Se voc est acostumado com programao orientada a objetos, talvez seja til pensar em eventos como se fossem mtodos de objetos. Grosseiramente falando, o objeto que o mtodo pertence criado pelo seletor do jQuery. Vinculando o evento customizado changeState para todos os elementos $(.light) similar a ter uma classe chamada Light com um mtodo changeState, e ento instanciamos novos objetos Light para cada elemento com o nome de classe light. Recapitulando: $.fn.bind e $.fn.trigger No mundo dos eventos customizados, h dois mtodos importantes do jQuery: $.fn.bind e $.fn.trigger. No captulo Eventos, ns vimos como usar estes mtodos para trabalhar com eventos do usurio; neste captulo, importante relemebrar duas coisas: O mtodo $.fn.bind recebe o tipo do evento e uma funo manipuladora do mesmo como argumentos. Opcionalmente, ele pode tambm receber dados relacionados ao eventos como seu segundo argumento, passando a funo manipuladora do evento para o terceiro argumento. Qualquer dado que passado ser disponvel para a funo manipuladora do evento na propriedade data do objeto do evento. A funo manipuladora do evento sempre recebe o objeto do evento como seu primeiro argumento. O mtodo $.fn.trigger recebe um tipo de evento como argumento. Opcionalmente, ele tambm pode receber um array de valores. Estes valores sero passados para a funo manipuladora de eventos como argumentos depois do objeto de evento. Aqui h um exemplo de uso do $.fn.bind e $.fn.trigger que usa dados customizados em ambos os casos: $(document).bind('myCustomEvent', { foo : 'bar' }, function(e, arg1, arg2) { console.log(e.data.foo); // 'bar' console.log(arg1); // 'bim' console.log(arg2); // 'baz' }); $(document).trigger('myCustomEvent', [ 'bim', 'baz' ]);

Uma aplicao de amostra


Para demonstrar o poder dos eventos customizados, ns vamos criar uma ferramenta simples para buscar no Twitter. A ferramenta ir oferecer vrias formas de um usurio fazer a busca por um termo: digitando numa caixa de texto, mltiplos termos de busca na URL e por requisitar os termos do trending topics.

94

Eventos Customizados

Os resultados para cada termo sero mostrados em um container de resultados; Estes containers podero ser expandidos, contraidos, atualizados, e removidos, individualmente ou todos de uma vez. Quando terminarmos, a applicao ficar dessa forma:

95

Eventos Customizados

Figura 11.1. Nossa aplicao concluda

96

Eventos Customizados

O Setup
Ns iniciaremos com HTML bsico: <h1>Twitter Search</h1> <input type="button" id="get_trends" value="Load Trending Terms" /> <form> <input type="text" class="input_text" id="search_term" /> <input type="submit" class="input_submit" value="Add Search Term" /> </form> <div id="twitter"> <div class="template results"> <h2>Search Results for <span class="search_term"></span></h2> </div> </div> Isso nos d um container (#twitter) para nosso widget, um template para nossos resultados (escondido via CSS), e um formulrio simples, onde usurios podem entrar com um termo de busca. (Para o bem da simplicidade, ns iremos assumir que a aplicao somente em JavaScript e que nossos usurios sempre tero CSS.) H dois tipos de objetos que ns iremos atuar sobre: os containers de resultados e o container do Twitter. Os containers de resultados so o corao da aplicao. Ns criaremos um plugin que preparar cada container de resultados assim que eles forem adicionados ao container do Twitter. Entre outras coisas, ele vincular os eventos customizados para cada container e adicionar os botes de ao no topo a direita de cada container. Cada container de resultado ter os seguintes eventos customizados: refresh populate remove Coloca o container no estado atualizando, e dispara a requisio para obter os dados para o termo de busca. Recebe os dados retornados em JSON e usa-os para alimentar o container. Remove o container da pgina depois que o usurio efetua a requisio para faz-lo. A verificao pode ser ignorada se true for passado como segundo argumento do manipulador de eventos. O evento remove tambm o termo associado com o container de resultados do objeto global contendo o termo de busca. Adiciona a classe collapsed ao container, que esconder os resultados via CSS. Ele tambm ir mudar o boto Collapse do container em um boto Expand. Remove a classe collapsed do container. Ele tambm ir mudar o boto Expand em um boto Collapse.

collapse expand

O plugin responsvel por adicionar os botes de ao ao container. Ele vincula cada evento de clique cada item da lista de aes e usa a classe do item de lista para determinar qual evento customizado ser disparado no container de resultados correspondente. $.fn.twitterResult = function(settings) { return $(this).each(function() { var $results = $(this),

97

Eventos Customizados

$actions = $.fn.twitterResult.actions = $.fn.twitterResult.actions || $.fn.twitterResult.createActions(), $a = $actions.clone().prependTo($results), term = settings.term; $results.find('span.search_term').text(term); $.each( ['refresh', 'populate', 'remove', 'collapse', 'expand'], function(i, ev) { $results.bind( ev, { term : term }, $.fn.twitterResult.events[ev] ); } ); // usa a classe de cada ao para determinar qual // evento ele ir disparar no painel de resultados. $a.find('li').click(function() { // passa o li que foi clicado para a funo // para que o mesmo possa ser manipulado se necessrio $results.trigger($(this).attr('class'), [ $(this) ]); }); }); }; $.fn.twitterResult.createActions = function() { return $('<ul class="actions" />').append( '<li class="refresh">Refresh</li>' + '<li class="remove">Remove</li>' + '<li class="collapse">Collapse</li>' ); }; $.fn.twitterResult.events = { refresh : function(e) { // indica que os resultados esto sendo atualizados var $this = $(this).addClass('refreshing'); $this.find('p.tweet').remove(); $results.append('<p class="loading">Loading ...</p>'); // obtm os dados do Twitter via jsonp $.getJSON( 'http://search.twitter.com/search.json?q=' + escape(e.data.term) + '&rpp=5&callback=?', function(json) { $this.trigger('populate', [ json ]); } ); },

98

Eventos Customizados

populate : function(e, json) { var results = json.results; var $this = $(this); $this.find('p.loading').remove(); $.each(results, function(i,result) { var tweet = '<p class="tweet">' + '<a href="http://twitter.com/' + result.from_user + '">' + result.from_user + '</a>: ' + result.text + ' <span class="date">' + result.created_at + '</span>' + '</p>'; $this.append(tweet); }); // indica que a atualizao dos // resultados est terminada $this.removeClass('refreshing'); }, remove : function(e, force) { if ( !force && !confirm('Remove panel for term ' + e.data.term + '?') ) { return; } $(this).remove(); // indica que ns no temos mais // um painel para o termo search_terms[e.data.term] = 0; }, collapse : function(e) { $(this).find('li.collapse').removeClass('collapse') .addClass('expand').text('Expand'); $(this).addClass('collapsed'); }, expand : function(e) { $(this).find('li.expand').removeClass('expand') .addClass('collapse').text('Collapse'); $(this).removeClass('collapsed'); }

99

Eventos Customizados

}; O container do Twitter ter somente dois eventos: getResults Recebe um termo de busca e checa se h um container de resultados para o termo; Se no, adiciona um container de resultados utilizando o template de resultados, configura o container utilizando o plugin $.fn.twitterResult discutido acima, e ento dispara o evento refresh no container de resultados para carregar de fato os resultados. Finalmente, ele armazena o termo de busca para que a aplicao no obtenha novamente o termo. Consulta o Twitter para obter os top 10 trending topics, depois itera sobre os resultados e dispara o evento getResults para cada um deles, adicionando assim um container de resultados para cada um dos termos.

getTrends

As vinculaes do container do Twitter vo ficar parecidas com isso: $('#twitter') .bind('getResults', function(e, term) { // certifica que ns j no temos um box para este termo if (!search_terms[term]) { var $this = $(this); var $template = $this.find('div.template'); // faz uma cpia da div do template // e insere-a como primeiro box de resultados $results = $template.clone(). removeClass('template'). insertBefore($this.find('div:first')). twitterResult({ 'term' : term }); // carrega o contedo utilizando o evento customizado // "refresh" que ns vinculamos ao container de resultados $results.trigger('refresh'); search_terms[term] = 1;

} }) .bind('getTrends', function(e) { var $this = $(this); $.getJSON('http://search.twitter.com/trends.json?callback=?', function(json var trends = json.trends; $.each(trends, function(i, trend) { $this.trigger('getResults', [ trend.name ]); }); }); }); At agora, ns escrevemos muito cdigo que no faz quase nada, mas ok. Ao especificar todos os comportamentos que ns queremos que nossos objetos de base tenham, ns criamos um framework slido para construir rapidamente a interface. Vamos comear ligando nossa caixa de texto e o boto Load Trending Terms. Para a caixa de texto, ns iremos capturar o termo que foi digitado e iremos pass-lo para o evento getResults do container do Twitter. O evento getTrends ser disparado ao clicarmos no boto Load Trending Terms:

100

Eventos Customizados

$('form').submit(function(e) { e.preventDefault(); var term = $('#search_term').val(); $('#twitter').trigger('getResults', [ term ]); }); $('#get_trends').click(function() { $('#twitter').trigger('getTrends'); }); Ns podemos remover, contrair, expandir e atualizar todos os resultados se adicionarmos alguns botes com IDs apropriados, assim como mostrado abaixo. Perceba como ns estamos passando o valor true para o manipulador de evento como seu segundo argumento, dizendo ao mesmo que ns no queremos verificar a remoo de containers individuais. $.each(['refresh', 'expand', 'collapse'], function(i, ev) { $('#' + ev).click(function(e) { $('#twitter div.results').trigger(ev); }); }); $('#remove').click(function(e) { if (confirm('Remove all results?')) { $('#twitter div.results').trigger('remove', [ true ]); } });

Concluso
Eventos customizados oferecem uma nova forma de pensar sobre seu cdigo: eles colocam nfase no comportamento, no no elemento que o dispara. Se voc gastar um tempo no incio para estabelecer as partes da sua aplicao e os comportamentos que essas partes necessitam ter, os eventos customizados podem fornecer um mtodo poderoso para voc fazer com que estas partes "conversem", seja uma de cada vez ou uma conversa em massa. Uma vez que os comportamentos de uma parte foram descritos, tornase trivial disparar estes comportamentos de qualquer parte, permitindo uma criao rpida da lgica da aplicao e que experimentos com opes da interface sejam triviais. Por ltimo, eventos customizados podem melhorar a clareza do cdigo e facilitar sua manuteno, pois eles deixam claro o relacionamento entre um elemento e seus comportamentos. Voc pode ver a aplicao completa em demos/custom-events.html e demos/js/customevents.js no cdigo de amostra.

101

Vous aimerez peut-être aussi