Hoch Inhalt dieses Kapitels:

Linkwerk
screeneXa

Erhältlich u.a. bei  Amazon.de

7

Fenster und Frames

Von Christine Kühnel

7.1 Grundlagen

Spätestens bei der Verwendung von Frames fragen Sie sich sicher, ob denn Informationen zwischen Frames ausgetauscht werden können, ob auf Objekte anderer Frames zugegriffen werden kann. Sie wollen auch mal hier und da ein Fenster selbst öffnen, vielleicht sogar anschließend Beziehungen zum Ursprungsfenster herstellen. Geht das alles? Natürlich geht das.

7.1.1 Das window-Objekt

Alles dreht sich um das window-Objekt

Sie haben das Objekt window bereits kennen gelernt, wissen, dass es der Repräsentant eines Fensters oder auch eines Frames ist. An diesem Objekt hängt alles, um dieses Objekt dreht sich alles, was es in diesen Zusammenhang zu sagen gibt. Wir tun deswegen gut daran, uns etwas genauer damit zu befassen.

Werfen wir also zunächst einen Blick auf die Eigenschaften und Methoden, die wir in diesem Kapitel benötigen werden (Tabelle 7.1 und Tabelle 7.2).

Eigenschaften des window-Objektes:

EigenschaftBeschreibung
documentrepräsentiert das geladene Dokument
framesArray, das für alle enthaltenen Frames je ein window-Objekt enthält
locationenthält Information über den aktuellen URL
nameName des Fensters bzw. Frames
openerFenster, welches dieses hier geöffnet hat
parentübergeordnetes Fenster
selfReferenz auf das Fenster selbst
statusNachricht in der Statuszeile
TopFenster der obersten Ebene, immer Repräsentant des tatsächlichen Browserfensters
windowwindow-Objekt(e) (so vorhanden)

Tabelle 7.1: Eigenschaften des window-Objekts

Die Liste aller Eigenschaften ist je nach Browser wesentlich länger. Ich habe mich hier auf diejenigen beschränkt, die bei allen Browsern anzutreffen sind. Nicht erwähnte Eigenschaften sind leider zumeist browserspezifisch. In der Praxis bedeutet das: verzichten oder Unterschiede berücksichtigen. Lassen Sie sich aber deswegen keine grauen Haare wachsen; für das, was mit Fenstern und Frames am häufigsten passiert, reichen die angeführten Eigenschaften. Auch dieses Kapitel werden wir damit weitestgehend bewältigen, lediglich ganz am Ende, wenn es um Größen und Positionen geht, müssen wir an Unterschiede denken. Und dort beginnt sozusagen die Kür im Umgang mit Fenstern. Die Pflicht werden wir noch ohne das alles absolvieren können.

Noch ein Wort zu self:

self ist window "selbst"

Die self-Eigenschaft enthält eine Referenz auf das Fenster selbst. Das heißt, self.meineFunktion zum Beispiel ist identisch mit window.meineFunktion und self.irgendeinWert mit window.irgendeinWert. Ich benutze self gern; es ist so schön anschaulich, vom window "selbst" auszugehen. Finden Sie nicht auch? 1

Methoden des window-Objektes:

MethodeBeschreibungAnmerkung
close()schließt ein Fenster
moveBy()bewegt ein Fenster um eine vorgegebene Distanzab MSIE4, NN4
moveTo()bewegt ein Fenster zu einer vorgegebenen Positionab MSIE4, NN4
open()öffnet ein Fenster
resizeBy()verändert die Größe um vorgegebene Werteab MSIE4, NN4
resizeTo()verändert die Größe auf vorgegebene Werteab MSIE4, NN4

Tabelle 7.2: Methoden des window-Objektes

Muss ich es noch erwähnen? Auch diese Liste ist nicht vollständig. Ähnlich wie bei den Eigenschaften gibt es auch hier eine Reihe zusätzlicher browserspezifischer Methoden. Sie sehen, sogar einige der hier angegebenen kommen nicht ohne die Anmerkung aus, welche Browser sie kennen. Aber noch immer gilt: kein Grund zur Panik, erst ganz am Ende des Kapitels werden wir damit konfrontiert.

Event-Handler

Was fehlt uns neben Eigenschaften und Methoden des window-Objektes noch? Die Event-Handler. Wir benötigen hier nur einen:

In der Inline-Schreibweise im body-Tag ist er Ihnen bereits begegnet, etwa so:

Wie Sie wissen, feuert er, wenn das Dokument komplett geladen wurde. Das gilt sowohl für einfache Dokumente als auch für Framesets, bei denen bezieht sich "geladen" auf das gesamte Frameset:

7.1.2 Eigene Fenster verwenden

Jetzt aber erst einmal genug der grauen Theorie, wenden wir uns der Praxis zu, öffnen wir endlich unsere ersten eigenen Fenster. Das erledigt window.open()für uns; die allgemeine Syntax dafür sieht so aus:

oNewWindow = window.open([sURL][,sName][,sFeatures]);

Bei sFeatures sollten wir etwas länger verweilen. Von Browser zu Browser müssen wir hier schon wieder mit Unterschieden leben. Am besten schauen wir uns das in der Übersicht in Tabelle 7.3: Parameter in window.open() an.

FeatureBeschreibungBrowser
directories ={ yes | no | 1 | 0 }Directory-Buttons
location ={ yes | no | 1 | 0 }Adress-Zeile
menubar ={ yes | no | 1 | 0 }Menü-Leiste
resizable ={ yes | no | 1 | 0 }in der Größe veränderbar
scrollbars ={ yes | no | 1 | 0 }Scrollleisten
status ={ yes | no | 1 | 0 }Statuszeile
height = numberHöhe
width = numberBreite
left = numberAbstand vom linken Bildschirmrand in PixelnMSIE ab4
top = numberAbstand vom oberen Bildschirmrand in PixelnMSIE ab4
screenX  = numberAbstand vom linken Bildschirmrand in PixelnNN4
ScreenY  = numberAbstand vom oberen Bildschirmrand in PixelnNN4
innerWidth = numberinnere Breite (ersetzt width)NN4
innerHeight = numberinnere Höhe (ersetzt height)NN4
fullscreen ={ yes | no | 1 | 0 }Vollbildmodus, ohne jegliche LeistenMSIE ab4
dependent ={ yes | no | 1 | 0 }abhängiges Fenster, wird geschlossen, wenn öffnendes Fenster geschlossen wirdNN4

Tabelle 7.3: Parameter in window.open()

Sie ahnen es, auch die Übersicht der Features ist nicht vollständig. Hier fehlen aber nur wenige, die Sie in der Praxis sicher kaum vermissen werden. Freuen Sie sich stattdessen mit mir, dass die Zahl der Übereinstimmungen recht groß ist. Wenn Sie nicht positionieren wollen oder nicht gerade vorhaben, den ohnehin nur bei MSIE ohne Weiteres möglichen Vollbildmodus zu nutzen, können Sie sogar auf jegliche Unterscheidung verzichten.

Hinweis

Auf eines sollten Sie aber unbedingt achten: Leerzeichen zwischen den Parametern sind zum Beispiel für Netscape-Browser Fehler, sie führen in der Regel dazu, dass der Browser die Interpretation an der Stelle abbricht und für alles, was danach kommt, Standardwerte verwendet. Also gewöhnen Sie sich am besten gleich an, grundsätzlich keine Leerzeichen zu schreiben.

