DevTools

Cheatsheet jQuery

Biblioteca JavaScript para manipulação DOM

Voltar às linguagens
jQuery
112 cards encontrados
Categorias:
Versões:

Seletores


12 cards
Documento pronto
// Forma completa:
$(document).ready(function() {
  // DOM carregado e seguro
});

// Forma curta (recomendada):
$(function() {
  // equivalente ao ready
});

// Múltiplos ready (todos executam):
$(function() { console.log("módulo A"); });
$(function() { console.log("módulo B"); });

Garante que o DOM está totalmente parseado antes de executar código. A forma curta $(fn) é idêntica ao $(document).ready(). Múltiplos handlers executam pela ordem de registo. Diferente de window.onload, não espera imagens/CSS.

Filtros de posição
$("li:first")     // primeiro li da página
$("li:last")      // último li
$("li:eq(2)")     // índice 2 (terceiro)
$("li:gt(3)")     // índice maior que 3
$("li:lt(3)")     // índice menor que 3
$("li:even")      // índices pares (0, 2, 4...)
$("li:odd")       // índices ímpares (1, 3, 5...)

// Equivalente com método (mais rápido):
$("li").first()
$("li").last()
$("li").eq(2)

Pseudo-selectores de posição filtram pelo índice na colecção. :eq(n) é zero-based. Versões método (.first(), .eq()) são mais rápidas que pseudo-selectores porque filtram depois da selecção CSS. :even/:odd úteis para zebrar tabelas.

find() e filter()
// find(): procura DENTRO dos seleccionados
$("ul").find("li.ativo")    // li dentro de ul
$("#form").find("input")    // inputs dentro do form

// filter(): reduz a selecção actual
$("li").filter(".ativo")    // só os que têm class
$("li").filter(function(i) {
  return $(this).data("tipo") === "especial";
});

// Diferença:
$("div").find("p")   // p DENTRO de div
$("div").filter("p") // divs que TAMBÉM são p (nada)

find() procura descendentes dos elementos seleccionados. filter() reduz a colecção actual por selector ou função. find() desce na árvore; filter() avalia os próprios elementos. Ambos aceitam função callback para lógica complexa.

Seletor de elemento
$("p")       // todos os parágrafos
$("div")     // todas as divs
$("li")      // todos os itens de lista
$("h1, h2")  // múltiplos tipos (vírgula = OU)

// Retorna objeto jQuery (array-like):
var paragrafos = $("p");
paragrafos.length;  // quantidade encontrada
paragrafos[0];      // primeiro elemento DOM (raw)

Seleciona todos os elementos do tipo indicado. Retorna um objecto jQuery (colecção), não um elemento DOM. A propriedade .length indica quantos encontrou. Aceder a [0] retorna o elemento nativo (sem métodos jQuery).

Filtros de estado
$(":button")       // todos os botões
$(":checkbox")     // checkboxes
$(":radio")        // radio buttons
$(":checked")      // marcados (checkbox/radio)
$(":selected")     // option seleccionada
$(":disabled")     // campos desactivados
$(":enabled")      // campos activos
$(":focus")        // elemento com foco
$(":hidden")       // invisíveis (display:none)
$(":visible")      // visíveis

Filtros de estado seleccionam por condição actual do elemento. :checked e :selected mudam conforme interacção do utilizador. :hidden inclui display:none, visibility:hidden e elementos com largura/altura zero. Reavaliam a cada chamada (não usar em loops).

Contexto e escopo
// Segundo parâmetro = contexto (limita busca):
$("li", document.getElementById("menu"))
// equivalente a:
$("#menu").find("li")

// this dentro de handlers:
$(".btn").click(function() {
  $(this)          // elemento clicado (jQuery)
  this             // elemento clicado (DOM raw)
  this.textContent // sem jQuery
});

// each() com contexto:
$("li").each(function() {
  $(this).addClass("visto");  // cada li
});

O segundo parâmetro de $() limita o contexto da busca (mais rápido em sub-árvores). Dentro de handlers, this refere o elemento DOM nativo; $(this) embrulha-o em jQuery para usar métodos. Em .each(), this muda a cada iteração. Arrow functions perdem o this — usar function().

Classe e ID
$(".menu")       // class="menu"
$("#topo")       // id="topo"
$(".card.ativo") // card E ativo (ambas)
$("div.caixa")   // div com class="caixa"

// ID é mais rápido (usa getElementById):
$("#unico")      // muito rápido
$(".muitos")     // usa querySelectorAll

