jQuery / Selector / :odd - Elemente mit ungeraden Indizes auswählen

jQuerys :odd wählt die Indizes 1, 3, 5 und so weiter im ausgewählten Satz, gezählt ab null. Gemeint sind also das zweite, vierte und sechste Element. Wer wegen „ungerade“ die erste sichtbare Zeile erwartet, erhält scheinbar das Gegenteil. Wählen Sie in neuem Code den Bereich mit einem normalen CSS-Selektor und filtern Sie anschließend mit .odd().

Bedeutung und Wechsel zu .odd()

Die Dokumentation zu :odd kennzeichnet den Selektor seit jQuery 3.4 als veraltet und empfiehlt die Methode .odd(). Sie wurde in 3.5 ergänzt, nimmt keine Argumente an und erzeugt ein neues jQuery-Objekt aus den Elementen mit ungeraden Indizes der aktuellen Menge. Veraltet bedeutet nicht entfernt: Der Vergleich wurde mit 3.7.1 und 4.0.0 erfolgreich ausgeführt.

Ersetzen Sie $("#records > tbody > tr:odd") durch $("#records > tbody > tr").odd(). Versionen vor 3.5 besitzen diese Methode nicht. Prüfen Sie vor einem Upgrade die Kompatibilität von Anwendung und Plugins.

Ausdruck Zählweise Anfangsergebnis
:odd oder .odd() für tbody-Zeilen Ausgewählte Datenzeilen ab null r2, r4
.odd() für alle Zeilen samt Kopfzeile Kopfzeile belegt Index null r1, r3, r5
tbody tr:nth-child(odd) Geschwisterposition je Elternteil ab eins r1, r3, r5

Vollständiges Tabellenbeispiel ausführen

Speichern Sie den gesamten Code als UTF-8 in odd-demo.html und öffnen Sie die Datei im Browser. Eine Paketinstallation ist unnötig; zum Laden der offiziellen Distribution über das Content Delivery Network (CDN) ist Internet erforderlich. Das Beispiel verwendet 4.0.0.

thead enthält eine Kopfzeile, tbody fünf Datenzeilen. IDs identifizieren Zeilen; Indizes ergeben sich aus dem aktuellen Auswahlbereich und der Dokumentreihenfolge. Die Schaltflächen verändern diese Bedingungen.

<!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>

Anfangs werden nur Datenzeilen ausgewählt und mit .odd() gefiltert. Item 2 und Item 4 sind markiert:

r2, r4 | 2

Bereich wechseln, Zeile einfügen und zurücksetzen

  1. Data rows .odd() zählt nur direkte tr-Kinder von tbody. Indizes 1 und 3 ergeben r2, r4 | 2.
  2. Include header .odd() berücksichtigt auch die thead-Zeile. Der Kopf belegt Index null; übrig bleiben r1, r3, r5 | 3.
  3. Data :nth-child(odd) wählt Geschwisterpositionen 1, 3 und 5 innerhalb von tbody: r1, r3, r5 | 3. Gleiches Ergebnis bedeutet hier keine gleiche Zählregel.
  4. Prepend one data row fügt Extra item am Anfang von tbody ein und berechnet .odd() neu. r1 rückt auf Index 1, daher r1, r3, r5 | 3. Die Prüfung der extra-ID verhindert Duplikate bei wiederholtem Klicken.
  5. Reset entfernt nur die ergänzte Zeile und wendet .odd() erneut auf die Daten an. Die ursprünglichen fünf Zeilen und Werte bleiben; wieder erscheint r2, r4 | 2.

show entfernt erst alle bisherigen marked-Klassen und markiert dann die neue Auswahl. Hervorhebungen sammeln sich dadurch nicht an. Begrenzen Sie auch in echten Tabellen ID und direkte Kindbeziehungen, damit fremde oder verschachtelte Tabellen ausgeschlossen bleiben.

Mit CSS odd vergleichen

Führen Sie direkt nach dem Öffnen oder Reset diesen Teilcode in der Entwicklerkonsole aus. Die ersten zwei Zeilen vergleichen alten Selektor und Ersatzmethode; die letzte nutzt :nth-child() nach CSS-Regeln.

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() zählt die gesamte ausgewählte Menge zusammen. :nth-child(odd) beginnt dagegen bei jedem Elternteil erneut, auch bei mehreren tbody-Elementen. :nth-child() zählt alle Elementgeschwister unabhängig vom Tag; an der errechneten Position muss zusätzlich tr passen. Leerraumtext und Kommentare zählen nicht als Elementgeschwister.

Filterreihenfolge und dynamische Zeilen

r1, r3, r4 und r5 tragen eligible. $("#records > tbody > tr.eligible").odd() sammelt zuerst diese vier Zeilen und behält r3 und r5. .odd() auf allen fünf Datenzeilen vor .filter(".eligible") lässt von r2 und r4 nur r4 übrig. Die Reihenfolge verändert die Menge, auf deren Basis Indizes entstehen.

Leere Mengen und Mengen mit nur einem Element besitzen keinen Index 1; .odd() bleibt leer. Ergebnisse aktualisieren sich nicht automatisch. Eine vor dem Einfügen gespeicherte Auswahl von r2 und r4 enthält später dieselben Elemente. Fragen Sie wie dataRows erneut ab, um aktuelle Positionen zu berücksichtigen.

Bei Problemen prüfen Sie den jQuery-Aufruf in Network, Fehler in Console und jQuery.fn.jquery. Bei umgekehrten Ergebnissen kontrollieren Sie Kopfzeile, tbody-Bereich, Filterreihenfolge und ergänzte Zeilen. Sichtbare Zeilennummer und nullbasierter Index sind unterschiedliche Angaben.