Tutorial: Ajax (8)
siehe auch:
(1): Was ist Ajax?
(2): Warum heißt Ajax so? Wo kann ich Ajax in Aktion sehen?
(3): Worin besteht die Ajax-Schnittstelle? Wie wird Ajax standardisiert?
(4): Welche Nachteile hat Ajax? Wie sicher ist Ajax?
(5): Ein einfacher Ajax-Kernel
(6): Eigenschaften und Methoden des XMLHTTPRequest-Objekts
(7): Ajax-Beispiel: Formularüberprüfung
Ajax-Beispiel: Tabellensortierung
Das Sortieren von Tabellen ist zwar mit etwas Aufwand auch direkt in JavaScript möglich. Doch dabei lauern zahlreiche Tücken, beispielsweise, wenn zu sortierende Einträge zusätzlich in Links verpackt werden sollen. Wenn die Daten der Tabelle aus einer Datenbank kommen, bietet sich Ajax als Alternative an. Wie so etwas aussehen kann, beschreiben wir im nachfolgenden Beispiel.
Tabellarische Daten aus einer Datenbank
Für unser Beispiel greifen wir auf die MySQL-Datenbank mit dem Namen cms aus dem ersten Beispiel zurück. Wir nehmen eine Tabelle namens users an, in der zugangsberechtigte Benutzer gespeichert sind. Aktuell seien dort unter anderem folgende Daten gespeichert:
+----+-----------------------+-----------------+---------------------+ | id | index_name | group_name | last_login | +----+-----------------------+-----------------+---------------------+ | 1 | Lyse, Anna | developers | 2007-07-12 09:27:23 | | 2 | Wahnsinn, Reiner | editors | 2007-06-28 13:02:01 | | 3 | Dolegstdinieder GmbH | service-editors | 2007-06-28 13:56:39 | | 4 | Error, Erika | editors | 2007-07-08 10:03:56 | | 4 | Krieg, Frieda | admins | 2007-07-12 21:11:21 | +----+-----------------------+-----------------+---------------------+
Die id-Spalte speichert Autoincrement-Werte. Die Spalte index_name enthält die Namen der Benutzer in einer Darstellungsform, die für eine sinnvolle alphabetische Sortierung optimal ist. In group_name werden Benutzergruppen gespeichert, denen die Benutzer zugeordnet sind. In der Spalte last_login wird der Zeitpunkt des letzten Logins eines Benutzers in einer für die Sortierung brauchbaren Form gespeichert.
Serverseitig setzen wir wieder ein PHP-Script ein, das die Datenbankabfrage besorgt. Außerdem bereitet das Script die HTML-Tabelle auf. Im HTML-Dokument wird wieder unser Ajax-Kernel eingebunden. In der ajax.js notieren wir der Einfachheit halber auch die Funktion zum Steuern der Tabellensortierung.
Basis-Dokument (PHP)
Vom Server lassen wir zunächst eine PHP-Datei (nennen wir sie z.B. index.php) ausliefern:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="de">
<head>
<title>Test</title>
<script type="text/javascript" src="ajax.js"></script>
</head>
<body>
<h1>Benutzer</h1>
<div id="user_list">
<?php
include("./userSort.php");
?>
</div>
</body>
</html>
Das „Script“ besteht vorwiegend aus gewöhnlichem, statischem HTML-Code. Lediglich an einer Stelle im Code ist ein PHP-Bereich notiert. Dort wird das Script userSort.php eingebunden. Im HTML-Kopfbereich wird das externe JavaScript ajax.js eingebunden.
Das HTML-Dokument besteht im sichtbaren Bereich nur aus einer Überschrift und einem div-Bereich mit dem id-Namen user_list. Diesen id-Namen werden wir verwenden, um in den entsprechenden div-Bereich die sortierte Tabelle zu platzieren.
Bevor das HTML-Dokument an den aufrufenden Browser gesendet wird, wird auf dem Server der Inhalt des PHP-Bereichs () durch den HTML-Code ersetzt, den das mit include eingebundene PHP-Script userSort.php erzeugt. Sehen wir uns dieses Script deshalb als nächstes an.
Serverseitiges Sortier-Script (PHP)
Der Code des Scripts userSort.php lautet wie folgt:
<?php
$dbh = mysql_connect("localhost", "dbuser", "dbpassword");
if(!$dbh) {
echo "<div>Keine Verbindung zum Datenbank-Management-System";
exit();
}
$sql = "USE cms";
$sqlResult = @mysql_query($sql, $dbh);
if(!$sqlResult) {
echo "<div>Keine Verbindung zur Datenbank</div>";
exit();
}
if(! isset($_GET['field']) or
($_GET['field'] != "index_name" and $_GET['field'] != "group_name"
and $_GET['field'] != "last_login"))
$sortField = "index_name";
else
$sortField = $_GET['field'];
if(! isset($_GET['order']) or ($_GET['order'] != "asc" and $_GET['order'] != "desc"))
$sortOrder = "asc";
else
$sortOrder = $_GET['order'];
$data = array();
$sql = "SELECT * FROM users ORDER BY " . $sortField . " " . $sortOrder;
$sqlResult = @mysql_query($sql, $dbh);
if(!$sqlResult) {
echo "<div>Kein Datenbankergebnis</div>";
exit();
}
else
while($record = mysql_fetch_array($sqlResult, MYSQL_ASSOC))
$data[] = $record;
if(empty($data)) {
echo "<div>Die Tabelle enthält keine Daten</div>";
exit();
}
$tableHTML = "<table border=\"1\">\n";
$tableHTML .= "<tr>\n";
$tableHTML .= "<th class=\"tlist\">Name ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('index_name',
'asc', 'user_list')\">▲</a> ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('index_name',
'desc', 'user_list')\">▼</a>";
$tableHTML .= "</th>\n";
$tableHTML .= "<th class=\"tlist\">Benutzergruppe ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('group_name',
'asc', 'user_list')\">▲</a> ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('group_name',
'desc', 'user_list')\">▼</a>";
$tableHTML .= "</th>\n";
$tableHTML .= "<th class=\"tlist\">Letztes Login ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('last_login',
'asc', 'user_list')\">▲</a> ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('last_login',
'desc', 'user_list')\">▼</a>";
$tableHTML .= "</th>\n";
$tableHTML .= "</tr>\n";
$tableHTML .= "[%tableAllRows%]\n";
$tableHTML .= "</table>\n";
$tableRowHTML = "<tr>\n";
$tableRowHTML .= "<td><a href=\"?showUser.php?id=[%id%]\">[%index_name%]</a></td>\n";
$tableRowHTML .= "<td><a href=\"?showGroup.php?name=[%group_name%]\">[%group_name%]</a></td>\n";
$tableRowHTML .= "<td>[%last_login%]</td>\n";
$tableRowHTML .= "</tr>\n";
$tableAllRowsHTML = "";
foreach($data as $record) {
$recordHTML = $tableRowHTML;
$recordHTML = str_replace("[%index_name%]", $record['index_name'], $recordHTML);
$recordHTML = str_replace("[%group_name%]", $record['group_name'], $recordHTML);
$recordHTML = str_replace("[%last_login%]", $record['last_login'], $recordHTML);
$recordHTML = str_replace("[%id%]", $record['id'], $recordHTML);
$tableAllRowsHTML .= $recordHTML;
}
$tableHTML = str_replace("[%tableAllRows%]", $tableAllRowsHTML, $tableHTML);
echo $tableHTML;
?>
Das Script versucht zunächst eine Verbindung zu MySQL herzustellen. Im Fehlerfall gibt es eine entsprechende Meldung aus und wird beendet. Anschließend setzt es das SQL-Statement USE cms ab, um die CMS-Datenbank unseres Beispiels auszuwählen. Auch hier wird im Fehlerfall eine Meldung ausgegeben und das Script beendet.
Als nächstes wird geprüft, ob das Script mit GET-Parametern aufgerufen wurde. Denn über die GET-Parameter field und order erfährt das Script, nach welcher Tabellenspalte ($_GET['field']) und in welcher Sortierrichtung ($_GET['order']: aufsteigend = asc oder absteigend = desc) sortiert werden soll. Fehlen die GET-Parameter, werden Defaultwerte (Feld index_name und Sortierrichtung asc) festgesetzt. Genau das, also der Aufruf ohne GET-Parameter, geschieht beim ersten Aufruf des Scripts mit der include-Anweisung im Basis-Dokument, die wir weiter oben bereits beschrieben haben.
Nachdem die Parameterfrage geklärt ist, wird ein Array namens $data initialisiert. In diesem Array werden die Daten gespeichert, die MySQL liefern soll. Der Grund, weshalb wir für dieses Beispiel Ajax einsetzen, ist ja, dass wir MySQL die Sortierung der Daten überlassen. Deshalb bauen wir das SQL-Statement zur Abfrage der Tabelle users so zusammen, dass sich die gewünschte Sortierung ergibt:
$sql = "SELECT * FROM users ORDER BY " . $sortField . " " . $sortOrder;
Die Variablen $sortField und $sortOrder wurden ja zuvor mit den Werten der GET-Parameter field und order oder mit Default-Werten versorgt. Je nach übergebenen GET-Parametern können also SQL-Statements entstehen wie beispielsweise:
$sql = "SELECT * FROM users ORDER BY last_login desc";
MySQL liefert die Daten in der gewünschten Sortierreihenfolge aus. Falls ein Fehler auftritt, wird wieder eine Meldung ausgegeben, und das Script wird beendet. In einer while-Schleife werden die von MySQL gelieferten Datensätze in den Array $data eingelesen.
In der zweiten Hälfte des Scripts userSort.php wird der HTML-Code der auszugebenden Tabelle zusammengesetzt. In der Variablen $tableHTML wird zunächst das Grundgerüst der Ausgabetabelle gespeichert. An der Stelle, wo die Zeilen der Tabelle mit den auszugebenden Datensätzen stehen sollen, haben wir einen Platzhalter namens [%tableAllRows%] notiert, der später ersetzt wird. In der Variablen $tableRowHTML wird der HTML-Code einer einzelnen Tabellenzeile gespeichert. Auch dort arbeiten wir mit Platzhaltern der Marke Eigenbau, nämlich [%id%], [%index_name%], [%group_name%] und [%last_login%]. Dann wird die Variable $tableAllRowsHTML initialisiert. In einer foreach-Schleife wird nun der Array $data abgearbeitet. Bei jedem Schleifendurchlauf wächst der Inhalt der Variablen $tableAllRowsHTML um den Wert von $recordHTML. In $recordHTML wird jeweils eine frische Version von $tableRowHTML gespeichert. Dann werden die darin enthaltenen Platzhalter durch die tatsächlichen Daten des jeweils abgearbeiteten Datensatzes ersetzt. Am Ende muss dann nur noch in $tableHTML der Platzhalter [%tableAllRows%] durch $tableAllRowsHTML ersetzt werden. Die fertige HTML-Tabelle mit den sortierten Daten wird in einem Stück mit echo $tableHTML ausgegeben.
JavaScript zur Steuerung der Sortierung
Doch wie kommt nun die für den Anwender so komfortable Möglichkeit zustande, die Tabelle während der Anzeige im Browser zu sortieren? Dazu werfen wir einen Blick auf die Tabelle, die das Sortierscript ausgibt:

