![]() |
HelferleinScript 'Debug-Infos':
|
|
| |
| E-Mail: | |
|---|---|
| Homepage-URL: |
Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!
Man schreibt eine Seite, in der man auch tüchtigerweise eine ansehnliche Menge
JavaScript-Code einsetzt. Leider reagiert das Script an manchen Stellen oder in bestimmten
Browsern nicht so, wie man es geplant hat.
Unter Umständen hilft es schon,
sich an bestimmten Stellen im Quellcode den Wert einer Variablen anzeigen zu lassen,
um dem Fehler auf die Spur zu kommen. Also schreibt man schnell hier und dort ein
alert() hin und gibt mit diesem dann den Wert einer Variablen aus.
Wenn es aber mehrere unterschiedliche Variablen an verschiedenen Stellen sein sollen?
Da kann es schnell zu sehr unübersichtlichen Konstrukten kommen. Deshalb ist
es vorteilhaft, ein Script zu haben, das man an zentraler Stelle speichern und pflegen
kann (z.B. http://localhost/debuginfos.js). Damit ist es möglich, mehrere Gruppen
von Variablen, auch unterschiedlicher Projekte, für solche alert()
Abfragen anzulegen, ohne unnötig viel in die original Projektdateien schreiben
zu müssen.
Um eine Vielzahl von Variablen problemlos handhaben zu können, ist es unbedingt
notwendig, zunächst die Existenz der Variable zu prüfen.
Dazu kann man
sich des Operators zur Typenbestimmung typeof bedienen. Eine weitere
Möglichkeit ist, dies mit dem try..catch - Statement zu prüfen.
Da letzteres aber erst mit Browsern, die mindestens JavaScript 1.5 verstehen möglich
ist und der typeof Operator schon in JavaScript 1.1 bekannt ist, wird
diesem hier der Vorrang gegeben. Bei den weiteren nötigen/möglichen Befehlen
und Funktionen (array.delete, array.push, array.pop) wurden auch solche
gewählt, die eine größtmögliche Rückwärtskompatibilität
erlauben. So kann das Script ab NS4 und IE4 bzw. mit Browsern, die JavaScript 1.2
verstehen, genutzt werden.
Anzeigebeispiel: So sieht's aus
<!-- Beispiel HTML Datei -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Beispieldatei: DebugInfos</title>
<!-- nur während der Entwicklungsphase eingebundene, zentrale JS-Datei -->
<script language="JavaScript1.2" src="debuginfos.js" type="text/JavaScript"></script>
<script language="JavaScript1.2" src="objekte.js" type="text/JavaScript"></script>
<script language="JavaScript1.2" type="text/JavaScript">
<!--
DI(1,'Aufruf vor Initialisierung der Variablen'); // Ausgabe von Informationen zu Variablen und Werten anfordern
// Objektinstanzen und Variablen initiieren
var loaded=false; // BeispielVariable (boolean)
var NumberOne = 22; // BeispielVariable (number)
var StringVar1 = "globale TextVariable eins"; // BeispielVariable (string)
var StringVar2 = "globale TextVariable zwei"; // BeispielVariable (string)
var Win; // Beispiel-Objekt (Window-Werte)
DI(1,'Aufruf nach der Initialisierung'); // Ausgabe von Informationen zu Variablen und Werten anfordern
// wird beim Ereignis 'resize' aufgerufen
function checkSize() {
DIC(); // Counter-Aufruf (= Wert um 1 erhoehen)
Win = new lib_win(); // aktuelle Fensterwerte in die Objektinstanz lesen
}
// wird beim Ereignis 'onload' aufgerufen
function setloaded() {
var StringVar2 = "lokale Stringvariable 2";
loaded = true;
NumberOne += 12;
Win = new lib_win();
StringVar1 = "Neuer Text in globale TextVariable eins";
StringVar2 = "Neuer Text in lokale Stringvariable zwei";
// Beachten Sie, dass hier die _lokale_ Variable 'StringVar2'
// gleichnamig ist mit der _globalen_ Variablen 'StringVar2'!
// In den DebugInfos ueberprueft und angezeigt wird aber
// nur der Wert der _globalen_ Variable!
DI(1,'Aufruf innerhalb der onLoad-Funktion'); // Ausgabe von Informationen zu Variablen und Werten anfordern
}
//-->
</script>
</head>
<body onload="setloaded()" onResize="checkSize()">
<p>
<br><br>
<a href="javascript:DI(1,'Abfrage der Wertegruppe 1')">Abfrage Wertegruppe 1</a>
<br><br>
<a href="javascript:DI(2,'Abfrage der Wertegruppe 2')">Abfrage Wertegruppe 2</a>
<br><br>
<a href="javascript:DI('','')">Nur Counter Abfrage</a>
<br><br>
</p>
</body>
</html>
<!-- die externe Scriptdatei: debuginfos.js -->
var counter = 0;
// Gruppen mit abzufragenden Variablen definieren (und bei Bedarf Trennlinien)
//
// WICHTIG! Wenn Sie Werte von Objektinstanzen abfragen wollen (z.B.: Win.IW),
// duerfen Sie mit if-typeof nur das Vorhandensein der Objektinstanz selber ueberpruefen.
// RICHTIG: if(typeof Win == 'undefined') ...
// FALSCH: if(typeof Win.IW == 'undefined') ...
// Anderenfalls erzeugen Sie bei Nichtvorhandensein der Objektinstanz einen Error.
//
function GetMyArrayNumber(N) {
out = new Array(); // out als _globales_ Array anlegen!
var VarName, VarValue;
if(N==1) {
VarName = "Win.IW";
if (typeof Win == 'undefined') VarValue = "undefined"; else VarValue = Win.IW;
push(VarName,VarValue);
VarName = "Win.OW";
if (typeof Win == 'undefined') VarValue = "undefined"; else VarValue = Win.OW;
push(VarName,VarValue);
push("-",0);
VarName = "Win.IH";
if (typeof Win == 'undefined') VarValue = "undefined"; else VarValue = Win.IH;
push(VarName,VarValue);
VarName = "Win.OH";
if (typeof Win == 'undefined') VarValue = "undefined"; else VarValue = Win.OH;
push(VarName,VarValue);
push("-",0);
VarName = "Variable1";
if (typeof Variable1 == 'undefined') VarValue = "undefined"; else VarValue = Variable1;
push(VarName,VarValue);
VarName = "Variable2";
if (typeof Variable2 == 'undefined') VarValue = "undefined"; else VarValue = Variable2;
push(VarName,VarValue);
VarName = "loaded";
if (typeof loaded == 'undefined') VarValue = "undefined"; else VarValue = loaded;
push(VarName,VarValue);
} else if(N==2) {
VarName = "bw.agent";
if (typeof bw.agent == 'undefined') VarValue = "undefined"; else VarValue = bw.agent;
push(VarName,VarValue);
VarName = "bw.dom";
if (typeof bw.dom == 'undefined') VarValue = "undefined"; else VarValue = bw.dom;
push(VarName,VarValue);
} else if(N=='Projekt1 Gruppe3') {
// Definition der 3. Gruppe von Variablen, die Sie in Ihrem Projekt hin und wieder aufrufen moechten ;-)
} else {
alert('DebugInfos abfragen ist nicht moeglich. Es fehlen Angaben!');
}
}
// Schluessel und Werte in das globale Array 'out' schreiben
//
function push(key,value) {
var i = out.length;
out[i] = new Array();
out[i]['key']=key;
out[i]['value']=value;
}
// Aufruf erhoeht den Counter um 1
//
function DIC() {++counter;}
// Gibt die Infos der gewuenschten Variablen-Gruppe aus
//
// Wenn weder fuer N noch msg Parameter uebergeben wurden ( also: DI('','') )
// wird nur der aktuelle Stand des counters angezeigt.
// Anderenfalls ist mindestens fuer N die gewuenschte Gruppe der anzuzeigenden Variablen,
// wie sie in der Funktion GetMyArrayNumber(N) definiert sind, anzugeben.
// Fuer msg ist eine Zeichenfolge (oder leere Zeichenfolge '') anzugeben.
//
function DI(N,msg) {
var ZU = "\n"; // Zeilenumbruch im AlertWindow (funktioniert so auch unter Windows. Anderenfalls: \r\n)
var info = "------- [Debug Infos] --------------------------------("+counter+")---"+ZU+ZU;
if(N=="" && msg=="") {
msg = "(Nur Counterinfo)";
info += msg + ZU;
info += ZU+"---------------------------------------------------------------"+ZU;
} else {
GetMyArrayNumber(N); // fuellt das Array 'out' mit den Schluesseln und Werten der Gruppe 'N'
info += msg + ZU;
info += ZU+"---------------------------------------------------------------"+ZU;
for (var i=0; i < out.length; ++i) { // schreibt alle Schluessel-Wert-Paare aus 'out' in die Variable Info
if(out[i]['key']=='-') {
info += "---"+ZU;
} else {
info += out[i]['key'] + " = " + out[i]['value'] + ZU;
}
}
info += "---------------------------------------------------------------"+ZU;
}
alert(info); // gibt alle Informationen aus
delete out; // globales Array 'out' wird geloescht!
}
In die HTML-Datei wird während der Entwicklungsphase die externe JavaScript-Datei
debuginfos.js eingebunden. In dieser Datei definiert man in der Funktion
GetMyArrayNumber(N) einen Block (oder mehrere Blöcke) mit Variablen,
deren Werte oder Existenz man überprüfen möchte. An die Variable
VarName wird per string (Zeichenfolge) der Name der zu
überprüfenden Variable übergeben.
In der Zeile darunter übergibt man einmal den Wert der Variable an den 'Operator
zur Typenbestimmung' typeof. Zur Laufzeit wird so überprüft,
ob die Variable vom Typ 'undefined' ist. Das wäre sie, wenn sie
a) gar nicht existent ist, oder b) keinen gültigen Wert enthält. Für
unser Vorhaben muss als gültiger Wert einer der folgenden Typen zurückgegeben
werden: string, number, boolean oder (mit Einschränkung) object.
Wenn der Testkandidat bei der Überprüfung ein true
(richtig/wahr) zurückgibt, wird für die lokale Variable VarValue
die Zeichenfolge 'undefined' als Wert übergeben (VarValue = "undefined";). Wenn die Überprüfung
ein false (falsch/unwahr) zurückgibt, wird der lokalen Variable
VarValue der tatsächliche Wert des Testkandidaten übergeben (VarValue = originalValue;).
Anschließend schreibt die Funktion push(Varname,VarValue) die
Werte als neue Schlüssel-Werte-Paare in das globale Array 'out'.
Sie müssen also einmal den Namen und zweimal den Wert des Testkandidaten in diese Routine schreiben. Peinlich korrekte Syntaxprüfung aller drei Variabelennennungen an dieser Stelle kann später einige Kopfschmerzen ersparen.
Für jeden weiteren 'Testkandidaten' wiederholt man das. Um eine bessere Übersicht
bei der Ausgabe mehrerer Variablen zu erreichen, kann man Trennzeilen einfügen.
(push("-",0);)
Die Funktion push(key,value) ermittelt mit out.length
die Anzahl der momentan im Array befindlichen Einträge. Wenn z.B. 10 Einträge
vorhanden sind, liefert array.length den Wert 10 zurück. Der 10.
Eintrag eines Arrays hat die Positionsnummer 9, da der erste Eintrag die Positionsnummer
0 hat (und nicht 1), deshalb wird mit dem ermittelten Wert ein neuer (der 11.) Eintrag
an Positionsnummer 10 erstellt. Diesem Eintrag werden dann der Name und der aktuelle
Wert der zu überprüfenden Variable zugewiesen.
Die Zuweisung eines neuen Wertes an letzter Stelle eines Arrays, also ein einfaches
Anhängen, lässt sich etwas bequemer mit array.push vornehmen.
Doch dieser Befehl steht, obwohl JavaScript 1.2, erst ab IE 5.5 zur Verfügung und wird deshalb hier nicht
genutzt. Das Pendant dazu ist array.pop.
Durch einen Aufruf der Funktion DI(N,msg) in der HTML-Datei
erreicht man an dieser Stelle des Scripts die Ausgabe
von Informationen zu den Variablen des mit N selektierten Blocks in
der Funktion GetMyArrayNumber(N). Mit msg kann man der
Ausgabe einen kurzen Hinweis beifügen, der bei mehreren Ausgaben in einem Durchlauf
zu mehr Übersicht verhilft. Wenn weder für N noch für
msg ein Parameter übergeben werden, also DI('',''),
wird nur der aktuelle Stand eines Counters angezeigt. Mit Hilfe des Counters kann
man z.B. die Anzahl ausgelöster Impulse für einen Eventhandler zählen.
In der Beispieldatei ist der Zähler in der Funktion checksize(),
die onResize aufgerufen wird, gesetzt. (Verkleinern und vergrößern Sie doch mehrmals das
Fenster und schauen sich danach eine Ausgabe an.)
In der Beispieldatei werden einige Variablen unterschiedlichen Typs und eine Objekt-Instanz
definiert. Die Objektinstanz gibt Werte zu Breite und Höhe Ihres Browserfensters wieder,
sofern Sie einen der folgenden Browser benutzen: IE, Mozilla und Derivate (Netscape, K-Meleon, Galeon, etc) und Opera.
Während des Ladevorgangs werden an drei Stellen Informationen der Gruppe eins ausgegeben. Ein Zähler
ist per Funktion an das Resize-Ereignis gebunden. Weiterhin wird bei der Auslösung
des Resize-Ereignisses immer die Instanz des Fensterobjektes aktualisiert.
Als Möglichkeit, nach dem Laden der Beispieldatei auch die aktuellen Werte abfragen zu können,
gibt es drei Links mit denen Sie jeweils die Funktion DI(N,msg) mit unterschiedlichen
Parametern aufrufen können.
Und mit der Reload-Taste Ihres Browsers können Sie die Ausführung ja wiederholen.
Wenn Sie Werte von Objektinstanzen abfragen wollen (z.B.: Win.IW), sollten Sie
mit if-typeof nur das Vorhandensein der Objektinstanz selbst überprüfen, andernfalls
erzeugen Sie bei Nichtvorhandensein der Objektinstanz einen unbehandelten Error
und das Script bricht ab.
Beispiel:
Sichere Abfrage des Wertes für Win.IW: if(typeof Win == 'undefined')
...
Unsichere und evtl. zu einem Error führende Variante: if(typeof Win.IW
== 'undefined') ...
Die folgenden Stellen werden empfohlen, um das obige Beispiel besser zu verstehen, oder um weitere Möglichkeiten und Details zu erfahren.
SELFHTML: Operator zur Typenbestimmung
SELFHTML: Fehlerbehandlung mit dem try..catch - Statement
SELFHTML: Variablen definieren
SELFHTML: Eigene Objekte definieren
SELFHTML: assoziative Arrays