Ponto (.) selecciona por class, cardinal (#) por id. Combinar como em CSS: .card.ativo exige ambas as classes. IDs são mais performantes pois usam getElementById nativo. Classes usam querySelectorAll internamente.

Seletor de atributo
$("[href]")              // tem atributo href
$("[type='text']")       // type exacto
$("[href^='https']")     // começa com
$("[href$='.pdf']")      // termina com
$("[class*='btn']")      // contém substring
$("[data-id]")           // tem data-attribute
$("input[name='email']") // input com name

// Combinar:
$("a[target='_blank'][rel='noopener']")

Colchetes [] filtram por atributo. ^= prefixo, $= sufixo, *= contém, = exacto. Combináveis entre si e com outros selectores. Úteis para data-attributes customizados. Mais lentos que classe/ID — preferir quando possível.

Seletores personalizados
// jQuery adiciona selectores não-CSS:
$(":input")     // input, textarea, select, button
$(":text")      // input[type=text]
$(":password")  // input[type=password]
$(":file")      // input[type=file]
$(":image")     // input[type=image]
$(":submit")    // input/button submit
$(":reset")     // input/button reset
$(":header")    // h1, h2, h3, h4, h5, h6
$(":animated")  // elementos em animação
$(":button")    // button e input[type=button]

Selectores :input e derivados são exclusivos do jQuery (não existem em CSS). :input selecciona todos os campos de formulário de uma vez. :header selecciona todos os headings. :animated detecta elementos com animação activa. Úteis mas mais lentos — usar com moderação.

Seletores combinados
$("ul li")       // descendente (qualquer nível)
$("ul > li")     // filho directo (só 1 nível)
$("h2 + p")      // irmão seguinte (adjacente)
$("h2 ~ p")      // todos os irmãos p seguintes

// Exemplo prático:
$("nav > ul > li > a")  // links directos no menu

Espaço = descendente (qualquer profundidade). > = filho directo. + = irmão imediatamente seguinte. ~ = todos os irmãos seguintes do mesmo tipo. Quanto mais específico, mais rápida a selecção.

Seletor de conteúdo
$("p:contains('erro')")   // texto contém "erro"
$("td:empty")             // células vazias
$("div:has(img)")         // divs que contêm img
$("p:parent")             // elementos com filhos

// :has() é poderoso:
$("li:has(> a.ativo)")   // li com link activo directo
$("form:has(input:visible)") // forms com campos visíveis

:contains() filtra por texto (case-sensitive). :has() selecciona pais que contêm determinado filho — muito versátil. :empty não tem filhos nem texto. :parent é o oposto de :empty. Estes são selectores jQuery (não CSS nativo), portanto mais lentos.

Performance de selectores
// RÁPIDO → LENTO:
$("#id")              // 1. getElementById
$(".classe")          // 2. getElementsByClassName
$("div.classe")       // 3. tag + classe
$("[data-x]")         // 4. atributo
$("div:visible")      // 5. pseudo-selector

// Dicas de performance:
var $lista = $("#lista");       // cache!
$lista.find("li.ativo");        // contexto
$lista.children(".item");       // filhos directos

// Evitar:
$("div .item")          // muito genérico
$("*")                  // todos os elementos
$("li:eq(0):visible")   // múltiplos filtros

A ordem de performance: #id > .classe > tag.classe > [attr] > :pseudo. Fazer cache de selecções repetidas em variáveis (prefixo $ por convenção). Usar .find() com contexto em vez de selectores longos. Evitar $("*") e pseudo-selectores encadeados.

Eventos


11 cards
on() — ligação de eventos
// Método recomendado (jQuery 1.7+):
$("#btn").on("click", function() {
  alert("clicado!");
});

// Múltiplos eventos:
$("#campo").on("focus blur", function() {
  $(this).toggleClass("activo");
});

// Objecto de eventos:
$("#form").on({
  submit: function(e) { e.preventDefault(); },
  reset: function() { limpar(); }
});

on() é o método universal de eventos (substitui bind(), live(), delegate()). Aceita string com eventos separados por espaço ou objecto. O handler recebe o objecto event com detalhes. Sempre preferir on() sobre atalhos como .click().

Eventos de teclado
$("input").on("keydown", function(e) {
  console.log(e.key);       // "a", "Enter", "Escape"
  console.log(e.code);      // "KeyA", "Enter"
  console.log(e.which);     // código numérico

  // Detectar teclas especiais:
  if (e.key === "Enter") { enviar(); }
  if (e.key === "Escape") { fechar(); }
  if (e.ctrlKey && e.key === "s") {
    e.preventDefault();
    guardar();
  }
});

// keypress (só caracteres imprimíveis):
$("input").on("keypress", fn);

keydown dispara ao premir qualquer tecla (incluindo especiais). e.key dá o valor legível, e.code a tecla física. e.ctrlKey, e.shiftKey, e.altKey detectam modificadores. keypress está deprecated — usar keydown. preventDefault() cancela acção nativa (ex: Ctrl+S).

trigger() — disparar eventos
// Disparar evento programaticamente:
$("#btn").trigger("click");
$("#form").trigger("submit");

// Forma curta:
$("#btn").click();     // dispara click
$("#form").submit();   // dispara submit

// Com dados extra:
$("#btn").trigger("click", ["extra1", "extra2"]);

// Handler recebe:
$("#btn").on("click", function(e, extra1, extra2) {
  console.log(extra1); // "extra1"
});

// Evento custom:
$("#app").trigger("dados:carregados", [dados]);
$("#app").on("dados:carregados", function(e, dados) {
  renderizar(dados);
});

trigger() dispara eventos programaticamente (como se o utilizador clicasse). Aceita dados extra como array no segundo parâmetro. Eventos custom (com namespace) criam comunicação entre módulos. A forma curta .click() sem argumentos dispara o evento. Útil para testes e coordenação de componentes.

off() — remover eventos
// Remover todos os clicks:
$("#btn").off("click");

// Remover TODOS os eventos:
$("#btn").off();

// Handler específico (função nomeada):
function handler() { console.log("oi"); }
$("#btn").on("click", handler);
$("#btn").off("click", handler);

// Namespaces:
$("#btn").on("click.app", fn1);
$("#btn").on("click.modal", fn2);
$("#btn").off("click.app");  // só remove fn1

off() remove handlers previamente ligados com on(). Sem argumentos remove tudo. Namespaces (.app, .modal) permitem remover grupos específicos sem afectar outros. Essencial para evitar memory leaks ao destruir componentes. Funções anónimas não podem ser removidas selectivamente.

Eventos de formulário
$("form").on("submit", function(e) {
  e.preventDefault();
  var dados = $(this).serialize();
  // enviar via AJAX
});

$("input").on("change", function() {
  // valor mudou E perdeu foco
  console.log($(this).val());
});

$("input").on("input", function() {
  // dispara a CADA tecla (tempo real)
  filtrar($(this).val());
});

$("select").on("change", function() {
  carregar($(this).val());
});

submit intercepta envio do formulário. change dispara quando o valor muda e o campo perde foco. input dispara a cada tecla (ideal para pesquisa em tempo real). serialize() converte o form em query string. Sempre preventDefault() no submit para evitar reload da página.

Event object
$("#caixa").on("click", function(event) {
  event.type;        // "click"
  event.target;      // elemento clicado (DOM)
  event.currentTarget; // elemento com handler (= this)
  event.pageX;       // posição X (documento)
  event.pageY;       // posição Y (documento)
  event.timeStamp;   // quando ocorreu

  // Qual botão do rato:
  event.which;       // 1=esq, 2=meio, 3=dir

  // Teclas modificadoras:
  event.ctrlKey;     // Ctrl premido?
  event.shiftKey;    // Shift premido?
  event.altKey;      // Alt premido?
  event.metaKey;     // Cmd (Mac) premido?
});

O objecto event contém todos os detalhes da interacção. target é quem originou; currentTarget é quem tem o handler. pageX/pageY para posição do rato. which identifica botão do rato ou tecla. Propriedades booleanas (ctrlKey, shiftKey) para combinações. Normalizado pelo jQuery (cross-browser).

Delegação de eventos
// Evento no PAI, filtro no seletor filho:
$("#lista").on("click", "li", function() {
  $(this).toggleClass("feito");
});

// Funciona com elementos futuros:
$("#lista").append("<li>Novo</li>");
// clique no novo li funciona automaticamente!

// Sem delegação (NÃO funciona com dinâmicos):
$("li").on("click", fn);  // só os existentes

// Múltiplos selectores:
$("#tabela").on("click", "td, th", fn);

Delegação: o evento liga-se ao pai e filtra pelo selector filho. Funciona com elementos criados depois da ligação. O evento "bolha" do filho até ao pai. Mais eficiente: 1 handler no pai vs N handlers nos filhos. Essencial para listas dinâmicas, tabelas e conteúdo AJAX.

preventDefault e stopPropagation
$("a").on("click", function(e) {
  e.preventDefault();      // cancela navegação
  // fazer algo custom (AJAX, modal...)
});

$(".dropdown").on("click", function(e) {
  e.stopPropagation();    // não fecha o menu pai
  $(this).toggleClass("open");
});

// return false = ambos:
$("a").on("click", function() {
  return false;  // preventDefault + stopPropagation
});

// Verificar se foi cancelado:
if (e.isDefaultPrevented()) { /* ... */ }

preventDefault() cancela a acção nativa (navegação, submit). stopPropagation() impede que o evento suba na árvore DOM (bubbling). return false num handler jQuery faz ambos. isDefaultPrevented() verifica se outro handler já cancelou. Usar com cuidado — stopPropagation pode quebrar delegação.

ready vs load vs DOMContentLoaded
// DOM pronto (sem imagens/CSS):
$(function() {
  // manipular DOM com segurança
});

// Tudo carregado (imagens, CSS, fonts):
$(window).on("load", function() {
  // calcular dimensões reais
  var altura = $("#hero img").height();
});

// Vanilla equivalente ao ready:
document.addEventListener("DOMContentLoaded", fn);

// Script no fim do body (alternativa):
// <script src="app.js"></script> antes de </body>

$(fn) / ready dispara quando o HTML está parseado (não espera recursos). $(window).on("load") espera tudo (imagens, CSS, fonts). Para manipular DOM, ready basta. Para dimensões de imagens, usar load. Scripts no fim do <body> dispensam ready (DOM já existe).

Eventos de rato
$("#caixa").on({
  mouseenter: function() { $(this).addClass("hover"); },
  mouseleave: function() { $(this).removeClass("hover"); },
  mousedown: function() { $(this).addClass("press"); },
  mouseup: function() { $(this).removeClass("press"); },
});

// hover() = mouseenter + mouseleave:
$("#caixa").hover(
  function() { $(this).fadeIn(); },   // enter
  function() { $(this).fadeOut(); }   // leave
);

// Coordenadas do rato:
$(document).on("mousemove", function(e) {
  console.log(e.pageX, e.pageY);
});

mouseenter/mouseleave não disparam em filhos (ao contrário de mouseover/mouseout). hover() é atalho para os dois. e.pageX/e.pageY dão coordenadas relativas ao documento. mousedown/mouseup para efeitos de pressão. Usar delegação para elementos dinâmicos.

one() — executar uma vez
$("#btn").one("click", function() {
  alert("Só aparece UMA vez!");
});
// segundo clique: nada acontece

// Útil para inicializações:
$("#app").one("scroll", function() {
  carregarDadosPesados();
});

// Com delegação:
$("#lista").one("click", "li", function() {
  $(this).addClass("primeiro-clique");
});
// Nota: one() com delegação dispara 1x POR elemento

one() liga um handler que se auto-remove após a primeira execução. Ideal para tutoriais, lazy loading e inicializações únicas. Com delegação, dispara uma vez por elemento filho (não globalmente). Equivalente a ligar com on() e chamar off() dentro do handler.

Manipulação do DOM


12 cards
Criar elementos
// Criar com HTML string:
var $item = $("<li>Novo item</li>");
var $card = $('<div class="card"><h3>Título</h3></div>');

// Com atributos:
var $link = $("<a>", {
  text: "Clique aqui",
  href: "/pagina",
  class: "btn btn-primary",
  target: "_blank"
});

// Criar e inserir:
$("#lista").append($item);
$("body").append($card);

Passar HTML ao $() cria elementos (não selecciona). O segundo parâmetro (objecto) define atributos e propriedades. O elemento fica em memória até ser inserido no DOM. Variáveis com prefixo $ indicam objectos jQuery por convenção. Criar fora do DOM e inserir uma vez é mais performante.

html() e text()
// html(): lê/define HTML interno
var conteudo = $("#caixa").html();
$("#caixa").html("<strong>Negrito</strong>");

// text(): lê/define só texto (sem tags)
var texto = $("#caixa").text();
$("#caixa").text("Sem <b>tags</b>");  // literal

// Diferença:
// html("<b>oi</b>") → mostra "oi" em negrito
// text("<b>oi</b>") → mostra "<b>oi</b>" literal

// Segurança: text() escapa automaticamente
$("#nome").text(inputUtilizador);  // seguro (XSS)

html() trabalha com HTML (interpreta tags). text() trabalha com texto puro (escapa tags). Sem argumentos, lêem; com argumento, definem. Usar text() para conteúdo do utilizador (previne XSS). html() substitui todo o conteúdo interno de uma vez.

each() — iterar elementos
// Iterar sobre colecção jQuery:
$("li").each(function(indice, elemento) {
  $(elemento).text((indice + 1) + ". " + $(elemento).text());
});

// this = elemento actual:
$(".card").each(function() {
  var titulo = $(this).find("h3").text();
  $(this).attr("title", titulo);
});

// Parar iteração:
$("li").each(function() {
  if ($(this).hasClass("stop")) return false;
  $(this).addClass("visto");
});

each() itera sobre cada elemento da colecção. this refere o elemento DOM actual (embrulhar com $(this) para métodos jQuery). return false dentro do callback para a iteração (como break). O callback recebe (índice, elemento). Não confundir com $.each() (para arrays/objectos).

append() e prepend()
// append(): insere no FIM (dentro)
$("#lista").append("<li>Último</li>");
$("#lista").append($("<li>").text("Outro"));

// prepend(): insere no INÍCIO (dentro)
$("#lista").prepend("<li>Primeiro</li>");

// Múltiplos de uma vez:
$("#lista").append(
  "<li>A</li>",
  "<li>B</li>",
  "<li>C</li>"
);

// appendTo() (inverso):
$("<li>Fim</li>").appendTo("#lista");
$("<li>Topo</li>").prependTo("#lista");

append() insere no final dos filhos; prepend() no início. Aceitam múltiplos argumentos, strings HTML ou objectos jQuery. appendTo()/prependTo() são a forma invertida (útil para chaining). Todos inserem dentro do elemento alvo, como filhos.

clone()
// Clonar sem eventos:
var $copia = $("#card").clone();
$("#galeria").append($copia);

// Clonar COM eventos e handlers:
var $copia2 = $("#card").clone(true);

// Clonar com eventos + descendentes:
var $copia3 = $("#card").clone(true, true);

// Modificar clone antes de inserir:
var $novo = $("#template").clone()
  .attr("id", "card-" + proximoId)
  .find(".titulo").text("Novo").end();
$("#lista").append($novo);

clone() duplica o elemento. Sem argumentos, não copia eventos. clone(true) copia handlers do elemento; clone(true, true) copia também dos descendentes. O clone é independente — modificar um não afecta o outro. Ideal para templates: clonar, personalizar e inserir.

map() — transformar colecção
// Extrair valores:
var textos = $("li").map(function() {
  return $(this).text();
}).get();  // .get() converte para array real

// Transformar:
var ids = $(".card").map(function() {
  return $(this).data("id");
}).get();

// $.map() (para arrays/objectos):
var dobros = $.map([1, 2, 3], function(n) {
  return n * 2;
});  // [2, 4, 6]

// grep (filtrar array):
var pares = $.grep([1,2,3,4,5], function(n) {
  return n % 2 === 0;
});  // [2, 4]

.map() transforma cada elemento e retorna nova colecção jQuery. .get() converte para array nativo. $.map() é a versão estática para arrays/objectos. $.grep() filtra arrays (equivalente a Array.filter). Útil para extrair dados de múltiplos elementos de uma vez.

before() e after()
// before(): insere ANTES (irmão)
$("#alvo").before("<p>Antes de mim</p>");

// after(): insere DEPOIS (irmão)
$("#alvo").after("<p>Depois de mim</p>");

// insertBefore() / insertAfter() (inverso):
$("<p>Novo</p>").insertBefore("#alvo");
$("<p>Novo</p>").insertAfter("#alvo");

// Diferença de append:
// append/prepend → DENTRO (filho)
// before/after   → FORA (irmão)

before() e after() inserem como irmãos (fora do elemento). append()/prepend() inserem como filhos (dentro). insertBefore()/insertAfter() são as versões invertidas. Todos aceitam HTML string, jQuery object ou DOM element.

wrap() e unwrap()
// wrap(): envolve cada elemento
$("p").wrap("<div class='wrapper'></div>");
// cada <p> fica dentro de uma div

// wrapAll(): envolve TODOS num só
$("p").wrapAll("<div class='grupo'></div>");

// wrapInner(): envolve o CONTEÚDO
$("#caixa").wrapInner("<span class='interno'></span>");

// unwrap(): remove o PAI (desembrulha)
$("p").unwrap();  // remove a div wrapper

// Exemplo: destacar texto
$("p").wrapInner("<mark></mark>");

wrap() envolve cada elemento individualmente. wrapAll() envolve todos num único wrapper. wrapInner() envolve o conteúdo (filhos) sem mover o elemento. unwrap() remove o pai directo. Úteis para adicionar estrutura sem reescrever HTML.

Chaining (encadeamento)
// Métodos retornam o objecto jQuery:
$("#caixa")
  .addClass("activo")
  .css("color", "red")
  .fadeIn(300)
  .find("span")
  .text("Olá");

// end() volta à selecção anterior:
$("#menu")
  .find(".item").addClass("visto")
  .end()                    // volta a $("#menu")
  .find(".badge").text("3")
  .end();                   // volta a $("#menu")

// Sem chaining (repetitivo):
var $c = $("#caixa");
$c.addClass("activo");
$c.css("color", "red");

Quase todos os métodos jQuery retornam this, permitindo chaining. end() reverte para a selecção anterior na pilha. Encadear melhora legibilidade e evita variáveis repetidas. Cuidado: find(), filter(), children() mudam a selecção — usar end() para voltar.

remove() e detach()
// remove(): apaga do DOM + eventos + dados
$("#item").remove();
$("li.feito").remove();  // múltiplos

// Com filtro:
$("li").remove(".antigo");

// detach(): apaga mas MANTÉM eventos/dados
var $el = $("#widget").detach();
// ... mais tarde:
$("#sidebar").append($el);  // eventos intactos

// empty(): remove só os FILHOS
$("#container").empty();  // fica vazio mas existe

remove() elimina o elemento e todos os seus eventos e data associados. detach() remove do DOM mas preserva eventos/dados em memória (para reinserir depois). empty() remove apenas os filhos, mantendo o pai. Usar remove() na maioria dos casos; detach() para mover elementos.

replaceWith() e replaceAll()
// replaceWith(): substitui o elemento
$("#antigo").replaceWith("<div class='novo'>Novo</div>");

// Com função (substituição dinâmica):
$("li").replaceWith(function(i) {
  return "<p>" + $(this).text() + "</p>";
});

// replaceAll() (inverso):
$("<span>N/A</span>").replaceAll(".vazio");

// Nota: eventos do original são perdidos
// (usar detach + insert se precisa manter)

replaceWith() substitui o elemento seleccionado por novo conteúdo. Aceita função para substituição dinâmica por índice. replaceAll() é a forma invertida. Eventos do elemento original são destruídos. Para manter handlers, usar detach() + inserção em vez de replace.

Manipulação em lote
// LENTO: inserir em loop (reflow a cada iteração)
for (var i = 0; i < 100; i++) {
  $("#lista").append("<li>" + i + "</li>");
}

// RÁPIDO: construir string e inserir 1x
var html = "";
for (var i = 0; i < 100; i++) {
  html += "<li>" + i + "</li>";
}
$("#lista").html(html);

// Ou: DocumentFragment
var $fragment = $(document.createDocumentFragment());
for (var i = 0; i < 100; i++) {
  $fragment.append("<li>" + i + "</li>");
}
$("#lista").append($fragment);

Cada inserção no DOM causa reflow (recálculo de layout). Inserir 100 elementos num loop = 100 reflows. Construir uma string HTML e inserir uma vez é muito mais rápido. DocumentFragment agrupa elementos fora do DOM e insere em batch. Para grandes listas, preferir .html() com string completa.

Traversing


11 cards
parent() e parents()
// parent(): pai directo (1 nível)
$("li").parent()         // o <ul> ou <ol>

// parents(): TODOS os ancestrais
$("a").parents()         // div, body, html...

// parents() com filtro:
$("a").parents("form")   // só ancestrais <form>
$("a").parents(".card")  // primeira .card acima

// closest(): sobe até encontrar (inclui self)
$("a").closest(".card")  // a .card mais próxima
// closest começa em this; parents começa no pai

parent() retorna o pai directo. parents() sobe até ao <html> (todos os ancestrais). closest() sobe e retorna o primeiro que corresponde (inclui o próprio elemento). closest() é ideal para delegação e encontrar containers. parents() com filtro retorna todos os que correspondem.

filter() e not()
// filter(): mantém os que correspondem
$("li").filter(".ativo")
$("li").filter(":even")
$("li").filter(function(i) {
  return $(this).text().length > 10;
});

// not(): remove os que correspondem (inverso)
$("li").not(".feito")
$("li").not(":first")
$("input").not(":disabled")

// is(): verifica (retorna boolean)
if ($("#caixa").is(":visible")) { /* ... */ }
if ($(this).is(".ativo")) { /* ... */ }

filter() reduz a colecção aos que correspondem. not() é o inverso — remove os que correspondem. Ambos aceitam selector, função ou elemento. is() retorna boolean (não filtra, só verifica). filter(fn) permite lógica arbitrária. is() é ideal em condições if.

closest() na prática
// Encontrar container a partir de botão:
$(".btn-delete").on("click", function() {
  var $card = $(this).closest(".card");
  $card.fadeOut(function() { $(this).remove(); });
});

// Em tabelas:
$("td a").on("click", function() {
  var $linha = $(this).closest("tr");
  var id = $linha.data("id");
});

// Em formulários:
$("input").on("invalid", function() {
  $(this).closest(".form-group").addClass("erro");
});

// closest vs parents:
// closest → primeiro match (sobe)
// parents → todos os matches

closest() é o método mais usado em delegação e handlers. Sobe na árvore até encontrar o primeiro correspondente (inclui o próprio). Ideal para encontrar o "container" relevante a partir do elemento clicado. Mais eficiente que parents().first(). Padrão comum: $(this).closest(".card").

children() e find()
// children(): filhos directos (1 nível)
$("ul").children()        // todos os <li> directos
$("ul").children(".ativo") // só li com class ativo

// find(): descendentes (qualquer nível)
$("ul").find("a")         // todos os links dentro
$("#form").find("input")  // todos os inputs

// Diferença:
// children → só 1 nível abaixo
// find     → qualquer profundidade

// children("*") = todos os filhos
$("#caixa").children().length;  // quantos filhos

children() retorna apenas filhos directos (1 nível). find() procura em qualquer profundidade. Ambos aceitam filtro opcional. find() é mais usado (mais flexível). children() é mais rápido quando só precisa do primeiro nível. Sem argumentos, retornam todos os descendentes/filhos.

has() e is()
// has(): mantém elementos que CONTÊM o selector
$("li").has("ul")       // li que têm sub-listas
$("div").has("img")     // divs com imagens
$("td").has("a.link")   // células com links

// is(): teste booleano
$("#form input").is(":focus")    // algum com foco?
$(".card").is(":visible")        // algum visível?
$(this).is("a[href^='http']")   // é link externo?

// Combinar:
$("li").has("> ul").addClass("tem-submenu");

has() filtra elementos que contêm descendentes correspondentes (não retorna os descendentes). is() testa se algum elemento da colecção corresponde (retorna true/false). has("> ul") verifica filhos directos. Ambos úteis para lógica condicional e classificação de elementos.

index() — posição do elemento
// Posição entre irmãos:
$("li").click(function() {
  var pos = $(this).index();  // 0-based entre irmãos
  console.log("Item " + pos);
});

// Posição numa colecção:
var $itens = $(".card");
$itens.click(function() {
  var i = $itens.index(this);
  console.log("Card " + i + " de " + $itens.length);
});

// Posição de selector:
var pos = $("li").index("#especial");

index() sem argumentos retorna a posição entre irmãos (zero-based). Com elemento/DOM como argumento, retorna a posição na colecção. Com selector, retorna a posição do primeiro match. Útil para tabs, sliders e navegação. Retornar -1 significa não encontrado.

siblings() e irmãos
// siblings(): todos os irmãos
$("li.ativo").siblings()          // outros li
$("li.ativo").siblings(".feito")  // irmãos com class

// next(): irmão seguinte (1)
$("li.ativo").next()

// prev(): irmão anterior (1)
$("li.ativo").prev()

// nextAll() / prevAll():
$("li.ativo").nextAll()   // todos depois
$("li.ativo").prevAll()   // todos antes

// nextUntil() / prevUntil():
$("li.ativo").nextUntil(".fim")  // até encontrar .fim

siblings() retorna todos os irmãos (exclui o próprio). next()/prev() retornam o irmão imediatamente seguinte/anterior. nextAll()/prevAll() retornam todos numa direcção. nextUntil() para ao encontrar o selector. Todos aceitam filtro opcional. Úteis para navegação em listas e tabs.

add() e addBack()
// add(): combina selecções
$("h1").add("h2").add("h3").css("color", "navy");
$("p").add(".nota").addClass("texto");

// addBack(): readiciona a selecção anterior
$("ul").find("li")   // só li
  .addClass("item")
  .addBack()         // ul + li
  .css("border", "1px solid #ccc");

// Sem addBack (repetir selector):
var $ul = $("ul");
$ul.find("li").addClass("item");
$ul.css("border", "1px solid #ccc");

add() combina múltiplas selecções num único objecto jQuery. addBack() readiciona os elementos da selecção anterior (antes do find()/filter()). addBack(selector) readiciona apenas os que correspondem. Evita repetir selectores em operações que afectam pais e filhos.

Navegação em tabelas
// Padrão comum: acções em linhas de tabela
$("#tabela").on("click", ".btn-edit", function() {
  var $tr = $(this).closest("tr");
  var id = $tr.data("id");
  var nome = $tr.find("td").eq(1).text();
  var email = $tr.find("td").eq(2).text();
  abrirModal(id, nome, email);
});

// Zebra striping:
$("#tabela tr:even").addClass("zebra");

// Destacar linha no hover:
$("#tabela").on("mouseenter", "tr", function() {
  $(this).addClass("hover");
}).on("mouseleave", "tr", function() {
  $(this).removeClass("hover");
});

Padrão típico: closest("tr") para a linha, find("td").eq(n) para células. data-id no <tr> armazena o identificador. :even para zebrar. Delegação com on() para botões dentro de células. Este padrão aplica-se a qualquer estrutura repetitiva (cards, listas, grids).

first(), last() e eq()
var $itens = $("li");

// first(): primeiro da colecção
$itens.first().addClass("destaque");

// last(): último da colecção
$itens.last().addClass("fim");

// eq(n): índice específico (zero-based)
$itens.eq(0).css("color", "red");   // primeiro
$itens.eq(2).css("color", "blue");  // terceiro
$itens.eq(-1).css("color", "green"); // último

// slice(inicio, fim):
$itens.slice(1, 4).addClass("meio"); // índices 1,2,3

Métodos de posição na colecção jQuery. eq(n) é zero-based e aceita negativos (-1 = último). slice() funciona como Array.slice (fim exclusivo). Todos retornam novo objecto jQuery (chainable). Mais rápidos que pseudo-selectores :first, :last, :eq().

contents()
// contents(): filhos incluindo texto e comentários
$("#caixa").contents()

// Diferença de children():
// children() → só elementos
// contents() → elementos + nós de texto + comentários

// Manipular texto dentro de elemento:
$("#paragrafo").contents().filter(function() {
  return this.nodeType === 3;  // nó de texto
}).wrap("<strong></strong>");

// Útil para iframes:
$("#frame").contents().find("body").css("font", "16px");

contents() retorna todos os nós filhos: elementos, texto e comentários. children() retorna apenas elementos. nodeType === 3 identifica nós de texto. Útil para manipular texto inline sem afectar tags. contents() em iframes dá acesso ao documento interno (mesma origem).

Atributos e Dados


11 cards
attr() — atributos HTML
// Ler atributo:
var href = $("a").attr("href");
var alt = $("img").attr("alt");

// Definir:
$("a").attr("href", "/nova-pagina");
$("img").attr("alt", "Descrição da imagem");

// Múltiplos de uma vez:
$("a").attr({
  href: "/link",
  target: "_blank",
  rel: "noopener"
});

// Com função:
$("li").attr("data-index", function(i) {
  return i;
});

attr() lê/define atributos HTML (o que está no markup). Sem argumento retorna o valor do primeiro elemento. Com argumento define em todos os seleccionados. Aceita objecto para múltiplos atributos. Retorna undefined se o atributo não existe. Para valores booleanos (checked, disabled), preferir prop().

hasClass()
// Verificar se tem classe:
if ($("#menu").hasClass("aberto")) {
  fecharMenu();
} else {
  abrirMenu();
}

// Equivalente com toggleClass:
$("#menu").toggleClass("aberto");

// Em colecções (qualquer elemento):
if ($(".card").hasClass("seleccionado")) {
  // pelo menos UM card tem a classe
}

// contains() nativo (alternativa):
this.classList.contains("activo");

hasClass() retorna true se qualquer elemento da colecção tem a classe. Não aceita múltiplas classes. Equivalente nativo: classList.contains(). Útil para condições if. Para alternar sem verificar, usar directamente toggleClass() (mais conciso).

Manipular múltiplos atributos
// Padrão: actualizar vários atributos
function actualizarLink($el, dados) {
  $el.attr({
    href: dados.url,
    title: dados.titulo,
    "aria-label": dados.titulo,
    target: dados.externo ? "_blank" : "_self"
  });
}

// Atributos condicionais:
$("a").each(function() {
  var $a = $(this);
  if ($a.attr("href").startsWith("http")) {
    $a.attr({ target: "_blank", rel: "noopener" });
  }
});

// Remover em lote:
$(".temp").removeAttr("style title data-debug");

attr({}) com objecto define múltiplos atributos numa chamada (mais legível). Atributos com hífen precisam de aspas ("aria-label"). Valores dinâmicos com ternário. removeAttr() aceita múltiplos separados por espaço. Padrão: agrupar atributos relacionados numa única chamada para clareza.

removeAttr()
// Remover atributo:
$("input").removeAttr("disabled");
$("img").removeAttr("width height");  // múltiplos

// Exemplo: activar campo
$("#campo").removeAttr("readonly");

// Diferença de attr("x", ""):
// removeAttr → atributo desaparece do DOM
// attr("x","") → atributo fica com valor vazio

removeAttr() elimina completamente o atributo do elemento. Aceita múltiplos nomes separados por espaço. Diferente de definir valor vazio — o atributo desaparece do markup. Útil para activar campos (disabled, readonly) ou remover estilos inline. Para propriedades booleanas, prop("x", false) é preferível.

val() — valores de formulário
// Ler valor:
var nome = $("#nome").val();
var opcao = $("select").val();

// Definir:
$("#nome").val("João");
$("textarea").val("Texto inicial");

// Select múltiplo:
$("#multi").val(["op1", "op2"]);  // array
var seleccionados = $("#multi").val();  // ["op1","op2"]

// Checkbox/radio (usar prop):
$("#check").prop("checked", true);
// val() em checkbox retorna o atributo value

// Limpar campo:
$("#busca").val("");

val() lê/define o value de campos de formulário. Em select, retorna o value da opção seleccionada. Em select multiple, retorna/aceita array. Para checkbox/radio, usar prop("checked") em vez de val(). Sem argumentos lê; com argumento define em todos os seleccionados.

innerHTML vs jQuery
// jQuery:
$("#caixa").html("<p>Novo</p>");
var conteudo = $("#caixa").html();

// Vanilla equivalente:
document.getElementById("caixa").innerHTML = "<p>Novo</p>";
var conteudo = document.getElementById("caixa").innerHTML;

// outerHTML (elemento + conteúdo):
var completo = $("#caixa").prop("outerHTML");

// jQuery para texto:
$("#caixa").text("Sem tags");
// Vanilla:
document.getElementById("caixa").textContent = "Sem tags";

html() equivale a innerHTML nativo. text() equivale a textContent. prop("outerHTML") obtém o elemento completo (incluindo a própria tag). jQuery normaliza diferenças entre browsers. Para inserir HTML de fontes não confiáveis, sanitizar antes ou usar text() (previne XSS).

prop() — propriedades DOM
// prop() para estados booleanos:
$("#check").prop("checked", true);
$("#campo").prop("disabled", true);
$("#select").prop("selectedIndex", 2);

// Ler:
var marcado = $("#check").prop("checked");  // true/false
var desactivado = $("#campo").prop("disabled");

// attr vs prop:
// attr("checked") → "checked" ou undefined (HTML)
// prop("checked") → true ou false (estado actual)

// Sempre prop para: checked, selected, disabled, readonly

prop() acede a propriedades do DOM (estado actual), não ao atributo HTML. Para checked, disabled, selected — usar sempre prop(). attr() retorna o valor do markup inicial; prop() retorna o estado em tempo real. Exemplo: checkbox marcado pelo user → prop("checked") = true, attr("checked") pode ser undefined.

data() — data-attributes
// HTML: <div data-user-id="42" data-nome="Ana">

// Ler (camelCase automático):
$("#div").data("user-id");   // 42 (número!)
$("#div").data("userId");    // 42 (equivalente)
$("#div").data("nome");      // "Ana"

// Definir (só em memória, não no HTML):
$("#div").data("temp", {x: 1});
$("#div").data("activo", true);

// Ler todos:
var tudo = $("#div").data();
// {userId: 42, nome: "Ana", temp: {x:1}, activo: true}

// Remover:
$("#div").removeData("temp");

data() acede a data-attributes com conversão automática de tipos (números, booleanos, JSON). Nomes com hífen viram camelCase. data(key, valor) armazena em memória jQuery (não altera o HTML). Aceita objectos e arrays. removeData() limpa. Mais rápido que attr("data-*") para leitura repetida.

Padrão toggle de estado
// Toggle de menu:
$("#btn-menu").on("click", function() {
  $("#menu").toggleClass("aberto");
  $(this).toggleClass("activo");
  $("#menu").attr("aria-expanded",
    $("#menu").hasClass("aberto")
  );
});

// Toggle de disabled:
function toggleCampo($campo, activo) {
  $campo.prop("disabled", !activo);
  $campo.toggleClass("desactivado", !activo);
}

// Estado com data:
$("#btn").on("click", function() {
  var $btn = $(this);
  var activo = !$btn.data("activo");
  $btn.data("activo", activo);
  $btn.text(activo ? "ON" : "OFF");
});

Padrão comum: toggleClass() + prop() + data() para gerir estado. Sincronizar atributos ARIA (aria-expanded) para acessibilidade. data() armazena estado lógico; classes controlam visual. Funções helper (toggleCampo) evitam repetição. Manter estado e UI sincronizados.

addClass() e removeClass()
// Adicionar classe(s):
$("#caixa").addClass("activo");
$("#caixa").addClass("visivel destaque");

// Remover:
$("#caixa").removeClass("activo");
$("#caixa").removeClass();  // remove TODAS

// Toggle (adiciona se não tem, remove se tem):
$("#caixa").toggleClass("aberto");

// Com condição:
$("#caixa").toggleClass("erro", temErro);
// true → adiciona; false → remove

// Com função:
$("li").addClass(function(i) {
  return "item-" + i;
});

addClass()/removeClass() manipulam classes sem afectar outras existentes. toggleClass() alterna (adiciona/remove). Segundo parâmetro booleano força adicionar ou remover. Sem argumentos, removeClass() remove todas as classes. Aceitam múltiplas classes separadas por espaço. Preferir classes a estilos inline.

data() vs attr("data-*")
// HTML: <button data-id="5" data-config='{"a":1}'>

// data() → converte tipos + cache em memória:
$("button").data("id");       // 5 (Number)
$("button").data("config");   // {a: 1} (Object)

// attr() → sempre string do HTML:
$("button").attr("data-id");       // "5" (String)
$("button").attr("data-config");   // '{"a":1}' (String)

// data() não reflecte mudanças no HTML:
$("button").attr("data-id", "99");
$("button").data("id");    // ainda 5 (cache!)
$("button").attr("data-id"); // "99"

// Regra: usar data() consistentemente

data() converte tipos automaticamente e faz cache em memória. attr("data-*") retorna sempre string do HTML actual. Atenção: após data() ler, mudanças no HTML via attr() não são reflectidas (cache). Usar um ou outro consistentemente. data() é preferível para performance e tipos.

CSS e Dimensões


11 cards
css() — ler e definir estilos
// Ler (retorna valor computado):
var cor = $("#caixa").css("color");        // "rgb(255, 0, 0)"
var tamanho = $("#caixa").css("font-size"); // "16px"

// Definir:
$("#caixa").css("color", "blue");
$("#caixa").css("font-size", "18px");

// Múltiplos (objecto, camelCase):
$("#caixa").css({
  backgroundColor: "#f0f0f0",
  border: "2px solid #333",
  padding: "10px",
  borderRadius: "4px"
});

css() sem argumento retorna o valor computado (não o inline). Com argumento define estilo inline. Objecto usa camelCase (não hífen). Múltiplas propriedades numa chamada. Valores numéricos sem unidade assumem px. Preferir addClass() a css() para estilos reutilizáveis.

fadeIn() e fadeOut()
// Fade (só opacity):
$("#caixa").fadeIn(400);
$("#caixa").fadeOut(400);
$("#caixa").fadeToggle(400);

// Opacidade parcial:
$("#caixa").fadeTo(300, 0.5);  // 50% opacidade

// Callback:
$("#overlay").fadeIn(200, function() {
  $("#modal").fadeIn(300);
});

// Sequência:
$("#a").fadeOut(200, function() {
  $("#b").fadeIn(200);
});

fadeIn()/fadeOut() animam apenas opacity (não afectam layout como show/hide). fadeTo() define opacidade parcial sem ocultar. fadeToggle() alterna. Aceitam duração (ms ou "slow"/"fast") e callback de conclusão. Encadear em callbacks para sequências. Elemento fica com display:none após fadeOut.

Fila de animações
// Animações encadeiam automaticamente:
$("#caixa")
  .fadeIn(300)
  .animate({ left: "100px" }, 500)
  .fadeOut(300);
// executa em sequência (fila "fx")

// queue() para inspeccionar:
var tamanho = $("#caixa").queue("fx").length;

// dequeue() para continuar manualmente:
$("#caixa").queue(function(next) {
  $(this).addClass("processando");
  setTimeout(next, 1000);  // chama next() para continuar
});

// Limpar fila:
$("#caixa").clearQueue();
$("#caixa").stop(true);  // equivalente

Animações jQuery entram numa fila ("fx") e executam em sequência. queue(fn) adiciona passos custom à fila (chamar next() para continuar). clearQueue() remove pendentes. stop(true) limpa fila + para actual. Para animações simultâneas, chamar animate() com propriedades no mesmo objecto.

width() e height()
// content (sem padding/border):
$("#caixa").width();    // 200
$("#caixa").height();   // 100

// Definir:
$("#caixa").width(300);
$("#caixa").height("50%");

// innerWidth/Height (content + padding):
$("#caixa").innerWidth();   // 220 (200 + 10+10)

// outerWidth/Height (+ border):
$("#caixa").outerWidth();   // 224 (220 + 2+2)

// outerWidth(true) (+ margin):
$("#caixa").outerWidth(true);  // 244 (224 + 10+10)

width()/height() retornam dimensões do conteúdo (sem padding/border/margin). innerWidth() inclui padding. outerWidth() inclui padding + border. outerWidth(true) inclui também margin. Retornam números (sem "px"). Para definir, aceitam número (px) ou string ("50%").

slideUp() e slideDown()
// Slide (anima altura):
$("#painel").slideDown(300);
$("#painel").slideUp(300);
$("#painel").slideToggle(300);

// Menu dropdown:
$("#menu-btn").on("click", function() {
  $("#dropdown").slideToggle(200);
});

// Acordeão:
$(".acc-header").on("click", function() {
  $(this).next(".acc-body").slideToggle(300);
  $(this).closest(".acc-item")
    .siblings().find(".acc-body").slideUp(300);
});

slideUp()/slideDown() animam a altura do elemento (efeito cortina). slideToggle() alterna. Ideal para menus dropdown, acordeões e painéis colapsáveis. O elemento precisa de overflow:hidden durante a animação (jQuery aplica automaticamente). Callback no segundo parâmetro.

CSS transitions vs jQuery
/* CSS (preferir para performance): */
.caixa {
  transition: opacity 0.3s, transform 0.3s;
  opacity: 1;
}
.caixa.oculto {
  opacity: 0;
  transform: translateY(-10px);
}

// jQuery só toggle a classe:
$("#btn").on("click", function() {
  $("#caixa").toggleClass("oculto");
});

// jQuery animate para o que CSS não faz:
$("#caixa").animate({ scrollTop: 0 }, 500);
// scroll não é animável com CSS transition

CSS transitions são mais performantes (GPU, não bloqueiam JS). Usar jQuery só para toggleClass e deixar CSS animar. animate() para o que CSS não faz: scroll, contadores, valores relativos. Transitions não precisam de fila/stop. Regra: CSS para visual, jQuery para lógica e scroll.

position() e offset()
// position(): relativo ao PAI posicionado
var pos = $("#filho").position();
pos.top;   // distância ao topo do pai
pos.left;  // distância à esquerda do pai

// offset(): relativo ao DOCUMENTO
var off = $("#caixa").offset();
off.top;   // distância ao topo da página
off.left;  // distância à esquerda da página

// Definir offset (move o elemento):
$("#caixa").offset({ top: 100, left: 50 });

// Scroll actual:
$(window).scrollTop();   // scroll vertical
$(window).scrollLeft();  // scroll horizontal

position() é relativo ao offset parent (pai posicionado mais próximo). offset() é relativo ao documento (página inteira). Ambos retornam {top, left}. offset() pode definir posição. Para elementos fixos na viewport, combinar offset() com $(window).scrollTop().

animate()
// Animação custom:
$("#caixa").animate({
  left: "200px",
  opacity: 0.5,
  width: "300px"
}, 500);

// Com easing e callback:
$("#caixa").animate(
  { top: "100px" },
  800,
  "swing",       // ou "linear"
  function() { console.log("fim!"); }
);

// Propriedades relativas:
$("#caixa").animate({ left: "+=50" }, 300);
$("#caixa").animate({ opacity: "-=0.2" }, 300);

// Nota: precisa position:relative/absolute

animate() anima propriedades CSS numéricas. Não anima cores (usar jQuery UI ou CSS transitions). +=/-= para valores relativos. Parâmetros: propriedades, duração, easing ("swing" ou "linear") e callback. Elemento precisa de position definido para animar top/left. Múltiplas propriedades animam em simultâneo.

Scroll e posição
// Scroll suave para elemento:
$("a[href^='#']").on("click", function(e) {
  e.preventDefault();
  var alvo = $($(this).attr("href"));
  $("html, body").animate({
    scrollTop: alvo.offset().top - 80  // offset header
  }, 500);
});

// Ler scroll:
$(window).scrollTop();    // posição actual
$(window).scrollTop(0);   // ir para topo

// Scroll de container:
$("#painel").scrollTop(200);

// Detectar fim de scroll:
$(window).on("scroll", function() {
  if ($(window).scrollTop() + $(window).height()
      >= $(document).height() - 100) {
    carregarMais();  // infinite scroll
  }
});

scrollTop() lê/define a posição de scroll. Animar $("html, body") para scroll suave cross-browser. Subtrair altura do header fixo ao calcular posição. $(window).height() + scrollTop() vs $(document).height() para detectar fim de página (infinite scroll). Fazer throttle ao evento scroll para performance.

show(), hide() e toggle()
// Mostrar/ocultar (sem animação):
$("#caixa").show();
$("#caixa").hide();
$("#caixa").toggle();  // alterna

// Com duração (vira animação):
$("#caixa").show(300);      // 300ms
$("#caixa").hide("slow");   // 600ms
$("#caixa").toggle("fast"); // 200ms

// Callback ao completar:
$("#caixa").hide(300, function() {
  console.log("ocultado!");
});

// hide() = display:none (guarda o display original)
// show() restaura o display anterior

show()/hide() alteram display (sem animação por defeito). Com duração, animam opacity + tamanho. toggle() alterna entre show/hide. jQuery memoriza o display original para restaurar. hide() define display:none. Callbacks executam após completar. "slow"=600ms, "fast"=200ms.

stop() e delay()
// Parar animação actual:
$("#caixa").stop();

// Parar e saltar para o fim:
$("#caixa").stop(true, true);

// Parar TODAS na fila:
$("#caixa").stop(true, false);

// Delay entre animações:
$("#caixa")
  .delay(500)          // espera 500ms
  .fadeIn(300)
  .delay(1000)         // espera 1s
  .fadeOut(300);

// Problema clássico: hover com fila
$("#menu").hover(
  function() { $(this).stop(true).slideDown(200); },
  function() { $(this).stop(true).slideUp(200); }
);

stop() interrompe a animação actual. stop(true) limpa a fila de animações pendentes. stop(true, true) salta para o fim. delay(ms) insere pausa entre animações na fila. Sempre usar stop(true) em hover para evitar acumulação de animações (bug clássico do jQuery).

Efeitos e Animações


11 cards
Efeitos básicos combinados
// show/hide com animação:
$("#caixa").show(400);       // aparece com scale
$("#caixa").hide(400);       // desaparece com scale
$("#caixa").toggle(400);     // alterna

// fade (só opacity):
$("#caixa").fadeIn(400);
$("#caixa").fadeOut(400);
$("#caixa").fadeToggle(400);

// slide (só altura):
$("#caixa").slideDown(400);
$("#caixa").slideUp(400);
$("#caixa").slideToggle(400);

// Duração: número (ms) ou string
// "slow" = 600ms, "fast" = 200ms

Três famílias de efeitos: show/hide (opacity + tamanho), fade (só opacity), slide (só altura). Todos aceitam duração em ms ou "slow"/"fast". toggle em cada família alterna automaticamente. Sem duração, show/hide é instantâneo; fade/slide precisam de duração. Callback no último parâmetro.

Animações simultâneas
// Simultâneas: propriedades no mesmo animate()
$("#caixa").animate({
  opacity: 0,
  left: "+=100",
  height: "toggle"
}, 500);

// Múltiplos elementos ao mesmo tempo:
$(".card").each(function(i) {
  $(this).delay(i * 100).fadeIn(400);
});
// efeito cascata (stagger)

// Paralelo com sincronização:
$("#fundo").animate({opacity: 0.5}, 300);
$("#texto").animate({fontSize: "2em"}, 300);
// ambos correm em paralelo (elementos diferentes)

Propriedades no mesmo animate() correm em simultâneo. Elementos diferentes animam em paralelo automaticamente. delay(i * 100) cria efeito cascata (stagger). A fila é por elemento — elementos distintos não se bloqueiam. Para sequências complexas, usar callbacks ou $.when().

Tooltip simples
// Tooltip com fade:
$("[data-tooltip]").on("mouseenter", function(e) {
  var texto = $(this).data("tooltip");
  var $tip = $('<div class="tooltip"></div>').text(texto);
  $("body").append($tip);

  $tip.css({
    top: e.pageY - 30,
    left: e.pageX + 10
  }).fadeIn(150);
}).on("mouseleave", function() {
  $(".tooltip").fadeOut(100, function() {
    $(this).remove();
  });
});

// Seguir o rato:
$("[data-tooltip]").on("mousemove", function(e) {
  $(".tooltip").css({ top: e.pageY - 30, left: e.pageX + 10 });
});

Tooltip criado dinamicamente com data-tooltip. Posicionado com e.pageX/pageY no mouseenter. fadeIn/fadeOut para transição suave. Remover do DOM após fadeOut (evitar acumulação). mousemove para seguir o cursor. Usar text() (não html) para prevenir XSS. Para produção, preferir bibliotecas dedicadas.

animate() avançado
// Múltiplas propriedades:
$("#caixa").animate({
  width: "toggle",      // alterna width
  opacity: "toggle",    // alterna opacity
  left: "200px",
  fontSize: "1.5em"
}, 600);

// Valores relativos:
$("#caixa").animate({ left: "+=100", top: "-=50" }, 400);

// Passo a passo (step callback):
$("#barra").animate({ width: "100%" }, {
  duration: 1000,
  step: function(now) {
    $(this).text(Math.round(now) + "%");
  },
  complete: function() {
    $(this).text("Concluído!");
  }
});

animate() aceita "toggle", "show", "hide" como valores para alternar. +=/-= para movimento relativo. Objecto de opções permite step (a cada frame) e complete (no fim). step útil para contadores e barras de progresso. Não anima cores, transforms ou propriedades não-numéricas.

Modal / Overlay
// Abrir modal:
function abrirModal() {
  $("#overlay").fadeIn(200);
  $("#modal").fadeIn(300).css("display", "flex");
}

// Fechar:
function fecharModal() {
  $("#modal").fadeOut(200);
  $("#overlay").fadeOut(300);
}

// Fechar com ESC ou clique no overlay:
$(document).on("keydown", function(e) {
  if (e.key === "Escape") fecharModal();
});
$("#overlay").on("click", fecharModal);

// Prevenir scroll do body:
$("body").css("overflow", "hidden");  // abrir
$("body").css("overflow", "");        // fechar

Padrão de modal: overlay (fundo escuro) + caixa central. fadeIn para abrir, fadeOut para fechar. Fechar com ESC e clique no overlay. Bloquear scroll do body com overflow:hidden. Usar z-index alto no CSS. Para acessibilidade, gerir focus e aria-modal.

Contador animado
// Animar número de 0 até alvo:
function animarNumero($el, alvo, duracao) {
  $({ valor: 0 }).animate({ valor: alvo }, {
    duration: duracao || 1500,
    easing: "swing",
    step: function() {
      $el.text(Math.floor(this.valor));
    },
    complete: function() {
      $el.text(alvo);  // garantir valor exacto
    }
  });
}

// Uso:
animarNumero($("#stats-users"), 15000);
animarNumero($("#stats-vendas"), 892);

// Com formatação:
step: function() {
  $el.text(Math.floor(this.valor).toLocaleString("pt-PT"));
}

Truque: animar um objecto plain ($({valor: 0})) e usar step para actualizar o texto. Math.floor() evita decimais durante a animação. complete garante o valor exacto no fim. toLocaleString() para formatação de milhares. Efeito visual popular em landing pages e dashboards.

Easing
// Easing built-in:
$("#caixa").animate({left: "200px"}, 500, "swing");
$("#caixa").animate({left: "200px"}, 500, "linear");

// swing: acelera no início, desacelera no fim (default)
// linear: velocidade constante

// Com jQuery UI (mais easings):
$("#caixa").animate({top: "100px"}, 800, "easeOutBounce");
$("#caixa").animate({left: "300px"}, 600, "easeInOutCubic");
$("#caixa").animate({width: "toggle"}, 500, "easeOutElastic");

// Definir default:
$.fx.speeds.lento = 1000;
$("#caixa").fadeIn("lento");

Easing controla a aceleração da animação. jQuery core tem só "swing" (default) e "linear". jQuery UI adiciona dezenas (easeOutBounce, easeInOutCubic, etc.). $.fx.speeds permite criar durações nomeadas custom. Para animações complexas, considerar CSS transitions/animations ou GSAP.

Acordeão
// HTML: .acc-item > .acc-header + .acc-body
$(".acc-header").on("click", function() {
  var $item = $(this).closest(".acc-item");
  var $body = $item.find(".acc-body");
  var aberto = $body.is(":visible");

  // Fechar todos:
  $(".acc-body").slideUp(300);
  $(".acc-item").removeClass("activo");

  // Abrir o clicado (se estava fechado):
  if (!aberto) {
    $body.slideDown(300);
    $item.addClass("activo");
  }
});

// Inicializar: primeiro aberto
$(".acc-item:first .acc-body").show();
$(".acc-item:first").addClass("activo");

Padrão acordeão: slideUp() fecha todos, slideDown() abre o seleccionado. is(":visible") verifica estado actual. closest() e find() para navegação. Classe activo para estilizar header. Permitir fechar todos ou manter sempre um aberto (remover o if). Inicializar estado no arranque.

Lazy load de imagens
// HTML: <img data-src="foto.jpg" class="lazy">
function lazyLoad() {
  $(".lazy").each(function() {
    var $img = $(this);
    var top = $img.offset().top;
    var scroll = $(window).scrollTop();
    var altura = $(window).height();

    if (top < scroll + altura + 200) {
      $img.attr("src", $img.data("src"))
          .removeAttr("data-src")
          .removeClass("lazy")
          .hide().fadeIn(400);
    }
  });
}

$(window).on("scroll", lazyLoad);
lazyLoad();  // verificar visíveis no load

// Nota: usar throttle no scroll!

Lazy load: imagem só carrega quando entra na viewport. data-src guarda a URL real; src fica vazio/placeholder. Verificar offset().top vs scrollTop() + height(). Margem de 200px para pré-carregar. fadeIn para transição. Sempre throttle no scroll. Hoje: preferir loading="lazy" nativo ou IntersectionObserver.

Callbacks de animação
// Callback ao completar:
$("#caixa").fadeOut(300, function() {
  $(this).remove();  // remover depois de ocultar
});

// Sequência com callbacks:
$("#a").fadeOut(200, function() {
  $("#b").fadeIn(200, function() {
    $("#c").slideDown(200);
  });
});

// Promise (jQuery 3+):
$("#caixa").fadeOut(300).promise().done(function() {
  console.log("todas as animações completas");
});

// $.when para múltiplos:
$.when(
  $("#a").fadeIn(300),
  $("#b").slideDown(300)
).done(function() {
  $("#c").show();
});

Callback executa quando a animação termina (por elemento). Para colecções, dispara uma vez por elemento. .promise().done() dispara uma vez quando todos terminam. $.when() espera múltiplas animações em paralelo. Padrão: animar → callback → próxima acção. Evitar nesting profundo (callback hell).

Tabs / Abas
// HTML: .tab-btn[data-tab] + .tab-panel[id]
$(".tab-btn").on("click", function() {
  var alvo = $(this).data("tab");

  // Desactivar todas:
  $(".tab-btn").removeClass("activa");
  $(".tab-panel").hide();

  // Activar seleccionada:
  $(this).addClass("activa");
  $("#" + alvo).fadeIn(200);
});

// Com URL hash:
var hash = window.location.hash.slice(1);
if (hash) {
  $('.tab-btn[data-tab="' + hash + '"]').click();
} else {
  $(".tab-btn:first").click();
}

Padrão tabs: botões com data-tab apontam para IDs de painéis. hide() todos + fadeIn() o activo. Classe activa para estilizar botão. Suportar URL hash para deep-linking. Disparar click() programaticamente para inicializar. Alternativa: CSS com :target (sem JS).

AJAX


11 cards
$.ajax() — método completo
$.ajax({
  url: "/api/dados",
  method: "GET",
  dataType: "json",
  data: { pagina: 1, limite: 20 },
  headers: { "X-Token": "abc123" },
  timeout: 5000,
  beforeSend: function() {
    $("#loading").show();
  },
  success: function(dados, status, xhr) {
    renderizar(dados);
  },
  error: function(xhr, status, erro) {
    alert("Erro: " + erro);
  },
  complete: function() {
    $("#loading").hide();
  }
});

$.ajax() é o método mais completo e flexível. method: GET, POST, PUT, DELETE. dataType: tipo esperado da resposta (json, html, text). data: parâmetros enviados. Callbacks: beforeSend (antes), success (sucesso), error (falha), complete (sempre). Base de todos os atalhos jQuery AJAX.

Enviar JSON
// POST com JSON:
$.ajax({
  url: "/api/produtos",
  method: "POST",
  contentType: "application/json",
  data: JSON.stringify({
    nome: "Produto X",
    preco: 29.90,
    tags: ["novo", "destaque"]
  }),
  success: function(resposta) {
    console.log("ID:", resposta.id);
  }
});

// Nota importante:
// contentType: "application/json" → enviar JSON
// (default é "x-www-form-urlencoded")
// data deve ser JSON.stringify()

// PUT e DELETE:
$.ajax({ url: "/api/x/1", method: "PUT", ... });
$.ajax({ url: "/api/x/1", method: "DELETE", ... });

Para enviar JSON: definir contentType: "application/json" e usar JSON.stringify() nos dados. Sem isto, jQuery envia como form-encoded. method aceita PUT, DELETE, PATCH. O servidor deve responder com JSON. Para APIs REST, este é o padrão mais comum. Headers de auth via headers: {}.

AJAX com formulários
$("form").on("submit", function(e) {
  e.preventDefault();
  var $form = $(this);
  var $btn = $form.find("[type=submit]");

  $btn.prop("disabled", true).text("A enviar...");

  $.ajax({
    url: $form.attr("action"),
    method: $form.attr("method"),
    data: $form.serialize(),
    success: function(r) {
      alert("Sucesso!");
      $form[0].reset();
    },
    error: function(xhr) {
      var erros = xhr.responseJSON.errors;
      $.each(erros, function(campo, msg) {
        $("#" + campo).after('<span class="erro">' + msg + '</span>');
      });
    },
    complete: function() {
      $btn.prop("disabled", false).text("Enviar");
    }
  });
});

Padrão de formulário AJAX: preventDefault(), serialize() para dados, desactivar botão durante envio. $form.attr("action") e $form.attr("method") respeitam o HTML. complete reactiva o botão (sucesso ou erro). Mapear erros de validação por campo. $form[0].reset() limpa o formulário nativo.

$.get() e $.post()
// GET simples:
$.get("/api/users", function(dados) {
  console.log(dados);
});

// GET com parâmetros:
$.get("/api/users", { activo: 1 }, function(dados) {
  listar(dados);
}, "json");

// POST:
$.post("/api/users", {
  nome: "Ana",
  email: "ana@email.com"
}, function(resposta) {
  alert("Criado: " + resposta.id);
}, "json");

// POST com error:
$.post("/api/login", dados)
  .done(function(r) { /* ok */ })
  .fail(function(xhr) { /* erro */ });

$.get() e $.post() são atalhos simplificados. Parâmetros: url, data, callback, dataType. Retornam jqXHR (thenable) — usar .done()/.fail() em vez de callback. $.getJSON() é atalho para GET com dataType json. Para configurações avançadas (headers, timeout), usar $.ajax().

Upload de ficheiros
// HTML: <input type="file" id="ficheiro">
$("#form-upload").on("submit", function(e) {
  e.preventDefault();

  var formData = new FormData(this);
  // ou: formData.append("ficheiro", $("#ficheiro")[0].files[0]);

  $.ajax({
    url: "/api/upload",
    method: "POST",
    data: formData,
    processData: false,   // NÃO processar dados
    contentType: false,   // NÃO definir content-type
    xhr: function() {
      var xhr = new XMLHttpRequest();
      xhr.upload.onprogress = function(e) {
        var pct = (e.loaded / e.total) * 100;
        $("#progresso").css("width", pct + "%");
      };
      return xhr;
    },
    success: function(r) { alert("Upload: " + r.url); }
  });
});

Upload usa FormData nativo. processData: false impede jQuery de serializar. contentType: false deixa o browser definir multipart. xhr.upload.onprogress para barra de progresso. this.files[0] acede ao ficheiro do input. Nunca usar $.post() para uploads — precisa de $.ajax() com estas opções.

Debounce para pesquisa
// Pesquisa com debounce (espera parar de escrever):
var timer;
$("#busca").on("input", function() {
  var termo = $(this).val();
  clearTimeout(timer);

  if (termo.length < 2) {
    $("#resultados").empty();
    return;
  }

  timer = setTimeout(function() {
    $.get("/api/busca", { q: termo }, function(dados) {
      var html = dados.map(function(item) {
        return "<li>" + item.nome + "</li>";
      }).join("");
      $("#resultados").html(html);
    });
  }, 300);  // 300ms após última tecla
});

// Abortar pedido anterior:
var xhrActual;
// xhrActual = $.get(...); xhrActual.abort();

Debounce: esperar N ms após a última tecla antes de pesquisar. clearTimeout cancela o timer anterior a cada input. Mínimo de 2 caracteres evita pedidos desnecessários. xhr.abort() cancela pedidos pendentes (evitar respostas fora de ordem). Padrão essencial para autocomplete e pesquisa em tempo real.

load() — carregar HTML
// Carregar HTML directamente num elemento:
$("#conteudo").load("/pagina.html");

// Carregar fragmento (selector):
$("#conteudo").load("/pagina.html #seccao");
$("#sidebar").load("/layout.html .widget");

// Com dados e callback:
$("#resultados").load("/busca", { q: "jquery" },
  function(resposta, status, xhr) {
    if (status === "error") {
      $(this).html("Erro: " + xhr.status);
    }
  }
);

// Substituir vs inserir:
// load() SUBSTITUI o conteúdo do elemento

load() faz GET e insere a resposta HTML directamente no elemento. Com selector após espaço, carrega só um fragmento da página. Callback recebe (resposta, status, xhr). Substitui o conteúdo existente. Ideal para carregar parciais, templates e conteúdo dinâmico sem JavaScript de parsing.

ajaxSetup e interceptores
// Configuração global:
$.ajaxSetup({
  headers: {
    "X-CSRF-TOKEN": $('meta[name="csrf"]').attr("content")
  },
  timeout: 10000,
  dataType: "json"
});

// Interceptar TODOS os pedidos:
$(document).ajaxStart(function() {
  $("#spinner").show();
});

$(document).ajaxStop(function() {
  $("#spinner").hide();
});

$(document).ajaxError(function(e, xhr, settings) {
  if (xhr.status === 401) {
    window.location = "/login";
  }
  console.error("AJAX erro:", settings.url);
});

$.ajaxSetup() define defaults para todos os pedidos AJAX (headers, timeout). Eventos globais: ajaxStart/ajaxStop (spinner global), ajaxError (tratamento central de erros), ajaxSuccess. Ideais para CSRF token, loading indicators e redirect em 401. Aplicam-se a todos os $.ajax(), $.get(), $.post().

Infinite scroll
var pagina = 1;
var carregando = false;
var fim = false;

$(window).on("scroll", function() {
  if (carregando || fim) return;

  var scrollFim = $(window).scrollTop() + $(window).height();
  var docAltura = $(document).height();

  if (scrollFim >= docAltura - 300) {
    carregando = true;
    pagina++;

    $.get("/api/posts", { page: pagina }, function(dados) {
      if (dados.length === 0) {
        fim = true;
        $("#feed").append('<p class="fim">Fim</p>');
        return;
      }
      dados.forEach(function(post) {
        $("#feed").append(renderizarPost(post));
      });
      carregando = false;
    });
  }
});

Infinite scroll: detectar proximidade do fim da página e carregar mais. Flags carregando e fim evitam pedidos duplicados. Margem de 300px para pré-carregar. Resposta vazia = não há mais dados. Sempre throttle no evento scroll para performance. Alternativa moderna: IntersectionObserver (sem scroll listener).

Promises e $.when()
// jQuery 3+ (compatível com Promise):
$.get("/api/dados")
  .done(function(dados) { /* sucesso */ })
  .fail(function(xhr) { /* erro */ })
  .always(function() { /* sempre */ });

// then() (encadeável):
$.get("/api/users")
  .then(function(users) {
    return $.get("/api/posts/" + users[0].id);
  })
  .then(function(posts) {
    renderizar(posts);
  })
  .catch(function(erro) {
    console.error(erro);
  });

// Múltiplos pedidos em paralelo:
$.when(
  $.get("/api/users"),
  $.get("/api/posts"),
  $.get("/api/comments")
).done(function(users, posts, comments) {
  // todos completos
});

jQuery 3+ retorna Promises compatíveis. .done()/.fail()/.always() são os callbacks jQuery. .then() permite encadear pedidos sequenciais. $.when() espera múltiplos pedidos em paralelo. Cada argumento de done em $.when é um array [data, status, xhr]. Preferir then/catch para código moderno.

Tratamento de erros
$.ajax({ url: "/api/dados" })
  .done(function(dados) {
    renderizar(dados);
  })
  .fail(function(xhr, status, erro) {
    switch (xhr.status) {
      case 400:
        mostrarErros(xhr.responseJSON.errors);
        break;
      case 401:
        redireccionar("/login");
        break;
      case 404:
        alert("Recurso não encontrado");
        break;
      case 422:
        var erros = xhr.responseJSON;
        Object.keys(erros).forEach(function(campo) {
          $("#" + campo).addClass("erro");
        });
        break;
      case 500:
        alert("Erro no servidor");
        break;
    }
  });

xhr.status dá o HTTP status code. xhr.responseJSON é a resposta JSON parseada (se dataType json). status (string): "success", "error", "timeout", "parsererror". Padrão: switch por status code com mensagens específicas. 422 para erros de validação com mapeamento por campo. Sempre tratar erros — nunca assumir sucesso.

Formulários


11 cards
serialize() e serializeArray()
// serialize(): query string
var dados = $("form").serialize();
// "nome=Ana&email=ana@mail.com&idade=25"

// serializeArray(): array de objectos
var arr = $("form").serializeArray();
// [{name: "nome", value: "Ana"}, {name: "email", value: "ana@mail.com"}]

// Converter para objecto:
var obj = {};
$.each(arr, function(i, campo) {
  obj[campo.name] = campo.value;
});

// Só campos específicos:
$("#form :input:not(:disabled)").serialize();

serialize() converte todos os campos do form em query string (pronto para POST). serializeArray() retorna array de {name, value}. Inclui apenas campos com name e não desactivados. Checkboxes/radios só se marcados. Ideal para enviar via AJAX. Não inclui file inputs (usar FormData).

Checkbox e radio
// Checkbox:
$("#termos").prop("checked");         // true/false
$("#termos").prop("checked", true);   // marcar
$("#termos").is(":checked");          // verificar

// Todos os marcados:
var marcados = $('input[name="tags"]:checked')
  .map(function() { return $(this).val(); })
  .get();  // ["js", "css"]

// Radio:
var opcao = $('input[name="tipo"]:checked').val();

// Marcar radio:
$('input[name="tipo"][value="admin"]').prop("checked", true);

// Select all / deselect all:
$("#select-all").on("change", function() {
  $(".checkbox-item").prop("checked", $(this).is(":checked"));
});

Para checkbox/radio, usar sempre prop("checked") (não attr). :checked filtra os marcados. .map().get() extrai valores como array. Radio: :checked retorna o seleccionado do grupo. Padrão "select all": propagar estado do checkbox mestre para todos os itens.

Feedback visual de estado
// Estados de botão:
function setEstadoBotao($btn, estado) {
  $btn.prop("disabled", estado === "loading");
  $btn.html({
    idle: "Enviar",
    loading: '<span class="spinner"></span> A enviar...',
    success: "✓ Enviado!",
    error: "✗ Erro — Tentar novamente"
  }[estado]);
  $btn.attr("class", "btn btn-" + estado);
}

// Uso:
setEstadoBotao($("#btn"), "loading");
$.post("/api/enviar", dados)
  .done(function() { setEstadoBotao($("#btn"), "success"); })
  .fail(function() { setEstadoBotao($("#btn"), "error"); });

Botões com estados: idle, loading, success, error. prop("disabled") impede duplo clique. Objecto de mapeamento para HTML por estado. Classe CSS por estado para estilização. Spinner inline durante loading. Feedback visual claro melhora UX. Reverter para idle após timeout em caso de erro.

Validação básica
$("form").on("submit", function(e) {
  var erros = [];

  var nome = $("#nome").val().trim();
  if (nome.length < 3) {
    erros.push("Nome: mínimo 3 caracteres");
    $("#nome").addClass("erro");
  }

  var email = $("#email").val();
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    erros.push("Email inválido");
    $("#email").addClass("erro");
  }

  if (erros.length > 0) {
    e.preventDefault();
    $("#erros").html(erros.map(function(e) {
      return "<li>" + e + "</li>";
    }).join(""));
  }
});

