Calocybe: Von den Dingen, die in javascript: Links passieren

Beitrag lesen

Ach Mist, da hab ich nicht alle Tuecken des Forums-Scripts bedacht (siehe <32093.html>). Da muss ich heute leider mal ein Doppelposting machen. Ich hoffe, ich habe jetzt alle "schaedlichen" Textstellen umgeschrieben.

Hallo liebe Antje!

(In reply to </selfhtml/sfarchiv/1999_3/t06448.htm#a31588>.)

:-), ich habe doch auf deinen Kommentar gewartet :-)

Dann will ich Dir den erneut nicht vorenthalten.

Das void() in menu.html verhindert, das der Navigator komische Sachen macht. *g* Er schreibt sonst den Dateinamen in das Fenster der menu.html, nachdem er im oberen Frame ganz richtig die location gewechselt hat. Ein darauffolgendes view source auf den Menu frame ist einfach nur... seltsam. Nehme ich jetzt mal als Bug hin.

»»

Es liegt daran, daß gleichzeitig der Link ausgeführt wird. Da gleiche Problem existiert bei window.open() hinter href. Siehe dazu auch </selfhtml/sfausles/tsfa_tcd.htm#a3>

Tatsaechlich! Dann hat ja mein Lieblings-Netsi doch keinen Bug! (Na zumindest nicht an dieser Stelle *g*) Dafuer hab ich gleich noch was fuer Deine Auslese (bzw. Deinen Teil derselben). Wusstest Du denn auch, *warum* das passiert, was da passiert? Mit anderen Worten, was das bedeutet, dass "der Link ausgefuehrt" wird? Schmoekern wir also mal wieder in der Specification.

http://developer.netscape.com/docs/manuals/js/client/jsref/location.htm#1203002 sagt: The javascript: protocol evaluates the expression after the colon (:), if there is one, and loads a page containing the string value of the expression, unless it is undefined. If the expression evaluates to undefined (by calling a void function, for example javascript:void(0)), no new page loads. Note that loading a new page over your script's page clears the page's variables, functions, and so on.

Also, wenn der Ausdruck, der da im HREF steht, etwas anderes als undefined zurueckliefert, dann wird eine Seite aufgebaut, die genau den Inhalt hat, die von dem Ausdruck zurueckgeliefert wird. Nun, da
    "<HTML><HEAD><TITLE>Moin Moin!</TITLE></HEAD><BODY><P STYLE="font-family:Arial; font-size:144pt; text-align:center;">Hallo!</P><P STYLE="text-align:right;"><A HREF="javascript:history.back();">Zurueck zum Posting</A></P></BODY></HTML>"
ein gueltiger JS-Ausdruck ist, der einen String zurueck gibt, sollte also die entsprechende Seite aufgebaut werden.

(Da das Forumsscript leider verhindert, die < und > Zeichen direkt in den Text zu schreiben, kann ich keinen Link anbieten. Ihr muesstet das Zeug also mal selber in die Adresszeile kopieren. Und zwar ohne Zeilenumbrueche!)

Und wieder mal: Geht!

Der Source code viewer (der mitunter sehr... nun "interessante" Resultate liefert) kommt mit dieser Form besser zurecht:
javascript:'<HTML><HEAD><TITLE>Moin Moin!</TITLE></HEAD><BODY><P STYLE="font-family:Arial; font-size:144pt; text-align:center;">Hallo!</P><P STYLE="text-align:right;"><A HREF="javascript:history.back();">Zurueck zum Posting</A></P></BODY></HTML>'

Yoh, gut. Deshalb hat er also z.B. bei der Zuweisung
    parent.upperframe.location.href = '1.html'
