AJAX und die script-Tags

Irgendwie fehlt mir der include in HTML-Files. Es wäre halt schön, wenn man eine HMTL-Seite aus kleinen HTML-Teilen, die sich vielleicht wie eine Direktory-Hierarchie irgendwo befinden, zusammenführen kann. Vielleicht sogar so, dass sie sich selbststeuernd aufrufen. Ein wenig Objektorietierung in HTML wäre ja nicht schlecht. Vielleicht erstmal ganz schlicht und einfach so, dass in f1.html irgendwo ein Aufruf zum Laden von f2.html steht und in f2.html wiederum f3.html aufgerufen wird. Man kann das mit <iframe src="..."> oder <object data="..."> machen, aber nun gibt es ja auch AJAX und vielleicht kann man ja dynamisch die Dateien nachladen. Soweit der Gedanke...

In meinem AJAX-Buch von Johannes Gamperl ist eine kleine ajaxRequest-Klasse beschrieben, die mal erst ausreichen sollte.

ajaxRequest = function(u,f,m,b,s) {
  this.url      = u;
  this.wState   = f || function() {};
  this.method   = m || "GET";
  this.body     = b || null;
  this.sync     = s || true;
  this.abortReq = false;
  this.req = (typeof window.ActiveXObject != 'undefined') ? 
    new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
  this.doRequest = function () {
    this.req.open(this.method, this.url, this.sync);
    if (this.headers)
      for (i=0; i < this.headers.lenght; i+=2)
        this.req.setRequestHeader(this.headers[i],this.headers[i+1]);
    this.req.onreadystatechange = this.wState;
    this.req.send(this.body);
  }
}
Ein Instanz läßt sich nun erzeugen mit:
var tag = new ajaxRequest("f2.html",function(){
    if (req.readyState == 4) alert(req.responseText);});
tag.doRequest();
Die Funktion muß natürlich noch angepaßt werden, so dass sie die aufgerufene HTML-Datei an ein Element bindet. Dafür muss ein Platzhalter herhalten, z. B. <span id="tag2"><span>. Dann sieht das Ganze so aus:
    if (req.readyState == 4) {
    d = document.getElementById("tag2");
    d.innerHTML = req.responseText;
Die aufzurufende Datei kann nun fast jede Art von gültiger HTML enthalten und wird an das Element angehangen (für XML gibt es andere Lösungen). Auch JavaScript-Teile können enthalten sein, so dass dem Aufruf eines weiteren ajaxRequests nichts im Wege steht. Allerdings werden die JavaScript-Passagen nicht evaluiert, so dass eine Extraktion und ein dezidierter eval-Aufruf erfolgen muß. Auf manchen Webseiten wird behauptet, dass Scripte nicht ladbar sind oder er werden reguläre Ausdrücke zur Extraktion verwendet; muß nicht sein, geht schlichter. Allerdings muß mindestens ein Struktur-Tag in der Datei sein z. B. <div> oder <span>, welches leer sein darf.
    if (req.readyState == 4) {
    d = document.getElementById("tag2");
    d.innerHTML = req.responseText;
    ds = d.getElementsByTagName("script");
    for(s=0;s < ds.length;++s) eval(ds[s].innerHTML);}
Um die Schreiberei ein wenig kleiner zu halten, hab ich es in eine Funktion ajaxScript integriert:
ajaxRequest = function(u,f,m,b,s) {
  this.url      = u;
  this.wState   = f || function() {};
  this.method   = m || "GET";
  this.body     = b || null;
  this.sync     = s || true;
  this.abortReq = false;
  this.req = (typeof window.ActiveXObject != 'undefined') ? 
    new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
  this.doRequest = function () {
    this.req.open(this.method, this.url, this.sync);
    if (this.headers)
      for (i=0; i < this.headers.lenght; i+=2)
        this.req.setRequestHeader(this.headers[i],this.headers[i+1]);
    this.req.onreadystatechange = this.wState;
    this.req.send(this.body);
  }
}
function ajaxScript(req,tag) {
    if (req.readyState == 4) {
    d = document.getElementById(tag);
    d.innerHTML = req.responseText;
    ds = d.getElementsByTagName("script");
    for(s=0;s<ds.length;++s) eval(ds[s].innerHTML);}
}
var tag = new ajaxRequest("f2.html",function(){
          ajaxScript(tag.req,"tag2");});
tag.doRequest();
In der Datei f2.html kann nun f3.html allein mit den beiden letzten Zeilen aufgerufen werden und einem Element mit der id="tag3" zugeordnet werden.
var tag2 = new ajaxRequest("f3.html",function(){
           ajaxScript(tag2.req,"tag3");}); 
tag2.doRequest();
Und so weiter ...