Validação client-side antes do submit. trim() remove espaços. Regex para email. addClass("erro") destaca campos inválidos. preventDefault() impede envio se houver erros. Mostrar mensagens num container. Complementar (não substituir) validação server-side. Limpar erros no input do campo.

Select dinâmico
// Preencher select via AJAX:
$("#pais").on("change", function() {
  var paisId = $(this).val();
  var $cidade = $("#cidade");

  $cidade.prop("disabled", true).html("<option>A carregar...</option>");

  $.get("/api/cidades", { pais: paisId }, function(dados) {
    var options = '<option value="">Seleccionar...</option>';
    dados.forEach(function(c) {
      options += '<option value="' + c.id + '">' + c.nome + '</option>';
    });
    $cidade.html(options).prop("disabled", false);
  });
});

// Ler seleccionado:
var valor = $("#cidade").val();
var texto = $("#cidade option:selected").text();

Selects dependentes: mudar um carrega opções do outro via AJAX. Desactivar durante loading. Reconstruir <option> com a resposta. val() retorna o value; option:selected + text() para o texto visível. Sempre incluir opção vazia inicial. Limpar select dependente quando o pai muda.

Autocomplete simples
var $input = $("#busca");
var $lista = $("#sugestoes");
var timer;

$input.on("input", function() {
  var termo = $(this).val().trim();
  clearTimeout(timer);

  if (termo.length < 2) { $lista.hide(); return; }

  timer = setTimeout(function() {
    $.get("/api/sugestoes", { q: termo }, function(dados) {
      var html = dados.map(function(item) {
        return '<li data-id="' + item.id + '">' + item.nome + '</li>';
      }).join("");
      $lista.html(html).show();
    });
  }, 250);
});