Hinweis

Fenster kleiner als 100x100 können Sie nicht so ohne Weiteres öffnen. Das ist eines der Sicherheitsfeatures 2 der Browser. Sowohl Microsoft als auch Netscape benutzen diese Grenze.

Jetzt wissen wir endlich genug, um unser erstes Fenster zu öffnen. Es soll fensterchen (sName) heißen, 400x300 Pixel groß sein, Statuszeile und Menüleiste haben und, wenn notwendig, Scrollleisten zeigen, außerdem soll der Benutzer die Größe verändern können.

Beispiel

Beginnen wir damit, den Parameterstring (sFeatures) in einer String-Variablen zusammenzubauen. So vorzugehen erweist sich meist als ein sehr praktisches Verfahren:

var para =  '';
para += 'width=400,height=300';
para += ',status=1,';
para += ',menubar=1';
para += ',scrollbars=1';
para += ',resizable=1';
para += ',toolbar=0';
para += ',location=0';
para += ',directories=0';

Diese Kombination halte ich persönlich übrigens für eine in vielen Fällen sinnvolle. Sie macht Vorgaben, lässt aber dem Benutzer noch genügend Freiheit, das Fenster seinen ganz persönlichen Wünschen anzupassen. Probieren Sie es ruhig aus, schauen Sie, ob Sie meine Meinung teilen.

Mit dem so vorbereitenden String ist es nun eine Kleinigkeit, das Fenster selbst zu öffnen:

neu = window.open('irgendwo.html','fensterchen',para);

Sinnvollerweise werden Sie die vorstehenden Anweisungen in einer Funktion unterbringen, um sie bei Bedarf aufrufen zu können.

Fenster, die man geöffnet hat, kann man auch wieder schließen. window.close() erledigt das. Sie dürfen allerdings nicht jedes beliebige Fenster schließen. Bei Fenstern, die Sie selbst per JavaScript geöffnet haben, und solchen, deren History nur den gerade aktuellen Eintrag enthält, steht Ihnen nichts im Wege. Anderenfalls wird der Browser zuerst einmal dem Benutzer die Frage stellen, ob ihm das recht ist. Diese Sicherheitsmaßnahme hat ihre Berechtigung. Stellen Sie sich vor, Sie surfen durchs Web, klicken sich unbesorgt von Link zu Link, ohne sich den URL jeder einzelnen Seite einzuprägen. Das müssen Sie ja auch nicht, denn genau dafür gibt es die History, die Sie zu jeder besuchten Seite ganz einfach wieder zurückführt. Und nun gelangen Sie plötzlich auf eine Seite, deren Autor meint, das Fenster wäre überflüssig, macht es einfach zu. Wie würden Sie reagieren? Ich vermute, zu Jubelstürmen reißt Sie das nicht gerade hin. Aus dem Grund hat man diese Abfrage eingebaut, die solches nur mit Zustimmung des Benutzers zulässt. Existiert nur dieses eine Fenster, so dass window.close() auch gleich den gesamten Browser schließen würde, fragen sie in der Regel auch erst einmal nach.

7.1.3 Beziehungen zwischen Fenstern und Frames

window ist Eigenschaft von window

In der Liste der Eigenschaften haben Sie gelesen, dass window eine Eigenschaft von window sein kann. Wie das? Wir haben gerade eben mit

neu = window.open()

ein Fenster geöffnet. Im Ergebnis ist jetzt neu eine Eigenschaft unseres Ursprungsfensters. Mit

alert(self.neu); 3

erkennen wir, dass es ein Objekt ist, genauer gesagt, ein window-Objekt. Damit haben wir auch gleich einen Weg gefunden, auf dessen Eigenschaften zuzugreifen: self.neu.Eigenschaft sollte uns das ermöglichen. Probieren wir es aus, bauen wir diesen Link in unsere Ursprungsdatei ein und klicken ihn nach dem Öffnen an:

<a href="javascript:for (var i in self.neu) alert(i)">
   über</a> <kbd>neu</kbd><br>

Sie sehen, die Eigenschaften des neuen Fensters werden Ihnen der Reihe nach genannt. 4 Damit ist es nun ein Leichtes für Sie, auch eventuell in diesem Fenster selbst definierte Variablen, Objekte und Funktionen zu erreichen.

Ursprungsfenster erreichen über opener

Was uns noch fehlt, ist der umgekehrte Weg. Sie wollen vom neuen Fenster auf das Ursprungsfenster zugreifen. Dafür gibt es die Eigenschaft opener. Versuchen wir jetzt also, diesen umgekehrten Weg zu gehen, schreiben wir in die Datei, die in das neue Fenster geladen wird:

<a href="javascript:for (var i in self.opener) alert(i)">
   über</a> <kbd>neu</kbd><br>

Es passiert, was wir erwartet haben: Wir bekommen die Eigenschaften des Ursprungsfensters nacheinander gezeigt. Haben Sie beobachtet, dass auch die Funktion oeffnen() und selbst neu dabei waren?

Das war aber noch nicht alles, was es zu "window ist Eigenschaft von window" zu sagen gibt. Denken Sie bitte an Frames. Sie wissen, jeder Frame hat sein eigenes window-Objekt, gehört aber zum übergeordneten Fenster. Es sieht aus, als würde es jetzt kompliziert. Keine Sorge, es bleibt überschaubar. Man muss nur ein paar Dinge dazu wissen.

Schauen wir uns ein Beispiel an, dessen Struktur Ihnen ganz sicher vertraut ist, ein Frameset mit zwei Frames.

<html><head>
<title>ein Frameset</title>
</head>
<frameset cols="30%,70%">
    <frame name="links" src="fuer_links.html">
    <frame name="rechts" src="fuer_rechts.html">
    <noframes>
    </noframes>
</frameset>
</html>

Bleiben wir zunächst auf dieser Ebene und sehen nach, welche Frames existieren. Dafür eignet sich frames[] recht gut. In dieser Collection finden wir die Frames eines Fensters wieder. Wie bereits bei anderen Collections gesehen, existiert eine Eigenschaft length, die uns die Anzahl der Elemente liefert. Da die Elemente window-Objekte sind, haben sie auch eine name-Eigenschaft. Das bedeutet, wir können den folgenden kleinen Script-Block im head unterbringen:

<script language="JavaScript" type="text/javascript">
<!--
function zeigeFrames()
{
  var Aus = '';
  Aus += 'frames.length  : '+window.frames.length+'\n';
  for (var i=0; i<window.frames.length; i++)
    Aus+='frames['+i+'].name : '+window.frames[i].name+'\n';
  alert(Aus);
}
window.onload = zeigeFrames;
// -->
</script>

Nachdem der Inhalt geladen wurde, erfahren wir:

  frames.length  : 2
  frames[0].name : links
  frames[1].name : rechts

Die Werte der name-Eigenschaften resultieren also auch bei Frames aus name-Attributen, nämlich aus denen der frame-Tags. Diese frame-Tags sind es also, mit deren Hilfe im HTML-Code die window-Objekte definiert werden.

Die Angabe numerischer Indizes in frames[] ist eine Möglichkeit, Frames anzusprechen. Wie bereits bei anderen Objekten gesehen, gibt es auch hier noch andere Wege. Sofort klar sind Ihnen sicher:

Wir haben weiter oben veranlasst, dass unsere Funktion zeigeFrames() nach dem Laden ausgeführt wird, indem wir mit

dem Event-Handler onload die Funktion zeigeFrames zugewiesen haben. Das ist zwar die eleganteste Art, aber Sie sollten daran denken, dass die alten Browser sie nicht kennen. Wenn Sie nicht ausschließen können, dass Ihre Skripte mit so einem Browser in Berührung kommen, verwenden Sie alternativ die Inline-Form:

<frameset cols="30%,70%" onload="zeigeFrames()">

Auf übergeordnete Fenster zugreifen

Auch hier ist die Umkehrung interessant: Wie kann man von einem Frame aus auf das "Hauptfenster" zugreifen? Auch einen Frame von einem anderen aus zu erreichen, hatte ich Ihnen versprochen. Dafür gibt es zwei Eigenschaften des window-Objektes, die uns gute Dienste leisten: top und parent.

top und parent

top weist immer auf das Fenster der obersten Ebene. parent weist auf die nächsthöhere Ebene. In unserem Beispiel sind sie identisch, aber manchmal geht es ja auch etwas verschachtelter zu. Sind gar keine Frames vorhanden, so sind beide identisch mit window selbst.

Beispiel

Nehmen wir an, in unserem Frame links gibt es eine Variable abc und im Frame rechts eine Funktion xyz(). Dann erreichen wir die beiden zum Beispiel so:

Von Frame links aus:

Von Frame rechts aus:

Lassen Sie Ihrer Phantasie freien Lauf, überlegen Sie, wie man kreuz und quer referenzieren kann, wie man vielleicht zusätzlich noch von einem Frame aus geöffnete Fenster erreicht oder sogar darin enthaltene einzelne Frames. Dass das alles tatsächlich geht, ist Ihnen sicher inzwischen klar geworden. Das Prinzip ist sehr logisch, man muss nur die Strukturen ständig im Auge behalten.

7.1.4 Inhalte dynamisch generieren

Dass Sie Teile einer Seite dynamisch mit Hilfe von JavaScript generieren können, wissen Sie bereits; document.write() haben Sie schon des Öfteren benutzt. Das ist immer dann sinnvoll, wenn es Passagen gibt, die in Abhängigkeit von konkreten Umständen variieren. Die entsprechenden JavaScript-Anweisungen dafür haben Sie an geeigneter Stelle in der Datei selbst untergebracht.

Was aber, wenn die statischen Teile gar nicht vorhanden sind oder nicht mehr der Rede wert sind? Haben Sie schon einmal daran gedacht, ganze Seiten dynamisch aufzubauen? Das kann recht praktisch sein, Sie sparen sich eine statische Datei, die vermutlich ohnehin kaum mehr als <html><head>, </head><body> und </body></html> enthalten würde. Dafür muss man den HTML-Code so einer physisch gar nicht existierenden Datei natürlich von "anderswo" aus aufbauen. Irgendwo müssen die dafür erforderlichen JavaScript-Anweisungen ja stehen. Wir haben gerade gesehen, dass Fenster und Frames von anderen Fenstern oder Frames aus angesprochen werden können. Was liegt also näher, als über genau diesen Weg komplette Inhalte aufzubauen?

Bevor wir das nun ausprobieren, müssen wir uns noch zwei Methoden des document-Objektes ansehen:

document.open() und document.close().

So ein dynamischer Aufbau hat damit immer die folgende Struktur 5:

Fensterreferenz.document.open();
Fensterreferenz.document.write();
Fensterreferenz.document.close();

Bitte verwechseln Sie document.open() und document.close() nicht mit window.open() und window.close().

Probieren wir es am Beispiel einer kleinen Test-Hilfe aus, lassen wir uns die Eigenschaften eines Objektes in einem neuen Fenster auflisten. Das Skript im folgenden Beispiel ist schon fast selbsterklärend, es öffnet ein Fenster, schreibt dort hinein den Code einer kompletten HTML-Datei von <html> bis </html>. Der eigentliche Inhalt ist eine Liste aller Eigenschaften unseres Objektes, die über for...in ermittelt wird. Beim Aufruf der Funktion zeigeObjekt() übergeben wir ganz einfach das Objekt als String, über das wir etwas erfahren wollen.

Beispiel

<html><head>
<title>zeige Objekt</title>
<script language="JavaScript" type="text/javascript">
<!--
function zeigeObjekt(pObjekt)
{
   var para =
   'height=400,width=500,scrollbars=1,resizable=1';
   Fenster=window.open('','Objekte',para);
   // die eigentliche Ausgabe etwas verzoegern
   setTimeout('schreibeObjekt("'+pObjekt+'")',100)
}

function schreibeObjekt(pObjekt)
{
   var Objekt = eval(pObjekt);
   var Eigenschaft;
   var Aus = '<html><head><title></title></head>';
   Aus += '<body><pre>\n';
   for(var i in Objekt)
   {
      // in JS1.0 verzichten Sie bitte auf diese
      // Unterscheidung, isNAN() ist dort in
      // der Regel nicht bekannt
      if (isNaN(parseInt(i)))
         Eigenschaft = pObjekt+'.'+i;
      else
         Eigenschaft = pObjekt +'['+ i + ']';
      Aus += Eigenschaft +'=' +Objekt[i] + '\n';
   }
   Aus += '</pre></body></html>';
   Fenster.document.open();
   Fenster.document.write(Aus);
   Fenster.document.close();
}
// -->
</script>
</head>
<body>
<p>
<a href="javascript:zeigeObjekt('window')">Info</a>
</p>
</body>
</html>

Hinweis

Warum habe ich zwei Funktionen benutzt, es ginge doch auch in einer? Ja, im Prinzip ist das richtig. Aber unter bestimmten Umständen kann es Ihnen passieren, dass die Zeit nicht ausreicht, die der Browser zum Öffnen des Fensters zur Verfügung hat. Sie erhalten eine Fehlermeldung, wenn Sie zu früh etwas hineinschreiben wollen. Deswegen bauen wir einen für uns kaum merklichen, für den Browser aber ausreichenden Zeitpuffer ein.

Auf eines möchte ich noch hinweisen. Dieses einfache Script hat einen ganz kleinen praktische Haken:

Für Testzwecke reicht es sicher, das zu wissen. Bei Skripten, die auf Rechnern der Besucher Ihrer Seiten laufen, sollten Sie sich allerdings Gedanken darüber machen, wie Fehler zu vermeiden, abzufangen und zu behandeln sind. Nutzen Sie das in Kapitel 3 über Browserunterschiede Gelernte und lesen Sie später in Kapitel 11 wie man Fehler abfangen und behandeln kann.

Externe JavaScript-Dateien sind praktisch für Tests

Möchten Sie diese und ähnliche Funktionen ganz schnell parat haben, wenn es etwas zu testen gibt? Dann packen Sie sie einfach in eine externe JavaScript-Datei. Die ist bei Bedarf ganz schnell eingebunden.

