Donnerstag, 28. Juni 2007

Tutorial: Ajax (7)

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


Ajax-Beispiel: Formularüberprüfung

Einer der klassischen Anwendungsfälle für JavaScript ist das Prüfen von Anwendereingaben in Formularen, bevor das Formular abgesendet wird. So war es beispielsweise immer schon möglich, mittels JavaScript zu prüfen, ob in einem Feld ein numerischer Wert, eine Mailadresse mit gültigem Format oder ein realistisches Datum eingegeben wurde. Nicht möglich war es jedoch zu prüfen, ob etwa ein eingegebener Name, der in einer Datenbanktabelle auf dem Server eindeutig sein soll, dort bereits vorhanden ist oder nicht. Ajax kann diesen Fall lösen, und unser erstes kleines Beispiel zeigt wie.

HTML-Formular

Nehmen wir an, in einem Content Management System (CMS) können Anwender Templates anlegen und verwalten. Jedes Template erhält einen Namen, unter dem es auflistbar ist – beispielsweise beim Erstellen von Webseiten. Der Template-Name muss deshalb eindeutig sein. Im HTML-Formular notieren wir dazu neben dem Eingabefeld für den Template-Namen eine Schaltfläche mit der Beschriftung Prüfen:

<div><input type="text" name="template_name" id="template_name" 
       class="text" style="width:390px" accesskey="n"> 
<input type="button" name="check_name" 
       class="button" style="width: 96px" value="Prüfen" 
       onclick="ajaxCheckDBValue('templates', 'name', 'string', 
                document.getElementById('template_name').value, 
                'check_result', 0)"></div>
<div id="check_result"></div>

Den Rest des gedachten HTML-Formulars sparen wir uns, da er nichts zur Sache beiträgt. Das erste input-Element definiert ein einzeiliges Eingabefeld, das unter anderem ein id-Attribut mit dem Wert template_name erhält. Das zweite input-Element definiert die Schaltfläche mit value="Prüfen" (Beschriftungstext). Damit die Schaltfläche beim Anklicken etwas tut, erhält das Element einen Event-Handler onclick=. Der JavaScript-Code, der diesem Event-Handler zugewiesen wird, ist der Aufruf einer JavaScript-Funktion namens ajaxCheckDBValue(). Dieser Funktion werden folgende Parameter übergeben:

  • 'templates' ist der Name einer Datenbanktabelle, in der die Namen von Templates gespeichert werden.
  • 'name' ist der Name der Tabellenspalte, in der die Namen von Templates gespeichert werden.
  • 'string' markiert die Art, wie die Daten in MySQL zu behandeln sind. Als mögliche Angaben benötigt dieser Parameter nur die möglichen Werte 'string' und 'num'.
  • document.getElementById('template_name').value referenziert den aktuellen Eingabewert des ersten input-Elements.
  • 'check_result' referenziert das div-Element, das unterhalb der beiden input-Elemente notiert ist. Dort soll das Ergebnis der Prüfung ausgegeben werden.
  • 0 bedeutet: es soll kein Datensatz von der Gegenprüfung ausgeschlossen werden. Was dieser Wert genau bedeutet, werden wir noch genauer beschreiben.

JavaScript zur Steuerung

In dem HTML-Dokument mit dem zuvor beschriebenen Formularausschnitt muss in jedem Fall unser Ajax-Kernel (siehe (5): Ein einfacher Ajax-Kernel) eingebunden werden. Angenommen, wir haben den Code des Kernels in einer Datei namens ajax.js gespeichert, die im gleichen Verzeichnis liegt, kann diese Datei wie üblich zwischen <head> und </head> so eingebunden werden:

<script type="text/javascript" src="ajax.js"></script>

Der Einfachheit halber notieren wir die Funktion ajaxCheckDBValue() ebenfalls in der Datei ajax.js — beispielsweise unterhalb der beiden Funktionen des Kernels. Die Funktion besteht aus folgendem Code:

function ajaxCheckDBValue(DBTable, DBField, type, fieldValue, outputId, exclDBId) {
   if(!document.getElementById)
      return;
   if(fieldValue == "") {
 document.getElementById(output_id).innerHTML = 
         "<span class=\"errortext\">Keinen Wert angegeben!</span>";
 return;
   }
   scriptUrl = "http://localhost/ajax-test/checkDBValue.php";
   paramStr = "?table=" + DBTable + "&field=" + DBField + "&type=" + 
               type + "&value=" + encodeURIComponent(value) +
               "&excldbid=" + exclDBId;
   doHttpRequest(scriptUrl + paramStr, outputId);
}