// Seleccionar sugestão (delegação):
$lista.on("click", "li", function() {
  $input.val($(this).text());
  $input.data("id", $(this).data("id"));
  $lista.hide();
});

// Fechar ao clicar fora:
$(document).on("click", function(e) {
  if (!$(e.target).closest("#busca, #sugestoes").length) {
    $lista.hide();
  }
});

Autocomplete: debounce + AJAX + lista de sugestões. data-id armazena o ID seleccionado. Delegação para cliques em itens dinâmicos. Fechar ao clicar fora com closest(). Mínimo 2 caracteres. Para acessibilidade: aria-autocomplete, navegação por teclado. Para produção, usar bibliotecas (Typeahead, Select2).

Validação em tempo real
// Validar ao sair do campo:
$("#email").on("blur", function() {
  var $campo = $(this);
  var valido = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test($campo.val());

  $campo.toggleClass("erro", !valido);
  $campo.next(".msg-erro").toggle(!valido);
});

// Limpar erro ao escrever:
$(".campo").on("input", function() {
  $(this).removeClass("erro");
  $(this).next(".msg-erro").hide();
});

// Validar força de password:
$("#pass").on("input", function() {
  var forca = calcularForca($(this).val());
  $("#forca").css("width", forca + "%");
});

Validar no blur (ao sair do campo) é menos intrusivo que a cada tecla. toggleClass(classe, boolean) adiciona/remove conforme condição. Limpar erro no input para feedback imediato. Mensagens de erro adjacentes (.next(".msg-erro")). Indicador de força para passwords. Balanço entre UX e validação rigorosa.

