index,follow

Rekursion am Beispiel von jQuery

16.12.2011, 13:03 von Daniel || (Kommentare: 0) || Mit anderen teilen

Wie im wahren Leben kommt es im Job manchmal zu Aufgabenstellungen, die immer wiederkehrende Abläufe beinhalten. Findige Programmierer greifen in diesen Fällen zur Rekursion.

Die Wikipedia beschreibt den Begriff mit folgenden Worten:

"Bei der rekursiven Programmierung ruft sich eine Prozedur, Funktion oder Methode in einem Computerprogramm selbst wieder auf. Auch der gegenseitige Aufruf stellt eine Rekursion dar."

Mehr gibt es dazu eigentlich auch nicht zu sagen. In der Rekursion geht es darum, einen ensprechenden Code so zu gestalten, dass er sich selbst bis zu einem Punkt x aufrufen kann. Knackpunkt hierbei ist die Abbruchbedingung (am Punkt x), da sich die Funktion sonst bis in das digitale Nirvana immer wieder selbst aufruft.

Eine hierarchische Liste

Mein Beispiel listet (unvollständig) die Verwaltungshierarchie Deutschlands auf. Klingt kompliziert, ist es aber nicht. Die Demo zeigt, wie es aussieht. Der Link dazu ist weiter unten zu finden.

  • Deutschland
    • ...
    • Sachsen
      • (Landkreis) Bautzen
        • Arnsdorf
        • (Stadt) Bautzen
          • Gesundbrunnen
          • Innenstadt
          • Nordostring
          • Ostvorstadt
          • Südvorstadt
          • Westvorstadt
          • ...
        • Bernsdorf
        • Bischofswerda
        • ...
      • Chemnitz
      • Dresden
      • Erzgebirgskreis
      • Görlitz
      • Leipzig
      • ...
    • Sachsen-Anhalt
    • Thüringen

Das Markup dazu sieht ausschnittsweise wie folgt aus. Es ist eine ganz normale, handelsübliche Liste:

<ul>
  <li>
    <input type="checkbox" id="state10" />
    <label for="state10">Sachsen</label>
    <ul>
      <li>
        <input type="checkbox" id="administrativeDistrict100" />
        <label for="administrativeDistrict100">Bautzen</label>
        <ul>
          <li>
            <input type="checkbox" id="municipality110" />
            <label for="municipality110">Arnsdorf</label>
          </li>
          <li>
            <input type="checkbox" id="municipality120" />
            <label for="municipality120">Bautzen</label>
            <ul>
              <li>
                <input type="checkbox" id="place121" />
                <label for="label121">Gesundbrunnen</label>
              </li>
              ...
            </ul>
          </li>
          ...
        </ul>
      </li>
      ...
    </ul>
  </li>
  ...
</ul>

Die Aufgabenstellung

Klickt ein Benutzer nun alle Einträge in einer Ebene (z.B. die Ortsteile von Bautzen) an, so soll die Checkbox der Elternliste (also die Stadt Bautzen) ebenfalls ausgewählt sein.

Das ist aber noch nicht alles. In den höheren Ebenen (was der Landkreis Bautzen und das Land Sachsen ist) soll ebenfalls geprüft werden, ob alle Kriterien erfüllt sind, dass die Elterncheckbox ausgewählt wird.

Demo

Um das ganze zu veranschaulichen, gibt es hier eine Demo dazu. Einfach mal ein bisschen mit den Checkboxen spielen.

Rekursion am Beispiel von jQuery

Das Script

Genug Geplänkel. Kommen wir nun zum spannenderen Teil. Wie sieht das Script in jQuery aus?

Es gibt die Funktion checkParentBoxes, die das gerade angeglickte Element übergeben bekommt.

function checkParentBoxes(el) {
  var parentCheckbox = $(el).parent().parent().siblings(":checkbox");
  var sameLevelCheckboxes = $(el).parent().parent().children().children(":checkbox");

  if (parentCheckbox.length == 1) {
    if ($(parentCheckbox).is(":checked")) {
      if (!$(el).is(":checked")) {
        $(parentCheckbox).attr("checked", false).removeAttr("checked");
      }
    } else {
      var i = 0;

      sameLevelCheckboxes.each(function() {
        if ($(this).is(":checked")) {
          i++;
        }
      });

      if (i == sameLevelCheckboxes.length) {
        parentCheckbox.attr("checked", true);
      }
    }

    checkParentBoxes(parentCheckbox);
  }
}

In der Funktion werden als erstes die Elterncheckbox (var parentCheckbox) und die Checkboxen der selben Ebene (var sameLevelCheckboxes) gespeichert.

Anschließend wird eine Abbruchbedingung (if (parentCheckbox.length == 1)) definiert, die abfragt, ob eine Elterncheckbox existiert. Würde es diese Bedingung nicht geben, so würde die Funktion irgendwann ins Leere laufen.

Im folgenden Code wird nun der Status der Elterncheckbox überprüft und angepasst. Wenn die gerade angeklickte Checkbox nicht ausgewählt ist (Zeilen 7 - 8), dann soll das Häkchen der Elterncheckbox entfernt werden.

Wenn dem nicht so ist, geht es ab Zeile 10 weiter. Die Checkboxen der selben Ebene werden überprüft (Zeilen 13 - 17). Ergibt diese Prüfung, dass alle ausgewählt sind Zeilen 19 - 21), so wird die Elterncheckbox ausgewählt.

Das war's auch schon mit der Funktionalität. Jetzt geht es um die höheren Ebenen. Der Selbstaufruf, also die Rekursion, muss jetzt noch an entscheidender Stelle erfolgen. In diesem Beispiel erfolgt das an letzter Stelle innerhalb der Abbruchbedingung:

if (parentCheckbox.length == 1) {
  ...
  checkParentBoxes(parentCheckbox); // hier erfolgt der Selbstaufruf
}

Der Trick hierbei ist die Übergabe der aktuellen Elterncheckbox als Argument an die Funktion. Damit springen wir in der Liste eine Ebene nach oben. Und die Überprüfung der Checkboxen beginnt auf's Neue. Bis die Abbruchbedingung sagt: "Bis hier hin und nicht weiter!".

Zum Schluss folgt noch die Einbindung der Funktion in das Dokument:

$(document).ready(function() {
  $("ul input[type=checkbox]").click(function() {
    checkParentBoxes($(this));
  });
});

Bei Fragen oder Anregungen freue ich mich über Kommentare.

Bildquelle: "Check list" von Fanginhoon bei sxc.hu

Schlüsselwörter zu diesem Beitrag

« Zurück

Hier schreibe ich,

Ich

Daniel Erlinger, als selbstständiger Webdesigner über die Themen Webdesign, Contao, Shopsysteme, Kreatives, Neues und alles, was sonst noch dazu passt.

Vernetzt

Twitter
Mister Wong
Contao Community

Einen Kommentar schreiben



Nutze Deinen Gravatar.


Bitte rechnen Sie 2 plus 1.