Vor einigen Jahren tauchte im Umfeld des Webdesigns der Begriff «DHTML» auf, einer Technik die das Verändern einer Webseite ermöglicht, ohne dabei eine neue Anforderung an den Server zu senden. Nun war DHTML weder eine HTML-Erweiterung, noch eine neue Programmiersprache. DHTML war lediglich der Sammelbegriff einiger Techniken und Methoden. Und sie alle verwendeten bestehende und bestens etablierte Standards: HTML, CSS und JavaScript/DOM.
Mit «AJAX» verhält es sich sehr ähnlich. AJAX nutzt mehrere etablierte Techniken um den Inhalt einer Seite basierend auf Daten zu verändern, die nach dem Ladeprozess vom Server geholt werden. Daher auch der Begriff «asynchron». In der Praxis sieht das so aus, dass der Benutzer im Browser eine Adresse eingibt und damit die zu dieser Adresse gehörende Webseite öffnet. Verwendet die Seite AJAX-Techniken, können durch Benutzerinteraktion jederzeit im Hintergrund Daten vom Server nachgeladen werden, der Inhalt einer Tabelle zum Beispiel.
Um asynchrone Webseiten selbst zu erstellen, ist es nicht zwingend erforderlich, auf eine AJAX-Bibliothek zurückzugreifen, es genügt, die Elemente zu verwenden, die JavaScript mit asynchronen Funktionen erweitern. Im wesentlichen ist dies das XMLHttpRequest -Objekt, das in allen neueren Browsern zu finden ist. Seine Funktionsweise ist sehr einfach: nachdem mit open() eine zu ladende Adresse angegeben wurde, kann die Anforderung mit send() zum Server gesandt werden. Einige weitere Funktionen und Attribute informieren über den Fortschritt des Ladeprozesses und darüber, ob die Operation erfolgreich war, oder nicht. Die folgende, kurze JavaScript Funktion nimmt als Argument eine URL entgegen und liefert als Ergebnis den Inhalt dieser URL:
function getURLContent(url) {
var xmlHttp = false;
var urlcontent = '';
// Mozilla, Opera, Safari sowie Internet Explorer 7
if (typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest();
}
if (!xmlHttp) {
// Internet Explorer 6 und aelter
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
xmlHttp = false;
}
}
}
if (xmlHttp) {
// Synchrones Lesen einer URL
xmlHttp.open('GET', url, false);
xmlHttp.send(null);
if (xmlHttp.status == 200) {
urlcontent = xmlHttp.responseText;
}
}
return(urlcontent);
}
Im ersten Teil der Funktion wird eine neue Instanz des XMLHttpRequest Objektes erzeugt. Ältere Versionen des IE erfordern eine leicht abweichende Syntax, deshalb wurde eine entsprechende Prüfung eingebaut, damit wir auf jeden Fall eine Instanz erhalten. Anschliessend wird mittels open() und send() eine Anforderung (GET, POST, HEAD) an den Server gesendet. open() legt die Adresse, die HTTP-Methode und den Asynchronmodus fest. send() sendet dann die Anforderung an den Server. Wichtig ist im folgenden der mittels open()festgelegte Asynchronmodus (AM). Wird für AM TRUE angegeben, wartet send() nicht bis das Eregbnis vorliegt, dieses muss mit Hilfe einer Callbackfunktion ermittelt werden. Bei AM=FALSE wartet send() solange, bis der Server das Ergebnis übermittelt hat. Mein Beispiel verwendet einfachheitshalber AM=FALSE.
Es ist nun nicht mehr Schwierig, eine Funktion zu schreiben, die mit Hilfe der beschriebenen Funktion einen in PHP oder PERL geschriebenen Serverscript aufruft und dessen Ergebnis an einer passenden Stelle auf der Webseite präsentiert. Wer in vorgegebenen Intervallen Daten vom Server holen will, kann setInterval() oder setTimeout verwenden. Wie die Daten anschliessend in die Webseite eingesetzt werden, kann bei SelfHTML nachgelesen werden.
Dies alles zusammengepackt auf einer schön gestalteten Webseite lässt bereits einen «Hauch von AJAX» aufkommen.
Update 16.8.2006: Probleme
Ein Problem, das im Internet immer wieder diskutiert wird, ist das Caching. Während Opera das Zwischenspeichern von xmlHTTPRequest Anfragem relativ leicht abgewöhnt werden kann, macht der Internet Explorer erfahrungsgemäss deutlich mehr Schwierigkeiten. Eine Suche in der Foren fördert einen Workaround zutage, der auch beim IE immer Wirkung zeigt: Der gewünschten URL wird bei jedem Aufruf eine Zufallszahl angehängt, also zum Beispiel:
var rnd = parseInt(Math.random()*99999999);
var url = 'example.php?random=' + rnd;
var content = getURLContent(url);
Damit wird verhindert, dass der aggressive Caching Algorithmus des IE greift: Da die Adresse jedesmal anders ist, muss der Redmond-Browser sie neu vom Server abholen. Natürlich ist dies eine Holzhammer-Methode, ich habe deshalb versucht, das Problem mit HTTP Head Anweisungen für alle Browser zu lösen. Der folgende PHP-Script wird von allen aktuellen Browser beim jedem Aufruf neu abgeholt:
< ?php
header("Pragma: no-cache");
header("Cache-Control: no-cache");
header("If-Modified-Since: 1980-01-01");
print "Inhalt der Seite";
?>