Posts mit dem Label XMLHttpRequest werden angezeigt. Alle Posts anzeigen
Posts mit dem Label XMLHttpRequest werden angezeigt. Alle Posts anzeigen

Dienstag, 17. Juli 2007

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')\">&#x25B2;</a> ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('index_name', 
                                         'desc', 'user_list')\">&#x25BC;</a>";
$tableHTML .= "</th>\n";
$tableHTML .= "<th class=\"tlist\">Benutzergruppe ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('group_name', 
                                         'asc', 'user_list')\">&#x25B2;</a> ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('group_name', 
                                         'desc', 'user_list')\">&#x25BC;</a>";
$tableHTML .= "</th>\n";
$tableHTML .= "<th class=\"tlist\">Letztes Login ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('last_login', 
                                         'asc', 'user_list')\">&#x25B2;</a> ";
$tableHTML .= "<a href=\"javascript:ajaxUserSort('last_login', 
                                         'desc', 'user_list')\">&#x25BC;</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:

sortierte Tabelle

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')\">&#x25B2;</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.


Mittwoch, 20. Juni 2007

Mozilla meets SELFHTML and Webkompetenz

Die PR-Agentur Arcendo hatte geladen, und die geladenen Gäste erschienen. Zusammengebracht werden sollten namhafte Vertreter von Mozilla Europe und vom Webprojekt SELFHTML. Keine schlechte Wahl, denn schließlich verzeichnen die Browser mit der Gecko-Engine in den Juni-2007-Statistiken von SELFHTML als Netscape getarnt eine satte Führungsrolle, und auch die Leser des Webkompetenz-Forums verwenden Mozilla-Browser, vor allem natürlich Firefox, zu über 50%. Nun bin ich ja eigentlich kein Vertreter von SELFHTML mehr, doch da der Event in den Räumen von Arcendo in München Haidhausen stattfand, fragte Thomas J. Sebestyen mich, ob ich dabei sein möchte.

Wir trafen auf keine Geringeren als auf den Kanadier Mike Shaver, ehemaliger Netscape-Mitarbeiter und Mitbegründer des Mozilla-Projekts, sowie auf den Franzosen Tristan Nitot, Präsident von Mozilla Europe. Die beiden sind derzeit auf einer PR-Tour, in der es um Themen geht, die uns allen wichtig sein sollten: um ein offenes, für alle zugängliches und für alle mitgestaltbares Web, damit einhergehend natürlich um OpenSource, um offene Kritik an bestehenden Webstandards sowie um die Frage, wie gefährlich jüngere Versuche kommerzieller Software-Firmen sind, dem Web neue, proprietäre Stempel aufzudrücken — vor allem sind damit Microsoft Silverlight und Adobe AIR gemeint.

Die knappe Zeit von etwas weniger als zwei Stunden reichte natürlich nicht aus, um über all diese Themen erschöpfend zu reden. Es wurde jedoch deutlich, dass die Mozilla-Leute die gegenwärtige technische Infrastruktur des Web, bestehend aus W3C-Standards, einem ECMA-Standard und einem breitgefächerten OpenSource-Angebot für die Server-Seite für ein sehr produktives Gespann hält, das es zu schützen und natürlich auch weiterzuentwickeln gilt, das aber auch noch Lücken hat. Es wurde festgestellt, dass sich das Web von einem ursprünglich dokument-orientierten Charakter hin zu einem multiplen Medium wandelt, das einerseits nach wie vor zahllose „Dokumente“, also textorientierte Informationen enthält, aber mittlerweile auch immer mehr Applikationen, also desktop-artige Anwendungen, die den Benutzern ermöglichen, persönliche oder Team-Daten im Web zu verwalten und zu verarbeiten, sowie immer mehr Multimedia. Vor allem bei diesen neuen Realitäten des Web fehlt es aber noch an der Dominanz und Präsenz offener Standards. Im Applikations-Sektor, der gerade erst so richtig zu boomen beginnt, stehen Microsoft, Adobe und einige andere kommerzielle Anbieter hächelnd in den Startlöchern. Das W3-Konsortium hat zwar applikations-relevante Spezifikationen wie das Document Object Model (DOM) oder die XMLHttpRequest-Schnittstelle (= Ajax) unter seinen Fittichen, doch das allein genügt nicht, um für den künftigen Markt der desktop-artigen Webanwendungen gerüstet zu sein. Und im Multimedia-Sektor hat Flash längst so deutlich das Rennen gemacht, dass es nur noch über die eigenen Füße stolpern könnte. W3C-Standards wie SVG oder SMIL wurden einfach nicht angenommern.