Wünschen Sie sich solche Hilfsfunktionen zum Objektbaum Ihrer Seiten noch komfortabler? In Kapitel 9 bekommen Sie kundige Anleitung zum Basteln. Viel eleganter als externe JavaScript-Dateien sind für solche Zwecke übrigens Bookmarklets. Die kennen Sie nicht? Das sind JavaScript-Anweisungen, die man direkt als Bookmark im Browser speichert. Damit stehen sie auf jeder Seite zur Verfügung, ohne dass der Code direkt in die Datei eingebunden werden muss.

Wollen Sie dies ausprobieren? Legen Sie sich einfach einmal ein Bookmark an, geben lediglich anstelle des gewohnten URLs ein:

javascript:alert('Hallo, ich bin ein Bookmarklet')

Was passiert, wenn Sie das Bookmark anwählen? Die Anweisung wird ausgeführt. Das ist das Prinzip - einfach und hilfreich. Mehr zum Thema Bookmarklets finden Sie auf der CD; schauen Sie bei Wolfgang Schwarz nach, er ist unter den Autoren dieses Buches der Spezialist für Bookmarklets.

7.1.5 Informationen weitergeben

Nicht immer reicht es aus, auf Fenster und deren Inhalte zuzugreifen, die zur gleichen Zeit geladen sind. Ab und an wünschen Sie sicher, Informationen an Seiten weiterzureichen, die erst später geladen werden. Dafür gibt es zwei grundlegende Herangehensweisen.

search- und hash-String benutzen

Links, in denen zum Beispiel Anker angesprungen werden oder in denen Parameter mitgegeben werden, kennen Sie. So etwas ist Ihnen von daher geläufig:

<a
href="http://xyz.de/irgendwo.html?x=17&y=abc">irgendwas</a>
<a
href="http://xyz.de/irgendwo.html#genauer">nach woanders</a>

Wir machen uns zunutze, dass man Seiten so aufrufen kann. Das Link-Objekt stellt uns die Teile sogar als separate Eigenschaften zur Verfügung. Schauen wir mal, was es so alles gibt. Die weiter oben benutzte Funktion zeigeObjekt() kann uns auch dabei helfen. Konstruieren wir also zwei Links und sehen nach:

Beispiel

<p>
<a href="xyz.html#irgendwas">...#irgendwas</a>
<br>
<a href="xyz.html?x=123&y=abc">...?x=123&y=abc</a>
<br></p>
<p>
<a href="javascript:zeigeObjekt('document.links[0]')">Info zum ersten Link</a><br>
<a href="javascript:zeigeObjekt('document.links[1]')">Info zum zweiten Link</a><br></p>

Je nach verwendetem Browser erhalten wir mehr oder weniger lange Listen der Eigenschaften unserer beiden Link-Objekte. Enthalten sind aber unabhängig vom Browser sicher

Folgen wir nun den beiden Links und sehen in der aufgerufenen Seite nach, ob die Werte in self.location wiederzufinden sind:

<a href="javascript:zeigeObjekt('self.location')">self.location</a>

Und siehe da, sie sind es 6. Damit haben wir einen Weg gefunden, den wir beschreiten können, wenn Werte von Seite zu Seite weitergereicht werden sollen.

window.name verwenden

Die eben beschriebene Lösung funktioniert, aber sie hat auch ein paar kleine Nachteile. Zum Beispiel wird durch Anhängen eines search-Strings an den URL die Seite neu angefordert, eine vielleicht im Cache des Besuchers bereits vorhandene Kopie nicht genutzt.

window.name

Schauen wir uns also noch eine andere Möglichkeit an, eine in meinen Augen viel elegantere. Die Idee besteht darin, window.name zu verwenden. Diese Eigenschaft existiert so lange, wie das Fenster selbst existiert. Eigentlich ganz einfach, nicht wahr? Man muss eben nur darauf kommen. Beschrieben wurde dieses Verfahren im März 1999 von Thomas Fischer in der Newsgroup de.comp.lang.javascript.

Wir benutzen wieder ein ganz einfaches Beispiel. Aus einer Select-Box soll der Besucher die Größe seines Wohnortes entsprechend der Einwohnerzahl heraussuchen.

Beispiel

<html><head>
<title>Einwohnerzahlen</title>
<script language="JavaScript" type="text/javascript">
<!--
function weitergeben(pObjekt)
{
   window.name=pObjekt.options[pObjekt.selectedIndex].value;
   window.location.href="naechsteSeite.html";
   return false;
}
// -->
</script>
</head>

<body>
<form onsubmit="return weitergeben(this.einwohner)">
Wieviel Einwohner hat Ihr Wohnort?<br>
Es sind mehr als
<select name="einwohner">
<option value="1000">0</option>
<option value="10000">1.000</option>
<option value="100000">10.000</option>
<option value="1000000">100.000</option>
<option value="10000000">1.000.000</option>
</select><input type=submit>
</form>
</body>
</html>

Die wirklich interessante Anweisung ist diese hier:

window.name=pObjekt.options[pObjekt.selectedIndex].value;

Der Wert von window.name wird in Abhängigkeit von der getroffenen Auswahl gesetzt. Eine andere Datei kann nun in dasselbe Fenster geladen werden, ohne dass die Information verloren geht. Versuchen wir es und greifen anschließend auf window.name zu:

<html><head>
<title> Einwohnerzahlen</title>
</head>
<body>
<p>
Aha, Sie wohnen also in einem Ort mit
<script language="JavaScript" type="text/javascript">
<!--
var einwohner = parseInt(window.name);
if (einwohner>1000)
   document.write('mehr als ' + einwohner/10);
if (einwohner>1000 && einwohner<1000000)
   document.write(' und ');
if (einwohner<1000000)
  document.write('weniger als ' + einwohner)
// -->
</script>
Einwohnern.</p>
</body>
</html>

window.name bleibt auch weiterhin erhalten, Sie müssen nicht ständig "weiterreichen", so wie das beim vorgenannten Verfahren nötig ist, wenn Sie auf die Information auch noch von weiteren Seiten aus zugreifen wollen. Ihre Besucher können zwischendurch sogar Abstecher zu anderen Seiten machen und wieder zurückkehren, sie dürfen nur das Fenster nicht schließen.

Eine Einschränkung existiert allerdings. Es sind nur Ziffern, Buchstaben und der Unterstrich zulässig. Sollten Sie andere Zeichen benötigen, so müssen Sie sich etwas einfallen lassen, wie Sie die geschickt durch zulässige ersetzen. Weil es zu weit führt, in diesem Buch auch darauf einzugehen, gestatten Sie mir, Sie auf einen Beitrag hinzuweisen, den Hatto v. Hatzfeld zu dieser Thematik für "SELFHTML aktuell" ([SELF00]) geschrieben hat. Er enthält u.a. auch eine Lösung zur Überwindung dieser kleinen Hürde: http://www.teamone.de/selfaktuell/artikel/wertueb.htm

7.1.6 Größe und Position

Kann man auch etwas über die Größe bestehender Fenster erfahren? Kann man Fenster positionieren? Kann man die Größe vorhandener Fenster verändern? Kann man Fenster verschieben? Ja, auch das ist möglich. Aber jetzt sind wir an der Stelle, an der die Einschränkungen und zum Teil auch die Unterschiede beginnen. Das alles ist ohnehin erst ab Netscape 4 bzw. Microsoft Internet Explorer 4 möglich, über ältere Browser brauchen wir also gar nicht zu reden. Und die neueren sind sich leider nicht einig, deswegen müssen wir unterscheiden. Also gehen wir die Möglichkeiten der Reihe nach an:

Position beim Öffnen vorgeben

InTabelle 7.3 haben wir gesehen, dass man dem Fenster im Parameterstring auch eine Position mitgeben kann. Zwar heißen die Vorgaben bei MS "left" und "top" und bei Netscape "screenX" und "screenY", aber in der Praxis verstehen die Netscape-Browser, die ich kenne, auch "left" und "top". Wollen Sie sich darauf nicht verlassen, dann bauen Sie beim Zusammenstellen der Parameter eine Browserunterscheidung ein. Darauf gehe ich hier nicht im Detail ein, denn Microsoft- und Netscape-Browser zu unterscheiden, wird Sie in Kapitel 10 ohnehin beschäftigen.

Fenster verschieben, Fenstergröße ändern

In Tabelle 7.2 haben wir Methoden des window-Objektes gesehen, die uns den Wunsch erfüllen, Fenstergrößen zu ändern (window.resizeBy(), window.resizeTo()) oder Fenster zu verschieben (window.moveTo(), window.moveBy()). Diese Methoden sind nicht kompliziert in ihrer Anwendung, ein paar kleine Beispiele verdeutlichen, was womit erreicht werden kann:

So, wie bereits beim Öffnen neuer Fenster, ist das Minimum auch hier 100x100, darin sind sich MS und Netscape einig. Beim Versuch, die linke obere Ecke eines Fensters auf negative Koordinaten zu schieben, reagieren sie nicht mehr so einheitlich, NN4 lässt das zum Beispiel nicht zu. Normalerweise werden Sie so etwas jedoch kaum brauchen, wenn doch, dann sollten Sie einen Blick in die jeweiligen Dokumentationen werfen und vor allem probieren.

Hinweis

Wollen Sie wirklich vorhandene Fenster verschieben oder deren Größe ändern? Für Fenster, die Sie selbst geöffnet haben, kann das ganz nett und witzig sein. Bevor Sie sich aber an das vielleicht einzige Fenster des Besuchers wagen, denken Sie bitte sehr gründlich nach. Es könnte sein, Ihr Besucher empfindet das, was Sie für ungeheuer cool halten, als störend.

Fenstergröße erfahren

Was verraten uns die Browser über Größe und Position von Fenstern?

Der Navigator 4 bietet dafür window-Eigenschaften an:

Eine direkte Analogie dazu ist bei Microsoft-Browsern nicht zu finden. Das window-Objekt schweigt sich über all das aus. Die Innenmaße eines Fensters lassen sich dennoch ermitteln. Ich muss an dieser Stelle ein klein wenig vorgreifen, denn eigentlich gehört das, was jetzt kommt, in Kapitel 9. MSIE hat ein body-Objekt, das dem body-Element entspricht. Zwei der Eigenschaften sagen uns etwas über die Maße des Fensters:

Da es sich um Eigenschaften von document handelt, ist ein geladenes Dokument Voraussetzung. Außenmaße und Position des Fensters bleibt uns MSIE schuldig.

screen-Objekt

Will man auf dem Bildschirm genau positionieren, so ist oft dessen Größe interessant. Dafür existiert das screen-Objekt (auch erst ab MSIE 4 bzw. NN 4) mit den Eigenschaften width und height, das bedarf sicher keiner näheren Erklärung.

Ein kleines Beispiel gönnen wir uns hier. Es hat zwar nicht unbedingt viel praktischen Nutzwert, ist aber anschaulich und außerdem ganz nett. Lassen wir ein Fenster hüpfen, von links oben nach rechts oben, nach rechts unten, nach links unten und immer so weiter.

Beispiel

Für solche Spielereien öffnen wir uns ein zusätzliches Fenster:

<html><head>
<title>Hopp, hopp, hopp</title>
<script language="JavaScript" type="text/javascript">
<!--
function machauf()
{
   var para =  '';
   para += 'width=300,height=200';
   para += ',status=0,menubar=0,scrollbars=0';
   para += ',resizable=1,toolbar=0,location=0';
   para += ',directories=0';
   Neu = window.open('hopphopp.html','',para);
}
// -->
</script>
</head>
<body>
<a href="javascript:machauf()">auf geht's</a>
</body>
</html>

Das Hüpfen machen wir uns einfach. Wir schreiben vier Funktionen, für jede Ecke eine. Natürlich wäre es eleganter, nur eine Funktion zu verwenden, ihr jeweils zu sagen, was gerade zu tun ist. Aber wäre das auch so schön anschaulich wie in der folgenden hopphopp.html?

<html><head>
<title>Hopp, hopp, hopp</title>
<script language="JavaScript" type="text/javascript">
<!--
// zuerst mal auf die richtige Groesse trimmen
function schritt1() {
   self.resizeTo(100,100);
   setTimeout('schritt2()',500);
}
//nach links oben
function schritt2() {
   self.moveTo(10,10)
   setTimeout('schritt3()',500);
}
// nach rechts oben
function schritt3() {
   self.moveTo(screen.width-breit,10)
   setTimeout('schritt4()',500);
}
// nach rechts unten
function schritt4() {
   self.moveTo(screen.width-breit,screen.height-hoch)
   setTimeout('schritt5()',500);
}
// nach links unten
function schritt5() {
   self.moveTo(10,screen.height-hoch)
   setTimeout('schritt2()',500);
}
// damit geht es los
function los()
{
   breit = 0;
   hoch  = 0;
   if ((self.innerWidth) ||
       (self.document.body &&
        self.document.body.offsetWidth))
   {
      breit = 130;
      hoch  = 130;
   }
   if (!breit) return;
   setTimeout('schritt1()',500);
}
// -->
</script>
</head>
<body bgcolor="#00ff00" onload="los()">
</body>
</html>

7.2 Übungen

Uebung

leicht

1. Übung

Schauen Sie sich bitte die Konstellation in Abbildung 7.1 an. Sie haben ein Frameset mit drei Frames: Links, Mitte und Rechts. Aus Mitte heraus haben Sie das Fenster Neu geöffnet. Das wiederum enthält die Frames Oben und Unten.

Abb. 7.1

Abbildung 7.1: Übung 1 Beziehungen zwischen Fenstern und Frames

Uebung

leicht

2. Übung

Wie stellen Sie fest, ob eine Datei Teil eines Framesets ist?

Uebung

mittel

3. Übung

Sie wollen eine kleine Galerie gleich großer Bilder präsentieren. Die Bilder sollen in einem kleinen zusätzlichen Fenster gezeigt werden. Für die Steuerung verwenden Sie bitte zwei Links:

Uebung

leicht

4. Übung

Welche Möglichkeiten haben Sie, Informationen von Seite zu Seite weiterzureichen?

Uebung

mittel

5. Übung

Eine kleine Farb-Spielerei gefällig? Lassen Sie doch mal die Hintergrundfarben für eine beliebige Anzahl von Frames zyklisch wechseln.

Uebung

schwer

6. Übung

Erinnern Sie sich an die Linkliste aus Kapitel 3?