Die Funktion erwartet fünf Parameter, die wir zuvor beim Aufruf der Funktion im HTML-Code bereits an einem Beispiel kennengelernt haben.

Zunächst überprüft die Funktion mit if(!document.getElementById), ob überhaupt die DOM-Schnittstelle zur Verfügung steht. Anschließend prüft sie, ob der übergebene Feldwert (Parameter fieldValue) überhaupt einen Wert hat. Falls der Benutzer in unserem Beispiel auf die Schaltfläche Prüfen klickt, ohne in dem Eingabefeld einen Wert eingegeben zu haben, können wir uns die Ajax-Verbindung nämlich sparen. In diesem Fall reagiert die Funktion mit der Ausgabe des Fehlers Keinen Wert angegeben. Die Ausgabe erfolgt dynamisch innerhalb des Formulars an der Stelle, an der auch die Ajax-Meldungen erscheinen sollen.

Sind diese Prüfunden überstanden, wird der Aufruf der Zentralfunktion doHttpRequest() des Ajax-Kernels vorbereitet (siehe siehe (5): Ein einfacher Ajax-Kernel). Der Funktion wird die URL eines serverseitigen Scripts übergeben sowie der id-Attributwert des HTML-Elements (outputId), in dem die serverseitig erzeugte Ergebnismeldung ausgegeben werden soll. Die URL des serverseitigen Scripts setzen wir zusammen aus der vollständigen HTTP-Adresse der Scriptdatei, gespeichert in scriptUrl, sowie einem GET-Parameterstring, gespeichert in paramStr. Über die GET-Parameter versorgen wir das serverseitige Script, ein PHP-Script, mit den nötigen Input-Daten. Alle Parameter, die unsere Funktion ajaxCheckDBValue() selbst erhalten hat, werden dabei an das serverseitige Script weitergegeben. Da der Feldwert, also die vom Anwender eingegebenen Daten (gespeichert in fieldValue) auch Zeichen enthalten können, die in einer URL-Adresse besondere Bedeutung haben, wenden wir die JavaScript-Standardfunktion encodeURIComponent() auf den Feldwert an. So wird der Feldwert URL-gerecht kodiert.

Zum Schluss wird die Ajax-Kernel-Funktion doHTTPRequest() mit den vorbereiteten Daten aufgerufen. Mehr ist nicht nötig. Die Ergebnismeldung wird vom serverseitigen Script erzeugt, und die Ajax-Kernel-Funktion sorgt dafür, dass sie an der gewünschten Stelle (nämlich im HTML-Element mit id-Attribut, das in outputId gespeichert ist) ausgegeben werden.

Serverseitige Verarbeitung

Wir nehmen für unser Beispiel an, dass es auf dem Server eine MySQL-Datenbank mit dem Namen cms gibt, zu der eine Tabelle namens templates gehört. In dieser Tabelle seien bislang folgende Daten gespeichert:

 +----+-------------+
 | id | name        |
 +----+-------------+
 |  1 | einspaltig  |
 |  2 | zweispaltig |
 |  3 | dreispaltig |
 +----+-------------+

Die id-Spalte speichert Autoincrement-Werte, wie sie in Datenbanktabellen häufig verwendet werden. In der Spalte name werden Template-Namen gespeichert. Diese Namen sollen tabellenweit eindeutig sein.

Unser serverseitiges PHP-Script checkDBValue.php, das in der Ajax-JavaScript-Funktion ajaxCheckDBValue() aufgerufen wird, hat also die Aufgabe, zu prüfen, ob der übergebene Wert, den der Benutzer im Feld eingegeben hat, in der Spalte name bereits vorhanden ist oder nicht.

Das PHP-Script hat in unserem Beispiel folgenden Code:

<?php

$dbh = mysql_connect("localhost", "dbuser", "dbpassword");
if(!$dbh)
   echo "<div>Keine Verbindung zum Datenbank-Management-System"; 
$sql = "USE cms";
$sqlResult = @mysql_query($sql, $dbh);
if(!$sqlResult)
   echo "<div>Keine Verbindung zur Datenbank</div>"; 
