jQuery / Methode / .parent() - Direkte Elternelemente auswählen

jQuerys .parent() liefert ein neues jQuery-Objekt mit den direkten Eltern der ausgewählten Elemente und geht genau eine Ebene nach oben. .parent(".card") übernimmt den jeweiligen Elternteil nur bei passendem Selektor. Es sucht nicht weiter oben nach einem Treffer. Mehrfach vorkommende gemeinsame Eltern erscheinen nur einmal.

parent, parents und closest unterscheiden

In der .parent()-API bezeichnet Elternteil den direkt übergeordneten Knoten im Document Object Model (DOM). Ein optisch umgebender Kasten oder CSS-Positionierungsbezug muss nicht dieser Knoten sein. Mit $(".pick").parent().addClass("picked") bearbeiten Sie das Ergebnis durch verkettete Methoden. Die ursprünglichen Buttons werden dabei weder verschoben noch gelöscht.

Methode Suchbereich Mit Selektor
.parent(".card") Genau eine Ebene darüber Passende direkte Eltern
.parents(".card") Eltern und höhere Vorfahren Passende Vorfahren
.closest(".card") Element selbst, dann aufwärts Erster Treffer je Ausgangselement

Für alle passenden Vorfahren verwenden Sie .parents(), für die nächste Karte trotz Zwischencontainer .closest(). closest prüft auch das Ausgangselement und kann auf einer Karte diese selbst liefern. parent nimmt einen optionalen Selektorstring an, keinen Callback und keine Ebenenzahl.

Vollständiges Beispiel mit verschachtelten Karten

Speichern Sie den gesamten Code in UTF-8 als parent-demo.html und öffnen Sie ihn im Browser. Für die offizielle jQuery-Datei 4.0.0 vom Content Delivery Network (CDN) benötigen Sie Internet, keine Installation. Anfangsauswahl, zusätzlicher Wrapper, neue Karte, Reset und beide Konsolenbeispiele wurden mit 3.7.1 und 4.0.0 ausgeführt.

Alphas zwei Buttons teilen alpha-body als direkten Elternteil. Betas Button liegt direkt in Karte beta. Türkise Umrisse zeigen Treffer. buttons zählt Ausgangsbuttons, parents die Ergebnisknoten und DOM buttons die weiterhin im Dokument vorhandenen Buttons.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Select immediate parents</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button, select { font: inherit; margin: 4px; max-width: 100%; }
    #board, .card, .body { padding: 12px; border: 1px solid #aab; margin: 10px 0; }
    .picked { outline: 3px solid teal; outline-offset: -3px; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <h1>Select one parent level</h1>
  <label for="mode">Traversal:</label>
  <select id="mode">
    <option value="parent">parent()</option>
    <option value="filtered">parent('.card')</option>
    <option value="closest">closest('.card')</option>
    <option value="ancestors">parents('section')</option>
  </select>
  <button type="button" id="wrap">Wrap Beta button</button>
  <button type="button" id="add">Add Gamma</button>
  <button type="button" id="reset">Reset</button>
  <section id="board">
    <article id="alpha" class="card">
      Alpha card
      <div id="alpha-body" class="body">
        <button type="button" id="alpha-one" class="pick"><span>Alpha one</span></button>
        <button type="button" id="alpha-two" class="pick">Alpha two</button>
      </div>
    </article>
    <article id="beta" class="card">
      Beta card
      <button type="button" id="beta-one" class="pick">Beta one</button>
    </article>
  </section>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      const initial = $("#board").html();
      function report() {
        const $buttons = $("#board .pick");
        let $result;
        switch ($("#mode").val()) {
          case "filtered": $result = $buttons.parent(".card"); break;
          case "closest": $result = $buttons.closest(".card"); break;
          case "ancestors": $result = $buttons.parents("section"); break;
          default: $result = $buttons.parent();
        }
        $("#board, #board *").removeClass("picked");
        $result.addClass("picked");
        const ids = $result.map(function () { return this.id; }).get();
        $("#result").text(`buttons=${$buttons.length}\nparents=${$result.length}: ${ids.join(", ") || "(none)"}\nDOM buttons=${$("#board .pick").length}`);
      }
      $("#mode").on("change", report);
      $("#wrap").on("click", function () {
        if (!$("#beta-body").length) $("#beta-one").wrap('<div id="beta-body" class="body"></div>');
        report();
      });
      $("#add").on("click", function () {
        if (!$("#gamma").length) $("#board").append('<article id="gamma" class="card">Gamma card <button type="button" id="gamma-one" class="pick">Gamma one</button></article>');
        report();
      });
      $("#reset").on("click", function () { $("#board").html(initial); $("#mode").val("parent"); report(); });
      report();
    });
  </script>