Máscara de input
// Máscara de telefone simples:
$("#telefone").on("input", function() {
  var v = $(this).val().replace(/\D/g, "");
  if (v.length > 9) v = v.slice(0, 9);

  if (v.length > 6) {
    v = v.replace(/(\d{3})(\d{3})(\d+)/, "$1 $2 $3");
  } else if (v.length > 3) {
    v = v.replace(/(\d{3})(\d+)/, "$1 $2");
  }
  $(this).val(v);
});

// Máscara de NIF (9 dígitos):
$("#nif").on("input", function() {
  $(this).val($(this).val().replace(/\D/g, "").slice(0, 9));
});

// Formatar ao sair:
$("#preco").on("blur", function() {
  var v = parseFloat($(this).val()) || 0;
  $(this).val(v.toFixed(2));
});

Máscaras formatam input em tempo real. replace(/\D/g, "") remove não-dígitos. slice() limita comprimento. Regex com grupos para inserir separadores. Formatar no blur para valores monetários. Para máscaras complexas, usar plugins (jquery.mask, inputmask). Sempre validar no servidor também.

Drag and drop básico
// Reordenar lista (sem plugin):
var $arrastado = null;

$("#lista li").on("dragstart", function() {
  $arrastado = $(this);
  $(this).addClass("arrastando");
});