Im HTML-Code der ausgegebenen Tabelle sind neben den Spaltenüberschriften jeweils zwei Links notiert, die durch die Symbole ▲ und ▼ aus dem erweiterten Unicode-Bereich das Sortieren der Tabelle nach der jeweilgen Spalte in der jeweiligen Sortierrichtung ermöglichen. Jeder dieser Links definiert einen JavaScript-Aufruf, zum Beispiel:
<a href="javascript:ajaxUserSort('index_name', 'asc', 'user_list')\">▲</a>
Es wird eine JavaScript-Funktion namens ajaxUserSort() aufgerufen. Dieser Funktion werden drei Parameter übergeben. Der erste Parameter ist der Datenbankname der Tabellenspalte, nach der sortiert werden soll. Der zweite Parameter bestimmt die Sortierrichtung, und der dritte Parameter gibt den id-Namen des HTML-Elements an, als dessen Inhalt die fertig erzeugte Tabelle eingefügt werden soll. Im obigen Beispielaufruf soll also nach der Tabellenspalte index_name (= „Name“) aufsteigend (asc) sortiert werden. Das Ergebnis soll als Inhalt des Elements mit dem id-Namen user_list ausgegeben werden.
Die Funktion ajaxUserSort notieren wir der Einfachheit halber wieder in ajax.js, wo auch der Code des Ajax-Kernels notiert ist. Der Code dieser Funktion lautet:
function ajaxUserSort(sortField, sortOrder, outputId) {
if(!document.getElementById)
return;
if(sortOrder != "asc" && sortOrder != "desc") {
document.getElementById(output_id).innerHTML =
"<span class=\"errortext\">Ungültige Angabe zur Sortier-Richtung!</span>";
return;
}
scriptUrl = "http://localhost/ajax-test/userSort.php";
paramStr = "?field=" + sortField + "&order=" + sortOrder;
doHttpRequest(scriptUrl + paramStr, outputId);
}
Die Funktion prüft zunächst, ob die DOM-Methode getElementById verfügbar ist. Falls nicht, kann das Script gleich abgebrochen werden. Als nächstes wird geprüft, ob der Parameterwert für die Sortierrichtung entweder asc (für aufsteigend) oder desc (für absteigend) lautet. Abschließend wird der Aufruf des Scripts zusammengesetzt, und die Ajax-Kernel-Funktion doHTTPRequest() wird aufgerufen. Der Parameter outputId, der den id-Namen des Ausgabeelements enthält, wird an diese Funktion weitergereicht. Der Ajax-Kernel besorgt den Aufruf des Scripts userSort.php und gibt die fertig sortierte Tabelle an der gewünschten Stelle im Dokument aus.
Alle Quelltexte dieses Beispiels einschließlich komplettem HTML-Dokument und MySQL-create-Daten können Sie als ZIP-Datei downloaden.

0 Comments: