Pular para o conteúdo
murad.guide

Introdução Completa à Web

Capítulo 19

DOM e eventos

5 min de leitura 946 palavras 2 gravuras

Até o capítulo 18 o JavaScript falava com o console. Agora ele fala com a página da Casa da Restinga. O DOM (Document Object Model, modelo de objeto do documento) é a árvore que o navegador monta a partir do HTML. Um evento avisa que a pessoa clicou ou digitou. Esta é o capítulo 19 de 23.

O exemplo está em exemplos/19-dom-eventos/. Abra index.html. Há um quadrado, um campo de texto e uma fileira de botões. Tudo usa querySelector e addEventListener.

Trabalhe na cópia inicio da etapa. Leia e digite o código; mude uma coisa. Antes de recarregar, anote sua previsão. Depois confira com a referência completa. Se nada mudar, confira o arquivo salvo e o caminho aberto. Blocos adicionais do capítulo podem ser digitados no console; o exemplo completo mostra a aplicação daquela etapa.

O que você vai aprender

Do arquivo à tela

Você escreve no editor. O navegador pede o HTML. Lê o arquivo, vê o <script src="script.js">, pede o JS, executa.

Nesta máquina o disco faz o papel de servidor. Abrir o arquivo (file://) e servir em http://127.0.0.1 são testes locais. Publicar na internet é outro passo. Não publique estes exercícios.

O script fica no fim do body. Assim as tags já existem quando o código procura por elas.

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Balcão — Casa da Restinga</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main>
    <h1>Balcão da Restinga</h1>
    <div class="quadrado"></div>
    <p>
      <button type="button" class="aviso">Tocar sino</button>
    </p>
    <label for="pedido">Pedido</label>
    <input id="pedido" class="pedido" type="text">
    <p class="eco">Nada digitado ainda.</p>
    <div class="fileira">
      <button type="button">1</button>
      <button type="button">2</button>
      <button type="button">3</button>
      <button type="button">4</button>
      <button type="button">5</button>
    </div>
    <p class="mesa">Nenhuma mesa.</p>
  </main>
  <script src="script.js"></script>
</body>
</html>

Botão que só dispara ação é <button type="button">. Não use div clicável.

Pare e experimente. Abra o exemplo. Preveja o título “Balcão da Restinga”. Recarregue. Confira a aba.

Erro comum: script no head sem espera. querySelector devolve null e a página quebra.

querySelector acha o nó; o ouvinte espera o clique

document e querySelector

document é o objeto global da página. querySelector recebe um seletor CSS e devolve o primeiro elemento que combina.

const quadrado = document.querySelector(".quadrado");
quadrado.style.backgroundColor = "seagreen";

Mesmo que o CSS pinte o quadrado de outra cor, o JS manda depois e ganha nesta propriedade.

No CSS a propriedade é background-color (com hífen). No JS vira backgroundColor (camelCase). padding-right vira paddingRight.

Pare e experimente. Troque "seagreen" por "coral". Preveja o quadrado alaranjado. Recarregue. Confira.

Erro comum: querySelector("quadrado") sem o ponto. Isso procura uma tag <quadrado>, que não existe.

querySelectorAll

querySelectorAll devolve todos os que combinam, numa lista com length. Percorra com for.

const alvos = document.querySelectorAll(".js-alvo");
for (let i = 0; i < alvos.length; i += 1) {
  alvos[i].textContent = "Atualizado no balcão";
}

textContent grava texto visível. Não interpreta HTML. Serve para status e rótulos.

Se ninguém combinar, querySelector devolve null. querySelectorAll devolve lista vazia, não null.

Pare e experimente. No HTML de estudo, ponha class="js-alvo" em dois p. Preveja dois textos iguais. Recarregue. Confira.

Erro comum: tratar querySelectorAll como um único nó e fazer alvos.textContent = …. A lista não tem textContent. Cada item tem.

Clique no button

Um evento é o aviso. O ouvinte (addEventListener) diz qual função roda.

const sino = document.querySelector(".aviso");
sino.addEventListener("click", function () {
  window.alert("Pedido no balcão da Restinga.");
});

Dois parâmetros: o nome do evento ("click") e a função. Essa função é o callback: o navegador a chama de volta quando o clique acontece.

alert vem de window.alert. No navegador você pode omitir window. Use com parcimônia: a caixa trava a página até o OK.

A linha termina em }); porque fecha a função, fecha a chamada e termina o comando.

