Archiv der Kategorie: Javascript

Script-Fehler beim IE6 finden

Meldet der IE6 einen Javascript-Fehler, der sich im Firefox nicht nachvollziehen lässt, so wird es schwierig. Der IE6 meldet zwar, er hätte in der Datei xy.php in Zeile x bei Zeichen y einen Fehler gefunden, aber diese Angaben sind irreführend. Oder doch nicht? Wie man dem Fehler auf die Spur kommen kann zeige ich hier.

Beim Aufrufen einer Seite wird zum Beispiel die folgende Fehlermeldung angezeigt:

Screenshot der 1. Fehlermeldung

Im Prinzip ist die Angabe von Zeile und Spalte gar nicht so verkehrt, nur die Datei-Angabe stimmt meist überhaupt nicht, da eine HTML-Seite zum einen oft aus verschiedenen Teilen per PHP zusammengesetzt wird und zum anderen der Javascript-Code häufig in eigene Dateien ausgelagert ist.

Um nun herauszubekommen, in welcher Datei der Teufel im Detail steckt, muss man den Debug-Modus aktivieren und die Anzeige der Script-Fehler ausschalten. Dies geschieht in Extras » Internetoptionen » Erweitert. Dort werden, wie unten gezeigt, die Häkchen bei »Skriptdebugging deaktivieren« und bei »Skriptfehler anzeigen« entfernt. Danach muss der IE neu gestartet werden, damit die Änderungen wirksam werden.

Screenshot der Internetopionen des IE6

Wird nun die betreffende Seite erneut aufgerufen, sieht die Fehlermeldung etwas anders aus:

Screenshot der 2. Fehlermeldung

Hier ist nun auch erstaunlicher Weise von Zeile 14 die Rede! Klick man nun auf »Ja«, wird der IE-Debugger gestartet und die Datei geladen und angezeigt, in der der Internet-Explorer den Fehler gefunden hat. Der Cursor wird allerdings an die Position gesetzt, die in der ersten Fehlermeldung angezeigt wurde: Zeile 15, Spalte 22.

Ausschnitt der Debug-Anzeige

Wenn wir uns aber an die Angabe aus der zweiten Fehlermeldung (Zeile 14) erinnern und unser Augenmerk auf die Zeile über dem Cursor richten, sehen wir dort in Spalte 22 einen zweiten Punkt, der dort nicht hingehört. Dies ist der Fehler!

Das Verfahren ist etwas umständlich, aber immerhin zielführend. Und wenn man sich erst einmal daran gewöhnt bzw. damit abgefunden hat, ist es recht nützlich.

ATA statt AJAX

