jQuery / Seletor / :odd - Selecionar elementos com índices ímpares
O seletor jQuery :odd escolhe os índices 1, 3, 5 e assim por diante no conjunto selecionado, contando a partir de zero. São o segundo, quarto e sexto elementos. Esperar a primeira linha por causa da palavra “ímpar” produz a impressão de um resultado invertido. Em código novo, delimite o conjunto com um seletor CSS comum e depois filtre com .odd().
Significado e migração para .odd()
A documentação de :odd marca o seletor como obsoleto desde o jQuery 3.4 e recomenda o método .odd(). Acrescentado na 3.5, ele não recebe argumentos e cria um novo objeto jQuery com os elementos de índices ímpares do conjunto atual. Obsoleto não significa removido: a comparação foi executada com sucesso em 3.7.1 e 4.0.0.
Substitua $("#records > tbody > tr:odd") por $("#records > tbody > tr").odd(). Versões anteriores à 3.5 não possuem esse método; confira a compatibilidade da aplicação e dos plugins antes de atualizar.
| Expressão | Regra de contagem | Resultado inicial |
|---|---|---|
| :odd ou .odd() nos tr de tbody | Conjunto de linhas de dados, a partir de zero | r2, r4 |
| .odd() em todos os tr com cabeçalho | O cabeçalho ocupa o índice zero | r1, r3, r5 |
| tbody tr:nth-child(odd) | Posição entre irmãos de cada pai, a partir de um | r1, r3, r5 |
Executar um exemplo completo de tabela
Salve todo o código em UTF-8 como odd-demo.html e abra no navegador. Não é necessário instalar pacotes, mas é preciso internet para carregar a distribuição oficial pela rede de distribuição de conteúdo, ou CDN. O exemplo usa 4.0.0.
thead contém uma linha de cabeçalho e tbody cinco de dados. Os IDs identificam as linhas; os índices dependem da ordem atual do documento e do escopo selecionado. Os botões alteram essas condições.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Odd indexes in table rows</title>
<style>
body { font: 16px/1.6 sans-serif; margin: 24px; }
table { border-collapse: collapse; width: 100%; max-width: 600px; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
tr.marked { background: #fff0b3; }
button { margin: 4px; padding: 8px; }
</style>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
<h1>Odd indexes in table rows</h1>
<table id="records">
<thead><tr id="heading"><th>Item</th><th>Amount</th></tr></thead>
<tbody>
<tr id="r1" class="eligible"><td>Item 1</td><td>10</td></tr>
<tr id="r2"><td>Item 2</td><td>20</td></tr>
<tr id="r3" class="eligible"><td>Item 3</td><td>30</td></tr>
<tr id="r4" class="eligible"><td>Item 4</td><td>40</td></tr>
<tr id="r5" class="eligible"><td>Item 5</td><td>50</td></tr>
</tbody>
</table>
<button type="button" id="data">Data rows .odd()</button>
<button type="button" id="all">Include header .odd()</button>
<button type="button" id="css">Data :nth-child(odd)</button>
<button type="button" id="prepend">Prepend one data row</button>
<button type="button" id="reset">Reset</button>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
function show($chosen) {
$("#records tr").removeClass("marked");
$chosen.addClass("marked");
const ids = $chosen.map((_, row) => row.id).get().join(", ");
$("#result").text(`${ids || "none"} | ${$chosen.length}`);
}
function dataRows() {
show($("#records > tbody > tr").odd());
}
$("#data").on("click", dataRows);
$("#all").on("click", () => show($("#records tr").odd()));
$("#css").on("click", () => show($("#records > tbody > tr:nth-child(odd)")));
$("#prepend").on("click", function () {
if (!$("#extra").length) {
$("#records > tbody").prepend('<tr id="extra"><td>Extra item</td><td>0</td></tr>');
}
dataRows();
});
$("#reset").on("click", function () {
$("#extra").remove();
dataRows();
});
dataRows();
});
</script>
</body>
</html>
Inicialmente, .odd() é aplicado somente aos dados. Item 2 e Item 4 ficam destacados e o resultado mostra:
r2, r4 | 2
Alterar o escopo, incluir uma linha e restaurar
- Data rows .odd() conta apenas tr filhos diretos de tbody. Os índices 1 e 3 produzem
r2, r4 | 2. - Include header .odd() inclui a linha de thead. O cabeçalho ocupa o índice zero e o resultado passa a
r1, r3, r5 | 3. - Data :nth-child(odd) seleciona as posições 1, 3 e 5 em tbody:
r1, r3, r5 | 3. Ter o mesmo resultado do botão anterior não significa usar a mesma regra. - Prepend one data row insere Extra item no início de tbody e recalcula .odd(). O antigo r1 vai para o índice 1:
r1, r3, r5 | 3. Conferir o ID extra evita duplicatas em cliques repetidos. - Reset remove somente a linha incluída e reaplica .odd() aos dados. As cinco linhas e valores originais permanecem;
r2, r4 | 2é restaurado.
show remove todas as classes marked anteriores antes de marcar o resultado novo, evitando destaques acumulados. Em tabelas reais, limite também o ID e as relações de filhos diretos para excluir outras tabelas ou tabelas aninhadas.
Comparar com odd do CSS
Logo após abrir ou usar Reset, execute este trecho no console de desenvolvimento. As primeiras duas linhas comparam o seletor antigo e seu substituto; a última usa :nth-child() segundo as regras CSS.
const ids = $set => $set.map((_, row) => row.id).get().join(", ");
console.log(ids($("#records > tbody > tr:odd")));
console.log(ids($("#records > tbody > tr").odd()));
console.log(ids($("#records > tbody > tr:nth-child(odd)")));
r2, r4
r2, r4
r1, r3, r5
.odd() conta o conjunto selecionado como uma sequência única. :nth-child(odd) reinicia as posições para cada pai, inclusive em vários tbody. :nth-child() conta todos os irmãos que sejam elementos, independentemente da tag, e exige que o candidato naquela posição também corresponda a tr. Espaços de texto e comentários não são elementos irmãos.
Ordem dos filtros e linhas dinâmicas
r1, r3, r4 e r5 possuem eligible. $("#records > tbody > tr.eligible").odd() reúne primeiro essas quatro linhas e mantém r3 e r5. Aplicar .odd() às cinco linhas antes de .filter(".eligible") mantém apenas r4 entre r2 e r4. A ordem muda o conjunto usado para calcular os índices.
Um conjunto vazio ou com um elemento não possui índice 1; .odd() também retorna vazio. Resultados não são atualizados automaticamente. Uma seleção de r2 e r4 salva antes da inserção continua contendo esses elementos depois dela. Consulte novamente, como dataRows, para refletir as posições atuais.
Se não houver resposta, confira a requisição do jQuery em Network, os erros em Console e jQuery.fn.jquery. Se o resultado parecer invertido, verifique a inclusão do cabeçalho, o escopo de tbody, a ordem dos filtros e as linhas acrescentadas. Diferencie o número visível do índice iniciado em zero.