So betrachtet wird also nachvollziehbar, welchen tieferen Sinn der gegenwärtige PR-Feldzug von Mozilla hat: gerade jener Bereich des Web, der gerne als Web 2.0 bezeichnet wird (der Ausdruck ist in den ganzen zwei Stunden des Meetings übrigens höchstens ein oder zweimal gefallen ;-), eröffnet neue zu besetzende Felder. Und es wäre schade, wenn wir am Ende für mehr als die Hälfte aller Web-Inhalte Browser-Plugins benötigen, weil dahinter proprietäre Closed-Source-Technologien stecken, die sich durchgesetzt haben. Alles in allem also ein sehr interessantes Gespräch mit zwei führenden Köpfen der OpenSource-Welt, an dessen Ende es noch ein paar Merchandizing-Geschenke gab, die auch bei meinen Kleinsten gut ankamen:


Amos und Joshua „firefoxing“

Partner-Eintrag zu diesem Eintrag im SELFHTML Weblog:
Die Zukunft des Open-Webs: SELFHTML im Gespräch mit Mozilla


Donnerstag, 7. Juni 2007

Tutorial: Ajax (6)

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


Eigenschaften und Methoden des XMLHTTPRequest-Objekts

Das XML-HTTP-Objekt verfügt entsprechend der Spezifikation des W3-Konsortiums über folgende Eigenschaften und Methoden:

Eigenschaft: onreadystatechange

Genaugenommen ist dies ein Event-Handler, dem beliebiger JavaScript-Code zugeordnet werden kann, beispielsweise ein Funktionsaufruf: onreadystatechange = tuWas();

Das Ereignis dieses Event-Handler wird immer dann ausgelöst, wenn sich der Verbindungsstatus einer zuvor abgesetzten HTTP-Anfrage ändert. Bei jedem Auslösen des Ereignisses nimmt die Objekteigenschaft readyState einen anderen Wert an.

Eigenschaft: readyState

Diese Eigenschaft speichert den aktuellen Verbindungsstatus einer zuvor abgesetzten HTTP-Anfrage, und zwar in Form einer Zahl. Folgende Werte sind möglich:

0 (oder Konstante: UNINITIALIZED):
Diesen Wert hat die Eigenschaft, bevor die Methode open() aufgerufen wurde, die eine HTTP-Anfrage einleitet.

1 (oder Konstante: LOADING):
Dieser Wert bedeutet, dass die HTTP-Verbindung zum Webserver erfolgreich zustande kam. Diesen Wert hat die Eigenschaft, wenn open() eine Verbindung mit dem Webserver aufnehmen konnte, aber noch keine konkrete Anfrage mit send() gestartet wurde.

2 (oder Konstante: LOADED):
Dieser Wert bedeutet, dass der HTTP-Request vollständig übertragen wurde, und dass die Antwort-Header-Zeilen vom Webserver bereits vorliegen. Wenn readyState diesen Wert hat, können bereits die Methoden getAllResponseHeaders() und getResonseHeader() angewendet werden, um die Server-Antwort schon vor der Übertragung der Nutzdaten auszuwerten.

