- Vimos novos elementos HTML para interação com o usuário:
<label for="numero-de-pasteis">Pastéis: </label> <input type="number" value="1" id="numero-de-pasteis"> <!-- não fecha! --> <button id="calcular">Calcular Conta</button>
- Para atribuir algum comportamento ao clique do
<button>
, é necessário usar JavaScript
- Para atribuir algum comportamento ao clique do
- Assim como em CSS, há 3 formas para incluir código JavaScript
- Arquivo externo com
<script src="arquivo.js"></script>
👍 - Embutido na tag
<script>...</script>
👎 - Inline em atributos
onclick
👎👎👎
- Arquivo externo com
- A preferida é arquivo externo, porque ela:
- Promove reutilização de código JavaScript por mais de um arquivo HTML
- Respeita o princípio da separação de responsabilidades
- O DOM é a visão que o JavaScript tem dos elementos da página
- Dá para recuperar/alterar elementos do DOM com o objeto
document
:// cria uma variável e recupera o elemento da logo (id="logomarca") let logoEl = document.querySelector('#logomarca'); // atribui um evento de 'click' ao elemento da logo logoEl.addEventListener('click', function() { alert('Logo clicada!!'); 👹 });
[DOM]: Document Object Model
- Relembrando o tipo
String
- Template strings
- Interpolação de valores
- Strings multilinha
- Função de transformação
- Representa um texto codificado em UTF-8
- Não existe o tipo
char
como em C/C++ e Java, apenas string 😉 - Usamos aspas simples ou duplas
"Abc" === 'Abc' // simples é mais legal!! mas basta ser consistente
- Possui uma propriedade chamada
length
com o seu comprimento:console.log('Cachorro'.length); // 8
- Exemplos:
let aranhas = 'fofofauna'; const caminhoVideo = 'videos/a.mp4'; const nomeCompleto = primeiro + ' ' + ultimo; // concatenou
- É uma forma mais recente para criar strings
- Formato: usa-se crase para delimitar. Exemplo:
-
// template string let fruta = `Kiwi`;
// string normal let fruta = 'Kiwi';
- Permite interpolar (substituir) variáveis dentro de strings:
-
const peso = 82; const nome = 'Kagaro Nakama'; // com template strings const frase = `${nome} pesa ${peso}kg`; // "Kagaro Nakama pesa 82kg"
const peso = 82; const nome = 'Kagaro Nakama'; // concatenando strings normais const frase = nome + ' pesa ' + peso + 'kg'; // "Kagaro Nakama pesa 82kg"
- A sintaxe é mais sucinta e legível
- Vejamos outros exemplos...
- É possível colocar expressões dentre de
${...}
. Exemplo:// supondo que existem variáveis preco=5 e qtde=2 let aConta = `Sua conta é R$ ${preco * qtde - 3}`; // "Sua conta é R$ 7"
-
// supondo variáveis dia, mês, ano e func. obtemMes const data = `${dia} de ${obtemMes(mes)} de ${ano}`; // Ex: "20 de janeiro de 2021"
const tom = 128; const corCinza = `rgb(${tom}, ${tom}, ${tom})`; // Ex: "rgb(128, 128, 128)"
- Mas qual é o tipo de dados??
console.log(typeof "texto"); // imprime "string" console.log(typeof `texto`); // imprime "string"
- É String mesmo! Só muda a sintaxe pra escrever
- Ou seja, a interpolação é apenas uma sintaxe mais legal para concatenar strings com variáveis/expressões
- Digamos que você queira que uma variável string contenha uma poesia (ocupando várias linhas)
- As template strings permitem que uma string ocupe mais do que uma linha no código fonte
-
// com template string let poesia = `Cavei cavei cavei Isto não é um poema Mas é profundo.`;
// com string normal let poesia = 'Cavei cavei cavei\n' + 'Isto não é um poema\n' + 'Mas é profundo.';
- Nesse caso, quando há uma quebra de linha no código fonte, é colocado um
\n
dentro da template string
- 3 Formas:
- Função tradicional
- Função anônima
- Função seta (anônima também)
-
function cadastrar() { // ... }
const cadastrar = function() { // ... };
- Função seta é uma sintaxe mais nova e sucinta para as anônimas ⬆
-
const cadastrar = () => { // ... };
- Omitir
function
- Seta entre parâmetros e corpo
return
implícito- Mantém o valor do ponteiro
this
- Omitir
- Os três primeiros itens já são legais o suficiente pra preferirmos a forma da função seta
- Vejamos alguns exemplos
-
function ciao() { return 'Ciao'; } function oi(prim, ult) { return 'Oi ' + prim + ' ' + ult; } function hi(name) { return 'Hi ' + name; } function fatorial(n) { let resultado = 1; while (n > 1) { resultado *= n; n--; } return resultado; } let ciao = () => 'Ciao'; let oi = (prim, ult) => 'Oi ' + prim + ' ' + ult; let hi = name => 'Hi ' + name; let fatorial = n => { let resultado = 1; while (n > 1) { resultado *= n; n--; } return resultado; }
let usuarios = ['Joel', 'Fani', 'Fúlvio'];
let alunos = [{ matricula: '...' }];
let numeros = [1, 4, 2, 5];
- Pegar apenas usuários que começam com letra 'F':
-
usuarios.filter(function(nome) { return nome.startsWith('F'); });
usuarios.filter(nome => nome.startsWith('F'));
-
- Buscar pelo aluno com uma matrícula:
-
alunos.find(function(aluno) { return aluno.matricula === '2005046102'; });
alunos.find(al => al.matricula === '2005046102');
-
- Vetor com os quadrados do original:
-
numeros.map(function(numero) { return numero ** 2; });
numeros.map(numero => numero ** 2);
-
- Relembrando
document.querySelector()
- Selecionando vários elementos
- Alterando o contéudo
- Alterando atributos
- Colocando/removendo classes
- O método
document.querySelector(seletor)
permite que, a partir de um código JavaScript, recuperemos um elemento do DOM- Ele recebe um único argumento que é um seletor CSS. Exemplo:
let logoEl = document.querySelector('#logomarca'); let tabelaEl = document.querySelector('#tesouros-pirata'); let principalEl = document.querySelector('main');
- Ele retorna um elemento HTML que pode ser alterado
- Também existe
document.querySelectorAll(seletor)
(repare oall
), que retorna mais de um elemento, mas veremos ele depois
- Ele recebe um único argumento que é um seletor CSS. Exemplo:
- O
document.querySelector
retorna apenas 1 elemento- Se tiver mais de um, retorna o primeiro encontrado
- O
document.querySelectorAll
retorna todos que forem selecionados:let inputs = document.querySelectorAll('input'); // retornou um 'NodeList' // com todos inputs da página console.log(`Quantidade de inputs na página: ${inputs.length}`); let primeiroInputEl = inputs[0];
- Para atribuir um evento a todos os elementos retornados:
let imagens = document.querySelectorAll('img'); // retornou um 'NodeList' // INCORRETO: um NodeList não possui um método "addEventListener" imagens.addEventListener('click', function() { }); // CORRETO: cada item do NodeList (array) é um elemento HTML, logo, // possui a propriedade "addEventListener" for (let i = 0; i < imagens.length; i++) { imagens[i].addEventListener('click', function() { }); }
-
Um
NodeList
é "praticamente um array" - ele possui os métodos essenciais:let inputs = document.querySelectorAll('input'); // inputs é um 'NodeList'
-
// propriedade .length (igual um array) console.log(`Quantidade de elementos: ${inputs.length}`);
// método 'forEach' (igual um array) inputs.forEach(function(el) { // ... });
// pegando um elemento como se fosse um array let primeiroEl = inputs[0];
- Um
NodeList
é praticamente um array, mas não possui todos os métodos. Por exemplo: -
umNodeList.length ✅ umNodeList[5] ✅ umNodeList.forEach(...) ✅ umNodeList.indexOf(...) ❌ umNodeList.sort() ❌ umNodeList.reverse() ❌ umNodeList.filter() ❌ umNodeList.find() ❌
umVetor.length ✅ umVetor[5] ✅ umVetor.forEach(...) ✅ umVetor.indexOf(...) ✅ umVetor.sort() ✅ umVetor.reverse() ✅ umVetor.filter() ✅ umVetor.find() ✅
- Se quiser transformar um
NodeList
em um vetor, usevetor = Array.from(umNodeList)
:let todosParagrafos = document.querySelectorAll('p'); // é um 'NodeList' todosParagrafos = Array.from(todosParagrafos); // agora é um 'Array'
- O objeto
document
dá acesso ao Document Object Model, ou DOM - Por exemplo, para pegar um elemento a partir de seu
id
e colocá-lo em uma variável:let botaoDeliciaEl = document.querySelector('#botao-delicia');
- Agora é possível fazer várias coisas com o botão, como:
- Associar um evento de clique
- Pegar ou alterar seus atributos
- Alterar seu conteúdo
- Alterar seu estilo
- Agora é possível fazer várias coisas com o botão, como:
::: figure .figure-slides.tag-anatomy.clean.flex-align-center
- Tags de abertura podem ter atributos:
<img src="bob-esponja.png">
- Em
<img>
, o atributosrc="..."
aponta para a URL do arquivo - Não deve haver espaço entre seu nome e seu valor:
<img src = "...">
👎<img src="...">
👍
- Em
-
É possível alterar o conteúdo de um elemento com
<iframe width="250" height="130" src="//jsfiddle.net/fegemo/wLp3kv59/embedded/result/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right" style="clear: right;"></iframe> <iframe width="250" height="153" src="//jsfiddle.net/fegemo/wLp3kv59/embedded/html/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right" style="clear: right;"></iframe>elemento.innerHTML
:let contador = 0; let contadorEl = document.querySelector('#contador'); // quando clicado, (1) conta e (2) altera conteúdo contadorEl.addEventListener('click', () => { contador++; // (1) conta contadorEl.innerHTML = contador; // (2) altera });
- É possível alterar atributos dos elementos:
<img src="imgs/pikachu.png" id="pokemon-lutando">
let pokemonEl = document.querySelector('#pokemon-lutando'); pokemonEl.src = 'imgs/bulbasaur.png'; // alteramos o 'src'
- Aqui, alteramos o atributo
src
daimg
, mas poderia ser qualquer um- Por exemplo, em
input
costumamos pegar/alterar ovalue
inputEl.value = 'novo valor';
- Por exemplo, em
- Aqui, alteramos o atributo
- É possível colocar ou remover classes de elementos:
botaoEl.classList.add('selecionado'); // coloca .selecionado imageEl.classList.remove('oculta'); // remove .oculta pEl.classList.toggle('expandido'); // coloca ou tira .expandido
-
<iframe width="250" height="170" src="//jsfiddle.net/fegemo/wbq109xg/embedded/result/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right bring-forward"></iframe>
Isso pode ser usado, por exemplo, para ↘
"marcar" elementos - Ou então pra fazer um menu lateral aparecer...
-
<iframe width="250" height="170" src="//jsfiddle.net/fegemo/wbq109xg/embedded/result/" allowfullscreen="allowfullscreen" frameborder="0" class="push-right bring-forward"></iframe>
Isso pode ser usado, por exemplo, para ↘
<iframe width="340" height="200" style="width: 340px" src="//jsfiddle.net/fegemo/wbq109xg/embedded/result,js,css/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
- Marca/desmarca elemento. Ideia:
- No evento de
'click'
de cada um:- Alterna a classe
.selecionado
do elemento que foi "clicado"el.classList.toggle('selecionado')
- Alterna a classe
- No evento de
- Apenas 1 elemento selecionado por vez. Ideia:
- No evento de
'click'
de cada um:- Tira a classe
.selecionado
de todos - "Re"coloca a classe no elemento "clicado"
- Tira a classe
- No evento de
<iframe width="100%" height="400" src="//jsfiddle.net/fegemo/dj37kc7e/embedded/result,html,js,css/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
- No HTML:
<body> <nav id="menu">...</nav> <main>...</main> </body>
- No JavaScript, alterna a classe
.menu-visivel
no<body>
- No CSS, desloca tudo para a direita quando o
<body>
tem.menu-visivel
- Atividade de hoje
- Que elemento foi clicado?
- Subindo na árvore do DOM
- Alternando uma classe
- Crie parágrafos que expandem/retraem e uma galeria 📓
- Baixe os arquivos e veja as instruções
no arquivo
README.md
- Baixe os arquivos e veja as instruções
no arquivo
- Há 2 atividades:
- Criar um código em JavaScript para fazer os botões "+"
expadirem ou retrairem o texto dos parágrafos
- Fazer no arquivo
atividade1.js
- Fazer no arquivo
- Criar uma galeria mostrando fotos e imagens da sonda Philae
- Fazer no arquivo
atividade2.js
- Fazer no arquivo
- Criar um código em JavaScript para fazer os botões "+"
expadirem ou retrairem o texto dos parágrafos
- É bastante comum associarmos uma mesma função (callback) a algum evento de vários elementos HTML diferentes
- Como no exercício: callback de
'click'
em TODOS os parágrafos -
-
::: result .example-ps.bullet <style>.example-ps p {font-size: 0.8em}</style>
<p>Parágrafo 1</p> <p>Parágrafo 2</p> <p>Parágrafo 3</p>
Parágrafo 1
Parágrafo 2
Parágrafo 3
:::
function colore() { let el = ??; // <-- quem colocar aqui?? el.style.background = 'lightblue'; }; let ps = document.querySelectorAll('p'); for (let pEl of ps) { pEl.addEventListener('click', colore); }
-
- Como no exercício: callback de
- Dentro da callback, é possível saber qual elemento foi alvo do evento!
- Precisamos usar o argumento de evento! (Próximo slide)
- Quando o navegador executa uma callback de eventos, ele passa um parâmetro com informações sobre o evento
- Tipicamente damos o nome de
e
,evt
ouevent
:-
let ps = document.querySelectorAll('p'); // igualzinho antes! for (let pEl of ps) { pEl.addEventListener('click', colore); }
-
function colore(e) { // repare o argumento 'e' (evento) let el = e.currentTarget; // <--- o elemento "alvo" do evento el.style.background = 'lightblue'; // colore parágrafo alvo do evento }
-
- Tipicamente damos o nome de
- Todo elemento do DOM conhece, na árvore, quem é:
- seu pai (
elemento.parentNode
ouelemento.parentElement
) - seus filhos (
elemento.childNodes
ouelemento.children
) - irmão anterior e irmão posterior
- seu pai (
- Exemplo: clicou numa
<img>
, mas quero a<div></div>
que é "pai" dela:function clicouNaImagem(e) { let clicadoEl = e.currentTarget; // a <img> que foi clicada let divEl = clicadoEl.parentNode; // <--- <div> é o pai da <img> console.log(divEl.id); // imprime id da div } let imgEl = document.querySelector('div > img'); imgEl.addEventListener('click', clicouNaImagem);
- Às vezes queremos colocar/remover uma classe em um elemento alternadamente
- Para isso, existe o
elemento.classList.toggle('nome-da-classe')
- Além de colocar/remover a classe, o método retorna:
true
se tiver colocado a classefalse
se tiver removido a classe
let colocou = booEl.classList.toggle('selecionado'); console.log(colocou); // imprime 'true', porque adicionou .selecionado colocou = booEl.classList.toggle('selecionado'); console.log(colocou); // imprime 'false', porque tirou .selecionado
- Livro "Javascript: The Good Parts" (Douglas Crockford)
- Mozilla Developer Network