So richtig schön war die noch nicht. Angewiesen darauf, für jede Form der Anzeige eine eigene Datei zu erstellen, war es nicht wirklich eine bequeme Lösung. Inzwischen wissen Sie, dass man Ausgaben auch in anderen Frames generieren kann. Das heißt, man könnte jetzt darüber nachdenken, die Liste selbst nur einmal zu laden und ganz verschiedene, sozusagen auf Knopfdruck abrufbare Anzeigefunktionen zu schreiben.

Uebung

mittel

7. Übung

Öffnen Sie ein kleines Fenster, positionieren Sie es in der linken oberen Bildschirmecke und verändern Sie die Größe schrittweise, bis sie ca. 2/3 der Bildschirmbreite und -höhe beträgt. Alle Aktionen sollen vom öffnenden Fenster aus erfolgen.

7.3 Tipps

Tipps zur 3. Übung

Tipps zur 5. Übung

Tipps zur 6. Übung

Tipps zur 7. Übung

7.4 Lösungen

Lösung zu 1

Lösung zu 2

Fragen Sie nach, ob das Fenster selbst identisch ist mit dem auf der obersten Ebene in der Fensterhierarchie:

Lösung zu 3

Das hier könnte die Datei mit den beiden Links sein:

<html>
<head>
<title>Kleine Galerie</title>
<script language="JavaScript" type="text/javascript">
<!--
// Browser, die kein image-Objekt kennen,
// blocken wir ab,
// initialisieren dann das Array fuer die Bilddateien,
// setzen uns einen Index, um zu wissen, bei welchem
// Bild unsere Anzeige angekommen ist
if (document.images)
{
   Bilder    = new Array();
   Bilder[0] = 'images/erstesBild.gif';
   Bilder[1] = 'images/zweitesBild.gif';
   Bilder[2] = 'images/drittesBild.gif';
   var index = 0;
}
// Fenster auf
function oeffnen()
{
   if (!document.images) return true;
   var para =  '';
   para += 'width=300,height=300';
   para += ',status=1,';
   para += ',menubar=1';
   para += ',scrollbars=1';
   para += ',resizable=1';
   para += ',toolbar=0';
   para += ',location=0';
   para += ',directories=0';
   fensterchen = window.open('bilder.html','neu',para);
   fensterchen.focus();
   return false;
}
// Bild wechseln
function naechstesBild()
{
// existiert fensterchen und darin dasBild?
   if (self.fensterchen &&
       self.fensterchen.document &&
       self.fensterchen.document.dasBild)   {
      index++;
      // Am Ende? Dann von vorn anfangen
      if (index >= Bilder.length)
         index = 0;
      // Bild tauschen
      fensterchen.document.dasBild.src=Bilder[index];
      fensterchen.focus();
   }
}   
// -->
</script>
</head>
<body>
<h1>Kleine Galerie</h1>
<p>
<a href="bilder.html"
   onclick="return oeffnen()">zeig mal die Bilder</a>
</p>
<p>
<a href="#"
   onclick="return naechstesBild()">nächstes Bild</a>
</p>
</body>
</html>

Die Datei bilder.html könnte so aussehen:

<html>
<head>
<title>Bilder</title>
</head>
<body>
<div align="center">
<img src="'images/erstesBild.gif" name="dasBild"
     width="200" height="200" border="0"
     alt="aus meiner Galerie">
</div>
</body>
</html>

Lösung zu 4

Es gibt verschiedene Möglichkeiten. Zuerst ist die Frage zu stellen, ob die Seiten, zwischen denen Informationen auszutauschen sind, gleichzeitig geladen sind. Ist das mit Sicherheit der Fall, dann ist das Problem schon so gut wie gelöst. Wenn sich die Fenster untereinander "kennen", können sie auch untereinander auf ihre Inhalte zugreifen.

Sollen Informationen im Wortsinn "weitergegeben" werden, also wirklich später verfügbar sein, dann bieten sich an: search- bzw. hash-String und window.name.

Lösung zu 5

Ich habe hier einmal 10 Frames benutzt 7 und ganz einfach in jeden Frame dieselbe Datei geladen, es kam ja nicht auf Inhalte an, und nachträglich die Hintergrundfarben in der Funktion initia() gesetzt. Danach geht es los. faerben() wird ein wenig zeitverzögert aufgerufen, die Variable lauf zeigt an, dass der Wechsel läuft.

<html>
<head>
<title>Famelei</title>
<script language="JavaScript" type="text/javascript">
<!--
function initia()
{
   self.frames[0].document.bgColor = "#ff0033";
   self.frames[1].document.bgColor = "#cc3399";
   self.frames[2].document.bgColor = "#cc66cc";
   self.frames[3].document.bgColor = "#9966cc";
   self.frames[4].document.bgColor = "#99ccff";
   self.frames[5].document.bgColor = "#33cc99";
   self.frames[6].document.bgColor = "#33cc00";
   self.frames[7].document.bgColor = "#ccff66";
   self.frames[8].document.bgColor = "#ffff66";
   self.frames[9].document.bgColor = "#ff9900";
   lauf = 1;
   setTimeout('faerben()',100);
}
// solange lauf wahr ist, werden die Hintergrundfarben
// versetzt
function faerben()
{
   var i = parent.frames.length-1;
   // letzte Farbe in der Kette merken
   var Farbe = parent.frames[i].document.bgColor
   while (i>0)
   {
      parent.frames[i].document.bgColor =
         parent.frames[i-1].document.bgColor;
      i--;
   }
   parent.frames[0].document.bgColor =Farbe;
   if (lauf)
      setTimeout('faerben()',500);
}
// -->
</script>
</head>
<frameset cols="*,*,*,*,*,*,*,*,*,*" onload="initia()">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
   <frame src="farbig.html">
</frameset>
<noframes></noframes>
</html>

In eine oder mehrere Dateien in den Einzelframes bauen wir noch eine Möglichkeit ein, das Spielchen zu stoppen. Was ist zu tun? Nicht viel. Das window mit dem Frameset enthält eine Variable lauf, nur wenn diese auf true steht, wird der nächste Farbwechselzyklus angestoßen. Also setzen wir die einfach auf false. Unsere kleine Beispieldatei farbig.html enthält dafür eine Funktion anhalten() und einen Button, mit dem sich die Funktion aufrufen lässt.

Fehler vermeiden, wenn Frames fehlen

Weil es passieren kann, dass Dateien, die eigentlich in einen Frame gehören, auch mal einzeln geladen werden, sorgen wir dafür, dass das Fehlen von Funktionen oder Variablen in anderen Frames nicht zu lästigen Fehlern führt. Eine einfache Abfrage auf Existenz reicht in der Regel aus; ist irgendetwas nicht vorhanden, dann soll auch nichts passieren. Hier ist es die Variable lauf, die wir benötigen, deswegen fragen wir nach mit if(parent.lauf).

Hinweis

Achtung! So etwas hat auch seine Tücken. Ist Ihnen aufgefallen, dass die Abfrage auch dann false liefert, wenn lauf zwar existiert, aber eben den Wert false hat? In dieser Übung macht das nichts, denn wir tun ohnehin nichts anderes als den Wert auf false zu setzen. Aber Sie sehen, man sollte kurz darüber nachdenken.

<html><head>
<title></title>
<script language="JavaScript" type="text/javascript">
<!--
function anhalten()
{
   if (parent.lauf) parent.lauf = 0;
}
// -->
</script>
</head>
<body bgcolor="#ffffff">
<form><input type="button" value="Halt!" onclick="anhalten()"></form>
</body>
</html>