$("#lista li").on("dragend", function() {
  $(this).removeClass("arrastando");
  $arrastado = null;
});

$("#lista li").on("dragover", function(e) {
  e.preventDefault();
});

$("#lista li").on("drop", function() {
  if ($arrastado && $arrastado[0] !== this) {
    $(this).before($arrastado);
    // enviar nova ordem ao servidor:
    var ordem = $("#lista li").map(function() {
      return $(this).data("id");
    }).get();
    $.post("/api/ordenar", { ordem: ordem });
  }
});

Drag and drop nativo HTML5 com jQuery. dragstart/dragend no arrastado. dragover + preventDefault() para permitir drop. drop reposiciona com before(). map().get() extrai nova ordem. Para funcionalidade completa, usar jQuery UI Sortable. HTML: draggable="true" nos itens.

Seleccionar e manipular campos
// Todos os campos de um form:
$("#form :input")  // input, select, textarea, button

// Por tipo:
$("#form input:text")     // type=text
$("#form input:password")
$("#form :checkbox")
$("#form :radio")
$("#form select")
$("#form textarea")

// Limpar todos:
$("#form")[0].reset();
// ou:
$("#form :input").val("").prop("checked", false);

// Desactivar/activar todos:
$("#form :input").prop("disabled", true);
$("#form :input").prop("disabled", false);