3 (oder Konstante: INTERACTIVE):
Diesen Wert hat die Eigenschaft, während die eigentlichen Nutzdaten vom Webserver empfangen werden. Die Eigenschaften responseText bzw. responseXML werden während dieses Zustands nach und nach mit den empfangenen Daten gefüllt.

4 (oder Konstante: COMPLETED):
Dies ist der Endzustand und bedeutet, dass die Server-Antwort komplett übertragen wurde.

Leider ist die Implementierung der Zustände von readyState in den verschiedenen Browsern nicht zuverlässig und einheitlich implementiert. So wertet beispielsweise der Opera-Browser nur die Zustände 3 und 4 aus. In der Praxis warten die meisten Ajax-Anwendungen deshalb bis readyState == 4, und beginnen dann mit der Verarbeitung der erhaltenen Antwortdaten.

Eigenschaft: responseText

Diese Eigenschaft enthält die vom Server gesendeten Nutzdaten als String. Was die Daten enthalten, hängt davon ab, was angefragt bzw. gesendet wurde. Bei Textdaten ist auch nichts weiter zur Zeichenkodierung festgelegt — all das sind Dinge, die das aufrufende JavaScript im Zusammenhang mit einem Aufruf vorher wissen muss.

Wenn es sich um Text oder HTML-formatierten Text handelt, werden empfangene Daten in der Regel über die DOM-0-Eigenschaft innerHTML in die aktuell angezeigte Webseite eingebaut.

Eigenschaft: responseXML

Diese Eigenschaft enthält nur dann einen konkreten Wert, wenn die Serverantwort explizit aus XML-Daten besteht. Gedacht ist diese Eigenschaft als Schnittstelle für das Document Object Model (DOM). Mit Hilfe der DOM-Schnittstelle von JavaScript lassen sich so empfangene Daten gezielt in die Dokumentstruktur der aktuell angezeigten Webseite einbauen.

Eigenschaft: status

Diese Eigenschaft speichert den HTTP-Statuscode einer Server-Antwort, sobald diese vorliegt. Nachfolgende Tabelle listet die wichtigsten HTTP-Statuscodes auf:

HTTP-Statuscode Erklärung
200 Der Server kann die angeforderten Daten wie gewünscht versenden. Dies ist der Normalfall, wenn keine Probleme auftauchen.
204 Der Server hat die Anfrage erhalten, sendet jedoch keine Daten zurück. Gut verwendbar ist dieser Status-Code bei Verwendung in serverseitigen Scripts, die zwar etwas auf dem Server erledigen, aber keinen neuen HTML-Code senden wollen.
301 Die angeforderten Daten befinden sich nicht mehr unter dem URI, sie wurden dauerhaft auf eine andere Adresse verschoben. In der Statusmeldung (Eigenschaft statusText) wird angegeben, unter welchem URI sich die Daten jetzt befinden.
302 Die angeforderten Daten wurden vorübergehend zu einem anderen URI verschoben. In der Statusmeldung (Eigenschaft statusText) wird angegeben, unter welcher Adresse sich die Daten derzeit befinden.
304 Die angeforderten Daten haben sich gegenüber einer früheren Anfrage nicht geändert und werden deshalb nicht erneut gesendet.
400 Die Anfrage enthält Syntaxfehler. Der Server kann die Anfrage deshalb nicht bearbeiten.
401 Die angeforderten Daten sind zugangsgeschützt. Der Server kann die Daten nur senden, wenn eine gültige Zugangskennung, bestehend aus Benutzername und Passwort, bei der Anfrage mit gesendet wird.
403 Der Server möchte die angeforderten Daten nicht herausgeben. Das passiert zum Beispiel, wenn der Zugriff auf die Ressource von dem IP-Adress-Bereich, aus dem die Anfrage kommt, in der Serverkonfiguration verboten wurde, die Ressource ganz und gar gesperrt wurde oder man versucht, ein Verzeichnislisting zu bekommen, dies jedoch in der Serverkonfiguration abgeschaltet wurde.
404 Der angeforderte URI existiert nicht.
500 Der Server kann die angeforderten Daten nicht senden, weil auf dem Server ein Fehler aufgetreten ist. Beispielsweise konnte das aufgerufene Script auf dem Server nicht gestartet oder korrekt ausgeführt werden.