if(! isset($_GET['table']) or empty($_GET['table']))
   echo "<div>Keine Datenbanktabelle angegeben</div>";
if(! isset($_GET['field']) or empty($_GET['field']))
   echo "<div>Keinen Feldnamen angegeben</div>";
if(! isset($_GET['type']) or empty($_GET['type']))
   echo "<div>Keinen Feldtyp angegeben</div>";
if($_GET['type'] != "string" and $_GET['type'] != "num")
   echo "<div>Falschen Feldtyp angegeben</div>";
if(! isset($_GET['value']) or empty($_GET['value']))
   echo "<div>Keinen Wert angegeben</div>";
if(! isset($_GET['excldbid']))
   echo "<div>Keine Angabe zu auszuschließenden Datensätzen</div>";

if($_GET['type'] == "string")
   $fieldValue = "'" . $_GET['value'] . "'";
else
   $fieldValue = $_GET['value'];
$sql = "SELECT COUNT(*) AS count FROM " . $_GET['table'] ." WHERE " .
       $_GET['field'] . " = " . $fieldValue;
if((int) $_GET['excldbid'] > 0)
   $sql .= " AND id <> " . (int) $_GET['excldbid'];
$sqlResult = @mysql_query($sql, $dbh);
if(!$sqlResult) 
   echo "<div>Kein Datenbankergebnis</div>";
else {
   $res = mysql_fetch_array($sqlResult, MYSQL_ASSOC);
   if($res['count'] > 0)
       echo "<div><span class=\"warning\">Wert bereits vorhanden! 
             Bitte einen anderen Wert eingeben!</span></div>";
   else
       echo "<div>Der eingegebene Wert ist verfügbar</div>";
}

?>

Das Script baut zunächst mit der PHP-Funktion mysql_connect() eine Verbindung zum MySQL-System des Servers auf. Die dabei übergebenen Parameter sind natürlich in einer anderen Umgebung entsprechend anzupassen. Anschließend wird das SQL-Statement USE cms an MySQL gesendet, um die gewünschte Datenbank auszuwählen.

Daran anschließend überprüft das Script seine per GET-Parameter erhaltenen Daten. Fehlen übergebene Parameter oder enthalten sie keine oder ungültige Werte, wird mit echo eine entsprechende Fehlermeldung ausgegeben. Alles, was das Script übrigens mit echo ausgibt, wird von Ajax verarbeitet und wie definiert in der aktuell angezeigten Webseite dynamisch eingeblendet.

In der zweiten Hälfte baut das Script dann das SQL-Statement der eigentlichen Prüfabfrage zusammen. Mit SELECT count(*) ... wird ein Statement erzeugt, bei dem MySQL als Ergebnis nur die Anzahl der Datensätze (Tabellenzeilen) zurückliefert, auf die die formulierte WHERE-Klausel zutrifft.

Falls der GET-Parameter excldbid einen Wert größer 0 hat, wird die WHERE-Klausel dahingehend erweitert, dass der Datensatz, bei dem die Spalte id den Wert von excldbid hat, nicht mit berücksichtigt wird. Warum das? Ganz einfach: angenommen, das HTML-Formular, welches den Ajax-Request auslöst, ist ein Formular, in dem Daten eines bestehenden Templates geändert werden. In diesem Fall ist der vorbelegte Feldwert in der Datenbank natürlich schon vorhanden. Ein Klick auf Prüfen würde aus eben diesem Grund das für den Benutzer verwirrende Ergebnis Wert bereits vorhanden! Bitte einen anderen Wert eingeben! erzeugen. Um dies zu verhindern, kann beim Ändern eines bestehenden Datensatzes dessen id-Wert im Parameter excldbid übergeben werden.

Das PHP-Script kann seine Arbeit beenden, wenn das MySQL-Ergebnis vorliegt. Wurden mehr als 0 Datensätze gefunden, ist der Wert nicht mehr verfügbar. Entsprechende Meldungen werden mit echo ausgegeben und vom Ajax-JavaScript in die Webseite eingefügt.

Alle Quelltexte dieses Beispiels einschließlich komplettem HTML-Dokument und MySQL-create-Daten können Sie als ZIP-Datei downloaden.


0 Comments:

 

Get Free Shots from Snap.com