Professional Documents
Culture Documents
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Caelum
Sumrio
Sumrio
1 Sobre o curso
1.1 Os exerccios
1.2 O projeto
10
12
14
16
17
21
22
22
22
26
29
29
31
32
34
35
37
38
40
41
41
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Sumrio
Caelum
41
42
43
45
46
47
4 jQuery
51
51
4.2 Eventos
54
56
57
57
58
62
65
65
5.2 String.replace()
65
66
67
68
70
72
72
74
75
76
78
78
80
6.3 $.getJSON
81
81
83
85
87
88
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
90
Caelum
Sumrio
90
91
92
92
93
94
96
97
98
100
102
103
103
105
105
107
109
8.4 ContentEditable
110
111
113
116
119
121
121
126
126
128
129
130
131
132
133
134
135
135
136
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Sumrio
Caelum
138
138
10.2 SASS
138
140
140
142
143
143
Verso: 19.7.17
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
CAPTULO 1
SOBRE O CURSO
Com a evoluo das tecnologias mobile, criou-se novas formas de se acessar informaes e servios web.
Hoje, para manter competitividade de mercado, as aplicaes web devem se adaptar no apenas a vrios
tamanhos de tela, mas s diferentes formas que o usurio pode interagir com a aplicao.
H alguns anos, o JavaScript desempenhava um papel secundrio entre as ferramentas utilizadas
pelos profissionais de desenvolvimento de aplicaes Web, apesar de ter sido criado especificamente
para melhorar a interao do usurio com as aplicaes, atravs da possibilidade de adicionarmos cdigo
que roda diretamente no cliente, ou seja, no navegador.
Nos ltimos anos, porm, o JavaScript tem ganhado cada vez mais espao e importncia nesse papel,
e inclusive vem sido usado no lado do servidor de aplicaes e j no tratado como um simples
coadjuvante. Dentre os casos de sucesso do uso do JavaScript, podemos destacar as aplicaes de
produtividade do Google: o GMail, Google Calendar e a sute Google Docs. Alm de utilizarem
JavaScript no lado do servidor, o uso da linguagem no lado do cliente garante que tenhamos as
facilidades de uso e interaes avanadas, partes estratgicas no sucesso desses produtos.
Esse cenrio s vem mudando graas s evolues das tecnologias e ferramentas de desenvolvimento,
evoluo dos navegadores, padronizao da plataforma Web como um todo e tambm s evolues
da linguagem em si.
Esse curso pretende apresentar ao aluno tcnicas e ferramentas que permitem uma aplicao se
adaptar ao dispositivo do usurio, com um maior aprofundamento no HTML e CSS e tambm explora
funcionalidades especficas de dispositivos mobile.
Ainda, mostrar ao aluno as caractersticas do JavaScript, desde as mais fundamentais, com
profundidade para que ele possa compreender como essa ferramenta pode ser melhor utilizada e ter suas
funcionalidades melhor exploradas, alm de apresentar algumas bibliotecas, como o jQuery, que hoje
so indispensveis para a produtividade do desenvolvedor.
1.1 OS EXERCCIOS
Os exerccios so essenciais para a melhor compreenso dos tpicos apresentados, pois neles vamos
aplicar as tcnicas recomendadas da linguagem e vamos analisar e solucionar, de maneira prtica, os
problemas que enfrentamos no dia a dia como desenvolvedores. Alm dos exerccios que fazem parte da
1 SOBRE O CURSO
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
proposta didtica, apontaremos no decorrer do curso alguns exerccios opcionais, sugerimos que os
mesmos sejam feitos pois neles iremos explorar algumas alternativas de soluo de problemas para
conhecermos melhor algumas caractersticas do JavaScript e das bibliotecas que fazem parte do curso.
Alm dos exerccios tambm apontaremos no decorrer do curso alguns desafios para que voc
coloque em prtica a sua capacidade analtica na soluo dos problemas. Alguns desafios iro requerer
alguma pesquisa e leitura de documentao, ento fique atento s referncias apresentadas na apostila e
pelo instrutor durante o curso.
1.2 O PROJETO
Durante todo o curso, trabalharemos na criao de uma aplicao que funcionar como um mural de
notas/cartes.
1.2 O PROJETO
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Faremos apenas uma pgina, e ela ter toda a dinamicidade necessria para o usurio utilizar sem
precisar recarregar o html no navegador.
Alm disso, nossa aplicao ser responsiva e suas funcionalidades sero implementadas levando em
conta algumas restries do usurio em diferentes plataformas.
1.2 O PROJETO
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
CAPTULO 2
Esse um cdigo importante e que repetido em todo incio de projeto. Ser que todo mundo digita
isso na mo, toda hora?
Como profissionais, estamos sempre buscando uma forma de melhorar nossa produtividade.
Atividades comuns e repetitivas como criao de tags e esqueletos de pginas no podem ocupar muito
tempo de desenvolvimento.
Ao longo do curso criaremos e editaremos muito cdigo. Usar um bloco de notas comum para
iniciar o projeto do curso acrescentaria muito tempo somente digitao do cdigo.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Emmet
Para digitar html e css de forma mais rpida, vamos usar uma fantstica ferramenta chamada
Emmet. O Emmet um plugin que consegue gerar cdigos, precisando apenas de alguma dica nossa
para saber o que escrever.
Para escrever o cdigo do esqueleto da pgina usando o Emmet basta digitar ! e em seguida
pressionar TAB. O TAB fala pro Emmet completar nosso cdigo. Como j escrevemos ! , ele sabe que
queremos um <!DOCTYPE> , ou seja, queremos uma nova pgina. Ele gera toda a estrutura bsica,
incluindo head , body , title etc.
Podemos fazer isso muito mais facilmente com o Emmet. Para criar uma tag, basta escrever o nome
6
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
gera o cdigo:
<ul></ul>
Para criar os <li> podemos fazer a mesma coisa. Mas precisamos de 6 deles. Para fazer de forma
rpida, podemos colocar um multiplicador para o Emmet saber quantos elementos criar:
<ul>
li*6
</ul>
E apertamos TAB:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Note que desde o comeo, queramos colocar os li s dentro da ul . Tambm podemos fazer isso de
uma vez com o Emmet ao invs de fazer por partes, usando o smbolo > :
ul>li*6
TAB de novo:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Falta colocar o contedo nos li s. Nosso contedo muito parecido. Podemos mandar o Emmet
adicionar contedo para gente usando {contedo} logo depois do nome da tag, por exemplo:
li{Item 1}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
E ao apertar TAB:
<li>Item 1</li>
Se o contedo for igual para todos os li s, podemos ainda mesclar as instrues de contedo com o
multiplicador:
li{Item 1}*6
vira:
<li>Item 1</li>
<li>Item 1</li>
<li>Item 1</li>
<li>Item 1</li>
<li>Item 1</li>
<li>Item 1</li>
Mas no queremos o nmero do item igual, queremos item de 1 a 6. Para isso o Emmet tem o
smbolo $ que serve como um contador que comea em 1 e vai incrementando:
li{Item $}*6
vira:
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
E o Emmet ainda mais poderoso. Queremos agora dar o id "lista" para o ul e a classe "item" para
cada li . Podemos dar atributos para os elementos que o Emmet vai criar usando os mesmo seletores
do CSS. Ou seja, para criar a ul j com id, usamos a expresso ul#lista . E para criar os li s com
classe, fazemos li.item .
Usando todas essas funcionalidades juntas, podemos rapidamente escrever um cdigo longo e
repetitivo, e sem o risco de cometer erros bobos:
ul#lista>li.item{Item $}*6
Apertar TAB:
<ul id="lista">
<li class="item">Item 1</li>
<li class="item">Item 2</li>
<li class="item">Item 3</li>
<li class="item">Item 4</li>
<li class="item">Item 5</li>
<li class="item">Item 6</li>
</ul>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Cada editor tem o seu jeito de instalar plugins. Vamos abordar aqui apenas alguns dos principais.
Sublime
Para facilitar a instalao de plugins, instale um plugin chamado Package Control seguindo as
instrues desse site: https://packagecontrol.io/installation.
Com o Package Control instalado, utilizaremos o atalho para acessar qualquer funcionalidade do
Sublime, o ctrl+shift+P. No campo que abre, procure e selecione a opo install package. Ele vai abrir
um novo campo com a mesma cara. Agora basta procurar o plugin pelo nome e selecionar a opo
desejada para instalar.
Atom
Selecione a opo Edit > Preferences no menu. Na nova janela, escolha no menu a esquerda a opo
"+ install". O Atom vai abrir um campo de busca. Nesse campo voc pode procurar o plugin pelo nome e
instal-lo.
Brackets
Selecione a opo Extension Managements no menu File. Novamente, basta procurar o plugin pelo
nome e clicar em install.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
10
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Mas ver o HTML fonte no o bastante. Se o site foi feito seguindo as boas prticas, a cor que
queremos no vai est l, e sim num arquivo CSS. Sabemos que CSS funciona com seletores. E agora?
Qual seletor ser que o pessoal do site da Caelum usou para atribuir a cor ao elemento que
selecionamos? Tag, id, class... tem muitas possibilidades!
A entra de novo o Developer Tools. Para renderizar a pgina, o navegador teve que ler todos o CSS e
aplicar os estilos nos respectivos elementos. Por isso, ao inspecionar um elemento, ele j nos mostra
tambm quais estilos esto aplicados nele. Ele tambm nos mostra em que arquivo est o estilo e qual o
seletor usado para aplic-lo ao elemento.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
11
Pronto!
Mas ser que h1 a melhor escolha? muito comum que aplicaes tenham mais informaes no
12
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
cabealho que apenas o nome. Menu de navegao ou menu de opes so os contedos mais
frequentes.
Se formos colocar um menu desses no nosso cabealho, melhor que ele seja uma tag mais
representativa, como a header , e fazer ele conter o nome e o menu:
<header>
<h1>Ceep</h1>
<nav>
...
</nav>
<header>
Mas agora, quem est com o fundo na cor que queramos para o cabealho? Apenas o h1 ! Temos
que mudar tambm no estilos.css:
header {
background: #0082c7;
}
Pera, a escolha da tag que vamos usar para o cabealho faz parte do contedo da nossa aplicao.
Uma mudana de contedo deveria causar uma mudana no CSS? Vamos lembrar que a boa prtica
deixar CSS s com o estilo. O ideal deix-lo independente das tags HTML.
A melhor forma de fazer isso com classes. Onde queremos essa cor na nossa aplicao? No
cabealho! Ento podemos criar uma classe que vai representar o cabealho, e aplicar a cor nele:
.cabecalho {
background: #0082c7;
}
Agora, basta dar essa classe para o elemento HTML que vai ser o nosso cabealho. O h1 no primeiro
caso e header no segundo:
<h1 class="cabecalho">Ceep</h1>
ou
<header class="cabecalho">
<h1>Ceep</h1>
<nav>
...
</nav>
<header>
Dessa forma, sempre teremos a aplicao com o mesmo estilo, no importa qual elemento HTML
estamos usando para represent-lo. Nosso estilo e nosso contedo esto desacoplados.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
13
3. Precisamos pegar a cor para o fundo. Para isso, v at o site da caelum e clique com o boto direito
em cima da seo e selecione Inspect Element.
14
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Acabamos de abrir o Developer Tools. Veja direita todos os estilos que foram aplicados no
elemento inspecionado.
Navegue pelo html at chegar no elemento que tem o background que queremos. Aproveite o
destaque que o navegador d para encontr-lo.
4. Agora que temos a cor em mos, vamos aplic-la no nosso cabealho. Para no depender da tag que
escolhermos, vamos usar uma classe.
<h1 class="cabecalho">
Ceep
</h1>
.cabecalho {
background: #0082c7;
}
Porque faz sentido colocarmos uma cor direto no body , se uma tag html?
6. Temos alguns espaamentos por padro do navegador. Inspecione os elementos da pgina com o
Developer Tools e descubra de onde vem esses espaamentos. Comente com a turma e com o
2.5 EXERCCIO: PREPARANDO O TERRENO PARA OS CARTES DO MURAL
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
15
instrutor.
7. Para remover os espao citados no item anterior, adicione as seguintes linhas de CSS:
* {
margin: 0;
padding: 0;
}
8. O ttulo ficou muito grudado na esquerda. Vamos colocar um espao para corrigir isso. Acrescente
em estilos.css:
.cabecalho {
padding: 16px;
}
Verifique a presena do padding no navegador usando o DevTools. O padding deve ficar destacado.
Evite digitar tudo isso, use Emmet a seu favor. No editor, digite:
div.cartao*5>p.cartao-conteudo>lorem
16
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
.cartao {
background: #EBEF40;
margin: 16px;
padding: 16px;
}
Media Query
bem difcil que os estilos de uma pgina permaneam iguais entre dispositivos diferentes. Afinal,
cada dispositivo tem suas caractersticas e limitaes. Nosso site deve se adaptar a elas.
Num celular, temos restries com a largura da tela. Nesses casos, muito comum que elementos
sejam empilhados, um abaixo do outro, aproveitando melhor o espao vertical da tela. Esse tipo de
alinhamento bem diferente do alinhamento que utilizamos numa tela maior, onde elementos tambm
so alinhados um do lado do outro, aproveitando o espao horizontal.
Dado que estamos implementando um design responsivo, nossa aplicao deve exibir o mesmo
contedo com esses alinhamentos diferentes em cada caso (tamanhos de tela). Precisamos de estilos
exclusivos para cada caso. Para isso, existem as media queries.
Usando Media Queries, podemos criar CSS que s ser aplicado em alguns casos. Por exemplo,
queremos que em telas grandes as sees de uma pgina se organizem em 2 colunas.
.secao {
display: block;
}
@media (min-width: 800px){
.secao {
display: inline-block;
width: 45%;
}
}
Aqui, em telas maiores que 800px, a classe secao vai ganhar as duas propriedades que faro a
configurao de duas colunas. Nas telas abaixo disso, esse CSS ignorado e vai seguir o estilo padro, de
um elemento em cima do outro.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
17
Viewport
Chamamos de viewport o espao disponvel para o site ser renderizado no browser.
Media queries que usam medidas de largura ou altura esto sempre se referindo s dimenses do
viewport.
@media (min-width: 650px){
.baleia {
display: inline-block;
}
}
O estilo acima ser aplicado quando o viewport tiver mais do que 650 pixels de largura. Como saber
a largura em pixels do viewport do aparelho? Podemos olhar para a resoluo da tela.
Um iPhone 6 tem resoluo de 1334 x 750 em uma tela de 4.7", resoluo maior que muitos
notebooks com telas maiores. Isso s e possvel porque os pixels fsicos do iPhone so muito menores
que os pixels fsicos de um notebook.
Se o site for renderizado com base na resoluo da tela, 1px no css seria equivalente a 1 pixel fsico da
tela. Teramos um site com tudo muito pequeno. Por isso, no usamos a resoluo do celular, mas sim,
uma medida que o prprio aparelho define como sendo seu tamanho de viewport ideal, uma dimenso
em pixels menor que a resoluo.
Para alterar a medida do nosso viewport criaremos a seguinte tag <meta> :
<meta name="viewport" content="width=device-width">
18
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
.elemento {
width: 50%;
}
No cdigo acima, a <div class="contexto"> sempre 10% menor que a largura do <body> . A
<div class="elemento"> est sempre com metade do tamanho da <div class="contexto"> .
H casos nos quais necessrio que nosso elemento fique exatamente com a altura ou largura da
pgina. Trabalhar com porcentagem nesses casos implica que o elemento seja filho direto da tag
<body> , o que pode impactar na semntica do site. Para esses casos, pode-se utilizar algumas unidades
muito parecidas com a porcentagem, mas que, independente do lugar no qual o elemento est inserido,
so sempre relativas ao tamanho do viewport. So as Viewport Units:
vw - % da largura do viewport
vh - % da altura do viewport
vmin - % do menor entre largura e altura
vmax - % do maior entre largura e altura
TIPOGRAFIA RESPONSIVA
O que acontece se colocarmos o font-size em porcentagem, como no exemplo abaixo?
.elemento {
font-size: 150%
}
O tamanho da fonte ser 150% da largura ou da altura? Nenhum dos dois, no caso acima, a
fonte ser 1.5 vezes maior que o font-size do elemento pai. Ou seja, o tamanho da fonte no est
sendo alterado de acordo com o tamanho do viewport.
Para que isso acontea, podemos usar unidades relativas ao viewport.
.elemento {
font-size: 1.5vw;
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
19
No Chrome o Responsive Mode evoluiu para fazer muito mais do que apenas simular um viewport
pequeno e passou a se chamar Device Mode.
possvel emular diversas outras caractersticas de hardware que variam de device para device, como
tela sensvel ao toque, conexo ruim, dados dos sensores de geolocalizao e acelermetro.
20
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
DICA!
Com o Emmet, digite apenas meta:vp . Ele j cria a tag meta corretamente, mas coloca
muito mais coisa no content do que precisamos. Apague-os deixando igual ao mostrado
acima.
Abra a pgina no navegador. Clique com o boto direito em qualquer lugar na pgina e selecione a
opo "Inspect Element" para abrir o DevTools. Procure pelo cone do modo responsivo (um
smartphone no Chrome e uma telinha no Firefox). Selecione o tamanho de tela adequado, e
recarregue a pgina.
2. Para separar os cartes da borda da pgina, criaremos uma section.container . Vamos usar uma
unidade relativa para adaptar o espaamento ao tamanho da tela.
Em principal.html:
<section class="container">
<!-- divs dos cartes aqui -->
</section>
Em estilos.css:
.container {
padding: 0 10%;
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
21
.cabecalho {
background: #0082c7;
padding: 16px; <-- apagar!
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
deles.
<div class="cartao">
Quando criamos vrios cartes, cada um fica em uma linha, pois o display padro da div
block . Se queremos mais de um carto por linha, podemos simplesmente aplicar o valor inlineblock :
.cartao {
display: inline-block;
}
Mas pera! Mesmo assim os cartes ainda esto ocupando a linha toda. Isso porque a largura dos
elementos no est definida, ento naturalmente cada um ocupa todo o espao disponvel. Para caber
mais de um na mesma linha, temos que definir uma largura fixa:
.cartao{
display: inline-block;
width: 190px;
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
23
Agora cabem vrios cartes na mesma linha. E olhe s, automaticamente o navegador j calcula
quantos cartes cabem e adapta de acordo. Nossa aplicao est responsiva e no precisamos fazer nada
a mais.
Bom, mais ou menos. Quando usamos o inline-block o navegador comea posicionando os
elemento na ordem de leitura, no nosso caso, da esquerda pra direita e quando no cabe mais, o prximo
elemento vai embaixo. Assim nossos cartes acabam descentralizados. Como resolver esse problema?
Queremos o tamanho dos cartes fixo, ento temos que colocar margens para alinh-los Mas quanto
de margem? Conseguimos calcular pra ficar certinho no centro? No sabemos nem a largura do
container! E quando o nmero de cartes na linha mudar? Teremos que usar uma combinao de
margens relativas e media queries s pra garantir que tudo fique centralizado.
O problema que estamos tendo aqui que queremos todos os cartes centralizados, ou seja,
queremos um comportamento que depende um do outro, um comportamento em grupo. Para isso
entra o Flexbox. O flexbox um tipo de display pensado para dizer como os filhos de um elemento
devem se posicionar dentro dele, como um conjunto, e ele responsvel em fazer os clculos necessrios.
Ento, para usarmos o flexbox para posicionar os cartes, precisamos que eles estejam dentro de um
mesmo elemento. Usamos, ento o <section> , para separar essa informao do resto da aplicao.
<section class="mural">
<div class="cartao">...</div>
<div class="cartao">...</div>
<div class="cartao">...</div>
<div class="cartao">...</div>
<div class="cartao">...</div>
</section>
Agora, vamos falar para o mural como os cartes devem se posicionar dentro dele, usando o
flexbox:
.mural{
display: flex;
}
24
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Ok, no era bem isso que queramos. A funo do flexbox fazer os elementos caberem no espao
separado para eles. Nesse caso, ele redimensionou todo mundo pra caber em uma nica linha. Agora
precisamos falar pra ele que ele deve manter o tamanho original e passar os elementos que no
couberem para a linha de baixo. Fazemos isso com a propriedade flex-wrap :
.mural{
display: flex;
flex-wrap: wrap;
}
Para deixar nossa aplicao ainda mais responsiva, vamos dizer que cada carto, apesar de ter
tamanho padro 190px, pode ser redimensionado para ficar maior se tiver espao sobrando na tela, mas
no couber um carto novo. Essa uma propriedade de cada carto, possvel fazer alguns poderem
redimensionar, enquanto outros no. No nosso caso, vamos colocar em todos:
.cartao {
flex-grow: 1;
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
25
O resultado bem impressionante! O flexbox uma ferramenta muito verstil e simples para
trabalhar com posicionamento que foi adicionada na verso CSS3.
Mas sendo uma ferramenta nova, o que acontece se o usurio estiver num navegador sem suporte a
ela? Quando o navegador ler o CSS ele vai considerar que a funcionalidade no existe e vai simplesmente
ignorar, assim o display vai ser renderizado usando o inline-block que colocamos anteriormente!
O flexbox sobrescreve o comportamento do display , mas se no existir flexbox, o inline-block
usado no lugar. Dessa forma, conseguimos fazer uma aplicao que funciona para ambos os usurios,
independente do suporte que o navegador dele d.
Note que comeamos a fazer a aplicao mais simples, que funciona em todos os lugares e depois
adicionamos funcionalidades apenas para os usurios que tem suporte a elas. Estamos trabalhando com
Progressive Enhancement, ou melhoria progressiva. Quando uma funcionalidade no funciona para
algum usurio, o navegador ento usa uma outra funcionalidade que a substitua para manter tudo
funcionando. Essa funcionalidade "reserva" recebo o nome de fallback.
DESCOBRINDO COMPATIBILIDADE
Sempre que vamos usar uma nova ferramenta ou proriedade, precisamos nos preocupar como
ela vai desenpenhar em todos os devices e navegadores. O "Can I Use" (http://www.caniuse.com)
um site mantido pela comunidade com as informaes sobre o suporte oferecido s
funcionalidades.
Box-sizing
O box model padro do CSS pode ser esquisito. Por isso a propriedade box-sizing do CSS3 nos
permite trocar o box model que queremos usar.
Por padro, todos os elementos tm o valor box-sizing: content-box o que indica que o
tamanho dele definido pelo seu contedo apenas. Mas podemos trocar por box-sizing: borderbox que indica que o tamanho agora levar em conta at a borda ou seja, o width ser a soma do
contedo com a borda e o padding.
26
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
.cartao {
width: 190px;
display: inline-block;
}
}
A partir de agora, todo nosso CSS ser para telas maiores que 560px.
2. Nossos cartes no esto respeitando o tamanho de 190px, confira no DevTools! Para que a largura
inclua o tamanho do padding e da borda, acrescente no carto:
.cartao {
box-sizing: border-box;
}
Para que o contedo dos cartes no fique centralizado precisamos alterar o alinhamento dentro do
carto.
.cartao {
text-align: left;
}
5. preciso dizer para o container que os cartes podem ir para outra linha.
.mural {
flex-wrap: wrap;
}
6. Anteriormente, definimos um tamanho de 190px para os cartes, o browser est respeitando isso,
sempre. Precisamos dizer ao o browser que ele pode aumentar nosso carto, caso necessrio.
.cartao {
flex-basis: 190px;
flex-grow: 1;
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
27
28
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
CAPTULO 3
AS FUNCIONALIDADES, O JAVASCRIPT E
O CSS
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
29
}
.cartao {
flex-basis: 190px;
flex-grow: 1;
}
Isto , o mural declarado como um container flex que permite elementos escorregarem nas linhas
debaixo ( flex-wrap: wrap ). Cada cartao possui um tamanho de 190px ( flex-basis ) mas que
pode ser esticado para ocupar todo o espao do pai ( flex-grow ).
Para mudarmos o layout para 1 carto por linha, a essncia alterar a direo do flex. Por padro,
todo elemento flex-direction: row , por isso os cartes so dispostos em linha. Podemos alterar a
direo do mural da seguinte maneira:
.mural {
flex-direction: column.
}
Mudar a direo do flex altera o significado da propriedade flex-basis que tnhamos colocado
nos cartes.
.mural {
flex-direction: column.
}
.cartao {
flex-basis: 190px;
flex-grow: 1;
}
Para que a funcionalidade seja aplicada em browsers que no suportam o flexbox, podemos alterar o
display: inline-block dos cartes para block .
.cartao {
flex-basis: auto;
width: auto;
display: block;
}
Mas, claro, no queremos mudar isso em todos os cartes. Vamos fazer com que essas regras sejam
aplicadas apenas quando o usurio clicar no boto de alterao do modo de visualizao.
30
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Note que esses estilos dependem totalmente do posicionamento do boto no html. Nosso boto ser
colocado dentro de um <header class="cabecalho"> , assim, esses estilos j no funcionaro mais.
<!-- O seletor #botaoMudaLayout:active + .mural j no funciona mais -->
<header class="cabecalho">
<h1 class="cabecalho-logo"> Ceep </header>
<button id="botaoMudaLayout">Muda Layout</button>
</header>
<section class="mural">
<div class="cartao"></div>
<div class="cartao"></div>
</section>
Outro ponto que enquanto o boto estiver sendo clicado, os cartes tero seu layout alterado.
Porm, ao soltar o boto, voltamos para o layout inicial.
Mudanas permanentes de estilo como essa, aps uma interao do usurio, ainda no so possveis
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
31
sem afetar nossa marcao. Para que nossos estilos se alterem em resposta a uma ao do usurio
usaremos JavaScript.
Essa linguagem de programao roda no navegador e permite que faamos lgicas muito mais
elaboradas sem a necessidade de um servidor. Alm disso, ele possui ferramentas que nos permite
interagir com os elementos do HTML, alterando seus estilos, contedo e atributos.
O termo "documento" frequentemente utilizado em referncias nossa pgina. No mundo frontend, documento e pgina so sinnimos.
Objetos Javascript
Mas como guardar tanta informao em apenas uma propriedade? Os principais tipos de dados do
Javascrit so string , number e boolean . Mas estes servem para apenas um valor, enquanto o
document precisa guardar toda a estrutura da nossa pgina.
Sempre que pensamos em guardar diversos valores, a primeria soluo que surge em nossa mente
um array. O array, permite guardar varios valores numa estrutura ordenada, dessa forma, se
precisarmos do valor de volta, basta saber que posio o colocamos.
//criando um array
var valores = [ 4 , 8.9 , true , "oi!" ]
//pegando o valor 4 que est primeira posicao (posicao zero):
valores[0];
Por causa dessa caracterstica, o document poderia facilmente ser um array. O nico problema
saber em qual posio est guardada a informao que queremos. Seria necessrio algum tipo de
documentao listasse o nmero de totas as propriedades. O ideal , ao invs de usarmos um nmero,
usassemos o nome do que queremos. Assim, o Javascript criou um tipo de dado mais complicado que
serve exatamente para isso, o object.
O object um tipo de dado que permite quardar valores e dar um nome para eles. Depois usamos o
nome para recuper-lo:
//criando um objeto
var pessoa = {
idade: 29,
altura: 1.75,
peso: 85,
32
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
fuma: true,
nome: "Andr"
}
//pegando o nome do objeto
pessoa.nome
//mudando a idade
pessoa.idade = 30
O DOM encontrada na propriedade local document uma estrutura que o navegador cria onde ele
representa cada elemento do html como um object javacript, com todas as suas propriedades (nome,
id, classes...).
BOM
Alm da estrutura da nossa pgina em memria, existe tambm uma estrutura que possui
informaes a respeito do prprio navegador, o BOM (Browser Object Model). Podemos acess-lo
atravs da propriedade window.
Tambm nessa propriedade que ficam guardados todas as funes e variveis globais, como as
funes alert e setTimeout , e as varivies console e at mesmo o `document**.
Alteraes no DOM
Ao alterarmos esses objetos, o navegador sincroniza as mudanas e alteram a aplicao em tempo
real.
Para testar isso, novamente recorremos ao DevTools. Nele existe a opo Console onde podemos
colocar cdigos JS e ver os resultados.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
33
querySelector
Como exemplo, vamos alterar a cor do cabealho da pgina. Precisamos primeiro pegar o elemento
JavaScript que representa esse ttulo:
document.querySelector("h1")
Esse comando usa os seletores CSS para encontrar os elementos na pgina. Usamos o seletor de
tagName mas poderamos ter usado outros:
document.querySelector(".class")
document.querySelector("#id")
Executando no console, voc vai perceber que o elemento correspondente selecionado. Podemos
ento manipular seu contedo. Voc pode ver o contedo textual dele com:
document.querySelector("h1").textContent
QUERYSELECTORALL
s vezes voc precisa selecionar vrios elementos na pgina. Vrias tags com a classe .secao
por exemplo. Se o retorno esperado mais de um elemento, usamos querySelectorAll que
devolve uma lista de elementos (array).
document.querySelectorAll(".cartao")
Podemos ento acessar elementos nessa lista atravs da posio dele (comeando em zero) e
usando o colchetes:
// primeiro carto
var cartoes = document.querySelectorAll(".cartao")
cartoes[0]
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
A propriedade style tem, dentro dela, todas as propriedades de CSS que o browser conhece.
Podemos acessar e alterar o valor do flex-direction , assim:
var mural = document.querySelector(".mural")
mural.style.flexDirection = "column"
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
35
Quando alteramos estilos diretamente pelo javascript, estamos inserindo estilos inline no elemento.
Exatamente como no exemplo abaixo:
<div class="mural" style="flex-direction:column">
<div class="cartao" style="flex-basis:auto; width:auto; display:block;></div>
<div class="cartao" style="flex-basis:auto; width:auto; display:block;></div>
</div>
O quo fcil manter os estilos do mural dessa forma? Se no quisermos mais usar flexbox, ou se
quisermos aplicar uma transio na mudana de layout, em quais lugares teremos que mexer? No
JavaScript. Dizemos que esse estilo est acoplado ao javascript.
At agora nossos estilos foram aplicados aos nossos componentes, atravs das classes que
colocvamos neles. Se nossa funcionalidade altera algum estilo, faremos com que ela modifique a classe
do elemento, no seu style .
ClassList API
Para trabalhar com classes usamos a ClassList API. No caso do mural, no qual precisamos
sobrescrever uma propriedade do CSS, adicionaremos uma classe:
document.querySelector(".mural").classList.add("mural--linhas")
No CSS:
.mural--linhas {
flex-direction: column;
}
.mural--linhas .cartao {
flex-direction: auto;
width: auto;
display: block;
}
H outras funes de manipulao possveis. Podemos verificar se um elemento possui certa classe
com classList.contains() recebendo o nome da classe.
var elemento = document.querySelector(".elemento")
if(elemento.classList.contains("elemento")){
alert("Tem a classe")
}
Ou ainda remover uma classe com certo nome usando classList.remove() . E, uma funo
36
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
INDICANDO MODIFICADORES
comum que classes seja acrescentadas aos nossos componentes para alterar ou adicionar
algum estilo em dado momento.
Essa classes no indicam a criao de componentes novos, mas a alterao de algum j criado.
Para indicar isso, usaremos o seguinte padro de nomenclatura:
.mural--linhas {
/* propriedades modificadas */
}
A renderizao padro um boto que depois pode ser estilizado pelo CSS. Colocamos tambm um
ID no elemento para poder referenci-lo tanto nos estilos quanto no JS.
Mas o que esse boto faz? Nada. Um button perdido no HTML no dispara ao alguma. Para
adicionar comportamento a ele, usaremos JavaScript. No caso, Eventos JavaScript.
Evento o nome dado a alguma ao que pode ser disparada em algum elemento da pgina. Um
boto, por exemplo, pode ser clicado, ento possui o evento de clique. Mas no s. Poderamos tratar o
evento de passar o mouse (mouseover) em algum elemento. Ou observar quando o evento de scroll na
pgina disparado. H muitos eventos diferentes e possveis no JS.
OUTROS EVENTOS
O seguinte site tem uma relao de todos os eventos possveis: https://developer.mozilla.org/ptBR/docs/Web/Events
No nosso exemplo, queremos lidar com o evento de clique do boto. No JavaScript, isso significa
3.6 RELEMBRANDO EVENTOS JAVASCRIPT
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
37
atrelar uma funo ao evento. Quando o clique acontecer, o navegador chama essa funo pra gente.
o que chamamos de funo de callback.
Para atrelar uma funo de callback, podemos usar as propriedades das tags html relativas a eventos,
que so as propriedades comeadas com on mais o nome do evento. Nesse caso queremos atrelar uma
funo ao evento de clique, ento usamos a propriedade onclick :
function alerta(){
alert("Fui clicado!");
}
<button id="mudaLayout" onclick="alerta()">Linhas</button>
Esse cdigo diz para o navegador que uma lgica javascript deve ser executada quando o evento de
click acontecer. Por enquanto, apenas chamamos uma funo que mostra um alerta.
2. O boto s precisa ser exibido no momento em que dois cartes cabem na mesma linha, ou seja, s
em telas maiores que 560px.
#mudaLayout {
display: none;
}
@media (min-width: 560px){
#mudaLayout {
display: inline-block;
}
}
38
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
width: auto;
display: block;
}
5. Agora vamos criar o nosso cdigo que vai trocar a visualizao quando clicarmos no boto. Ele deve
tratar o evento de clique no boto.
Crie a funo que adiciona a classe mural--linhas ao elemento (ou tira, se j tiver):
function mudaLayout(){
document.querySelector(".mural").classList.toggle("mural--linhas");
}
Teste no navegador.
6. Experimente chamar essa funo direto no console.
E o que acontece se escrever apenas mudaLayout , sem parnteses?
As funes no javascript so outro tipo de dado, ela representa uma lgica no lugar de um nmero
ou um texto. E essa lgica pode ser executada mais tarde com o uso dos parnteses.
7. Para deixar o cabecalho mais bonito, v na pasta 47 e copie os arquivos cabecalho.css e
opcoeDaPagina.css para uma pasta css dentro do projeto. Depois, importe esses arquivos no
<head> do index.html.
<link rel="stylesheet" href="css/cabecalho.css">
<link rel="stylesheet" href="css/opcoesDaPagina.css">
D uma olhada no contedo desses arquivos. O que teramos que mudar no html para ele funcionar
direito?
Ele deve ficar assim:
<header class="cabecalho container">
<h1 class="cabecalho-logo">Ceep</h1>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
39
<div class="opcoesDaPagina">
<button id="mudaLayout"
class="opcoesDaPagina-opcao opcoesDaPagina-botao"
>
Linhas
</button>
</div>
</header>
Note que ainda no queremos executar a funo mudaLayout , queremos apenas quardar ela dentro
da propriedade onclick para ser executada quando o evento for disparado. Por isso passamos o nome da
funo, sem o uso dos parnteses.
Mas e se precisarmos de dois comportamentos diferentes no clique desse boto? Toda vez que
passamos uma nova funo de callback para a propriedade onclick, ns estamos apagando os outros
callbacks que ele j possua. Isso significa que podemos at apagar comportamentos que so padro no
navegador, quebrando nossa pgina de maneiras imprevisveis.
O ideal seria ns adicionarmos uma nova funo de callback sem apagar as existentes. Para isso, foi
criada a funo addEventListener . Basta passar para ela o nome do evento e a funo de callback:
document.querySelector("#mudaLayout").addEventListener("click", mudaLayout);
40
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
41
Para cada carto teremos um boto de remover que quando clicado aplica a classe cartao--some no
respectivo carto:
.cartao--some {
opacity: 0;
transition: .2s ease-in;
}
A propriedade this
Primeiramente, precisamos saber qual foi o boto clicado.
function removeCartao(){
var botaoRemove = this;
}
Navegando no DOM
Agora que temos o boto em mos, podemos acessar qualquer outro elemento dentro dele com
botaoRemove.querySelector("seletor") , porm, o que precisamos acessar um de seus parentes,
no caso, dois nveis acima.
<div class="cartao">
<div class="opcoesDoCartao">
<button class="opcoesDoCartao-remove">Remover</button>
</div>
<p class="cartao-conteudo">
Lorem...
</p>
</div>
O DOM uma estrutura de dados complexa que armazena cada tag da pgina de forma hierrquica.
Na computao, damos o nome de rvore para essa estrutura.
42
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Dizemos que cada tag da pgina um n. Cada n interligado aos seus vizinhos. No nosso caso,
precisamos acessar os pais do boto:
function removeCartao(){
var botaoRemove = this;
var cartao = botaoRemove.parentNode.parentNode;
}
No queremos o comportamento de um <a> , mas queremos um atributo que aponte para o carto,
um atributo que diz qual o carto a ser removido.
<div class="cartao">
<div class="opcoesDoCartao" id="cartao_1">
<button class="opcoesDoCartao-remove" href="#cartao_1">Remover</button>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
43
</div>
<p class="cartao-conteudo">
Lorem...
</p>
</div>
Essa possibilidade de comunicao entre o HTML e o JavaScript muito til em diversos cenrios.
To til que bastante frequente querermos pendurar todo tipo de dados no HTML para depois acessar
pelo JS.
H quem use o class para isso, por exemplo. Usando valores especiais l dentro que depois pode
acessar via classList no JS. Mas no uma boa ideia. Alm de misturar as coisas, as classes so
limitadas (o espao um separador, ento no permite o uso de valores com espao).
No cdigo anterior, adicionamos um atributo customizado data-ref . Ele um atributo nosso, sem
nenhum valor semntico nem nenhuma funcionalidade especial. Coloc-lo apenas no HTML no vai
fazer nada. Precisamos acess-lo e implementar nossa funcionalidade.
function removeCartao(){
var botaoRemove = this;
var idDoCartao = botaoRemove.getAttribute("data-ref");
var cartao = document.querySelector("#" + idDoCartao);
44
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
cartao.classList.add('cartao--some');
}
dataset API
Existe tambm uma forma especial de acessar os data attributes com mais facilidade, atravs da
propriedade dataset . Por exemplo, para acessar o data-ref faramos:
<button class="opcoesDoCartao-remove" data-ref="cartao_1">Remover</button>
document.querySelector("button").dataset.ref;
No caso, nossa transio de .2s aplicada na classe cartao--some no ser visvel, j que, logo aps a
adio da classe, o carto removido.
3.14 REMOVENDO ELEMENTOS DO DOM E RELEMBRANDO SETTIMEOUT
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
45
Precisamos esperar que a transio acabe antes de remover o carto. Para isso, criaremos um timer
que executar nosso trecho de cdigo aps um certo tempo.
A funo setTimeout permite que agendemos alguma funo para execuo no futuro e recebe o
nome da funo a ser executada e o nmero de milissegundos a esperar.
function removeCartao(){
var botaoRemove = this;
var seletorCartao = "#cartao_" + botaoRemove.dataset.ref;
var cartao = document.querySelector(seletorCartao);
cartao.classList.add("cartao--some");
setTimeout(function(){
cartao.remove()
}, 170);
}
uma funo til para implementar funcionalidades que devem esperar pra executar.
SETINTERVAL
Isso funciona, mas o elemento deslocado de uma vez quando passamos o mouse. E se quisermos
algo mais sutil? Uma animao desse valor mudando lentamente, mostrando o elemento se deslocando
na tela? Usamos CSS3 Transitions.
Sua sintaxe possui vrios recursos mas seu uso mais simples, para esse nosso caso, seria apenas:
#teste:hover {
transition: top 2s;
46
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Para explorar o comportamento dos tipos de animaes disponveis, e como criar uma curva de
velocidade customizada para sua animao, existe uma ferramenta que auxilia a criao do cubicbezier : http://www.roblaplaca.com/examples/bezierBuilder/
Podemos ainda usar mais de uma propriedade ao mesmo tempo, incluindo cores!
#teste {
position: relative;
top: 0;
color: white;
}
#teste:hover {
top: 30px;
color: red;
transition: top 2s, color 1s ease;
}
Se quisermos a mesma animao, mesmo tempo, mesmo efeito para todas as propriedades, podemos
usar o atalho all (que j o valor padro, inclusive):
#teste:hover {
transition: all 2s ease;
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
47
enquanto ela ter apenas um boto. Use o editor mltiplo para isso: segure a tecla Ctrl e clique em
todos os lugares que vai colocar o novo cdigo. O editor vai duplicar o cursor:
Ateno! Lembre de dar ids diferentes para cada carto, e atribuitir ao data-ref o valor referente
ao id do carto dele!
2. Para dar um efeito suave remoo, criaremos a classe cartao--some.
.cartao--some {
opacity: 0;
transition: 0.2s ease-in;
}
48
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
4. Agora precisamos falar para o boto chamar essa funo quando clicamos nele. Use o
addEventListener :
//pega os botes
var botoes = document.querySelectorAll(".opcoesDoCartao-remove");
for (var i = 0; i < botoes.length; i++) {
//adiciona o evento em cada boto
botoes[i].addEventListener("click", removeCartao);
};
6. Teste o resultado!
Espera-se que o boto de "Remover" esteja funcionando devidamente com uma rpida transio na
opacidade do carto.
7. (Opcional) Estamos agora com vrios arquivos css. Procure no estilos.css propriedades que
poderiam estar em algum dos outros arquivos. Mova o cdigo para l e apague o que est repetido.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
49
50
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
CAPTULO 4
JQUERY
O jQuery o mais usado framework JavaScript do mercado. Ele muito importante no dia a dia e todo
programador front-end deve estar pelo menos familiarizado com ele.
O jQuery no um bicho de sete cabeas. Pense nele como um conjunto de funes JavaScript que
voc importa na sua pgina. So funes que te ajudam, por exemplo, a esconder as diferenas entre os
navegadores.
O jQuery foi feito para atender ao padro comum de programao front-end, onde primeiro
obtemos um objeto da pgina e depois utilizamos diversas funes e atributos para modificar seu estado,
e consequentemente, sua exibio no navegador.
Sendo assim, veremos como o jQuery acessa e altera elementos, inclusive como funciona seu
mecanismo de evento.
jQuery object
O primeiro componente que vamos analisar, e o principal, o jQuery object, que no cdigo tambm
conhecido como $ , seu alias. O uso mais comum do $ como a funo de fbrica de objetos do
jQuery:
var jsBotao = document.querySelector("#mudaLayout"); // com JavaScript puro
4 JQUERY
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
51
No exemplo acima, ao ser executada, a funo $ recebe uma String como argumento, contendo um
seletor CSS. O retorno um objeto assim como quando utilizamos a funo querySelector de
document, mas com uma pequena diferena: ele no o elemento do DOM, mas um objeto do jQuery
que guarda o elemento do DOM.
VARIVEL "JQUERY"
No lugar de usar o recomendado alias $ , voc pode usar diretamente o objeto jQuery , mas a
primeira forma recomendada, pela simplicidade da escrita:
var jqBotao = jQuery("#mudaLayout");
Outra vantagem do uso do jQuery para selecionar os elementos do documento que suas funes j
fazem o tratamento necessrio para que recebam um elemento ou um objeto que contenha mais de um
elemento.
// usamos querySelectorAll, porque queremos uma lista de Li"s
var jsCartoes = document.querySelectorAll(".cartao");
// usamos a mesma funo $, s que agora ela traz uma lista de elementos.
var jqCartoes = $(".cartao");
Mais uma vez necessrio conhecer os seletores CSS, pois o jQuery suporta todos, inclusive os
seletores mais modernos do CSS3. Alm disso, como veremos mais a frente, o jQuery possui
seletores exclusivos. No se preocupe com eles ainda, veremos algum deles mais a frente.
52
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Uma alterao inocente como essa s funciona a partir do Internet Explorer 10. Nas verses
anteriores deste navegador necessrio usar a propriedade innerText .
Com jQuery, no nos preocupamos se a propriedade existe ou no, pedimos sua funo text que
execute esta tarefa para ns:
var botao = $("#mudaLayout");
botao.text("Blocos");
Como j foi dito antes, as funes do jQuery se encarregaro da compatibilidade do nosso cdigo
entre mltiplos navegadores.
No exemplo acima, com uma nica chamada, todas as li's recebero "Sou um item". Isso porque o
jQuery object que est na varivel itens guarda dentro dele todos os elementos que tem a classe
"item". Queremos escrever menos cdigo e o jQuery vai nos ajudar muito nisso.
E voc ainda pode evitar a declarao da varivel itens :
$(".item").text("Sou um item");
E A FUNO VAL()?
A funo val() utilizada para obter e alterar o valor de elementos como input , select e
textarea .
Padro de utilizao
Um padro para se utilizar o jQuery o de escrever todo cdigo em uma funo annima e envi-la
com argumento para a funo $ :
$(function() {
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
53
A principal vantagem desse padro que, como estamos interagindo com elementos do documento,
essencialmente, o jQuery espera todos os elementos serem carregados e a pgina disparar o evento
"DOMContentLoaded", garantindo assim que nosso cdigo vai funcionar sem deixar nenhum elemento
"para trs".
Esse padro de utilizao que permite importar scripts que manipulem o documento na tag
<head> . No entanto, ele desnecessrio se for seguida a boa prtica de carregar os scripts antes do
fechamento da tag body.
4.2 EVENTOS
Para criar um carto, nosso usurio digitar o contedo dele num <textarea> , dentro de um
formulrio.
<form class="novoCartao" action="#">
<textarea class="novoCartao-conteudo"></textarea>
<input type="submit" value="Adicionar">
</form>
4.2 EVENTOS
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
No lugar de jogarmos o resultado da busca numa varivel, podemos associar o elemento de maneira
inline :
$(".novoCartao").on("submit", function() {
//aqui o cdigo de criao do carto
});
Cancelando os eventos
Em qualquer evento, temos disponvel no callback do nosso Event Listener uma varivel event .
Para ter acesso a ela, precisamos pedir ela como parmetro:
$(".novoCartao").on("submit", function(event) {
//aqui o cdigo de criao do carto
});
4.2 EVENTOS
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
55
E A FUNO BIND?
Nas verses do jQuery anteriores 1.7, a funo bind era utilizada mas, a partir da verso 1.7,
recomenda-se o uso da funo on . A sintaxe a mesma, o que muda o nome da funo:
$("button").bind("click", function(event) {
alert("Executou");
event.preventDefault();
});
Shorthand Event
Tambm possvel utilizar os mtodos de atalho, os shorthand events, com jQuery para os eventos
mais comuns do JavaScript. Temos, por exemplo, a funo submit, atalho para o on("submit", ...) :
$(".novoCartao").submit(function(event) {
//aqui o cdigo de criao do carto
});
Veja que escrevemos menos cdigo usando os shorthand events do jQuery. Assim, vamos usar on()
quando formos executar um mesmo cdigo para diferentes eventos ou quando formos trabalhar com o
mecanismo de delegao de eventos, assunto que veremos mais a frente.
56
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Encadeamento de funes
O jQuery permite o encadeamento de funes. Abaixo, a verso no encadeada:
var botao = $(".opecoesDoCartao-remove");
botao.text("Remover");
botao.click(function(event) {
// seu cdigo
})
CSS
Podemos alterar o estilo de elementos dinamicamente com jQuery atravs de sua funo css:
$(".mural").css("flex-direction", "column").css("background-color", "black");
Repare que, no exemplo acima, chamamos duas vezes a funo css . Podemos evitar isso passando
como parmetro um objeto do JavaScript onde cada propriedade equivale a uma propriedade do CSS. A
diferena que a propriedade vem entre aspas:
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
57
var estilos = {
"flex-direction" : "column",
"background-color" : "black"
}
$(".aviso").css(estilos);
addClass e removeClass
Como no JavaScript puro, o ideal deixarmos o CSS no seu 'quadrado', facilitando sua manuteno.
Podemos adicionar e remover classes usando jQuery com suas funes addClass e removeClass
respectivamente:
$(".aviso").addClass("invisivel");
$(".aviso").removeClass("invisivel");
toggleClass
Quando queremos 'ligar' ou 'desligar' uma classe, podemos ainda utilizar a funo toggleClass:
// se no tiver a classe, coloca; se tiver, remove
$(".aviso").toggleClass("invisivel");
show e hide
No exemplo acima, usamos uma classe que torna elementos da nossa pgina invisveis mas, com
jQuery, podemos usar suas funes show e hide para conseguir a mesma funcionalidade:
$(".aviso").hide(); // esconde
$(".aviso").show(); // mostra
toggle
Ocultar e exibir elementos na tela algo muito comum. por isso que existe a funo toggle.
Quando chamada num elemento visvel, ela o tornar invisvel. Quando chamada mais uma vez, tornar
o elemento visvel novamente:
// se estiver visvel, torna invisvel;
// se estiver invisvel, torna visvel
$(".aviso").toggle();
Agora que avanamos mais um pouco no uso do jQuery, vamos ver quais dessas funes podem nos
ajudar a fazer a criao dos nossos cartes.
58
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
novoCarto.classList.add("cartao");
Dessa forma, criamos um elemento do DOM na mo. Portanto, perdemos as vantagens do jQuery.
Por isso, o jQuery tem sua prpria forma de criar elementos.
Para manipular esse objeto, podemos utilizar vrias funes, tanto do JavaScript como do jQuery,
mas podemos definir os atributos e valores do elemento em sua construo.
Alterando propriedades
O resultado da execuo do cdigo acima seria uma tag, como exemplificada abaixo:
<button></button>
No exemplo acima, nosso boto carece de atributos. Podemos adicion-los atravs da funo attr :
var botao = $("<button>");
botao.attr("data-ref", "cartao_1");
botao.text("Remover");
O resultado da execuo do cdigo acima seria uma tag como exemplificada abaixo:
<button data-ref="cartao_1">Remover</button>
Podemos chegar no mesmo resultado passando para a funo $ um objeto JavaScript contendo os
atributos que queremos definir no novo elemento:
var botao = $("<button>", {data-ref: "cartao_1"}).text("Remover");
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
59
O jQuery tem diversas funes que nos permitem adicionar elementos no documento utilizando
qualquer elemento como referncia. A seguir, vamos explorar alguns exemplos considerando a seguinte
estrutura HTML:
<ul id="menu">
<li class="item">
<a href="#">Home</a>
</li>
<li class="item">
<a href="#">Empresa</a>
</li>
<li class="item">
<a href="#">Produtos</a>
</li>
</ul>
appendTo() e prependTo()
A funo appendTo inclui o elemento como ltimo filho (child) dos elementos que atendem o
seletor:
$("<span>", { class : "info" }).text("Novo span!").appendTo(".item");
No exemplo acima, a funo appendTo coloca um <span> como ltimo filho de cada elemento
que receber a classe "item" no documento:
<ul id="menu">
<li class="item">
<a href="#">Home</a>
<span class="info">Novo span!</span>
</li>
<li class="item">
<a href="#">Empresa</a>
<span class="info">Novo span!</span>
</li>
<li class="item">
<a href="#">Produtos</a>
<span class="info">Novo span!</span>
</li>
</ul>
Similar ao appendTo existe o prependTo, que coloca o elemento como primeiro filho dos
elementos obtidos pelo seletor.
$("<span>", { class : "info" }).text("Novo span!").prependTo(".item");
<ul id="menu">
<li class="item">
<span class="info">Novo span!</span>
<a href="#">Home</a>
</li>
<li class="item">
<span class="info">Novo span!</span>
<a href="#">Empresa</a>
</li>
<li class="item">
<span class="info">Novo span!</span>
<a href="#">Produtos</a>
60
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
</li>
</ul>
APPEND() E PREPEND()
insertAfter()
A funo insertAfter adiciona o elemento como irmo (sibling) logo aps cada elemento
retornado pelo seletor:
// Nesse exemplo adicionei um texto ao elemento
var novoSpan = $("<span>", { class : "info" }).text("Novo span!");
$(novoSpan).insertAfter("#menu li.item a");
<ul id="menu">
<li class="item">
<a href="#">Home</a>
<span class="info">Novo span!</span>
</li>
<li class="item">
<a href="#">Empresa</a>
<span class="info">Novo span!</span>
</li>
<li class="item">
<a href="#">Produtos</a>
<span class="info">Novo span!</span>
</li>
</ul>
insertBefore()
A funo insertBefore adiciona o elemento como irmo (sibling) antes de cada elemento
retornado pelo seletor:
// Nesse exemplo adicionei um texto ao elemento
var novoSpan = $("<span>", { class : "info" }).text("Novo span!");
$(novoSpan).insertBefore("#menu li.item a");
O resultado seria:
<ul id="menu">
<li class="item">
<span class="info">Novo span!</span>
<a href="#">Home</a>
</li>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
61
<li class="item">
<span class="info">Novo span!</span>
<a href="#">Empresa</a>
</li>
<li class="item">
<span class="info">Novo span!</span>
<a href="#">Produtos</a>
</li>
</ul>
AFTER() E BEFORE()
2. Para estilizar o form, copie da pasta 47 o novoCartao.css para a pasta css e importe esse arquivo no
principal.html.
<link rel="stylesheet" href="css/novoCartao.css">
3. Precisamos agora criar o evento no submit do <form> para criar o carto e coloc-lo na pgina. No
principal.js adicione o cdigo.
$(".novoCartao").submit(function(event){
//impede que a pgina recarregue
event.preventDefault();
//pega o que o usurio digitou
var campoConteudo = $(".novoCartao-conteudo");
var conteudo = campoConteudo.val().trim();
//cria os elementos do carto e adiciona no DOM
62
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
if (conteudo){
var conteudoTag = $("<p>").addClass("cartao-conteudo")
.append(conteudo);
$("<div>").addClass("cartao")
.append(conteudoTag)
.prependTo(".mural");
}
//apaga o contedo do textarea
campoConteudo.val("");
});
4. Nosso cdigo no vai funcionar. Falta importarmos o jquery. Copie o jquery.js da pasta 47 e copie
para uma pasta js no seu projeto. No esquea de importar ele no principal.html ANTES do
principal.js
[...]
<script src="js/jquery.js"></script>
<script src="principal.js"></script>
</body>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
63
//criando o contador
var contador = $(".cartao").length;
$(".novoCartao").submit(function(event){
[...]
if(conteudo){
//soma um no contador
contador++;
//cria atributo data-ref no botaoRemove
var botaoRemove = $("<button>").addClass("opcoesDoCartao-remove")
.attr("data-ref", contador)
.text("Remover")
.click(removeCartao);
[...]
//cria atributo id no cartao
$("<div>").attr("id","cartao_" + contador)
.addClass("cartao")
.append(opcoes)
.append(conteudoTag)
.prependTo(".mural");
}
[...]
});
64
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
CAPTULO 5
5.2 STRING.REPLACE()
Qualquer manipulao de texto que envolva trocar um pedao do texto por outro pode ser feito por
meio da funo replace .
var conteudo = "Esse o conteudo do carto.\n Acabei de pular uma linha".
conteudo.replace("\n", "<br>")
//resultado "Esse o conteudo do carto.<br> Acabei de pular uma linha".
No caso acima, em que temos apenas um "\n", o replace acontece com sucesso. Num caso com
5 DANDO PODERES AO CONTEDO
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
65
No queremos trocar apenas 1 carcter. Precisamos dizer ao javascript que para qualquer caractere
"\n" efetuaremos a troca. Precisamos mostrar ao javascript um padro de caracteres a serem trocados.
No exemplo acima, utilizando a sintaxe especial da expresso regular, testamos se a varivel frase
possui algum dgito, representado pelo padro \d.
66
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
O resultado da funo match acima retorna apenas um array de um elemento. Repare que, na
string, o padro /\d/ aparece mais de uma vez, mas a funo parou imediatamente na primeira
ocorrncia.
Para encontrar todas as ocorrncias de um determinado padro, podemos passar o parmetro "g"
(global) para a expresso regular:
var frase = "Quanto 10 mais 20?";
var ocorrencias = frase.match(/\d/g);
// retorna um array com quatro elementos["1", "0", "2", "0"].
Repare que o resultado acima no o esperado, pois ele considerou cada dgito dos nmero
individualmente. Se um ou mais dgitos forem necessrios, utiliza-se o operador + . Ele indica para a
expresso regular para considerar os dgitos seguintes enquanto o resultado for um nmero:
var frase = "Quanto 10 mais 20?";
var ocorrencias = frase.match(/\d+/g);
// retorna um array com dois elementos["10", "20"].
2. (opcional) Quando algum texto for marcado **dessa forma** queremos que ele se torne um texto
em negrito: <b> dessa forma </b> . Crie um replace com uma Expresso Regular que seja capaz
disso.
3. (desafio) Quando algum texto for marcado *dessa forma* queremos que ele se torne um texto em
itlico: <em> dessa forma </em> . Crie um replace com uma Expresso Regular que seja capaz
disso.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
67
E assim por diante. O pai do pai do pai do pai uma grande multiplicao de valores at chegar na
raiz do documento, o <html> . Se no tiver uma fonte definida, a maioria dos navegadores usa 16px
como padro para o <html> .
Isso quer dizer que esse cdigo:
<html>
<body>
<main style="font-size: 1.5em">
<h1 style="font-size: 2em">Titulo</h1>
<p style="font-size: 0.75em">Texto.</p>
</main>
</body>
</html>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
dizer que voc pode mudar o font-size de um elemento e isso afetar todos os seus filhos. muito til
para criar sees na pgina onde os elementos devem aumentar proporcionalmente entre si um
componente, um widget.
Ou seja, usamos em para facilitar a escrita do nosso CSS. E por isso bom dominar o uso de em e
saber aproveit-lo no seu cdigo.
O em , claro, no para todos os cenrios. Ele vincula as medidas do filho com o font-size do pai.
Voc mexe no pai e o filho afetado. Isso s vezes indesejado. S usamos em quando existe uma
relao estrutural entre o filho e o pai e queremos que um afete o outro. Onde no fizer sentido,
continue usando px.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
69
O REM
O rem uma medida nova parecida. A diferena que a conta no leva em considerao todos
os pais, mas apenas a raiz, o . Isso quer dizer que mexer no font-size de algum elemento na pgina
no vai refletir e atrapalhar outros. S se mexermos no
mesmo. til para o caso do design responsivo que vimos antes.
Mas lembre que o em multiplicar pelo font-size do pai uma coisa boa em muitas situaes.
Vrias partes da pgina podem ser encaradas como pequenos componentes autocontidos. E mexer
no pai do componente tem que afetar todos os filhos. O em excelente pra isso, ao contrrio do
rem .
Alm de flex-start , temos flex-end , center e outros. Essa imagem ajuda a entender:
70
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
71
O padro o valor strech . E importante saber tambm que o align-items muda a disposio
dos elementos no eixo principal do flex. Isso quer dizer que se estamos trabalhando om row (padro),
ele diz respeito ao alinhamento vertical dos filhos; se fosse column , seria o alinhamento horizontal.
O ponto ruim que no funciona em todos os navegadores. Mas h um bom suporte, desde o IE9
por exemplo. Caso voc queira suportar navegadores mais antigos, fcil implementar essa funo onde
ela no existir. Consulte:
https://developer.mozilla.org/ptBR/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Compatibilidade
72
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
font-size: 1em;
width: 11em;
flex-basis: 11em;
}
.cartao--textoMedio {
font-size: 1.5em;
width: 9em;
flex-basis: 9em;
}
.cartao--textoGrande {
font-size: 2em;
width: 6em;
flex-basis: 6em;
}
}
3. Criaremos agora a funo que nos dir qual o tipo do noso carto. Primeiramente, precisamos contar
o nmero de quebras de linha, o total de letras e o tamanho da maior palavra. Depois, baseados
nesses dados, decidir qual categoria dar ao carto.
function decideTipoCartao(conteudo){
var quebras = conteudo.split("<br>").length;
var totalDeLetras = conteudo.replace(/<br>/g, " ").length;
var ultimoMaior = "";
conteudo.replace(/<br>/g, " ")
.split(" ")
.forEach(function(palavra){
if (palavra.length > ultimoMaior.length) {
ultimoMaior = palavra;
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
73
}
});
var tamMaior = ultimoMaior.length;
//no mnimo, todo carto tem o texto pequeno
var tipoCartao = "cartao--textoPequeno";
if (tamMaior < 9 && quebras < 5 && totalDeLetras < 55) {
tipoCartao = "cartao--textoGrande";
} else if (tamMaior < 12 && quebras < 6 && totalDeLetras < 75) {
tipoCartao = "cartao--textoMedio";
}
return tipoCartao;
}
4. Agora, para mudar os tipos dos cartes, chamaremos nossa funo decideTipoCartao passando o
contedo do carto. Adicionaremos seu retorno como classe de todo novo carto. O cdigo a seguir
ser colocado no Event Listener de submit do formulrio de novos cartes.
$(".novoCartao").submit(function(event){
//... aqui, cdigo de aulas passadas
if (conteudo){
contador++;
var botaoRemove = $("<button>").addClass("opcoesDoCartao-remove")
.attr("data-ref", contador)
.text("Remover")
.click(removeCartao);
var opcoes = $("<div>").addClass("opcoesDoCartao")
.append(botaoRemove);
// **cdigo novo** chamada para nova funo
var tipoCartao = decideTipoCartao(conteudo);
// **cdigo novo** adicionando classe no novo carto
$("<div>").attr("id","cartao_" + contador)
.addClass("cartao")
.addClass(tipoCartao)
.append(opcoes)
.append(conteudoTag)
.prependTo(".mural");
}
//... aqui, cdigo de aulas passadas
});
74
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Ao usar $(".cartao") obtemos uma lista de todos os elementos com essa classe. A aplicamos o
hide() que esconde todos os elementos.
O problema que no queremos esconder todos. Queremos pegar os cartes mas filtr-los para
esconder apenas os que baterem com nossa regras.
A funo filter
Dada uma lista de elementos jQuery, podemos chamar a funo filter para refin-la. Essa funo
recebe cada elemento da lista e deve retornar true ou false, indicando se o elemento deve ou no ser
usado.
Por exemplo, para filtrar e esconder todos os cartes cujo texto tem exatos 5 caracteres:
$(".cartao").filter(function(){
return $(this).text().length == 5;
}).hide();
Vamos usar a funo filter no exerccio com um exemplo mais complexo para implementar a busca
textual dos cartes.
O cdigo anterior no funciona, pois est buscando pela ocorrncia de "termoBuscado". Precisamos
criar um padro baseado num valor varivel, que vem do usurio. Para isso, criaremos uma expresso
regular dinamicamente:
var texto = "Conteudo do meu carto";
var termoBuscado = "conteudo";
var regex = new RegExp(termoBuscado, "i");
var temPalavraConteudo = texto.match(regex);
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
75
A funo RegExp , quando invocada com um new , constri uma expresso regular baseada nos
seus dois parmetros. O primeiro o padro, em formato de texto. O segundo, as flags da regex, no
nosso caso, um "i" indicando que queremos uma regex case-insensitive.
Se mandarmos imprimir o valor da varivel regex acima veremos /conteudo/i
76
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
77
CAPTULO 6
Internet Explorer
Um dos problemas com a tcnica AJAX que verses muito antigas do Internet Explorer no
implementam esse objeto em seu interpretador de JavaScript. Em vez disso, necessrio utilizar um
componente ActiveX, que funciona de maneira semelhante, porm com sintaxe um tanto diferente.
A funo $.ajax
J vimos que um dos objetivos do jQuery fornecer uma maneira de escrevermos um nico script e
a biblioteca se encarregar de selecionar, a partir das funcionalidades disponveis em cada navegador,
qual objeto ou componente deve ser utilizado. Para fazer chamadas assncronas com o jQuery podemos
utilizar seu utilitrio ajax :
$.ajax(/* objeto com configuraes */);
Esse objeto com configuraes que passamos como argumento para o utilitrio ajax deve conter
pelo menos dois atributos: o endereo para onde ser feita a requisio sob a chave url e uma funo
que executada caso a requisio retorne com sucesso sob a chave success :
78
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
$.ajax({
url: "http://www.servidor.com/servico",
success: function (data, textStatus, jqXHR) {
// a resposta da requisio pode ser acessada pelo objeto "data"
}
});
Passagem de parmetros
Caso seja necessrio passarmos alguma informao na requisio, como parmetro, podemos inclulas na URL, por exemplo http://www.servidor.com/servico?promocao=janeiro . Note que os
parmetros de requisio devem ser convertidos para um formato possvel de ser transmitido em uma
URL.
Para o trabalho de converter strings em valores vlidos para uma URL (a funo
encodeURLComponent("string qualquer") faz isso para ns), podemos passar todas as informaes
Formato da resposta
Como mencionado antes, uma requisio AJAX pode devolver uma resposta em diversos formatos:
HTML, XML, JSON etc. A funo ajax do jQuery permite especificarmos qual ser o formato da
resposta do servidor para que o prprio jQuery processe a resposta e nos d um objeto do JavaScript que
representa essa resposta. Para isso, basta passarmos uma propriedade dataType no objeto de
configuraes que passamos para essa funo.
Se a resposta for um XML, por exemplo, podemos chamar a funo ajax da seguinte forma:
$.ajax({
url: "http://www.servidor.com/servico",
data: {
"busca": "evento caelum"
},
dataType: "xml",
success: function (data, textStatus, jqXHR) {
// data ser um objeto do JavaScript que representa o XML
}
});
Assim, com esse utilitrio possvel obter uma poro de informaes relevantes, de uma poro de
servios teis.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
79
O exemplo acima mostra apenas o status do erro e o texto recebido como resposta mas, em outros
cenrios, esta funo poderia avisar elegantemente ao usurio sobre a ocorrncia de algum problema ou
definir um comportamento padro a ser executado em caso de falha.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
JSON (JavaScript Object Notation) um formato de troca de dados. A sua estrutura facilita sua
manipulao e criao, tanto para seres humanos quanto para mquinas. H ganho de performance em
seu processamento se comparado com o XML. Este formato nada mais do que um objeto JavaScript,
com a diferena de seus atributos virem sempre entre aspas.
Um exemplo de JSON:
{
"nome": "Golden Valve",
"preco": 109.0,
"descricao": "Feito com o mais finos dos materiais especialmente para voc",
"imagem": "img/produto-6.jpg"
}
6.3 $.GETJSON
Apesar do AJAX ser uma tcnica que, desde a sua concepo, se preocupa com arquivos XML,
muito comum servidores enviarem um JSON (JavaScript Object Notation) como resposta s requisies.
O JSON nada mais do que um objeto JavaScript, com a diferena de que suas propriedades devem vir
entre aspas.
O JSON muito menor do que um XML e o efeito mais direto disto a rapidez com que os dados
so transferidos, sem falar da rapidez com a qual o browser realiza o processamento dos dados.
O jQuery possui a funo $.getJSON , especializada em trabalhar com dados no formato JSON:
$.getJSON("http://www.servidor.com/servico", function(retorno) {
});
O primeiro parmetro a URL que retornar os dados; o segundo, a funo de callback que
recebe como parmetro os dados retornado pela URL.
3. Use o jQuery para fazer a requisio assncrona. No esquea de pegar a resposta como parmetro.
Vamos imprimir o resultado no console para ver se est funcionando.
6.3 $.GETJSON
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
81
$("#ajuda").click(function(){
$.getJSON("https://ceep.herokuapp.com/cartoes/instrucoes",
function(res){
console.log(res);
}
);
});
6. Substitua o cdigo de adio de cartes no Event Listener de submit do formulrio de novos cartes,
82
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
83
Na coluna name temos as urls de todas as requisies feitas, e nas prximas colunas vrias
informaes a respeito de cada uma delas:
Method: o mtodo da requisio (GET ou POST)
Status: cdigo de resposta do servidor
Initiator: linha de cdigo que iniciou a requisio
Size: quantidade de dados baixados
Time: tempo total desde a chamada at ela ser completada
Timeline: grfico mais detalhado do tempo gasto
Podemos ainda saber mais detalhes clicando no nome da requisio. A aba Headers contm as
informaes que no so relevantes para o usurio. So em sua maioria protocolos de comunicao da
web. Umas dessas informaes exatamente o cabecalho do CORS:
84
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
2. Ao clicar no boto salvar, criaremos uma lista com todos os cartes. Criaremos, tambm, um objeto
com todas as informaes que nosso servidor precisa para salv-los.
$("#sync").click(function(){
var cartoes = [];
$(".cartao").each(function(){
var cartao= {};
cartao.conteudo = $(this).find(".cartao-conteudo").html();
cartoes.push(cartao);
});
//escolha seu nome de usuario aqui
var mural = {
usuario: "seu.email@exemplo.com.br"
,cartoes: cartoes
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
85
$.ajax({
url: "https://ceep.herokuapp.com/cartoes/salvar"
,method: "POST"
,data: mural
,success: function(res){
console.log(res.quantidade + " cartes salvos em "
+ res.usuario);
}
,error: function(){
console.log("No foi possvel salvar o mural");
}
});
});
Clique no boto salvar. Se uma mensagem de sucesso aparecer no console, os cartes foram salvos
com sucesso.
3. Os estilos referentes ao botaoSync esto no arquivo botaoSync.css, na pasta do curso. Copie esse
arquivo para a pasta css do seu projeto e inclua no head de principal.html:
<link rel="stylesheet" href="css/botaoSync.css">
Sempre que o AJAX de salvar os cartes terminar, seja com sucesso ou erro:
$("#sync").click(function(){
// cdigo omitido. Apenas adicione as novidades abaixo
$.ajax({
url: "https://ceep.herokuapp.com/cartoes/salvar"
,method: "POST"
,data: mural
,success: function(res){
// novidade aqui
$("#sync").addClass("botaoSync--sincronizado");
console.log(res.quantidade + " cartes salvos em "
+ res.usuario);
}
,error: function(){
// novidade aqui
$("#sync").addClass("botaoSync--deuRuim");
console.log("No foi possvel salvar o mural");
}
,complete: function(){
$("#sync").removeClass("botaoSync--esperando");
}
86
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
});
});
Para que as informaes sejam aproveitadas ento, necessrio que o nosso script tenha uma funo
com o mesmo nome que o servidor responde, tratando essa resposta. Essa funo o que chamamos de
funo de callback. O utilitrio ajax do jQuery j trata automaticamente o nome da funo de callback:
basta definirmos que queremos utilizar o formato JSONP:
$.ajax({
url: "http://www.servidor.com/servico",
dataType: "jsonp",
success: function (data, textStatus, jqXHR) {
// Essa a funo de callback
}
});
$.getJSON e JSONP
Quando utilizarmos a funo $.getJSON para obter JSONP, precisamos adicionar na url um
parmetro e um valor. Geralmente esse parmetro tem o nome "callback" e o valor pode ser qualquer
nome que estipularmos. O retorno vir dentro de uma funo com este nome:
$.getJSON("http://servidor.com.br/servico?callback=nomeFuncao",
function(retorno) {
});
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
87
88
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
89
CAPTULO 7
O problema desse cdigo que ele a varivel global. Isso quer dizer que qualquer parte da
aplicao, qualquer arquivo .js, qualquer funo, agora tem acesso a essa varivel usuario . Os
problemas so muitos.
A qualquer hora o valor dela pode ser alterado. H possibilidade de conflito, afinal usuario um
nome bastante comum que pode acabar sendo usado em outra parte da aplicao. No fim, temos um
cdigo mais confuso de ler, menos elegante e mais propenso a erro.
Para corrigir, s h uma soluo: esconder a varivel e tir-la do escopo global.
Escopo de funo
A linguagem JS s tem dois escopos possveis: o global que vimos e o escopo de funo. Ou a varivel
acessvel por todos, ou ela uma varivel local de funo.
Portanto, para resolver o problema que citamos do global, a nica soluo colocar numa funo:
function executa() {
var usuario = "seu.email@exemplo.com.br";
}
Nesse momento, sabemos que a varivel usuario no mais legvel fora da funo. Por isso,
precisamos colocar a chamada ao JSON l dentro tambm, para poder ter acesso ao valor de usuario :
function executa() {
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
}
90
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Claro que s criar a funo no suficiente. Afinal ela precisa ser chamada com executa(); para
rodar o cdigo. Isso deixa escancarado outro problema: o nome da funo o nosso novo global.
Na tentativa de esconder a varivel usuario dentro da funo, acabamos criando uma funo
global com nome executa . O mesmo problema volta. A chance de algum reescrever esse nome em
outro lugar. O cdigo feio e difcil de manter.
IIFE
Em JavaScript, tudo um valor, uma expresso. Inclusive funes. Podemos atribuir funes a
variveis e podemos passar funes como parmetro, como j fizemos tantas vezes.
Sabendo disso, possvel pensar num truque. Definir a funo sem nome no nos permite cham-la
depois (ela no tem nome!). Mas a prpria definio da funo em si devolver um valor funcional que
pode ser invocado imediatamente. Parece difcil mas invocar a funo logo que ela definida:
(function() {
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
})();
Repare o () no final. Isso indica invocao. Mas ao invs de passar o nome da funo antes,
7.2 IIFE: IMMEDIATELY INVOKED FUNCTION EXPRESSIONS
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
91
passamos a prpria funo. Uma expresso que devolve a funo como valor.
O nome disso Expresses de Funes Imediatamente Invocveis. Ou IIFE. uma excelente prtica
para encapsulamento e organizao de cdigo.
Tente acessar a varivel usuario no console, veja que ela no est disponvel no escopo global.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
ajuda.js
adicionaCartao.js
Depois, na pgina, vamos importar cada parte separadamente.
E performance?
H uma preocupao, bastante vlida, com relao a performance. A boa prtica diz que menos
arquivos, menos requests, so melhores para performance.
Isso nem sempre verdade, mas em geral uma boa diminuir sim, em especial se usarmos o
HTTP/1.1 clssico.
Mas em desenvolvimento queremos quebrar tudo isso para um melhor cdigo, mais organizado.
Parecem coisas conflitantes, mas no so. Mais pra frente, estudaremos ferramentas que permitem fazer
mudanas como essa na nossa aplicao automaticamente, antes de colocar o cdigo em produo.
Teremos vrios arquivos isolados em desenvolvimento e um arquivo juntado apenas em produo. Por
enquanto, nosso foco na organizao do cdigo.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
93
<script src="js/mudaLayout.js"></script>
<script src="js/busca.js"></script>
<script src="js/novoCartao.js"></script>
<script src="js/ajuda.js"></script>
<script src="js/sincronizacao.js"></script>
<script src="js/adicionaCartao.js"></script>
2. No fim deve dar um erro. No console deve aparecer que no existe a funo adicionaCartao .
Porque? Vamos resolver esse problema em seguida.
3. Ficou sobrando algum cdigo no principal.js? Ele ainda necessrio?
4. Onde voc colocou a funo de remover carto? Onde ela ainda usada? Discuta com a turma qual
soluo eles encontraram.
s uma funo
Lembre que uma IIFE uma funo. Ns conseguimos o encapsulamento apenas pensando no
escopo local da funo que isola as variveis. O que mais temos em funes? Retorno.
Se pensar bem, uma funo totalmente isolada do mundo exterior (encapsulamento) mas se
comunica com o mundo externo atravs de parmetros (entrada) e do retorno (sada). Toda funo
pode retornar alguma coisa para quem chama. Mesmo nossas IIFEs.
Um novo comportamento
Lembra do nosso mdulo de usurio? Ele encapsula a varivel e o comportamento do AJAX
associado ao usurio.
(function(){
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
})()
Imagine que queremos uma funo que descarta o usurio atual. Uma funo simples, que apenas
zera a varivel usuario . Como essa varivel faz parte da nossa IIFE, est encapsulada, a nova funo
precisa estar l dentro tambm:
(function(){
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
94
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
function descartaUsuario() {
usuario = undefined;
}
})()
Uma coisa a se reparar temos uma funo dentro da outra. Sem problemas. No JavaScript funes
so objetos normais e podem aparecer em qualquer lugar.
A nova funo descartaUsuario faz exatamente o que queremos. Mas ela est dentro da IIFE. Isso
quer dizer que s l dentro vamos enxerg-la. Apenas cdigo da IIFE pode chamar a funo nova.
E se quisermos chamar essa funo em outro ponto na aplicao?
Repare no retorno da funo. E repare na primeira linha, onde pegamos esse retorno e guardamos
numa varivel. Essa varivel (por acaso com mesmo nome, mas no precisaria) est no escopo global.
Isso quer dizer que qualquer parte do programa pode cham-la.
IIFEs com retorno so um bom jeito de encapsular um cdigo e s expor aquilo que realmente
necessrio.
Annimos
possvel simplificar ainda mais e deixar a funo interna sem nome e retorn-la diretamente:
var descartaUsuario = (function(){
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
return function() {
usuario = undefined;
};
})();
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
95
96
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Muitas funes
O mdulo de usurio estava assim, com apenas uma funo:
var descartaUsuario = (function(){
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
function descartaUsuario() {
usuario = undefined;
}
return descartaUsuario;
})();
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
97
}
return ???;
})();
Annimos
possvel, claro, configurar o objeto com as funes direto no momento do retorno com funes
annimas:
var moduloUsuario = (function(){
var usuario = "seu.email@exemplo.com.br";
$.getJSON(...);
return {
descarta: function () {
usuario = undefined;
},
atualizaDados: function () {
// chama JSON de usurio
}
};
})();
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Para calcular quantos cartes foram removidos aps a sincronizao, faremos o seguinte clculo: id
do ltimo carto adicionado menos quantidade de cartes que foram salvos l no servidor.
O id do ltimo carto s est disponvel dentro do mdulo adicionaCartao que criamos no exerccio
anterior. Para que alm da funo que adiciona um carto, ele retorne tambm o valor da varivel
contador, transformaremos nosso mdulo adicionaCartao, que est no arquivo adicionaCartao.js,
mudando seu retorno e mudando seu nome para controladorDeCartoes.
1. O retorno atual do mdulo uma funo annima, voltaremos a cham-la de adicionaCartao.
var adicionaCartao = (function(){
//... aqui, cdigo de exerccios anteriores
var contador = 0;
function adicionaCartao(conteudo, cor){
contador++;
var botaoRemove = $("<button>").addClass("opcoesDoCartao-remove")
.attr("data-ref", contador)
.text("Remover")
.click(removeCartao);
var opcoes = $("<div>").addClass("opcoesDoCartao")
.append(botaoRemove);
var tipoCartao = decideTipoCartao(conteudo);
var conteudoTag = $("<p>").addClass("cartao-conteudo")
.append(conteudo);
$("<div>").attr("id","cartao_" + contador)
.addClass("cartao")
.addClass(tipoCartao)
.append(opcoes)
.append(conteudoTag)
.css("background-color", cor)
.prependTo(".mural");
}
return adicionaCartao;
})();
2. Nosso mdulo precisa retornar alm da funo adicionaCartao, a varivel contador. Para isso,
transformaremos seu retorno num objeto e renomearemos o mdulo para controladorDeCartoes.
var controladorDeCartoes = (function(){
//... aqui, cdigo de exerccios anteriores
var contador = 0;
function adicionaCartao(conteudo, cor){
//... lgica do adicionaCartao
}
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
99
return {
adicionaCartao: adicionaCartao
,idUltimoCartao: function(){
return contador;
}
}
})();
4. Agora nosso mdulo se chama controladorDeCartoes. Ento melhor que mudemos o nome do
arquivo para refletir essa mudana e continuar fcil de mexer no projeto. Renomeie o arquivo
adicionaCartao.js para controladorDeCartoes.js.
No esquea de alterar tambm a tag script no principal.html
5. Para visualizar quantos cartes foram removidos aps a sincronizao com o servidor, o cdigo
destacado deve ser colocado no callback de sucesso do AJAX de salvar os cartes no arquivo
sincronizacao.js.
$("#sync").click(function(){
//... aqui, cdigo de exerccios anteriores
$.ajax({
url: "https://ceep.herokuapp.com/cartoes/salvar"
,method: "POST"
,data: mural
,success: function(res){
$("#sync").addClass("botaoSync--sincronizado");
console.log(res.quantidade + " cartes salvos em " + usuario);
// **cdigo novo**
var quantidadeRemovidos= controladorDeCartoes.idUltimoCartao()
- res.quantidade
console.log(quantidadeRemovidos + " cartoes removidos")
}
,error: function(){
$("#sync").addClass("botaoSync--deuRuim");
console.log("No foi possvel salvar o mural");
}
,complete: function(){
$("#sync").removeClass("botaoSync--esperando");
}
});
}
Remova um carto e salve. Veja no console se mostra quandos cartes foram deletados.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Agora que nosso mdulo est completo, conseguimos disponibilizar para fora a funo
adicionaCartao . Mas a aplicao ainda pode dar o mesmo erro : adicionaCartao is not defined. O
que pode acontecer para o javascript falar pra gente que no existe uma funo chamada
adicionaCartao?
Para poder usar essa funo, o navegador deve ler a funo primeiro. E com tantos arquivos,
podemos facilmente esquecer de importar o controladorDeCartoes.js no HTML. Ou mais, podemos
simplesmente errar a ordem das tags <script> ;
Para funcionar, a IIFE do novoCartao.js depende de um objeto externo, o objeto
controladorDeCartao . Como a IIFE uma funo, toda dependncia externa pode ser passada como
parmetro, basta criar uma varivel interna para receber esse valor e passar normalmente nos parnteses
que invocam a funo:
(function(controlador){
$(".novoCartao").submit(function(event){
var campoConteudo = $(".novoCartao-conteudo");
var conteudo = campoConteudo.val()
.trim()
.replace(/\n/g, "<br>");
if(conteudo){
controlador.adicionaCartao(conteudo);
}
campoConteudo.val("");
event.preventDefault();
});
})(controladorDeCartoes);
Essa estratgia nos d duas vantagens. A primeira que podemos dar o nome que quisermos para a
varivel internamente, potencialmente deixando nosso cdigo menos verboso. A segunda que no final
da IIFE temos uma lista de dependncias que ela precisa para funcionar. Assim, basta ler a ltima linha
para saber quais mdulos precisam ser importados no HTML antes.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
101
102
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
103
104
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
CAPTULO 8
A temos vrios pontos da aplicao que vo disparar essa sincronizao. Por exemplo o boto de
sincronizar e o boto que adiciona novos cartes:
$("#sync").click(function(){
// chama a funcao de sincronizacao
sincroniza();
});
$(".novoCartao").submit(function(){
// ... resto da logica
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
105
Repare que j tivemos o trabalho de colocar cada lgica numa funo separada, mas ainda temos que
chamar todas elas em todos os lugares. No uma boa ideia e vamos esquecer alguma.
Outra opo seria manter apenas a chamada ao sincroniza() e colocar toda as outras lgicas
(spinner, formulrio, log) dentro dela. Mas a teremos uma grande funo super complicada cheia de
comportamento. Falamos que uma funo com muita responsabilidade, pouco coesa.
Dando um passo atrs, em JavaScript, temos outros cenrios com essa mesma limitao que j foram
resolvidos. Quando clico em um boto qualquer, vrias aes podem ser executadas, sem que uma
precise conhecer (acoplar) a outra. E vrios elementos podem disparar cliques em pontos diferentes da
aplicao.
O que faz tudo isso funcionar muito bem no mundo do JS? Eventos.
106
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Quando esse comando executado, um evento disparado em todo o documento. como clicar em
um boto, ou passar o mouse por cima, mas qualquer elemento na pgina pode estar esperando esse
evento acontecer. Agora falta registrar algum que ficar escutando pelo evento. Para isso, usamos a
funo on como estamos acostumados, com a diferena de que trabalharemos com o evento que
criamos:
$(document).on("precisaSincronizar", function(event) {
// posso fazer o ajax
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
107
});
$(document).on("precisaSincronizar", function(event) {
// e eu posso fazer o spinner
});
No exemplo acima, para o evento "precisaSincronizar', temos dois 'observadores' que sero
executados quando o evento for disparado. Conseguimos acesso informao que foi pendurada no
momento do disparo do evento por meio do segundo argumento da funo de callback.
Podemos adicionar quantos 'observadores' quisermos para este evento, desacoplando-os da fonte
geradora, facilitando, assim, a manuteno de nosso cdigo.
A FUNO ONE
Muitas vezes queremos processar um evento apenas uma vez. por isso que existe a funo
one. Ela assemelha-se funo on com a diferena de que parar de escutar o evento aps o ter
processado uma primeira vez. Exemplo:
$(".botao").one("click", function(event) {
alert("Executarei este alerta apenas uma vez");
});
Agora, temos 4 funes que criamos com as lgicas independentes que devem ser disparadas no
momento da sincronizao. As 4 podem ser listeners desse evento customizado:
$(document).on("precisaSincronizar", mostraSpinner);
$(document).on("precisaSincronizar", desabilitaFormulario);
$(document).on("precisaSincronizar", logDeSincronizacao);
$(document).on("precisaSincronizar", sincroniza);
Repare como nenhuma funo conhece outra funo. Tudo desacoplado. Tudo com eventos. E
usando um evento criado por ns. Eventos customizados so uma tima forma de melhorar o design do
nosso cdigo.
108
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
2. Nosso boto de sync, quando clicado, deve disparar o evento "precisaSincronizar". Crie o seguinte
Event Listener em sincronizacao.js.
$("#sync").click(function(){
$(document).trigger("precisaSincronizar");
});
Teste seu boto de sincronizar, ele deve estar funcionando como antes.
3. Nosso mural deve ser sincronizado sempre que cartes forem adicionados ou removidos. Adicione
triggers do evento precisaSincronizar nesses dois pontos do cdigo.
Em novoCartao.js, para sincronizar toda vez que criamos um novo carto:
(function(controlador){
"use strict";
$(".novoCartao").submit(function(event){
var campoConteudo = $(".novoCartao-conteudo");
var conteudo = campoConteudo.val().trim()
.replace(/\n/g, "<br>");
if(conteudo){
controlador.adicionaCartao(conteudo);
$(document).trigger("precisaSincronizar");
}
campoConteudo.val("");
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
109
event.preventDefault();
});
})(controladorDeCartoes);
4. Alm do disparo de eventos, existe algum outro jeito de fazer essa sincronizao automtica? Discuta
com a turma e com o instrutor.
8.4 CONTENTEDITABLE
Agora que a funo de adicionar e remover cartes est pronta, vamos criar um nova funcionalidade:
a edio de cartes. Para editar cartes, precisamos que o usurio passe pra gente o novo contedo. O
HTML possui vrias tags para entrada de dados: input, textarea. Uma vez criado, precisamos de uma
forma para o usurio salvar a edio. Naturalmente surge a idia de usar um <form> :
<form class="edita">
<textarea class="edita-conteudo"></textarea>
<button>Salvar<button>
</form>
Note que ele muito parecido com o formulrio de adiciona. No podemos reaproveit-lo? O
HTML o mesmo, mas o que deve acontecer quando salvamos muda drasticamente quando queremos
editar ou s criar um novo carto. Alm disso, quando estamos editando um carto no fim da pgina, o
foco teria que mudar para o comeo. Como que fica a usabilidade da aplicao?
O ideal podermos editar diretamente o valor do contedo do carto. No HTML5 possvel
tambm transformar qualquer elemento HTML em editvel. Basta colocar o atributo
contenteditable :
<p class="cartao-conteudo" contenteditable>Texto que usuario pode mexer</p>
Agora o usurio pode clicar no pargrafo, digitar texto, apagar. Realmente editar seu contedo.
Depois, em JavaScript, podemos pegar o valor digitado apenas olhando a propriedade
110
8.4 CONTENTEDITABLE
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
111
Foco no javascript
Quando podemos fazer a sincronizao da edio do contedo do carto?
Sempre que um elemento focado, um evento focus disparado. Assim, possvel executar um
cdigo sempre que o elemento for focado.
$(".elemento").on("focus", function(){
});
Da mesma forma, existe um evento disparado quando o foco sai do elemento. O evento blur .
Podemos usar desses eventos para fazer a sincronizao.
$(".elemento").on("blur", function(){
$(document).trigger("precisaSincronizar");
});
Durante alguma interao do usurio poder ser necessrio que algum elemento arbitrrio ganhe ou
perca foco. No javascript possvel fazer isso com as funes focus e blur , respectivamente.
//elemento ganha foco
elemento.focus();
//elemento perde foco
elemento.blur();
Acessibilidade
recomendado que qualquer elemento que seja focado tenha uma resposta visual. possvel estilizar
um elemento focado com pseudo classe focus , no css.
.elemento:focus {
border: 2px solid blue;
}
Alguns estilos so aplicados por padro a elementos que esto focados. No Google Chrome
elementos focados ficam com o que parece ser uma borda azul. No Firefox o elemento focado fica
com uma borda preta e tracejada.
Tabindex
possvel adicionar um atributo tabindex a qualquer elemento do HTML. O atributo pode ter 3
112
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
tipos de valores.
Um tabindex maior que 0 indica a posio do elemento dentro da navegao. O valor 1 indica que
ele o primeiro a ser focado. Seguido dos elementos com valor 2, depois os com valor 3... O elemento a
seguir o primeiro a ser focado na navegao da pgina
<p tabindex="1">
...
</p>
Um tabindex igual a 0 diz que o elemento acessvel via navegao com o teclado e que pode ser
focado. Porm, o elemento no tem uma posio especfica dentro da navegao. Ele segue a hierarquia
do DOM.
<p tabindex="0">
...
</p>
Um tabindex menor que 0 diz que o elemento no deve ser focado via navegao de teclado,
porm, deve ganhar a habilidade de ser focado caso seja clicado.
<p tabindex="-1">
...
</p>
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
113
2. No precisamos mais da criao das opces do carto e do boto remove dentro do mdulo
controladorDeCartoes . O arquivo controladorDeCartoes.js deve ficar mais ou menos assim:
var controladorDeCartoes = (function(){
//...
function adicionaCartao(conteudo, cor){
contador++;
var opcoes = criaOpcoesDoCartao(contador);
var tipoCartao = //...
var conteudoTag = //...
$("<div>").attr("id","cartao_" + contador)
.addClass("cartao")
.addClass(tipoCartao)
.append(opcoes)
.append(conteudoTag)
.css("background-color", cor)
.prependTo(".mural");
}
//...
})();
3. Agora, qualquer alterao nas opes do carto devem ser feitas no mdulo criaOpcoesDoCartao.
Adicionaremos a opo de edio do carto. Note que o boto de edio muito parecido com o de
remoo. Tente reaproveitar o cdigo do botaoRemove, que j existe.
114
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
}
var ehPraEditar = false;
function toggleEdicao(){
var cartao = $("#cartao_" + this.dataset.ref);
var conteudo = cartao.find(".cartao-conteudo");
if(ehPraEditar){
ehPraEditar = false;
conteudo.attr("contenteditable", false);
conteudo.blur();
}else {
ehPraEditar = true;
conteudo.attr("contenteditable", true);
conteudo.focus();
}
}
return function(idNovoCartao){
var botaoRemove = //cdigo do botaoRemove
var botaoEdita = $("<button>").addClass("opcoesDoCartao-edita")
.addClass("opcoesDoCartao-opcao")
.attr("data-ref", idNovoCartao)
.text("Editar")
.click(toggleEdicao);
var opcoes = $("<div>").addClass("opcoesDoCartao")
.append(botaoRemove)
.append(botaoEdita);
return opcoes;
}
})();
4. Mostrar as opes de todos os cartes deixa a pgina poluda. S mostraremos as opes quando o
carto ou as prprias opces estiverem focadas ou com o mouse sobre elas. Adicione em cartao.css:
.cartao .opcoesDoCartao-opcao {
opacity: 0;
transition: opacity .2s ease;
}
.cartao:hover .opcoesDoCartao-opcao,
.cartao:focus .opcoesDoCartao-opcao,
.cartao .opcoesDoCartao:focus .opcoesDoCartao-opcao,
.cartao .opcoesDoCartao-opcao:focus {
opacity: 1;
}
Por que fizemos estilos das opes do carto dentro do arquivo cartao.css? Comente com a turma e
com o instrutor.
5. Os estilos aplicados no foco do carto ainda no esto sendo aplicados. Para que o carto seja focvel
necessrio dar um tabindex a ele. No arquivo controladorDeCartoes.js:
8.6 EXERCCIO: ACRESCENTANDO A OPO DE EDIO DO CARTO
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
115
Que valores a propriedade outline pode ter? Voc acha que tirar o outline pode ser um problema
de acessibilidade? Discuta com a turma e com o instrutor.
7. Para deixar nossas opes mais bonitas, pegue o arquivo opcoesDoCartao.css da pasta 47. Importe
ele no nosso html.
Procure a pasta img e cole na nossa pasta app tambm.
Se adicionamos um listener em algum evento desses, corremos o risco de executar nosso callback
muitas vezes. E se a funo fizer algo potencialmente pesado, podemos ter problemas de performance.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
O jeito evitar que a funo de callback seja chamada para cada disparo do evento. De alguma forma
retardar o evento. H vrias formas de lidar com isso. Um padro bem conhecido o "debounce".
Ele muito til quando estamos interessados apenas no final da interao do usurio. Por exemplo:
o usurio faz scroll mas quero executar algo apenas quando ele parar de fazer scroll. Ou o usurio est
digitando algo e quero executar algo ao fim da digitao.
Ou seja, queremos executar nosso listener quando certo evento acabar de ser chamado.
O Debounce Pattern
A ideia executar um certo listener apenas se o evento no tiver sido chamado h algum tempo.
Esperamos um tempo determinado (1 segundo por exemplo) para ver se o evento no vai ser disparado
novamente. Se no for, um sinal que ele parou de ser chamado ento podemos invocar nosso callback.
Como implementar isso? mais simples do que parece.
Vamos por partes. Com o setTimeout conseguimos agendar nossa funo para ser executada no
futuro. Podemos fazer ento algo assim:
// evento que dispara muito
window.onscroll = function() {
setTimeout(function(){
// lgica pesada
}, 1000);
}
Esse cdigo adiciona um listener de scroll que, ao invs de executar a lgica complicada dentro dele,
adia 1000ms (1s) sua execuo. Repare que se o scroll disparar 1000 vezes ainda faremos 1000 vezes a
lgica complicada, apenas adiamos 1s.
O que queremos dar o prximo passo: evitar que a lgica complicada seja chamada 1000 vezes. Ela
deve ser chamada apenas uma vez 1s aps o trmino do scroll. O segredo usar o clearTimeout para
impedir que a execuo anterior seja realmente chamada. O cdigo curto mas exige uma certa
abstrao para se entender que a lgica vai ser chamada somente uma vez no fim:
var timer;
// evento que dispara muito
window.onscroll = function() {
clearTimeout(timer);
timer = setTimeout(function(){
// lgica pesada
}, 1000);
}
Repare que guardamos o ltimo timer na varivel global timer . Antes de agendar o prximo
timeout, removemos o anterior. Isso efetivamente deixa apenas um timer ativo por vez. E o ltimo que
foi chamado.
8.7 EVENTOS E PERFORMANCE DO SITE
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
117
Efetivamente, o que fazemos zerar o contador a cada vez que o evento disparado. Assim, a lgica
s ser executada depois que o usurio parou de fazer aquela interao repetida.
THROTTLE PATTERN
Outra forma de lidar com lgicas pesadas em eventos que so disparados diversas vezes
seguidas simplesmente reduzir proporcionalmente a quantidade de vezes que a lgica vai ser
chamada. Chamamos isso de Throttle Pattern.
Podemos fazer isso facilmente usando um contador:
var contador = 1;
window.onscroll = function(){
if(contador >= 10){
//lgica pesada
contador = 0;
}
contador++;
}
No exemplo acima, nossa lgica pesada ser executada uma vez para cada dez disparos do
evento de scroll
Generalizando o Debounce
Se precisarmos de debounce em muitos lugares da aplicao, no vamos querer replicar esse tipo de
cdigo. Podemos definir uma funo debounce que recebe qualquer funo de lgica e transforma
numa verso com debounce.
A ideia chamar assim:
window.onscroll = debounce(function(){
// lgica pesada
});
Essa funo debounce uma generalizao da ideia anterior devolvendo uma funo para ser usada
no callback:
function debounce(callback) {
var timer;
return function() {
clearTimeout(timer);
timer = setTimeout(callback, 1000);
};
}
118
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
2. (desafio) Faa uma funo debounce genrica que possamos usar sempre que precisarmos desse
tipo de recurso.
8.8 EXERCCIO (OPCIONAL): EDIO DO CARTO E O DEBOUNCE PATTERN
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
119
Ser que necessrio colocar um event listener em cada opo de cor? Quantos event
listeners teremos se nossa pgina tiver 20 caixas?
Uma alta quantidade de event listeners pode causar problemas de performance no seu site. Para
diminuir o nmero de event listeners necessrios, podemos utilizar algumas tcnicas.
Event Bubbling
Quando clicamos na pgina, como o navegador sabe qual o elemento alvo do click? Na verdade
muito simples: cada elemento uma "caixa" na pgina, ento o navegador olha qual caixa contm o
ponto que foi clicado. Portanto se clicarmos em uma <li> , o navegador v que o ponto do clique est
dentro da "caixa" que o `%
%. Mas essa a nica caixa que contm esse ponto?
Como o <li> est dentro de um <ul> , quando clicamos em qualquer <li> dessa lista, podemos
dizer que estamos clicando tambm, na <ul> . Assim, no caso abaixo, a mensagem ser exibida se
clicarmos tanto nos <li> 's quanto na <ul> .
$(".lista").click(function(){
console.log("Lista foi clicada");
});
No seguinte caso, qual mensagem aparece primeiro se um algum <li> da lista for clicado?
$(".lista").click(function(){
console.log("Lista foi clicada");
});
$(".lista-trocaCor").click(function(){
console.log("Item foi clicado");
});
Na verdade estamos clicando nos dois elementos (e tambm em todos os pais na hierarquia). A
primeira mensagem ser: "Item foi clicado". Os eventos so disparados primeiramente no elemento alvo
do evento, ou seja, o <li> e depois seguem na ordem de parentesco do HTML.
Damos a esse comportamento dos eventos o nome de bubbling.
120
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Delegao de eventos
Para reduzir o nmero de event listeners na troca de cores utilizarmos o comportamento de
bubbling dos eventos para fazer o que chamamos de delegao de eventos.
Queremos chamar um lgica sempre que algum clica numa cor. Como todas as cores so <li>
dentro da <ul> , vamos colocar o listener na <ul> .
$(".lista").click(function(){
//cdigo que troca a cor
});
Para garantir que usurio clicou em algum item e no em algum outro ponto da lista precisamos
saber quem realmente foi clicado. Para isso, trabalharemos com o objeto event que o browser
disponibiliza em todo evento. O objeto event tem um atributo chamado target que representa o
elemento alvo da interao. No caso, o clique.
// preciso pedir o objeto com as informaes do evento
$(".lista").click(function(event){
//elemento que foi clicado
event.target
});
Para garantir que o elemento clicado um item da lista, basta acrescentar uma verificao:
$(".lista").click(function(event){
if(event.target.classList.contains("lista-trocaCor")){
var itemDaLista = event.target
}
});
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
121
122
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
123
5. (desafio) Conseguimos trocar as cores do carto, porm, isso ainda no sincronizado com o
servidor. Faa com que as cores sejam sincronizadas.
124
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
125
CAPTULO 9
APNDICE - AUTOMATIZAO DE
TAREFAS
Mesmo com um projeto pronto para produo ainda necessrio realizar uma srie de tarefas. Colocar
prefixos no css para ajustar compatibilidade, concatenar arquivos css e js para diminuir o nmero de
requisies do navegador, retirar os espaamentos desses arquivos para que eles sejam carregados mais
rpidos...
Muitas vezes o desenvolvedor realiza essas tarefas manualmente, o que pode demandar muito
tempo, alm do projeto estar vulnervel a possveis erros que o desenvolvedor possa cometer.
Para solucionar problemas como esses, foram criadas no mercado ferramentas de construo (build)
de projetos como Ant, Gradle e Maven, mas h algumas que nasceram voltada especialmente para
programadores front-end: o Grunt e o Gulp por exemplo.
So ferramentas diferentes. Foram feitos em JavaScript e com grande foco em automatizar tarefas de
front-end. Se voc, por exemplo, for seguir as boas prticas de performance para sites, j deve se
preocupar em minificar CSS e JavaScript ou ainda juntar arquivos para diminuir o nmero de requests e
at fazer CSS sprites. Ou talvez voc esteja usando algum pr-processador de CSS como o LESS, SASS ou
Stylus.
Aqui no curso vamos ver Gulp que mais simples de usar e to bom quanto o famoso Grunt.
126
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Dentro dele, podemos executar qualquer cdigo JavaScript que no dependa de um browser. Por
exemplo:
> 17 * 43
731
> var curso = "Caelum";
undefined
> console.log(curso);
Caelum
undefined
Mas repare que todo cdigo que envolva o browser e o DOM no funciona. No temos acesso a
objetos como document , window ou navigator :
> alert("oi")
ReferenceError: alert is not defined
Executando um mdulo
Imagine que queremos fazer a converso de textos **dessa forma** para um texto <b>dessa
forma</b> em vrios lugarem da nossa aplicao. Podemos tranformar essa lgica num mdulo, vamos
cham-lo de formatador.js:
var formatadorDeTexto = (function(){
function emNegrito(texto){
return texto.replace(/\*\*(.*)\*\*/g, "<b>$1</b>");
}
return{
emNegrito: emNegrito
}
})();
Como no temos o window, precisamos de outra forma de usar um JS externo. Para isso, o node
criou a funo require , e us-la bem fcil:
require("formatador.js");
O problema que o node mantm os escopos dos arquivos separados, pra evitar poluio de
variveis globais. Isso quer dizer que, mesmo importando o formatador.js, a varivel
formatadorDeTexto no estar disponvel.
Resolvemos isso com duas mudanas: primeiro, nosso cdigo que chama o require deve receber o
mdulo e salvar em uma varivel:
var formatadorDeTexto = require("formatador.js");
E, depois, o prprio arquivo formatador.js precisa estar preparado pra devolver o mdulo. No
node.js, a maneira de fazer isso atribuindo o mdulo a varivel module.exports :
// no final do arquivo formatador.js
module.exports = formatadorDeTexto;
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
127
Instalando Node.js
Voc pode baixar os instaladores do Linux, Mac e Windows na prpria pgina do Node.js em
http://nodejs.org/download/
128
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Instalando o Gulp
Com o Node.js instalado, utilize o gerenciador de pacotes npm na pasta do seu projeto para
instalar o Gulp:
npm install gulp
Dentro da pasta do projeto, ser criada a pasta node_modules com o gulp e todas as suas
dependncias.
GULP GLOBAL
Caso no seja possvel instalar o gulp globalmente, voc pode executar o gulp com o
comando:
./node_modules/.bin/gulp
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
129
console.log("Oi Mundo!");
});
Repare como usamos require no Node.JS para importar um mdulo. E a temos a API do Gulp
com a definio das tarefas, as tasks. Cada task recebe um nome e uma funo com o cdigo que ela
deve executar. No exemplo, no muito til, apenas mostramos uma mensagem na sada.
Para executar muito simples. Dado que seu cdigo est no gulpfile.js na raiz do projeto, basta
executar:
gulp oi
Ou seja, o comando gulp e o nome da task. Nas prximas sesses, veremos como fazer tasks mais
teis.
3. Crie um arquivo chamado gulpfile.js na pasta root do seu projeto. Dentro dele use o require para
usar o gulp e criar a primeira task
var gulp = require("gulp");
gulp.task("oi", function(){
console.log("Oi Mundo!");
});
130
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Usando o autoprefixer na mo
O autoprefixer um mdulo node que voc pode instalar e chamar na linha de comando. Passa o seu
CSS e ele adiciona os prefixos no seu arquivo.
npm install autoprefixer
autoprefixer arquivo.css
Agora precisamos criar a task que execute o autoprefixer para ns. Usando a sintaxe do gulp, vamos
encadeando as chamadas e transformaes nos arquivos. Importante saber a origem dos arquivos
( src ) e o destino dos arquivos ( dist ):
gulp.task("prefix", function(){
return gulp.src("css/*.css")
.pipe(autoprefixer())
.pipe(gulp.dest("css/"));
})
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
131
PIPE()
A funo pipe que vimos acima referente a um conceito de encadeamento, muito comum
no terminal. como colocar comandos numa linha de produo: o segundo comando vai usar o
resultado do primeiro, o terceiro vai usar o resultado do segundo, e assim por diante. Para isso,
usamos o caracter | (pipe).
comando1 | comando2 | comando3
Repare que no src passamos todos os arquivos .css da pasta css/. Podemos passar outros caminhos
e at ger-los dinamicamente. tudo JavaScript.
Ento encadeamos uma chamada ao autoprefixer() , o plugin que importamos. Ele vai agir na
lista de arquivos carregada anteriormente. No fim, escrevemos os arquivos transformados de volta na
pasta css/.
Para rodar essa task:
gulp prefix
Criamos uma nova task copy que pega todos os arquivos e subpastas de src/ e copia para a pasta
dist/.
Agora podemos rodar com gulp copy . E precisamos mudar nossa task de prefixos para agir apenas
na pasta dist/.
132
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
3. No terminal rode o comando gulp copy . Procure pela nova pasta dist e veja se deu tudo certo.
4. Agora vamos fazer funcionar o prefixador. Comece instalando o plugin do autoprefixer no projeto
usando o npm no terminal:
$ npm install --save-dev gulp-autoprefixer
5. Agora vamos criar a tasks para colocar os prefixos. Nossa aplicao deve se compatvel com as duas
ltimas verses de todos os navegadores e O Internet Explorer a partir do 10.
Fique atento aos caminhos de origem e destino e com as funes pipe
gulp.task("prefix", function(){
return gulp.src("dist/css/*.css")
.pipe(prefixer({
browsers: ["last 2 versions","IE 10"]
}))
.pipe(gulp.dest("dist/css"));
});
6. No terminal, rode o comando gulp prefix . Depois de terminado, abra a pasta css dentro da pasta
dist e veja o resultado.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
133
Agora, s precisamos digitar o comando gulp prefix e ele vai chamar as outras tasks.
Mas note que sempre queremos chamar a task prefix. Ento podemos configurar uma task default
134
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
3. Quando adicionamos um arquivo, a task copy se encarrega de colocar eles na pasta dist. Mas e uma
alterao? E uma remoo? Queremos que a pasta dist represente exatamente o estado da src
Crie uma nova task, para limpar a pasta dist sempre antes de copiar. Pra isso, instale o del do
Node.js pelo terminal.
$ npm install del
4. Agora, no gulpfile.js, use o require para pegar o del e criar a task. No esquea de acrescentar essa
dependncia no "copy"
var del = require("del");
gulp.task("clean", function(cb){
del(["dist/**/*"], cb);
});
gulp.task("copy", ["clean"], function(){
//...
});
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
135
Podemos usar o plugin gulp-watch para executar as tasks pra gente sempre que houver alguma
mudana no nosso projeto. Podemos instal-lo com:
npm install gulp-watch
Depois disso, h vrias formas de usar. Uma delas tratar o watch como um filtro nas tasks que j
temos. Por exemplo, na que lida com os prefixos:
gulp.task("prefix", function() {
return gulp.src("src/css/*.css")
.pipe(watch("src/css/*.css"))
.pipe(autoprefixer())
.pipe(gulp.dest("dist/css/"));
});
3. Agora crie a task para assistir a modificaes dos arquivos do nosso projeto. Faa-o chamar a task
"prefix" quando isso ocorrer
gulp.task("watch", function(){
watch("src/**/*", function(){
gulp.start("prefix");
});
});
136
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
4. No terminal, inicie o watch com o commando gulp watch . Se o terminal travar, porque est
funcionando. O Watch uma task que vai ficar rodando enquanto desenvolvemos.
Abra no navegador o dist/principal.html, pois ele que usa os CSSs modificados pelo gulp. Depois
faa uma alterao no projeto original. Recarrege o dist/principal.html pgina e veja que a altero j
entrou na pasta dist tambm.
Veja no terminal as tarefas que o gulp executou sem voc fazer nada, apenas por ter feito uma
modificao.
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
137
CAPTULO 10
10.2 SASS
O SASS bem antigo e j passou por muita coisa. Originalmente escrito em Ruby, j foi
implementado em JavaScript e C++. Tem duas variaes de sintaxes, uma totalmente inovadora e outra
que funciona como uma extenso da sintaxe do CSS. Vamos preferir essa ltima, a SCSS.
Nesting de seletores
138
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
Um recurso bastante comum nos pr-processadores facilitar a escrita de seletores de vrios nveis.
Imagine um CSS comum assim:
header {
width: 90%;
}
header h1 {
font-size: 1.5em;
}
Colocamos certa regra no header e outra no h1 dentro do header. Mas e se mudarmos o header
para usar uma classe .cabecalho ? Temos 2 lugares pra mexer. Fora que existe uma certa
desorganizao no cdigo original: o seletor do h1 est ligado ao do header mas nada impede que
escrevamos tudo espalhado no arquivo.
Existe no SASS ento o recurso de escrever seletores aninhados:
header {
width: 90%;
h1 {
font-size: 1.5em;
}
}
Repare que o h1 declarado dentro do header . Isso no CSS vlido. No fim, o SASS vai gerar
um CSS parecido com o que vimos antes, com o seletor header h1 .
Repare como precisamos escrever o seletor header h1 duas vezes. Se um dia precisar mudar, h 2
lugares pra fazer isso.
Com SASS, podemos escrever media queries sem seletores dentro de outro seletor. Desta forma:
header h1 {
font-size: 1.5em;
@media (min-width: 600px) {
font-size: 2em;
}
10.2 SASS
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
139
Isso no CSS vlido. um atalho do SASS que permite no duplicar os seletores nas media queries.
No fim, ser gerado o CSS anterior, com o seletor duplicado.
A podemos escrever uma task nova, bem parecida com as que j fizemos. A diferena que vamos
chamar sass() para fazer a compilao:
gulp.task('sass', function(){
return gulp.src('dist/scss/*.scss').
.pipe(sass())
.pipe(gulp.dest('dist/css'));
});
Mas e se acontecer algum erro na compilao? Podemos pedir para o Gulp imprimir esses erros e
assim descobrir onde precisamos corrigir. Basta adicionar o comando dos gulp-sass
sass().on('error', sass.logError)
gulp.task('sass', function(){
return gulp.src('dist/scss/*.scss').
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('dist/css'));
});
140
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
3. Agora vamos configurar o gulp para ele poder processar o scss. No terminal, use o npm para instalar
o gulp-sass no projeto:
$ npm install --save-dev gulp-sass
5. Crie uma task que pegue todos os arquivos na pasta scss, processe o SASS e salve o resultado na pasta
css. Vamos fazer tudo isso na pasta dist, para no alterar o nosso projeto original:
gulp.task('sass', function(){
return gulp.src('dist/scss/*.scss')
.pipe(sass())
.pipe(gulp.dest('dist/css'));
});
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
141
Repare que os valores mudam mas h muita repetio ainda. No SASS, podemos isolar cdigo
repetido em mixins. como se fossem funes como as que temos em JavaScript. Recebem parmetro e
permitem encapsular cdigo nelas.
A sintaxe SASS determina um bloco @mixin que recebe um nome e uma lista de parmetros
(variveis):
@mixin tamanhoCartao($fonte, $largura){
font-size: $fonte;
width: $largura;
flex-basis: $largura;
}
142
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
3. Agora, mude os tamanhos para usar o mixin que criamos, passando os valores certos de cada um:
.cartao--textoPequeno {
@include tamanhoCartao(1em, 11em);
}
.cartao--textoMedio {
@include tamanhoCartao(1.5em, 9em);
}
.cartao--textoGrande {
@include tamanhoCartao(2em, 6em);
}
Procure o arquivo .css gerado e veja o resultado. Note que o resultado final tambm tm prefixos.
Voc pode descobrir mais funcionalidades do SASS na documentao do site oficial http://sasslang.com/
Apostila gerada especialmente para Heres Edison Valdivieso Tobar Neto - heresneto@gmail.com
143