</body>
</html>

Anfangs ergeben drei Buttons zwei unterschiedliche Eltern, weil der gemeinsame Elternteil nur einmal vorkommt.

buttons=3
parents=2: alpha-body, beta
DOM buttons=3
  1. parent('.card') liefert nur beta. Alphas direkter Elternteil ist .body; die Suche geht nicht weiter bis alpha.
  2. closest('.card') liefert alpha und beta. Alphas Zwischencontainer .body wird auf dem Weg zur nächsten Karte übergangen.
  3. parents('section') liefert den gemeinsamen Vorfahren board einmal.
  4. Drücken Sie Wrap Beta button und wählen Sie parent(): alpha-body und beta-body erscheinen. parent('.card') ist nun leer. Die Buttons bleiben bestehen, nur ihre direkte Hierarchie ändert sich.
  5. Add Gamma ergänzt einen Button direkt in einer neuen Karte. parent('.card') findet nur gamma, closest('.card') drei Karten. Wiederholtes Einpacken oder Ergänzen erzeugt keine Duplikate.
  6. Reset stellt ursprüngliches HTML und parent()-Modus wieder her. Ändern Sie jeweils eine Bedingung und setzen Sie dann zurück.

report() wählt die Buttons jedes Mal neu. Ein gespeichertes const $parents = $(".pick").parent() aktualisiert sich bei späteren DOM-Änderungen nicht automatisch. Suchen Sie nach neuen Wrappern oder Knotenverschiebungen erneut, wenn aktuelle Beziehungen benötigt werden.

Duplikate, leere Ergebnisse und Ereignisse

Führen Sie nach Reset den folgenden Code in der Entwicklerkonsole aus. parent bei leerer Auswahl ergibt ebenfalls ein jQuery-Objekt der Länge null. Prüfen Sie .length vor direktem Knotenzugriff. Der Elternteil von html kann document statt eines normalen Elements sein; elementtypische Eigenschaften wie tagName sind nicht für jeden Ergebnisknoten vorauszusetzen.

const $buttons = $("#board .pick");
console.log(`buttons=${$buttons.length}; unique parents=${$buttons.parent().length}`);
console.log(`Alpha parent(.card)=${$("#alpha-one").parent(".card").length}`);
console.log(`Alpha closest(.card)=${$("#alpha-one").closest(".card").attr("id")}`);
console.log(`card closest itself=${$("#alpha").closest(".card").attr("id")}`);
console.log(`empty parent count=${$().parent().length}`);
console.log(`html parent is document=${$("html").parent().get(0) === document}`);
buttons=3; unique parents=2
Alpha parent(.card)=0
Alpha closest(.card)=alpha
card closest itself=alpha
empty parent count=0
html parent is document=true

Beim Klick auf ein span im Button ist event.target dieses span. Verwenden Sie in einem normalen delegierten Handler this, um vom passenden Button auszugehen. Der folgende Code in derselben Seitenkonsole löst einen span-Klick aus und entfernt danach nur seinen eigenen Handler-Namensraum.

$("#board").on("click.parentExample", ".pick", function (event) {
  console.log(`parent=${$(this).parent().attr("id")}; target=${event.target.tagName.toLowerCase()}`);
});
$("#alpha-one span").trigger("click");
$("#board").off(".parentExample");
parent=alpha-body; target=span

Das Ziel ist span, der gemeldete Elternteil aber alpha-body des Buttons. $(event.target).parent() würde den Button selbst liefern. Eine Pfeilfunktion erhält den Button hier nicht als this; verwenden Sie eine normale Funktion. Für die Karte rufen Sie auf dem Button .closest(".card") auf.

Unerwartete Eltern untersuchen

Prüfen Sie das tatsächliche DOM im Elements-Bereich der Entwicklerwerkzeuge. Fügt ein Plugin einen Wrapper-div ein, kann .parent(".card") leer werden. Entscheiden Sie zuerst zwischen direktem Elternteil und nächstem passenden Vorfahren, statt beliebig .parent().parent() anzuhängen.

Ein zu breiter Ausgangsselektor kann mehrere unzusammenhängende Eltern gestalten. Begrenzen Sie ihn beispielsweise auf #board .pick und prüfen Sie Ergebnislänge und IDs vor Änderungen. Kontrollieren Sie bei leeren Ergebnissen zunächst, ob Ausgangselemente zum Ausführungszeitpunkt existieren. Die DOM-Bereit-Funktion des Beispiels läuft nach dem Parsen des anfänglichen HTML; erneutes report() berücksichtigt später ergänzte Buttons.