Da habe ich doch heute beim Lesen des Ajax-Artikels in der neuen c’t (05/2006 S. 152) feststellen müssen, dass ich, ohne es zu wissen, schon mal Ajax zu Fuß gecodet haben. Naja, nicht ganz, denn mit XML hatte das nichts zu tun. Daher müsste man das eher ATA (Asynchronous Tag Apending 😉 nennen. Immerhin auch ein Scheuerzeugs.

Ich musste für eine Webanwendung eine Möglichkeit schaffen, Daten in ein Formular hinzufügen, daraus zu entfernen und auch ändern zu können. Es ging hier um Rufnummern. Natürlich sollte dazu das Formular nicht jedes mal neu aufgerufen werden.

Ich behalf mir also mit einem Popup-Fenster, in dem über ein kleines Formular die Rufnummer bearbeitet oder hinzugefügt werden konnte. Diese Formular bekommt die Daten per GET über den Link geliefert und wertet diese per PHP aus. Beim Abschicken des Formulars wird über den Eventhandler „onClick“ des Buttons die Funktion sendData() aufgerufen. Diese überträgt die Formular-Daten als assoziatives Array an die aufrufende Seite, indem dort je nach Mode die Funktion changeMSN oder an addMSN aufgerufen wird.

function sendData(bnt,mode) {
  var theForm = bnt.form;
  var str = "";
  var MSNarray = new Array();
  for (var i = 0; i > theForm.length; ++i) {
    // Das Array zusammenbauen:
    switch (theForm.elements[i].type) {
      case "button" : break; // überspringen

      case "checkbox" : MSNarray[theForm.elements[i].name] = theForm.elements[i].checked ? "X" : "";
                        break;

      default: MSNarray[theForm.elements[i].name] = theForm.elements[i].value;
    }
  }
  // Daten übertragen:
  if(mode == "ADD") {
    opener.addMSN(MSNarray);
  } else {
    opener.changeMSN(MSNarray);
  }
  self.close();
}

Diese Funktionen fügen dann entweder eine Rufnummer im Formular hinzu (addMSN) oder verändern eine schon vorhandene (changeMSN).

addMSN geht zunächst einmal das übergebene Array durch und holt sich u.a. die Rufnummer. Dann muss diese dem HTML-Dokument hinzugefügt werden. Die Nummern sind in einer Tabelle organisiert, die sich mit

msntbl = document.getElementById("msnlist_body");

aus dem DOM-Baum fischen lässt. Um nun eine Zeile an die Tabelle anzuhängen müssen verschiedene DOM-Objekte erzeugt und angehängt werden:

  // neues tr-Element erzeugen:
  var newTR = document.createElement("tr");
  // das neue Element am Ende der Tabelle anhängen:
  msntbl.appendChild(newTR);
  // neues td-Element erzeugen (bleibt leer):
  var newTD = document.createElement("td");
  // das neue Element an das TR anhängen:
  newTR.appendChild(newTD);
  // noch ein neues td-Element erzeugen (für die MSN):
  var newTD = document.createElement("td");
  // auch an das TR anhängen:
  newTR.appendChild(newTD);
  // das Atribut ID erzeugen und anhängen:
  var AttrID = document.createAttribute("id");
  AttrID.nodeValue = "MSN_"+msn;
  newTD.setAttributeNode(AttrID);
  // jetzt können wir das neue Element per ID ansprechen:
  document.getElementById("MSN_"+msn).className = "msn";
  // Text-Knoten erzeugen
  if(RNBvon == "") {
    var Txt = document.createTextNode(msn);
  } else {
    var Txt = document.createTextNode(msn+"-"+RNBvon+"..."+RNBbis);
  }
  // an das zuletzt erzeugte TD anhängen:
  newTD.appendChild(Txt);

  // noch ein neues td-Element erzeugen (für die PK und die serialisierten Daten):
  var newTD = document.createElement("td");
  // auch an das TR anhängen:
  newTR.appendChild(newTD);
  // neues INPUT-Element erzeugen:
  var newInput = document.createElement("input");
  newTD.appendChild(newInput);
  // das Atribut type erzeugen und anhängen:
  var AttrType = document.createAttribute("type");
  AttrType.nodeValue = "hidden";
  newInput.setAttributeNode(AttrType);
  // das Atribut ID erzeugen und anhängen:
  var AttrId = document.createAttribute("id");
  AttrId.nodeValue = "MSNdata_"+msn;
  newInput.setAttributeNode(AttrId);
  // jetzt können wir das neue Input-Element per ID ansprechen:
  document.getElementById("MSNdata_"+msn).name = "MSN["+msn+"]";
  document.getElementById("MSNdata_"+msn).value = serialize(MSNarray);

Wie man sieht, werden die eigentlichen Daten in ein Input-Element als serialisierten String eingefügt. Ich habe diesen Weg gewählt, da ich wesentlich mehr Daten übertragen als in diesem Beispiel dargestellt. Die Serialisierung entspricht der von PHP, so dass PHP diesen String dann in ein Array umwandeln kann. Ich werde vielleicht in einem späteren Artikel auf diese Sache näher eingehen.
Nach dieser DOM-Arie ist die neue Nummer im Formular sichtbar.

Die Funktion changeMSN muss anders arbeiten. Sie muss die betroffene Rufnummer aus der Liste heraussuchen und verändern. Das ist relativ einfach, da die Nummer Bestandteil der ID aller Elemente ist und diese über getElementById zu fassen sind. Hier am Beispiel des versteckten Input-Elements:

  // den serialisierten String holen:
  var feature_item = document.getElementById("MSNdata_"+msn);
  ...
  // String bearbeiten
  ...
  // den neuen serialisierten String schreiben:
  feature_item.value = newSerial;

So einfach kann das sein 🙂
Das Löschen funktioniert ähnlich, da ich die Nummer im Formular nicht wirklich entferne, sondern nur die Darstellung mit

  document.getElementById("MSN_"+msn).style.textDecoration='line-through';

ändere und die Nummer einem versteckten Inuput-Element mit der ID deleteMSN hinzufüge.

So weit für heute mit dem AJAX für Arme. Demnächst mehr in diesem Theater.