Pare e experimente. Troque o texto do alerta. Preveja a frase nova. Recarregue. Clique no botão. Confira.

Erro comum: escrever addEventListener("Click") com C maiúsculo. O nome é "click" em minúsculas.

Digitação: keyup e change

keyup dispara quando a tecla sobe. input.value é o que está no campo. Copie para um parágrafo.

const campo = document.querySelector(".pedido");
const eco = document.querySelector(".eco");
campo.addEventListener("keyup", function () {
  eco.textContent = campo.value;
});

Use keyup (e não keydown) para não ficar uma letra atrasado: keydown ocorre antes do caractere entrar no campo.

change no mesmo espírito espera a pessoa sair do campo (Tab ou clique fora). Útil para aplicar uma cor só no fim.

const tinta = document.querySelector(".pedido");
tinta.addEventListener("change", function () {
  document.querySelector(".quadrado").style.backgroundColor = tinta.value;
});

Digite navy e saia do campo. Cor inválida: o quadrado não muda.

Pare e experimente. Digite Café coado no pedido. Preveja o mesmo texto em .eco a cada letra. Recarregue se o ouvinte não ligou.

Erro comum: ouvir keydown e copiar value. A última tecla ainda não está no campo.

Início da referência desta etapa no navegador local

Um ouvinte na fileira

Vários botões, um pai. O clique sobe (bubbling) até o container. Você escuta o pai e pergunta quem foi o event.target.

const fileira = document.querySelector(".fileira");
const mesa = document.querySelector(".mesa");
fileira.addEventListener("click", function (evento) {
  const botao = evento.target.closest("button");
  if (!botao) {
    return;
  }
  mesa.textContent = "Mesa " + botao.textContent.trim();
});

evento sempre chega; antes você o ignorava. target é a tag de origem. closest("button") garante que você pega o botão mesmo se o clique acertar um filho.

Isso se chama delegação. Um ouvinte só. A calculadora da próximo capítulo usa a mesma ideia.

Pare e experimente. Clique no 3. Preveja “Mesa 3”. Recarregue. Clique no 5. Confira.

Erro comum: ouvir o document inteiro e reagir a qualquer clique da página, inclusive no título. Ouça só .fileira.

Atividades

  1. Por que o <script> fica no fim do body neste exemplo?
  2. querySelector(".quadrado") devolve o quê se houver dois elementos com essa classe?
  3. Qual a diferença entre keyup e change no campo?
  4. Na fileira, para que serve evento.target?

Respostas comentadas

  1. Para o HTML já ter nascido. Se o script rodar antes, querySelector acha null.
  2. Só o primeiro. Para os dois, use querySelectorAll.
  3. keyup atualiza a cada tecla. change espera a pessoa sair do campo.
  4. É a tag onde o evento começou. Com closest("button") você obtém o botão clicado.

MDN

O arquivo completo

Referência do exemplo 19-dom-eventos, reproduzida aqui para que você possa conferir sem sair da página.

dom.js

const quadrado = document.querySelector(".quadrado");
quadrado.style.backgroundColor = "seagreen";
document.querySelector(".aviso").addEventListener("click", () => {
  quadrado.style.backgroundColor = "coral";
});
const campo = document.querySelector(".pedido");
const eco = document.querySelector(".eco");
campo.addEventListener("keyup", () => {
  eco.textContent = campo.value || "Nada digitado ainda.";
});
const fileira = document.querySelector(".fileira");
const mesa = document.querySelector(".mesa");
fileira.addEventListener("click", (evento) => {
  const botao = evento.target.closest("button");
  if (!botao) return;
  mesa.textContent = "Mesa " + botao.textContent;
});