:input selecciona todos os campos (input, select, textarea, button). Filtros por tipo: :text, :checkbox, :radio. reset() nativo restaura valores iniciais. prop("disabled") em lote para bloquear formulários durante processamento. val("") limpa texto; prop("checked", false) desmarca.

Formulário multi-step
var passoActual = 1;
var totalPassos = $(".step").length;

function mostrarPasso(n) {
  $(".step").hide();
  $(".step").eq(n - 1).fadeIn(300);
  $("#progresso").text("Passo " + n + " de " + totalPassos);
  $("#btn-anterior").toggle(n > 1);
  $("#btn-seguinte").toggle(n < totalPassos);
  $("#btn-submit").toggle(n === totalPassos);
}

$("#btn-seguinte").on("click", function() {
  if (validarPasso(passoActual)) {
    passoActual++;
    mostrarPasso(passoActual);
  }
});

$("#btn-anterior").on("click", function() {
  passoActual--;
  mostrarPasso(passoActual);
});

mostrarPasso(1);

Formulário em passos: cada .step é uma secção. eq(n-1) mostra o passo actual. fadeIn para transição. Botões anterior/seguinte com toggle() condicional. Validar cada passo antes de avançar. Barra de progresso com texto ou percentagem. Submeter só no último passo.

Dicas e Boas Práticas


