Baumansicht und Schieberegler mit AjaxWeb-2.0-Controls
Pro & Contra: Baumansichten
Baumansicht und Schieberegler mit Ajax
Der Sinn der meisten Web-Anwendungen besteht in der Verwaltung unterschiedlich gearteter Daten. Bugtracker verwalten Fehlerbeschreibungen, Projektmanagementsoftware Aufgaben und Projektmitglieder. Die Liste lässt sich beliebig erweitern. Damit der Benutzer bei einer größeren Datenmenge nicht den Überblick verliert, werden diese Daten in der Regel kategorisiert. Viele Anwendungen setzen dazu Baumansichten ein. Diese haben den Vorteil, dass beliebige Bereiche auf- und zugeklappt werden können, je nachdem, welche Daten gerade benötigt werden.
Der Nachteil einer Treeview war jedoch bisher immer, dass bei einer stark hierarchisierten Datenhaltung mit vielen Daten mit langen Ladezeiten zu rechnen war. Der Grund liegt auf der Hand. Um die Treeview rein auf Browserseite mit Javascript zu verwalten, müssen alle notwendigen Daten aus der Datenbank geladen und in Javascript-Quellcode umgesetzt werden – ein nicht zu unterschätzender Zeitaufwand. Einmal mehr lässt sich dieses Problem hervorragend mit Ajax-Mitteln beheben. Wie bereits in den vorangegangenen Ausgaben gezeigt, ist das Nachladen von Daten zum Zeitpunkt ihrer Verwendung eine Stärke von Ajax.
Baumansicht mit Yahoo-Widget
Baumansicht und Schieberegler mit Ajax
Glücklicherweise gibt es bereits vorgefertigte Komponenten, die frei verfügbar sind und die einen Großteil der Arbeit erledigen. Für die Baumansicht kommt für das folgende Beispiel eine Komponente des Yahoo-UI-Projekts zum Einsatz (developer.yahoo.com/yui/treeview). Sie ist ein Bestandteil des vor kurzem freigegebenen Javascript-Frameworks, das von Yahoo zur Entwicklung von Web-Anwendungen wie dem neuen Yahoo Mail verwendet wird. Die Tree-Komponente bietet ausreichende Funktionen für die meisten Anwendungen und funktioniert mit einer Vielzahl von Browsern.
Die Verwendung mit und ohne Ajax-Anbindung ist außerdem sehr einfach. Das folgende Listing zeigt den Einsatz des Yahoo-Tree-Controls ohne die Zuhilfenahme von Ajax-Techniken.
var tree;
function init() {
tree = new YAHOO.widget.TreeView("divt");
var rootNode = tree.getRoot();
var node = new YAHOO.widget.TextNode ("Kategorie 1", root, false);
tree.draw();
}
Dieses kurze Stück Code genügt, um eine funktionierende Baumdarstellung mit einem Unterknoten zu erzeugen. Weitere Knoten und Unterknoten lassen sich mit new YAHOO.widget.TextNode einfügen. Die Funktion init() muss nur noch im Body-Onload-Event aufgerufen werden, damit die Baumansicht gleich nach dem Laden der Seite zur Verfügung steht. Nun geht es an den Einsatz von Ajax. Das Ziel, dass die Unterknoten erst dann geladen werden, wenn der übergeordnete Knoten geöffnet wird, ist mit dem Yahoo-Control einfach zu realisieren. Die Zeile
tree.setDynamicLoad(loadNodeData);
aktiviert das dynamische Nachladen der Unterknoten. Die Funktion loadNodeData wird immer dann aufgerufen, wenn ein bislang noch nicht aufgerufener Knoten geöffnet wird. Diese Funktion kümmert sich nun darum, dass die Daten vom Server geladen und anschließend in Tree-Nodes umgesetzt werden. Ein Aufruf der übergebenen Callback-Funktion sorgt dafür, dass die Daten auch übernommen werden. Erst anschließend sind die neu eingefügten Unterknoten sichtbar. Der normale Aufbau der Funktion würde dann wie folgt aussehen:
function loadNodeData(node, cb_complete) {
var id= node.data.id;
//--- Unterknoten nachladen und in Nodes umsetzen
//--- Neuaufbau des Baumes veranlassen
cb_complete();
}
Ajax-Stolperstein
Baumansicht und Schieberegler mit Ajax
Leider kommt Ihnen hier die asynchrone Verarbeitung von Ajax etwas in die Quere. Das heißt, die Callback-Funktion kann nicht aufgerufen werden, da die Daten noch gar nicht fertig geladen sind. Der Aufruf der Tree-Callback-Funktion kann also erst in der Daten-Callback-Funktion von Ajax erfolgen und muss somit irgendwo zwischengespeichert werden.
arrCallbacks = new Array();
function loadNodeData(node, cb_complete) {
var id= node.data.id;
arrCallbacks[id] = cb_complete;
new Ajax.Request('load_subnode.php',
{parameters:"parent="+id, onComplete: cb_dtate} );
}
function cb_data(result) {
for (i=1; i < result.length; i++) {
//--- Umsetzung in Unterknoten
new YAHOO.widget.TextNode(...);
}
eval(arrCallbacks[result[0]]+"();");
}
Die Yahoo-Tree-Komponente bietet noch eine Unmenge an Möglichkeiten, die den Rahmen dieses Artikels bei Weitem sprengen würden. So lassen sich beispielsweise die Knoten mit Icons und auch Checkboxen versehen oder das Verhalten der Knoten beim Anklicken verändern.
Ajax mal synchron
Baumansicht und Schieberegler mit Ajax
Das A von Ajax steht bekanntlich für die asynchrone Verarbeitung der Daten. Das bedeutet, dass die aufrufende Funktion nicht auf die Ergebnisse der Serverseite wartet, sondern der darauf folgende Quellcode weiter abgearbeitet wird. Das führt zu teilweise kuriosen Konstrukten, wie es auch beim Ajax-Beispiel weiter oben der Fall ist. Mit der populären Javascript-Bibliothek Prototype (prototype.conio.net) sind neben den normalen asynchronen Ajax-Zugriffen auch synchrone möglich. Man spricht hier von Ajax ohne A.
Während Ajax auf Callback-Funktionen angewiesen ist, die aufgerufen werden, wenn der Zugriff auf dem Server verarbeitet wurde, wird bei der synchronen Verarbeitung der Quellcode nach dem Ajax-Funktionsaufruf erst weiter verarbeitet, wenn ein Ergebnis vom Server vorliegt. Die folgenden Listings zeigen den Unterschied. Die asynchrone Verarbeitung funktioniert mit der angesprochenen Callback-Funktion. Die Reihenfolge der Alert-Boxen wäre also 1 und anschließend 2.
//--- asynchrone Verarbeitung
new Ajax.Updater("response", "data.php", {parameters:"id=13", onComplete: cb_ajax});
alert('1');
function cb_ajax(transport) {
alert("2");
}
Bei der synchronen Verarbeitung gibt es keine Callback-Funktion. Die Verarbeitung der auf den Ajax-Aufruf folgenden Quellcodezeilen erfolgt erst, wenn die Ergebnisse vom Server vorliegen:
//--- synchrone Verarbeitung
var ajax=new Ajax.Updater("response", "data.php", {parameters: "id=13",
asynchronous: false});
ajax.updateContent();
alert("Verarbeitung beendet");
Mit der synchronen Verarbeitung der Daten wird der Quellcode für das Nachladen der Unterknoten einfacher.
function loadNodeData(node, cb_complete) {
var id = node.data.id;
//--- Unterknoten per AJAX laden
var ajax=new Ajax.Updater("response", "subnodes.php", {parameters: "id="+id, asynchronous: false});
ajax.updateContent();
//--- Umsetzung in Unterknoten
new YAHOO.widget.TextNode(...);
//--- Neuaufbau des Knotens
cb_complete();
}
Big Brother is watching you
Baumansicht und Schieberegler mit Ajax
Das dem Web zu Grunde liegende HTTP-Protokoll ist zustandslos. Das bedeutet, dass keine Verbindung mehr zwischen Client und Server existiert, nachdem die Seite an den Browser übertragen wurde. Was normalerweise positiv ist, kann für manche Einsatzzwecke auch von Nachteil sein. Angenommen, ein Server, auf dem eine Suchmaschine läuft, soll mit einem Web-Interface ausgestattet werden, das es dem Benutzer erlaubt, die Volltextindizierung über den Browser zu starten. Dieser Prozess kann je nach Anzahl der Dokumente sehr lange dauern – teilweise Stunden. Für den Benutzer der Web-Oberfläche ist es somit nicht ersichtlich, ob die Indizierung noch läuft oder bereits abgeschlossen ist. Viele solcher Web-Interfaces behelfen sich damit, dass die Seite immer wieder neu geladen wird, um auf der Serverseite per PHP-Skript zu prüfen, ob der lange laufende Prozess noch aktiv ist.
Auch diese Anwendung ist wieder ein Beispiel dafür, wie Ajax sinnvoll verwendet werden kann. Das Vorgehen ist einfach: In regelmäßigen Abständen wird per Ajax eine Funktion auf dem Server aufgerufen. Dies geschieht am besten mit der Funktion window.setTimeout. So ist sichergestellt, dass die Oberfläche der Web-Anwendung sich selbst aktuell hält, ohne dass die Seite neu geladen wird. Die Funktion verwendet das Framework Prototype für die Ajax-Aufrufe.
function updateState() {
new Ajax.Request('process_state.php', {onComplete: cbState} );
//--- Aufruf alle 5 Sekunden
window.setTimeout('updateState()',5000);
}
function cb_state(result) {
//--- Umsetzung in HTML und Ausgabe in DIV
}
Die per Ajax auf der Serverseite aufgerufenen PHP-Skripts können überprüfen, ob der zu überwachende Prozess noch läuft oder nicht. Je nach Status wird das Ergebnis per Ajax an den Browser zurückgegeben und dort für den Benutzer optisch aufbereitet.
Tricksen mit PHP
Baumansicht und Schieberegler mit Ajax
Da PHP auf Grund seines Funktionsumfangs nicht dazu geeignet ist, Prozesse auf Betriebssystem-Ebene zu überwachen, greifen Sie zu einem kleinen Trick, der auf Unix-Systemen gang und gäbe ist. Viele Anwendungen schreiben hierfür eine Datei, wenn sie gestartet werden, und löschen diese beim Beenden wieder (zum Beispiel httpd.pid des Apache Webservers). Ist dies beim zu überwachenden Prozess nicht der Fall, so muss der Umweg über ein Start-Skript gewählt werden.
Die folgende Windows-Batch-Datei zeigt das generelle Vorgehen.
del process_lock.txt
echo 1 > process_lock.txt
prozess.exe index
del process_lock.txt
exit
Die so erzeugte Datei process_lock.txt kann im Ajax-Skript einfach mit der PHP-Funktion file_exists abgefragt werden. Existiert sie, so ist der Prozess noch aktiv, ansonsten nicht.
Schieberegler
Baumansicht und Schieberegler mit Ajax
Schieberegler sind bei Desktop-Anwendungen oft anzutreffen, in Web-Anwendungen aber eher selten. Der Grund dafür ist, dass die Programmierung solcher Controls bislang sehr aufwendig war. Mit dem Aufkommen von Javascript-Frameworks wie Yahoo UI oder Scriptacolous gehört dieses Problem der Vergangenheit an. Viele dieser Frameworks bieten fix und fertige Lösungen, die sehr einfach eingesetzt werden können.
Das folgende Listing zeigt den Aufbau eines Schiebereglers mit dem Yahoo-UI-Framework (developer.yahoo.com/yui/slider).
var slider;
function init() {
slider=YAHOO.widget.Slider.getHorizSlider ("sbg", "sthmb", 0, 100);
}
Dieser Quellcode wandelt einen HTML-Bereich in einen horizontalen Schieberegler um. Dazu muss dieser HTML-Code allerdings einen bestimmten Aufbau besitzen, der den folgenden Quellcode-Zeilen entspricht:

Das Aussehen des Reglers lässt sich vielfältig beeinflussen, entweder per CSS über die ID des div-Bereichs oder zum Beispiel auch über die Auswahl der Grafik für den zu verschiebenden Pfeil.
Wird an Stelle der Funktion getHorizSlider einfach die Methode getVertSlider aufgerufen, erhalten Sie statt eines horizontalen Reglers einen vertikalen.
Einraster
Baumansicht und Schieberegler mit Ajax
Neben dem Aussehen lässt sich auch das Verhalten beeinflussen. Mit so genannten Tick-Marks lassen Sie den Schieberegler immer nur an bestimmten Punkten einrasten und verhindern somit die Auswahl von ungültigen Werten. Dazu muss bei der Initialisierung des Sliders nur ein zusätzlicher Wert an die Funktion getHorizSlider oder getVertSlider übergeben werden.
Ein Aufruf der Funktion mit den folgenden Parametern
slider=YAHOO.widget.Slider.getHorizSlider("sbg", "sthmb", -500, 1000, 100);
erzeugt einen vertikalen Slider mit dem Wertebereich zwischen -500 und 1000 und erlaubt nur die Auswahl von Werten in den vorgegebenen Hunderterschritten.
Auch Schieberegler lassen sich mit Ajax verwenden. So ist es denkbar, die Werte nach ihrer Änderung per Ajax an den Server zu übertragen und zu speichern. Dazu lassen sich vom Control implementierte Event-Handler wie onChange verwenden, die aufgerufen werden, wenn der Schieberegler neu positioniert wurde.
slider.onChange= function(offsetFromStart) {
//--- Speicherung per AJAX
}
Fazit
Baumansicht und Schieberegler mit Ajax
Mit den vorgestellten Mitteln vereinfachen und erweitern Sie die Bedienoberfläche von Web-Anwendungen und gestalten sie für Ihre Besucher komfortabler und benutzerfreundlicher.
Neben dem umfangreichen Yahoo-Framework existieren noch etliche weitere Bibliotheken wie das geniale Prototype, auf das die Redaktion im nächsten Heft in einem weiteren Beitrag zurückkommt. Es finden sich auch einige Spezialisten für die Ajax-orientierte Umsetzung von Tree-Controls. Allerdings sind diese oftmals kostenpflichtig, so dass ein Einsatz nicht immer sinnvoll ist.