Lösung 6

Prinzip der Lösung:

Bauen wir ein Frameset mit zwei Frames. Die JavaScript-Routinen und die Daten, also das Array mit unseren Links, bringen wir am besten im Fenster der obersten Ebene unter, d.h., wir müssen sie in die Datei einbauen, in der das Frameset definiert wird. Das lässt uns die Freiheit, Frames nach Wunsch einfach zu ändern, ohne dass etwas verloren geht. Natürlich verwenden wir dafür externe JavaScript-Dateien.

In einem der Frames können wir die "Knöpfe" unterbringen, auf die man nur noch drücken muss - na ja, Buttons tun es sicher auch. Der andere Frame wird die jeweils dynamisch generierte Anzeige enthalten.

Ein paar zusätzliche Methoden für verschiedene Anzeigevarianten sind nach den Übungen in Kapitel 3 sicher keine Schwierigkeit mehr.

Die Lösung selbst

Beginnen wir mit den Routinen zum Aufbauen der Daten und zum Ausgeben. Die packen wir alle zusammen in eine JavaScript-Datei, meine heißt bookmark_routinen.js. Die Konstruktor-Funktion und ein paar Methoden sind Ihnen so neu nicht, sie ähneln denen, die wir bereits früher verwendet haben.

So richtig neu sind die beiden Funktionen zeigeAlphabetisch() und such(). Ich werde darauf jetzt aber nicht so sehr eingehen, denn die Routinen sind nicht kompliziert, Sie verstehen sie sicher auch ohne weitere Erklärung. Für die Sortierung habe ich ein ganz einfaches Verfahren gewählt, was für diesen Zweck jedoch vollkommen ausreichend ist.

Vielleicht fällt Ihnen auf, dass ich die Funktionen gar nicht als Methoden zugewiesen habe. Dann sehen Sie sich bitte die Datei mit den "Knöpfen" an. Da immer nur eine der Methoden gebraucht wird, habe ich kurz entschlossen auch nur eine im Objekt vorgesehen, nämlich zeigeEintrag. Aktuell ändere ich lediglich deren Referenz, weise die jeweils passende Funktion zu.

// Konstruktorfunktion fuer Links
function macheLink(pTitel, pAdresse, pAutor, pThema,
                   pAnmerkung, pScreenshot)
{
   this.Titel      = pTitel;
   this.Adresse    = pAdresse;
   this.Autor      = pAutor;
   this.Thema      = pThema;
   this.Anmerkung  = pAnmerkung;
   if (pScreenshot.length > 0)
      this.Screenshot = pScreenshot;
   else
      this.Screenshot = 'keinbild.gif';
   this.erledigt = false;
   this.zeigeEintrag = zeigeEintrag;
}
// fuegt als Methode einer Liste von Links neue hinzu
function hinzufuegen(pTitel, pAdresse, pAutor, pThema,
                     pAnmerkung, pScreenshot)
{
   this[this.length] = new macheLink(pTitel,
                           pAdresse, pAutor,
                           pThema, pAnmerkung, pScreenshot);
}
// bereitet Ausgabe fuer einen einzelnen Eintrag vor
// wird von allen anderen Ausgabefunktionen benutzt
function zeigeEintrag()
{
   var Aus = '';
   Aus += '<dl>';
   Aus += '<dt>';
   Aus += '<a href="' + this.Adresse + '">';
   Aus += '<img src="images/';
   Aus += this.Screenshot;
   Aus += '" width="110" height="83" alt="'+this.Titel;
   Aus += '" border="0" align="middle" ';
   Aus += 'hspace="2" vspace="1">';
   Aus += this.Titel + '</a></dt>';
   Aus += '<dd>' + this.Anmerkung + '</dd>';
   Aus += '<dd>' + this.Autor + '</dd>';
   Aus += '</dl>';
   return Aus;
}

Die folgende Funktion wird aufgerufen, wenn das komplette Frameset geladen ist, d.h., die Objekte werden angelegt, die Liste kann "mit Daten gefüllt" werden. Die Daten holen wir aus einer anderen Datei, das ist übersichtlicher und änderungsfreundlicher. Bei mir heißt sie bookmark_eintraege.js. Wir sehen sie gleich im Anschluss.

/* * * legt Liste an * * */
function macheLinkliste()
{
   // erst mal nachsehen, ob der Browser Arrays kennt
   if (window.Array)
   {
      // eine "Liste" fuer alle Links anlegen
      meineLinks = new Array();
      // Methode fuer das Hinzufuegen definieren
      meineLinks.hinzufuegen = hinzufuegen;
      // Vorbereitungen sind abgeschlossen,
          // Daten koennen kommen
          Bookmarks_anlegen();
   }
}
/* * * verschiedene Anzeigevarianten * * */
// zeigt ungeordnet
function zeigeUngeordnet(wohin)
{
  for (var i=0; i<this.length; i++)
  wohin.document.writeln(this[i].zeigeEintrag());
}
// zeigt thematisch geordnet
function zeigeThematisch(wohin)
{
   for (var i=0; i<this.length;i++)
      this[i].erledigt=false;
   var AusgabeThema = '';
   for (var i = 0; i < this.length; i++)
      if ((this[i].Thema != AusgabeThema) &&
          !this[i].erledigt)
      {
         AusgabeThema = this[i].Thema;
         wohin.document.writeln('<h2>' + AusgabeThema + '</h2>');
         for (var j = i; j < this.length; j++)
           if (this[j].Thema == AusgabeThema)
           {
             wohin.document.writeln(this[j].zeigeEintrag());
               this[j].erledigt = true;
           }
      }
}
// zeigt alphabetisch geordnet
function zeigeAlphabetisch(wohin)
{
   var Zw;
   var fertig = false;
   // sortieren
   while (!fertig)
   {
      fertig = true;
      for (var i = 0; i < this.length-1; i++)
      {
         if (this[i].Titel > this[i+1].Titel)
         {
            fertig    = false;
            Zw        = this[i];
            this[i]   = this[i+1];
            this[i+1] = Zw;
         }
      }
   }
   for (var i=0; i<this.length;i++)
   wohin.document.writeln(this[i].zeigeEintrag());
}   
// sucht nach Zeichenfolge
function such(wohin)
{
   var wonach = Suchbegriff.toLowerCase();
   for (var i=0; i<this.length; i++)
     if ((this[i].Titel.toLowerCase().indexOf(wonach) > -1)
     ||
     (this[i].Autor.toLowerCase().indexOf(wonach) > -1)
     ||
     (this[i].Anmerkung.toLowerCase().indexOf(wonach) > -1))
  wohin.document.writeln(this[i].zeigeEintrag());
}

Datei bookmark_eintraege.js (auszugsweise):

function Bookmarks_anlegen()
{
   // einzelne Links eintragen
   with (meineLinks)
   {
      hinzufuegen('JavaScript-Informationen',
         'http://mintert.com/javascript/',
         'S. Mintert',
         'JavaScript',
         'Buch, Chronologie von JavaScript, Standards etc.',
         'javascriptmintert.gif');
      hinzufuegen('JavaScript-Notizen',
         'http://netz-notizen.de/javascript',
         'Ch. Kühnel',
         'JavaScript',
         'Beispiele, Tipps zu JavaScript und DHTML',
         'javascriptnotizen.gif');
      hinzufuegen('HTML 4',
         'http://www.w3.org/TR/html4/',
         'W3C',
         'HTML',
         'Spezifikation HTML 4',
         '');
   }
}