11 cards
Cache de selectores
// MAU: selecciona a cada uso
$("#menu").addClass("aberto");
$("#menu").find("li").show();
$("#menu").css("opacity", 1);

// BOM: cache em variável
var $menu = $("#menu");
$menu.addClass("aberto");
$menu.find("li").show();
$menu.css("opacity", 1);

// Convenção: prefixo $ para objectos jQuery
var $lista = $("#lista");
var $itens = $lista.find("li");
var $btn = $(".btn-submit");

// Re-seleccionar só se DOM mudou

Cada $() percorre o DOM — evitar repetições. Guardar em variável com prefixo $ (convenção). Reutilizar para múltiplas operações. Re-seleccionar apenas se o DOM foi modificado. find() no cache é mais rápido que novo selector global. Impacto significativo em loops e handlers frequentes.

Padrão módulo (IIFE)
// IIFE: Immediately Invoked Function Expression
(function($) {
  "use strict";

  var config = { velocidade: 300 };

  function init() {
    ligarEventos();
    carregarDados();
  }

  function ligarEventos() {
    $("#btn").on("click", handler);
  }

  function handler() {
    $("#painel").slideToggle(config.velocidade);
  }

  function carregarDados() {
    $.get("/api/dados", renderizar);
  }

  function renderizar(dados) { /* ... */ }

  // Iniciar quando DOM pronto:
  $(init);

})(jQuery);

IIFE cria escopo privado — variáveis não poluem o global. Passar jQuery como parâmetro permite usar $ com segurança (modo noConflict). "use strict" activa modo estrito. Funções privadas inacessíveis externamente. $(init) inicia quando DOM pronto. Padrão clássico de organização antes de módulos ES6.

jQuery 3.x e migração
// Removido no jQuery 3:
// .load(), .unload(), .error() (atalhos de eventos)
// → usar .on("load", fn)

// .bind()/.live()/.delegate() (deprecated)
// → usar .on()

// $.parseJSON() → JSON.parse()
// $.trim() → String.prototype.trim()
// $.type() → typeof / instanceof

// Novo no jQuery 3:
// .addClass() aceita função
// SVG support
// requestAnimationFrame para animações
// Promises compatíveis (then/catch)

// Plugin de migração:
// jquery-migrate (mostra warnings)

jQuery 3 removeu métodos deprecated: atalhos de eventos, .bind(), .live(). Substituir por .on(). Utilitários como $.trim() têm equivalentes nativos. jQuery 3 usa requestAnimationFrame (animações mais suaves). Promises compatíveis com standard. jquery-migrate ajuda na transição (mostra warnings no console).

Delegação vs ligação directa
// Directo: só elementos existentes
$("li").on("click", fn);
// 100 li = 100 handlers em memória

// Delegação: 1 handler no pai
$("#lista").on("click", "li", fn);
// 1 handler, funciona com futuros li

// Quando usar delegação:
// - Elementos dinâmicos (AJAX)
// - Muitos elementos (performance)
// - Listas, tabelas, grids

// Quando usar directo:
// - Elementos estáticos e poucos
// - Eventos que não bolham (focus, blur)
//   → usar focusin/focusout para delegação

Delegação: 1 handler no pai vs N handlers nos filhos. Menos memória, funciona com elementos futuros. Obrigatório para conteúdo dinâmico (AJAX). focus/blur não bolham — usar focusin/focusout para delegação. Para poucos elementos estáticos, ligação directa é aceitável. Preferir delegação por defeito.

noConflict()
// Se outra biblioteca usa $ (Prototype, etc.):
var jq = jQuery.noConflict();
jq("#caixa").hide();

// Ou IIFE com jQuery:
(function($) {
  // $ é jQuery aqui dentro
  $("#caixa").hide();
})(jQuery);

// Libertar $ E jQuery:
var jq = jQuery.noConflict(true);

// Verificar disponibilidade:
if (typeof jQuery !== "undefined") {
  (function($) {
    // código jQuery seguro
  })(jQuery);
}

noConflict() liberta a variável $ para outras bibliotecas. noConflict(true) liberta também jQuery. Padrão IIFE com (jQuery) permite usar $ internamente sem conflito. Verificar typeof jQuery antes de usar (scripts condicionais). WordPress usa noConflict por defeito — sempre IIFE ou jQuery().

jQuery vs Vanilla JS moderno
// jQuery → Vanilla equivalente:
$("#id")         → document.getElementById("id")
$(".classe")     → document.querySelectorAll(".classe")
$el.addClass("x") → el.classList.add("x")
$el.attr("href") → el.getAttribute("href")
$el.on("click")  → el.addEventListener("click")
$el.html("<p>")  → el.innerHTML = "<p>"
$.ajax()         → fetch()
$el.fadeIn()     → el.animate([{opacity:0},{opacity:1}])

// jQuery ainda útil para:
// - Suporte a browsers antigos (IE)
// - Ecossistema de plugins
// - Código legacy
// - Prototipagem rápida

Vanilla JS moderno cobre quase tudo: querySelector, classList, fetch, Web Animations API. jQuery ainda relevante para IE11, plugins e código legacy. fetch() substitui $.ajax() (mas sem IE). Para projectos novos sem IE, vanilla ou frameworks são suficientes. jQuery não está morto — mas não é obrigatório.

Evitar memory leaks
// MAU: remover sem limpar eventos
$("#widget").remove();  // remove() limpa (ok)

// MAU: innerHTML não limpa eventos jQuery
$("#container").html("");  // ok (jQuery limpa)
document.getElementById("c").innerHTML = "";  // LEAK!

// BOM: limpar antes de remover
$("#widget").off().removeData().remove();

// Ao destruir componentes:
function destruirModal() {
  $("#modal").off();           // eventos
  $("#modal").removeData();    // dados
  $("#modal").remove();        // DOM
  $(document).off("keydown.modal");  // namespace
}

// SPA: limpar ao mudar de "página"

Memory leaks: eventos/dados órfãos quando DOM é removido sem jQuery. remove() e html() do jQuery limpam automaticamente. innerHTML nativo NÃO limpa. off() + removeData() antes de remover para segurança. Namespaces facilitam limpeza selectiva. Crítico em SPAs e componentes que criam/destróem frequentemente.

Plugins jQuery
// Criar plugin:
$.fn.destacar = function(opcoes) {
  var settings = $.extend({
    cor: "yellow",
    bold: true
  }, opcoes);

  return this.each(function() {
    $(this).css({
      backgroundColor: settings.cor,
      fontWeight: settings.bold ? "bold" : "normal"
    });
  });
};

// Uso:
$("p").destacar();
$("p").destacar({ cor: "#ff0", bold: false });

// Regras:
// 1. Retornar this.each() (chaining)
// 2. $.extend para defaults + opções
// 3. Prefixo $.fn para métodos de instância

Plugins estendem $.fn (protótipo jQuery). return this.each() mantém chaining. $.extend() faz merge de defaults com opções do utilizador. this dentro do plugin é o objecto jQuery (não DOM). Aceitar objecto de opções para flexibilidade. Plugins populares: Slick, Select2, DataTables, Magnific Popup.

Checklist de performance
// 1. Cache de selectores
var $el = $("#caixa");  // não repetir $()

// 2. Delegação em vez de N handlers
$("#lista").on("click", "li", fn);

// 3. Batch DOM (1 inserção vs loop)
var html = items.map(render).join("");
$("#lista").html(html);

// 4. Throttle/debounce em scroll/resize
$(window).on("scroll", throttle(fn, 100));

// 5. Selectores específicos
$("#form").find("input")  // rápido
$("form input")           // mais lento

// 6. Evitar layout thrashing
var w = $el.width();     // ler
$el.width(w + 10);       // escrever (1x)

// 7. Remover o que não usa
$el.off().removeData().remove();

Resumo de performance: cache, delegação, batch DOM, throttle, selectores específicos. Layout thrashing: alternar leitura/escrita de dimensões causa reflows múltiplos — agrupar leituras e escritas. find() com contexto mais rápido que selector global. Limpar eventos/dados ao remover. Ferramentas: Chrome DevTools Performance tab para identificar bottlenecks.

Throttle e debounce
// Debounce: espera parar (pesquisa)
function debounce(fn, delay) {
  var timer;
  return function() {
    var ctx = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(ctx, args);
    }, delay);
  };
}
$(window).on("resize", debounce(recalcular, 250));

// Throttle: no máximo 1x por intervalo (scroll)
function throttle(fn, limite) {
  var ultima = 0;
  return function() {
    var agora = Date.now();
    if (agora - ultima >= limite) {
      ultima = agora;
      fn.apply(this, arguments);
    }
  };
}
$(window).on("scroll", throttle(verificarPosicao, 100));

Debounce: executa após N ms de inactividade (pesquisa, resize). Throttle: no máximo 1 execução por intervalo (scroll, mousemove). Sem estes, eventos disparam centenas de vezes/segundo. apply(ctx, args) preserva contexto. Essenciais para performance em eventos de alta frequência. Bibliotecas: lodash tem ambos.

$.extend() e $.each()
// $.extend(): merge de objectos
var defaults = { cor: "azul", tamanho: 12, activo: true };
var opcoes = { cor: "vermelho", tamanho: 16 };
var final = $.extend({}, defaults, opcoes);
// { cor: "vermelho", tamanho: 16, activo: true }

// Deep merge (nested):
$.extend(true, {}, obj1, obj2);

// $.each(): iterar arrays/objectos
$.each([10, 20, 30], function(i, valor) {
  console.log(i, valor);
});

$.each({ nome: "Ana", idade: 25 }, function(chave, valor) {
  console.log(chave + ": " + valor);
});

// Nota: $.each ≠ .each() (método de colecção)

$.extend() faz merge de objectos (primeiro é o target). {} como primeiro evita mutar defaults. true para deep merge (objectos nested). $.each() itera arrays (i, valor) e objectos (chave, valor). Diferente de .each() que é método de colecção jQuery. Ambos são utilitários estáticos ($.).