As Web APIs representam um conjunto de interfaces fornecidas pelos navegadores, permitindo que o JavaScript interaja com o ambiente web. Elas são a ponte entre o seu código e o documento HTML renderizado, bem como as funcionalidades do próprio navegador.
Tradicionalmente, o JavaScript pode ser categorizado em três pilares:
- ECMAScript: A linguagem base, definindo a sintaxe e a lógica fundamental.
- DOM (Document Object Model): API para interagir e manipular a estrutura, o conteúdo e o estilo de documentos HTML e XML.
- BOM (Browser Object Model): API para interagir com o navegador em si, como o histórico, a janela e a localização.
As Web APIs englobam tanto o DOM quanto o BOM, fornecendo ferramantas essenciais para construir interfaces de usuário dinâmicas e responsivas.
Entendendo o Document Object Model (DOM)
O DOM é uma representação estruturada de um documento HTML ou XML como uma árvore de objetos. Cada parte do documento — elementos, atributos, texto — é um nó nessa árvore. Através do DOM, o JavaScript pode acessar e modificar esses nós.
- Documento: O HTML completo é representado pelo objeto global
document. - Elementos: As tags HTML (como
<div>,<p>,<button>) são objetos do tipo Elemento. - Nodos: Um conceito mais abrangente, onde tudo no documento (elementos, texto, comentários, atributos) é considerado um nodo.
Selecionando Elementos da Página
Para manipular qualquer parte do HTML, primeiro precisamos selecioná-la. As Web APIs oferecem diversos métodos para isso, com querySelector e querySelectorAll sendo opções modernas e flexíveis, que utilizam seletores CSS.
<div id="container-principal">
<h2>Minha Seção</h2>
<p class="info-texto">Este é um parágrafo de informação.</p>
<ul>
<li class="item-lista">Item 1</li>
<li class="item-lista destaque">Item 2</li>
<li class="item-lista">Item 3</li>
</ul>
</div>
const container = document.querySelector('#container-principal');
console.log(container); // Seleciona o div pelo ID
const primeiroParagrafo = document.querySelector('.info-texto');
console.log(primeiroParagrafo); // Seleciona o primeiro elemento com a classe 'info-texto'
const todosItens = document.querySelectorAll('.item-lista');
console.log(todosItens); // Retorna um NodeList de todos os elementos com a classe 'item-lista'
console.log(todosItens[1].textContent); // Acessa o texto do segundo item
const itemDestaque = document.querySelector('ul .destaque');
console.log(itemDestaque); // Seleciona o item com a classe 'destaque' dentro de um 'ul'
Respondendo a Eventos do Usuário
Os eventos são a forma como o JavaScript detecta e reage às interações do usuário ou a mudanças no navegador. Cada evento possui:
- Fonte do Evento: O elemento HTML que disparou o evento.
- Tipo de Evento: A ação ocorrida (clique, pressionar tecla, enviar formulário, etc.).
- Manipulador de Eventos: A função JavaScript que será executada em resposta ao evento.
Evantos de Clique
O evento de clique é um dos mais comuns, disparado quendo um usuário clica em um elemento.
<button id="botao-saudacao">Diga Olá</button>
<p id="saudacao-display"></p>
const botao = document.getElementById('botao-saudacao');
const displaySaudacao = document.getElementById('saudacao-display');
botao.addEventListener('click', () => {
displaySaudacao.textContent = 'Olá, mundo!';
displaySaudacao.style.color = 'blue';
});
Eventos de Teclado
Esses eventos são disparados em resposta a interações com o teclado. Os tipos mais comuns são keydown (tecla pressionada) e keyup (tecla liberada).
<input type="text" id="campo-texto-teclado" placeholder="Digite algo...">
<p id="tecla-pressionada-info"></p>
const campoTexto = document.getElementById('campo-texto-teclado');
const infoTecla = document.getElementById('tecla-pressionada-info');
campoTexto.addEventListener('keydown', (event) => {
infoTecla.textContent = `Você pressionou a tecla: ${event.key}`;
if (event.key === 'Enter') {
alert('Enter foi pressionado!');
}
});
campoTexto.addEventListener('keyup', (event) => {
console.log(`Tecla ${event.key} foi liberada.`);
});
Acessando e Modificando Atributos e Propriedades
Elementos HTML possuem atributos definidos no código-fonte e propriedades que são acessíveis via JavaScript. Muitas vezes, um atributo HTML tem uma propriedade DOM correspondente que pode ser lida e modificada diretamente.
Elementos Comuns (Imagens)
<img id="imagem-dinamica" src="caminho/para/imagem1.jpg" alt="Descrição da Imagem 1" width="150">
<button id="trocar-imagem-btn">Trocar Imagem</button>
const imagem = document.getElementById('imagem-dinamica');
const btnTrocar = document.getElementById('trocar-imagem-btn');
btnTrocar.addEventListener('click', () => {
if (imagem.src.includes('imagem1')) {
imagem.src = 'caminho/para/imagem2.jpg'; // Altera o atributo src
imagem.alt = 'Descrição da Imagem 2'; // Altera o atributo alt
imagem.title = 'Nova Imagem Carregada'; // Adiciona ou altera o atributo title
} else {
imagem.src = 'caminho/para/imagem1.jpg';
imagem.alt = 'Descrição da Imagem 1';
imagem.title = 'Imagem Original';
}
});
Elementos de Formulário
Controles de formulário como <input>, <textarea> e <select> possuem propriedades específicas (e.g., value, checked) que são frequentemente manipuladas.
Botão de Alternância (Ex: Reproduzir/Pausar)
<button id="controle-audio-btn">Reproduzir</button>
const btnAudio = document.getElementById('controle-audio-btn');
btnAudio.addEventListener('click', () => {
if (btnAudio.textContent === 'Reproduzir') {
btnAudio.textContent = 'Pausar';
// Lógica para iniciar a reprodução
} else {
btnAudio.textContent = 'Reproduzir';
// Lógica para pausar a reprodução
}
});
Contador Simples
<input type="number" id="valor-contador" value="0" readonly>
<button id="incrementar-btn">+</button>
<button id="decrementar-btn">-</button>
const displayContador = document.getElementById('valor-contador');
const btnIncrementar = document.getElementById('incrementar-btn');
const btnDecrementar = document.getElementById('decrementar-btn');
btnIncrementar.addEventListener('click', () => {
let valorAtual = parseInt(displayContador.value);
displayContador.value = valorAtual + 1;
});
btnDecrementar.addEventListener('click', () => {
let valorAtual = parseInt(displayContador.value);
displayContador.value = valorAtual - 1;
});
Funcionalidade "Selecionar Todos"
<input type="checkbox" id="selecionar-tudo-master"> <label for="selecionar-tudo-master">Selecionar Tudo</label><br>
<input type="checkbox" class="item-selecionavel"> Item A<br>
<input type="checkbox" class="item-selecionavel"> Item B<br>
<input type="checkbox" class="item-selecionavel"> Item C<br>
const masterCheckbox = document.getElementById('selecionar-tudo-master');
const itemCheckboxes = document.querySelectorAll('.item-selecionavel');
masterCheckbox.addEventListener('change', () => {
itemCheckboxes.forEach(checkbox => {
checkbox.checked = masterCheckbox.checked;
});
});
itemCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', () => {
// Verifica se todos os itens estão selecionados
const todosMarcados = Array.from(itemCheckboxes).every(item => item.checked);
masterCheckbox.checked = todosMarcados;
});
});
Gerenciando Estilos de Elementos
O JavaScript pode alterar a aparência visual dos elementos de duas maneiras principais: diretamente via a propriedade style ou manipulando as classes CSS.
Estilos Inline (element.style)
Modifica as propriedades CSS diretamente no atributo style do elemento. É útil para mudanças rápidas e pontuais, mas pode ser menos gerenciável para estilos complexos.
<p id="texto-estilizavel" style="font-size: 16px; color: black;">Clique para mudar o estilo.</p>
const textoEstilo = document.getElementById('texto-estilizavel');
textoEstilo.addEventListener('click', () => {
let tamanhoAtual = parseInt(textoEstilo.style.fontSize);
textoEstilo.style.fontSize = (tamanhoAtual + 4) + 'px'; // Aumenta o tamanho da fonte
textoEstilo.style.color = textoEstilo.style.color === 'black' ? 'red' : 'black'; // Alterna a cor
});
Estilos Baseados em Classes (element.classList)
A abordagem preferida para gerenciar estilos complexos é alternar classes CSS. Isso mantém a separação de responsabilidades (HTML para estrutura, CSS para estilo, JS para comportamento) e facilita a manutenção.
<style>
body {
transition: background-color 0.3s, color 0.3s;
margin: 0;
padding: 20px;
min-height: 100vh;
}
.tema-claro {
background-color: #f0f8ff;
color: #333;
}
.tema-escuro {
background-color: #222;
color: #eee;
}
</style>
<body class="tema-claro">
<p>Este é um parágrafo de exemplo para alternar o tema.</p>
<button id="alternar-tema-btn">Alternar Tema</button>
</body>
const bodyElement = document.body;
const btnAlternarTema = document.getElementById('alternar-tema-btn');
btnAlternarTema.addEventListener('click', () => {
bodyElement.classList.toggle('tema-escuro');
bodyElement.classList.toggle('tema-claro');
});
Manipulação Dinâmica de Nodos
As Web APIs permitem não apenas modificar elementos existentes, mas também criar novos, inseri-los ou removê-los do documento.
Inserindo Nodos
Para adicionar novos elementos ao DOM:
- Crie o novo elemento usando
document.createElement(). - Defina seu conteúdo e atributos, se necessário.
- Anexe-o a um elemento pai existente usando
appendChild()(no final) ouinsertBefore()(antes de um nó de referência).
<div id="lista-dinamica">
<p class="item-existente">Item Base 1</p>
<p>Item Base 2</p>
</div>
<button id="adicionar-item-btn">Adicionar Item</button>
const containerLista = document.getElementById('lista-dinamica');
const btnAdicionar = document.getElementById('adicionar-item-btn');
btnAdicionar.addEventListener('click', () => {
// 1. Criar um novo elemento
const novoParagrafo = document.createElement('p');
novoParagrafo.textContent = `Novo Item ${containerLista.children.length + 1}`;
novoParagrafo.style.color = 'green';
// 2. Inserir no final
containerLista.appendChild(novoParagrafo);
// Exemplo de insertBefore: Inserir um h3 antes do primeiro p
const tituloExtra = document.createElement('h3');
tituloExtra.textContent = 'Seção Dinâmica';
const primeiroP = containerLista.querySelector('.item-existente');
if (!document.querySelector('#lista-dinamica h3')) { // Adiciona apenas uma vez
containerLista.insertBefore(tituloExtra, primeiroP);
}
});
Removendo Nodos
Para remover um elemento do DOM, use parentNode.removeChild(childElement). O elemento removido ainda existe na memória e pode ser reanexado se necessário.
<div id="lista-remocao">
<span>Item 1</span><br>
<span id="item-para-remover">Item 2 (para remover)</span><br>
<span>Item 3</span>
</div>
<button id="remover-elemento-btn">Remover Item 2</button>
<button id="restaurar-elemento-btn" disabled>Restaurar Item 2</button>
const listaRemocao = document.getElementById('lista-remocao');
const itemARemover = document.getElementById('item-para-remover');
const btnRemover = document.getElementById('remover-elemento-btn');
const btnRestaurar = document.getElementById('restaurar-elemento-btn');
let elementoRemovido = null;
btnRemover.addEventListener('click', () => {
if (itemARemover && itemARemover.parentNode) {
elementoRemovido = listaRemocao.removeChild(itemARemover);
console.log("Elemento removido do DOM:", elementoRemovido);
btnRemover.disabled = true;
btnRestaurar.disabled = false;
}
});
btnRestaurar.addEventListener('click', () => {
if (elementoRemovido) {
listaRemocao.appendChild(elementoRemovido); // Reinsere o elemento removido
console.log("Elemento restaurado no DOM.");
btnRemover.disabled = false;
btnRestaurar.disabled = true;
}
});