jQuery / Selector / :empty - Selecionar elementos sem conteúdo

O :empty do jQuery seleciona elementos sem elementos filhos nem texto. Restrinja o alcance com $("#data td:empty") para preencher células vazias. Um elemento visualmente vazio com espaços ou tags filhas não corresponde; um que contém apenas um comentário corresponde.

O que é considerado vazio?

O conteúdo descrito na documentação de :empty inclui nós de texto. Portanto, indentação e quebras de linha entre tags podem contar. As diferenças abaixo foram verificadas executando este exemplo com jQuery 4.0.0 e 3.7.1.

Conteúdo do elemento Corresponde a :empty? Motivo
Nada Sim Sem filhos nem texto
Espaços, quebra de linha ou   Não Espaços são texto
Somente comentário Sim Comentários não contam nesse teste
Um span vazio ou br Não Existe um elemento filho

A definição do CSS Selectors Level 3 também desconsidera comentários nessa decisão. Um atributo title ou class não torna o elemento preenchido. Já esconder um filho com display:none não o remove da estrutura. Não julgue apenas pela aparência.

Exemplo completo: preencher células vazias

Salve todo o código em UTF-8 como empty-demo.html e abra no navegador. Não é necessário instalar pacotes, mas é preciso conexão para carregar jQuery pela rede de distribuição de conteúdo (CDN). O exemplo fixa a distribuição oficial em jQuery 4.0.0.

blank está realmente vazia, spaces contém três espaços e comment contém apenas comentário. O span de nested e o br de break são filhos mesmo sem texto visível. O resultado e os botões ficam fora da tabela selecionada.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Empty table cells</title>
  <style>
    body { font: 16px/1.6 sans-serif; margin: 24px; }
    table { border-collapse: collapse; width: 100%; max-width: 600px; }
    td { border: 1px solid #aaa; padding: 16px; min-width: 80px; }
    .is-empty { background: #fff0b3; }
    button { margin: 16px 8px 0 0; padding: 8px; }
  </style>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
  <h1>Empty table cells</h1>
  <table id="data">
    <tr><td id="blank"></td><td id="spaces">   </td></tr>
    <tr><td id="comment"><!-- note --></td><td id="text">Hello</td></tr>
    <tr><td id="nested"><span></span></td><td id="break"><br></td></tr>
  </table>
  <button type="button" id="fill">Fill empty cells</button>
  <button type="button" id="reset">Reset</button>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      function render() {
        const $empty = $("#data td:empty");
        $("#data td").removeClass("is-empty");
        $empty.addClass("is-empty");
        const ids = $empty.map((_, cell) => cell.id).get().join(", ");
        $("#result").text(`${ids || "none"} | ${$empty.length}`);
      }
      $("#fill").on("click", function () {
        $("#data td:empty").text("N/A");
        render();
      });
      $("#reset").on("click", function () {
        $("#blank, #comment").empty();
        render();
      });
      render();
    });
  </script>
</body>
</html>

Ao abrir, o parágrafo mostra o seguinte e as células blank e comment ficam destacadas em amarelo:

blank, comment | 2

Observar e redefinir o exemplo

  1. Pressione Fill empty cells. As duas células correspondentes recebem N/A. Uma nova seleção resulta em none | 0.
  2. Confira spaces, nested e break. Seus espaços ou filhos impedem o preenchimento.
  3. Pressione Reset. Os conteúdos de blank e comment são removidos, e ambas voltam a corresponder. Somente essas células são redefinidas; o comentário original não é restaurado.

.text("N/A") insere uma string para exibição. render primeiro remove o destaque de todas as células e o aplica apenas às atualmente vazias. Isso evita manter a marca antiga nas células recém-preenchidas. Confira tanto a operação quanto o estado exibido.

Restringir a seleção e repeti-la após mudanças

Prefira $("#data td:empty") a $(":empty") para o documento inteiro. Assim você não seleciona acidentalmente elementos vazios fora da tabela, incluindo span e br. Após abrir o exemplo ou usar Reset, execute este trecho na console de desenvolvimento para ver a quantidade e os IDs:

const $empty = $("#data td:empty");
console.log($empty.length);
console.log($empty.map((_, cell) => cell.id).get().join(", "));
2
blank, comment

Uma seleção jQuery não é uma lista viva atualizada automaticamente quando o documento muda. Se você mantiver $empty e preencher as células, a length do objeto continua 2. Execute novamente o seletor para contar as células vazias atuais. Por isso render cria uma nova seleção a cada chamada.

Diferenciar .empty(), :parent e valores de entrada

:empty é uma condição de seleção. O método .empty() remove filhos e texto, mas mantém os elementos selecionados, sendo adequado ao Reset. A condição oposta, :parent, seleciona elementos com filhos ou texto. Não é o método .parent(), que acessa o elemento pai.

Um input pode corresponder a :empty mesmo com o valor JB, pois seu valor não é conteúdo filho. Para validar uma entrada, leia o valor atual com .val() e compare com uma string vazia. Tratar uma entrada só de espaços como vazia exige outra regra. Estrutura vazia e valor vazio são verificações diferentes.

Se nada acontecer, verifique no painel Network se o jQuery carregou e procure erros como $ is not defined na Console. Confira também os IDs e se a edição acrescentou espaços entre as tags da célula supostamente vazia.