Ajax ist Teil vieler Webanwendungen und vereint eine Menge von Protokollen, Sprachen und Formaten. Es gilt als Sammelbegriff dafür, dynamisch eine geladene Webseite direkt im Browser umzuorganisieren. Kleine Codestücke in Javascript greifen auf das Document-Object-Model (DOM) zu, formatieren HTML-Elemente per CSS oder laden neue Inhalte über HTTP mittels »XML-HttpRequest«-Objekten nach. Eine Reihe von Ajax-Funktionen dienen primär der Optik und der Präsentation der Inhalte. Daher steht der Web-2.0-Ansatz oft im Ruf, aufgedunsen und schwer überschaubar zu sein.
Dabei gibt es eine Reihe nützlicher Funktionen, die clientseitige Aufgaben übernehmen, die zwar auch ein Server erledigen kann, der aber dazu oft nicht schnell genug reagiert. Als Beispiel hält eine Liste her, deren Elemente der Anwender mit der Maus im Browser neu anordnet. Dazu sind keine HTTP-Requests an den Server notwendig. Aufgrund der Vielfalt an Browsern und wegen unterschiedlicher Ausrichtung auf einen Einsatzzweck, hat der Webentwickler die quälende Auswahl zwischen einem guten Dutzend Toolkits und Bibliotheken. Wer sich einmal für eines entscheidet, bindet sich und seinen Code oft daran. Daher will die Entscheidung wohldurchdacht sein.
Solide Grundlage
Kaum zwei Frameworks sind deckungsgleich in ihrem Umfang oder ihrer Ausrichtung: Die Entwickler des Frameworks Scriptaculous legen den Fokus auf Animation und Drag-and-Drop, Dojo kommt mit drei Varianten für Grundfunktionen (Core), Widgets (Dijit) sowie Tabellen und Grafiken (Dojo X) daher. Die Yahoo Interface Library (YIL) bietet Funktionen für die Benutzerschnittstelle und legt Wert auf die Wartbarkeit und Updates dieser Komponenten.
Alle drei Kandidaten sollen eine Liste von Utensilien eines Reisekoffers lokal und ohne Zutun eines Webservers umsortieren. Dies geschieht per Drag-and-Drop, also per Nutzerinteraktion. Die Liste liegt als »ul«-Container in HTML vor und könnte initial von PHP erzeugt sein (siehe Listing 1). In der Praxis handelt es sich natürlich nicht um Kofferinhalte wie im Spiel "Ich packe meinen Koffer", sondern beispielsweise um Bilder einer Galerie oder Aufgaben in einer Taskplanungssoftware.
01 <p>Meine Koffer:</p>
02 <ul id='bag01'>
03 <li id='item01_1'>Buch</li>
04 <li id='item01_2'>Hemd</li>
05 <li id='item01_3'>Zahncreme</li>
06 <li id='item01_4'>Fotos</li>
07 </ul>
08
09 <ul id='bag02'>
10 <li id='item02_1'>Hose</li>
11 <li id='item02_2'>Laptop</li>
12 <li id='item02_3'>Wecker</li>
13 <li id='item02_4'>T-Shirt</li>
14 </ul>
|
Wer das von Hand schreiben wollte, stellt sich mit der Implementation des Drag-and-Drop-Teil einer Herausforderung. Das auch noch browserübergreifend zu implementieren, wäre eine Qual. Die Codefragmente lassen sich lokal und ohne Webserver ausprobieren. Im realen Umfeld würden die Applets ihren Status nach dem Umordnen natürlich zurück an den Server übertragen.
Scriptaculous
Der erste Blick gilt dem Toolkit Scriptaculous, das seinen Namen gleich kreativ für die eigene URL verwendet [1]. Es ist Spezialist für Animationen, Drag-and-Drop und vorgefertigte Ajax-Controls. Den DOM- und Javascript-Part überlässt es der zugrundel iegenden Bibliothek Prototype [2]. Sie kapselt eine Reihe von browserabhängigen Verhaltensweisen und stellt mächtige Objekte und Methoden zur Verfügung, die dem Programmierer ebenso wie den eigentlichen Toolkits das Leben deutlich vereinfachen (siehe Abbildung 1).
Abbildung 1: Die Webseite von Scriptaculous zeigt die Möglichkeiten der Animationskomponenten.
Das Paket erfordert einen Download, bringt dabei aber schon die Prototype-Bibliothek mit. Scriptaculous baute darauf auf. Das Toolkit lässt sich denkbar einfach einrichten: Der Entwickler legt das Paket im Unterverzeichnis »scripts/« an und verlinkt es im »head«-Bereich der Webseite:
<script src="scripts/lib/prototype.js"
type="text/javascript"></script>
<script src="scripts/src/scriptaculous.js"
type="text/javascript"></script>
Der Code lädt zuerst Prototype als Grundlage aus dem Verzeichnis »scripts/lib/«, danach die erweiterten Funktionen von Scriptaculous aus dem Verzeichnis »scripts/src/«. Wer nicht alle Funktionen benötigt, darf den Aufruf der Bibliothek »scriptacolous.js« um einen Parameter erweitern und aus den möglichen Paketen »builder«, »effects«, »dragdrop«, »controls« und »slider« auswählen. Das spart Ladezeit. Die Pakete »dragdrop« und »slider« lassen sich beispielsweise mit
<script src="scripts/src/scriptaculous.js?load=dragdrop,slider"
type="text/javascript"></script>
laden. Alle anderen ignoriert die Bibliothek. Die Kofferinhalte aus Listing 1 stellt der Entwickler als zwei unsortierte Listen mit den HTML-Tags »ul« und »li« dar. Sie stehen für die zwei Koffer, die der Nutzer gepackt hat. Allerdings soll er nun in der Lage sein, zwischen den Koffern noch einzelne Gegenstände auszutauschen. Dazu benötigen die Listen ebenso wie die einzelnen Elemente eindeutige IDs. Das Framework fordert hier eine Konvention in der Namensgebung: Die IDs der einzelnen Elemente trennt der Entwickler durch einen Unterstrich vom restlichen Namen ab. Die ID »item021« würde also ohne weitere Konfiguration (siehe »format« in Tabelle 1) nicht funktionieren, die ID »item02_1« tut es.
|
|
|
Option
|
Funktion
|
|
»tag«
|
Sind die zu sortierenden Elemente keine Listenelemente
»li«, so ist dies mit dem Parameter »tag« zu ändern, zum Beispiel »tag: div«.
|
|
»format«
|
Regular Expressions ändern die Namenskonvention der zu
sortierenden Elemente. Die Voreinstellung ist »/^[^_-](?:[A-Za-z0-9-_]*)[_](.*)$/«.
|
|
»onUpdate«
|
Ruft nach abgeschlossenem Verschieben eines Elements eine
Callback-Funktion auf, die beispielsweise den neuen Zustand speichert.
|
Anschließend folgt ein Javascript-Block im Quellcode unterhalb der Listen. Der Browser interpretiert den Quellcode der Seite Zeile für Zeile. Daher läuft Javascript ins Leere, wenn die referenzierte Elemente noch nicht in der DOM-Struktur enthalten sind. Alternativ könnte der Entwickler den Code auch erst beim Laden mit dem »onload«-Ereignis der Seite ausführen lassen.
Für das Beispiel stellt Scriptaculous eine spezielle Gruppe von Funktion zur Verfügung. Diese Gruppe ist unter dem Begriff »Sortable« zusammengefasst. Das Array »bagList« definiert in Listing 2 die beiden Listen. Die Funktion »Sortable.create()« macht eine existierenden Liste sortierbar. Dabei steht der erste Parameter für die ID der Liste, der zweite ermöglicht, verschiedene Optionen anzugeben. Damit der Anwender die Elemente zwischen den beiden Listen austauschen kann, benötigt der Code die Angabe der Option »containment«, der ab Zeile 5 als Wert den Inhalt des Arrays »bagList« benötigt. Die Funktion »Sortable.create()« kennt zusätzlich die in Tabelle 1 aufgeführten Optionen. Als durchaus überschaubares Ergebnis des Codes erhält der Anwender eine Liste mit Drag-and-Drop-Funktionalität (siehe Abbildung 2).
01 <script language="javascript"
02 type="application/javascript">
03 bagList = new Array("bag01", "bag02");
04
05 Sortable.create('bag01', {containment: bagList});
06 Sortable.create('bag02', {containment: bagList});
07 </script>
|
Abbildung 2: Der knappe Scriptaculous-Code von nur neun Zeilen Code lässt den Anwender die einzelnen Listenelemente mit der Maus umordnen.