In der Frameset-Deklaration versorgen wir die beiden Frames mit Namen, dann können wir sie später leichter ansprechen. Nachdem alles geladen ist, müssen wir lediglich den Aufbau der Linkliste anstoßen, indem wir die Funktion macheLinkliste() aufrufen. Bis zu dem Augenblick sollten wir unbedingt damit warten, um sicher zu sein, dass wirklich alles da ist, was wir brauchen.

<html>
<head>
<title>Linkliste</title>
<script language="JavaScript" src="bookmark_routinen.js" type="text/javascript"></script>
<script language="JavaScript" src="bookmark_eintraege.js" type="text/javascript"></script>
<frameset cols="200,*" onload="macheLinkliste()">
 <frame src="zu_linkliste_aufrufe.html" name="Arbeitsframe">
 <frame src="zu_linkliste_dummy.html" name="Anzeigeframe">
</frameset>
<noframes></noframes>
</html>

Was uns jetzt noch fehlt, sind lediglich die Aufrufe. Die finden wir in zu_linkliste_aufrufe.html. Hier merken wir uns geschickter Weise das Ausgabeziel in einer Variablen (wohin). Damit geben wir den Zielframe nur an dieser einen Stelle an, sind also recht flexibel, sollte uns irgendwann dieser Frame nicht mehr so recht gefallen für diesen Zweck. Alles andere ist sicher selbsterklärend. Doch nicht? Probieren Sie die Lösung von der CD! Anschauung ist auch keine schlechte Lehrmeisterin.

<html>
<head><title></title>
<script language="JavaScript" type="text/javascript">
<!--
var wohin = parent.Anzeigeframe;
function ruf(wie)
{
  if (wie == 'thematisch')
    parent.meineLinks.zeige = parent.zeigeThematisch;
  else
    if (wie == 'alphabetisch')
      parent.meineLinks.zeige = parent.zeigeAlphabetisch;
    else
       if (wie == 'suchen')
       {
         if (self.document.forms[0].begriff.value.length<2)
           alert('Suchbegriff zu kurz');
         else
         {
           parent.Suchbegriff =
              self.document.forms[0].begriff.value;
           parent.meineLinks.zeige = parent.such;
         }
       }
       else
         parent.meineLinks.zeige = parent.zeigeUngeordnet;
  wohin.document.open();
  wohin.document.writeln('<html><head></head><body>');
  parent.meineLinks.zeige(wohin);
  wohin.document.writeln('</body></html>');
  wohin.document.close();
}
// -->
</script>
</head>
<body>
<h1>Meine Links</h1>
<form>
<input type="button" value="ungeordnet"
       onclick="ruf(this.value)"><hr>
<input type="button" value="thematisch"
       onclick="ruf(this.value)"><hr>
<input type="button" value="alphabetisch"
       onclick="ruf(this.value)"><hr>
<input type="text" name="begriff" value=""
       size="15" maxlength="30">
<input type="button" value="suchen"
       onclick="ruf(this.value)"><br>
(in Thema, Autor und Anmerkung)<hr>
</form>
</body>
</html>

Lösung zu 7

Das ist eine mögliche Lösung:

<html><head>
<title>Immer groesser</title>
<script language="JavaScript" type="text/javascript">
<!--

Die Funktion zur Fehlerbehandlung fängt Fehler ab. An sich dürften keine auftreten, wenn man grundsätzlich dafür sorgt, dass auf das Fenster Neu nur zugegriffen wird, wenn es auch da ist, also auch dann nicht, wenn es zwischenzeitlich von Hand geschlossen wurde. Darüber sollte die closed-Eigenschaft Auskunft geben. Das ist die Theorie, bei Netscape-Browsern funktioniert sie auch, aber MSIEs sind an der Stelle etwas bugbehaftet. Deswegen habe ich mich hier entschlossen, Fehlermeldungen einfach abzufangen.

function Fehlerbehandlung()
{ return true; }
window.onerror = Fehlerbehandlung;
function machauf()
{
   var para =  '';
   para += 'width=100,height=100';
   para += ',status=0,menubar=0';
   para += ',scrollbars=0,resizable=1';
   para += ',toolbar=0,location=0';
   para += ',directories=0';
   // positionieren links oben
   para += ',left=0';
   para += ',top=0';
   Neu = window.open('waechst.html','',para);
// kleine Verzögerung, dann beginnt das Wachstum
   setTimeout('los()',80);
}
function los()
{
   // gar kein Fenster da?
   if (!self.Neu) return;
   // kein screen-Objekt, dann ist Browser zu alt
   if (!self.screen) return;
   // initialisieren
   var horizontal = 0;
   var vertikal   = 0;
   var Neu_breit  = 0;
   var Neu_hoch   = 0;
   var breit = screen.width/3*2;
   var hoch  = screen.height/3*2;
   if (Neu && Neu.innerWidth)
   {
      // Netscape
      var Neu_breit = Neu.innerWidth;
      var Neu_hoch  = Neu.innerHeight;
   }
   else
      if (Neu && Neu.document.body &&
          Neu.document.body.offsetWidth)
      {
         // MSIE
         var Neu_breit = Neu.document.body.offsetWidth;
         var Neu_hoch  = Neu.document.body.offsetHeight;
      }
   if (!Neu_breit) return;
   if (Neu_breit < breit)
      horizontal = 10;
   if (Neu_hoch < hoch)
      vertikal = 10;
   Neu.resizeBy(horizontal,vertikal);
   setTimeout('los()',80);
}
// -->
</script>
<body>
<p><a href="javascript:machauf()">machauf</a></p>
</body>
</html>

Die Datei, die in das kleine Fenster geladen wird, ist nicht interessant. Sie spielt selbst keine Rolle.

1 Ich habe keine Idee, warum es so ist, weiß nur, dass es so ist: self wird gern mit this verwechselt. Dabei haben die beiden doch gar nichts miteinander zu tun! [zurück]

2 Es gibt Möglichkeiten, mit Hilfe erweiterter Privilegien einige der Einschränkungen aufzuheben, aber das ist ein eigenes umfangreiches, jedoch vergleichsweise wenig praxisrelevantes Thema. Deswegen konnte es in diesem Workshop nicht berücksichtigt werden. [zurück]

3 Voraussetzung ist natürlich, dass neu im gesamten window (global) bekannt ist, nicht etwa nur lokal innerhalb einer Funktion. [zurück]

4 Komplett finden Sie das Beispiel, das wir gerade Schritt für Schritt aufgebaut haben, auf der beiliegenden CD. [zurück]

5 document.open() wird auch gelegentlich weggelassen. [zurück]

6 Ausnahmen bestätigen auch hier die Regel. Unter file-Protokoll steht search nicht bei allen Browsern zur Verfügung, bekannt sind MSIE3 und MSIE4. Wahrscheinlich ist das kaum störend für Sie, denn unter http funktioniert es. [zurück]

7 Vorsicht! 10 Frames, die knabbern an den Ressourcen des Rechners! [zurück]

Linkwerk
screeneXa