einfach "1.html" ins Browserfenster geschrieben, denn diese Zuweisung hat ja als Ergebnis eben diesen Dateinamen. (BTW: Nur deshalb funktionieren solche Mehrfachzuweisungen wie a=b=c, denn b=c hat c zum Ergebnis, welches danach an a zugewiesen wird. Man koennte sicher auch schreiben a=eval("b=c"). Ach probieren wir's doch gleich aus: <javascript:alert(a = eval('b = 7-13'));> Na also!)

Fragt sich nur, warum denn nach einem window.open()-Aufruf dieses geheimnisvolle "[object window]" ins Browserfenster geschrieben wird, wie Du in </selfhtml/sfausles/tsfa_tcd.htm#a3> schreibst. Nun, waehrend JS durchaus zwischen verschiedenen Variablentypen unterscheidet (es wurde hier schon das Gegenteil behauptet), nimmt es automatisch eine dem Kontext entsprechende Umwandlung in den verlangten Typ vor, sobald dies erforderlich ist. So wird in dem Ausdruck
    z = "Hallo " + 42;
die Zahl 42 in den String "42" umgewandelt, damit die Stringverkettung durchgefuehrt werden kann.
Wenn nun also der Browser den Rueckgabewert eines JS-Ausdrucks ins Fenster schreiben will, erwartet er natuerlich einen String. Wenn er wie im Beispiel oben mit dem puren HTML-Code einen bekommt, ist das sehr schoen und er freut sich, weil er nicht so viel machen muss. Wenn nicht, wie bei window.open(), ist er aber auch nicht geschockt, sondern ruft die bei *jedem Objekt eingebaute* Methode toString() auf, die ihm idealerweise einen String zurueckliefert, der moeglichst passend zum Objekt ist. So liefert z.B. Date.toString() eine Zeichenkette, die die im Objekt gespeicherte Zeit repraesentiert. Function.toString() liefert den reformatierten Quellcode der zugrundeliegenden Funktion. (So kann man auf die Seite http://developer.netscape.com/docs/manuals/js/client/jsguide/index.htm gehen und dort in die Adresszeile javascript:alert(toc.getGIFStatus); eingeben, um sich den Quellcode der Funktion getGIFStatus() aus dem Frame toc (das Inhaltsverzeichnis links) anzeigen zu lassen. Schaut man sich dann mal den Original code an, stellt man fest, dass der Text in der alert-Box nicht 100%-ig mit dem uebereinstimmt; z.B. wurden Kommentare entfernt und Semikolonse hinzugefuegt.) Viele Objekte haben nun aber die toString()-Methode nicht ueberladen (ja, so heisst das in der objektorientierten Programmierung (OOP)), d.h. sie haben keine eigene Methode dieses Namens definiert, sondern erben die Implementierung des Objekts, von dem sie abstammen. Und das waere dann das Object-Objekt (ich meine das Objekt namens Object). (Das ist jetzt aber nur so'ne Vermutung, so richtig explizit hingeschrieben habe ich das nirgends in der Spec gefunden.) Beim Object-Objekt steht dann: "[...] gibt [object 'type'], zurueck, wobei 'type' der Typ des Objekts oder der Name der Konstruktor-Funktion, die das Objekt erstellt hat, ist." Naja, im Original ist es leichter zu verstehen: http://developer.netscape.com/docs/manuals/js/client/jsref/object.htm#1193350. Da window.open() ja ein window-Objekt zurueckliefert, wird von dem die toString()-Methode aufgerufen - da es keine eigene hat, eben die geerbte - und die gibt nun mal "[object window]" zurueck, was dann ins Browserfenster geschrieben wird. Ausser beim IE natuerlich. ;-) Wer's nochmal ausprobieren will: <javascript:alert(window.open('http://www.anywhere.de'));>.

So weit, so gut. Doch noch sind wir nicht am Ende, he he *eg*. Jetzt wollen wir ja noch wissen, wie denn das mit dem undefined ist. Also: Wenn der Ausdruck im HREF undefined liefert, wird die location gelassen wie sie ist, und nichts wird ins Browserfenster geschrieben. Und wie bekomme ich nun dieses undefined? Naja, man koennte einfach auf eine Eigenschaft zugreifen, die es nicht gibt, z.B. <javascript:alert(window.laberdumm);>. Viel cooler und vor allem sauberer ist es aber, die void()-Funktion zu verwenden. Und ausserdem ist das der vorgesehene Weg: http://developer.netscape.com/docs/manuals/js/client/jsref/ops.htm#1042625.

Der Ausdruck, der void() uebergeben wird, wird vor dem Aufruf ausgewertet. Logisch, denn bevor man ein Argument einer Funktion uebergeben kann, muss es berechnet werden. void() tut dann aber nichts als das das Argument zu ignorieren und undefined zurueckgeben. Natuerlich wollen wir das gleich mal ausprobieren, so ist es ja viel anschaulicher. Der Ausdruck "irgendwas" liefert den Wert "irgendwas" zurueck, wie man anhand von <javascript:alert('irgendwas');> sieht. (Na ist ja nicht zu fassen!) Wenn wir den Wert aber voiden (engl.: ungueltig machen), kommt undefined raus: <javascript:alert(void('irgendwas'));>. Das window-Objekt, das von window.open() zurueckgegeben wird, wird also durch void() einfach ignoriert und vergessen. Genauso geht es dem Dateinamen "1.html" aus der Zuweisung. Tja, so einfach ist das.

Wie in der Auslese steht, kann man auch den eigentlichen Code in eine Funktion setzen, und die dann im HREF aufrufen. Geht auch, denn solange aus einer Funktion nichts zurueckgegeben wird (durch return mit Parameter), kommt da eben nichts zurueck; man redet dann auch von undefined *g*. Also bitte kein return true oder sowas in die Funktion schreiben! Uebrigens gibt auch die alert()-Funktion nichts zurueck (wie man anhand von <javascript:alert(alert(7+8));> sieht), deshalb funktionieren diese ganzen JS-Hyperlinks hier so schoen.

So Maedel, das muss erstmal reichen fuer heute. *g* Die andere Sache mit den windows und frames, worum es ja eigentlich ging, habe ich erstmal weggelassen. Erstens war ich gestern abend zu muede (na ok, es war natuerlich heute frueh), und zweitens haette ich gnadenlos die 12000-Byte-Grenze des Forumsscripts ueberschritten, wenn ich mir dazu auch noch Gedanken gemacht haette. (Sind ja jetzt schon fast 9kB.) Aber Du weisst ja, Du entkommst mir nicht! Ist also nur aufgeschoben. ;-)

An dieser Stelle dann noch der obligatorische Hinweis, dass ich das alles nur mit Netscape 4.08 en WinNT getestet habe.

Trotz der Begruessung sind natuerlich auch die Kommentare aller anderen erwuenscht... ach naja, das wisst Ihr ja, ist ja schliesslich ein Forum, ne?

Also dann geh ich erst mal schlafen...
Bye then
Roland aka Calocybe

P.S. Stefan, ich finde die Sache mit dem [link:] ist die genialste Idee, die Du in der ganzen Forumszeit hattest.