Eigenschaft: statusText

Diese Eigenschaft ist nur im Zusammenhang mit der Eigenschaft status zu betrachten. Sie enthält die vom Webserver mitgelieferte Textmeldung zu einem Statuscode. In einigen Fällen (z.B. bei den Statuscodes 301 und 302) enthält die Meldung wichtige zusätzliche Angaben.

Methode: abort()

Mit dieser Methode wird eine laufende Kommunikation mit dem Webserver abgebrochen. Der Event-Handler onreadystatechange wird auf 0 zurückgesetzt. Die verwendete Instanz des XMLHTTPRequest-Objekts kann für eine neue Webserver-Anfrage genutzt werden. Sinnvoll ist der Einsatz dieser Methode beispielsweise, wenn der Anwender die Möglichkeit hat, eine Aktion, für die Ajax zum Einsatz kommt, mit Hilfe einer „Abbrechen“-Schaltfläche zu stoppen. Die Abbrechen-Schaltfläche kann in einem solchen Fall die abort()-Funktion starten.

Methode: getAllResponseHeaders()

Diese Methode ist aufrufbar, sobald der Server zumindest seinen Antwort-Header gesendet hat (die Eigenschaft readyState muss mindestens den Wert 2 haben). Sie liefert die gesamten Header-Felder der Server-Antwort als eine Zeichenkette zurück. Um bestimmte Header-Felder abzufragen, ist die Methode getResponseHeader() besser geeignet. Beispiel (httpRequest ist der Name der Objektinstanz des XMLHTTPRequest-Objekts):

httpRequest.getAllResponseHeaders();

erzeugt eine Rückgabe, die so ähnlich aussieht wie:

Date: Sun, 10 Jun 2007 04:58:38 GMT
Server: Apache/1.3.31 (Unix)
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/plain; charset=utf-8

Methode: getResponseHeader(name)

Diese Methode ist ebenso wie getAllResponseHeaders() aufrufbar, sobald der Server zumindest seinen Antwort-Header gesendet hat (die Eigenschaft readyState muss mindestens den Wert 2 haben). Im Parameter name muss die Bezeichnung eines HTTP-Header-Feldes übergeben werden. Die Methode liefert dann den zugehörigen Wert als Zeichenkette zurück, sofern das Feld im HTTP-Antwort-Header überhaupt vorkommt. Beispiel:

httpRequest.getResponseHeader("Content-Type");

erzeugt eine Rückgabe, die so ähnlich aussieht wie:

Content-Type: text/plain; charset=utf-8

Methode: open(method, url[, asyncFlag[, userName[, password]]])

Die open()-Methode öffnet eine HTTP-Verbindung zu einem Webserver. Dabei müssen mindestens die beiden Parameter method und url übergeben werden.

Der Parameter method bestimmt die Übertragungsmethode. Üblich sind die Angaben "get" und "post". Weitere mögliche HTTP-Methoden sind "put" und "head", die jedoch in der Praxis seltener verwendet werden. Die Standardmethode ist "get". Die Methode "post" wird dann verwendet, wenn das Ajax-Script selbst schon Nutzdaten an den Server senden will. Ein möglicher Anwendungsfall wären Formulardaten, die bereits während der Eingabe und vor dem Absenden des Formulars auf dem Server zwischengespeichert, überprüft oder anderweitig verarbeitet werden sollen.

Der Parameter url ist keine vollständige HTTP-Adresse, sondern nur eine Pfadangabe. Denn wie bereits erwähnt, kann ein Ajax-Script nur Adressen auf demjenigen Webserver aufrufen, von dem aus es selbst an den Browser übertragen wurde. In aller Regel handelt es sich bei der Adresse, die mit url übergeben wird, um ein für den Webserver ausführbares Script, also z.B. um ein PHP-Script oder um ein CGI-Script in Perl.

Wenn Sie für den Parameter asyncFlag explizit einen Wert übergeben wollen, müssen Sie true oder false übergeben. Mit true erzwingen Sie einen asynchronen Scriptablauf, und mit false einen synchronen Scriptablauf.
Ein asynchroner Scriptablauf bedeutet, dass JavaScript nicht wartet, bis die Antwort des Webservers vollständig übertragen wurde, sondern dass der Rest des JavaScripts sofort abgearbeitet wird. Bei einem synchronen Scriptablauf verhindert der Aufruf der Methode send() den weiteren Ablauf des JavaScripts so lange, bis die Serverantwort vollständig eingetroffen ist.
Der Default-Wert ist true, also ein asynchroner Scriptablauf. Der Vorteil davon ist, dass JavaScript seine Aufgaben erledigen kann und weitere Anwenderaktionen beispielsweise nicht blockiert sind. Dabei entsteht jedoch das Problem, dass die Daten des Webservers erst eintreffen, wenn das JavaScript bereits fertig durchgelaufen oder zumindest im Ablauf schon weiter ist. Aus diesem Grund wird bei asynchonem Scriptablauf eine sogenannte Callback-Funktion definiert, die dann aufgerufen wird, wenn die Serverantwort vorliegt. Der Event-Handler dafür ist onreadystatechange.

Die Parameter username und password sind nur dann von Bedeutung, wenn der Webserver für die über Ajax aufgerufene URL eine Identifizierung verlangt. Es ist jedoch nicht empfehlenswert, solche Inhalte über Ajax aufzurufen, da dann Benutzername und Passwort im JavaScript-Quelltext stehen, der für Web-Benutzer leicht einsehbar ist.

Methode: send([content])

Diese Methode sendet eine HTTP-Anfrage an den Webserver. Zuvor muss die Verbindung zum Webserver mit der Methode open() erfolgreich hergestellt worden sein. Wenn Sie als Anfragemethode get verwenden, übergeben Sie send() keinen Parameter. Wenn Sie dagegen post verwenden, müssen Sie send() eine Zeichenkette übergeben, welche die zu postenden Daten enthält. Diese Daten müssen in der Form www-form-urlencoded vorliegen, also so kodiert sein wie ein GET-Parameterstring (Felder durch & trennen, Feldname und Feldwert durch = trennen, www-form-url-eigene Zeichen hexadezimal kodieren — für letzteres stellt JavaScript die Funktion encodeUri() zur Verfügung).

Methode: setRequestHeader(name, value)

Mit dieser Methode können Sie der HTTP-Anfrage gewünschte HTTP-Header übergeben. So können Sie beispielsweise gewünschte Zeichensätze angeben — im Prinzip kann name alles sein, was in HTML an <meta http-equiv=... zugewiesen werden kann, und value alles, was im gleichen HTML-Tag content= zugewiesen werden kann.


Samstag, 28. April 2007

Tutorial: Ajax (3)

siehe auch:
(1): Was ist Ajax?
(2): Warum heißt Ajax so? Wo kann ich Ajax in Aktion sehen?


Worin besteht die Ajax-Schnittstelle?

Die Ajax-Schnittstelle besteht in einem speziellen JavaScript-Objekt, das HTTP-Requests absetzen und HTTP-Responses empfangen kann. Nun gehört ein solches Objekt nicht seit jeher zum Umfang von JavaScript, und deshalb stellt sich natürlich die Frage: wie und wo ist es implementiert, und welcher Browser kennt es?

Die Entwicklungen eines entsprechenden Script-Objekts gehen auf Microsoft zurück. Bereits 1997 verfügte der damalige MS Internet Explorer 4.0 über eine „Remote-Scripting-Komponente“, die allerdings nur mit dem hauseigenen Webserver Exchange funktionierte. Seit Produktversion 5.0 (1999) lässt sich im Internet Explorer ein XML-HTTP-Objekt in Form einer ActiveX-Komponente ansprechen. Seit Version 7.0 kennt der Internet Explorer ebenso wie alle übrigen heute verbreiteten Browser, also etwa Firefox, Safari oder Opera, ein ActiveX-unabhängiges XML-HTTP-Objekt.

Folgende Browserweiche genügt, um die Ajax-Schnittstelle in allen heute verbreiteten Browsern zu initialisieren:

var httpRequest = false;
if(window.XMLHttpRequest)  // Mozilla, Safari, Opera, MS IE 7, ...
   httpRequest = new XMLHttpRequest();
else if(window.ActiveXObject) { // MS IE 5, 6
   try {
      httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
   }
   catch (e) {
      try {
         httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e) {}
   }
}

Die Variable httpRequest soll das XML-HTTP-Objekt speichern. Über sie sind nach erfolgreicher Initialisierung Zugriffe auf Eigenschaften und Methoden des XML-HTTP-Objekts möglich. Zunächst wird die Variable mit dem Wert false initialisiert. Wenn ein XML-HTTP-Objekt erfolgreich initialisiert werden kann, ändert sich dieser Anfangswert.

Für alle modernen Browser genügt die Abfrage if(window.XMLHttpRequest). Damit wird geprüft, ob das XML-HTTP-Objekt im JavaScript-Interpreter verfügbar ist. Wenn ja, wird mit httpRequest = new XMLHttpRequest(); eine Instanz des Objekts in der zuvor erwähnten Variable httpRequest gespeichert.

Für das ActivX-basierte XML-HTTP-Objekt früherer Internet-Explorer-Versionen ist die Objektinitialisierung etwas komplexer. Mit if(window.ActiveXObject) wird zunächst herausgefunden, ob der Browser ein ActivXObject kennt, was ihn einigermaßen zuverlässig als Internet Explorer ausweist. Da es von Microsofts XML-HTTP-Objekt zwei Versionen gibt, wird auf beide Versionen geprüft. Zunächst wird getestet, ob die neuere Version ("Msxml2.XMLHTTP") verfügbar ist. Wenn nicht, wird versucht, die ältere Version ("Microsoft.XMLHTTP") anzusprechen. All diese Anfragen werden in try-catch-Statements eingebunden, um Laufzeitfehler zu vermeiden.

Die gute Nachricht lautet: es sind keine weiteren Verrenkungen für einzelne Browser erforderlich. Hat die Variable httpRequest ein XML-HTTP-Objekt gespeichert, kann fortan für alle Browser gleich programmiert werden, da das Objekt selbst, also seine Eigenschaften und Methoden, in allen Browsern gleich implementiert sind.

Wie wird Ajax standardisiert?

Die Entwicklung des XML-HTTP-Objekts verlief zunächst weitgehend ungesteuert. Mittlerweile hat sich jedoch das W3-Konsortium der Sache angenommen. Die aktuelle Spezifikation des XMLHTTPRequest-Objekts, wie es im offiziellen Wortlaut heißt, ist unter folgender Adresse zu finden:

http://www.w3.org/TR/XMLHttpRequest/

Derzeit (Stand: April 2007) ist dort noch keine Empfehlung (Recommendation) zu finden, sondern „nur“ eine Working Draft, also ein Arbeitsentwurf. Da das W3-Konsortium jedoch in diesem Fall eigentlich nur sanktioniert, was längst realisiert ist und genutzt wird, ist in der Spezifikation nicht mehr mit dramatischen Änderungen zu rechnen.

Der Einsatz von Ajax ist also keine halbseidene, proprietäre Angelegenheit mehr, sondern darf sich mittlerweile auf die Normierungshoheit des W3-Konsortiums berufen.


 

Get Free Shots from Snap.com