Frames



Frames sind bereits in HTML eingeführt worden und ihre Verwaltung, obwohl kompliziert und voller Fußangeln, ließ eigentlich keine Wünsche offen. Trotzdem bietet JavaScript den Zugriff auf  Frames. Dazu ist das Objekt "frames" definiert, eine Variante des Objektes "window". Die Eigenschaften und Methoden von window, aber auch die Unterobjekte document, event, history und location gelten auch für frames.
In JavaScript, wo man es mit den Arrays hat, werden Frames in der Reihenfolge ihrer Definition in der Form frames[0], frames[1],... registriert und sind so außer mit ihrem Namen ebenfalls ansprechbar. Allerdings, wie es bei der Objektorientierung so geht, werden die Frames nicht für eine ganze Frameseite durchgezählt, sondern immer nur in Bezug auf ihr "Elternfenster", das parent heißt. Wie bei allen Arrays dieser Art kann man mit length die Länge der Framearrays in jedem Fenster erfragen. Ich frage mich allerdings, was mit einem Seitengestalter los ist, der so weit die Übersicht verloren hat, daß er solche Fragen stellen muß!

Frames verwalten

Um die Syntaxunterschiede zwischen HTML und JavaScript zu verdeutlichen, möge in einem HTML-Frameset ein linkes Fenster "fr_menue" und ein rechtes Fenster "fr_inhalt" definiert worden sein. Auf der Seite, die ins Menü-Fenster geladen wird, soll der Link auf eine Seite "inhalt1.htm" verweisen, die in "fr_inhalt" geladen und angezeigt werden soll. Vergleichen Sie die beiden Aufrufe!

HTML:
<a href="inhalt1.htm" target="fr_inhalt">Erste Seite</a>
JavaScript, Variante 1:
<form><input type="button" value="Erste Seite" onClick="javascript:parent.frames[1].location.href='inhalt1.htm'"></form>
Variante 2:
<form><input type="button" value="Erste Seite" onClick="javascript:parent.fr_inhalt.location.href='inhalt1.htm'"></form>

Im JavaScript-Fall wurden zwar Buttons genutzt, auch Bilder wären möglich, der Aufruf ist aber deutlich länger (und fehleranfälliger) geworden. parent ist der reservierte Name des übergeordneten Fensters. Bei der hier verwendeten Zählung muß parent zwangsläufig mit dem allerobersten Fenster top identisch sein.
Kürzer wird es mit JavaScript bei der Beendigung einer Framestruktur. Denn hier ist die Adressierung einer neu zu ladenden Seite auf das Gesamtfenster einfacher.

HTML:
<a href="neueseite.htm" target="_top">Erste Seite</a>
Javascript:
top.location.href="neueseite.htm"

 Was hier fehlt, ist allerdings der Anlaß, die angegebene JavaScript-Zeile auszuführen. Das könnte wieder ein geeignet gewähltes Event sein.



JavaScript wird im Zusammenhang mit Frames gerne angewendet, um statt einfacher Links optisch aufgepeppte Buttons (etwa mit veränderlicher Farbe) für die Navigation einzusetzen. Allerdings gibt es dabei keine spezifischen Frame-Probleme, sondern es ist eine Nutzanwendung der Ereignissteuerung.


Fremden Frames entkommen

Eine sinnvolle Anwendung der Eigenschaft length gibt es überraschenderweise doch. Man kann damit Seiten gegen das Einladen in fremde Frames zu schützen, weil dabei wegen fehlenden Platzes die Darstellung erheblich leiden kann. Dazu dient die Zeile:

<script language=JavaScript>
   if (top.frames.length != 0)top.location=self.location;
</script>

Die Bedingung, daß das Frame-Array im Fenster top eine Länge ungleich Null hat, heißt, daß die Zielseite Frames enthält. In diesem Fall wird das ganze Fenster top zum Ziel der neuen Seite erklärt, was die Frames hinfällig macht.


Frameinhalte nicht ohne Frame laden

Ein dem vorhergehenden entgegengesetztes Problem läßt sich mit sehr ähnlichen Mitteln lösen. Die zu einer Frame-Site gehörenden Seiten werden u.U. von Suchmaschinen gefunden und  von Nutzern direkt geladen. Da auf Seiten, die für Frames bestimmt sind, meist Navigationshilfen fehlen, ist der Leser völlig hilflos, wenn ihn der Autor oder weitere Seiten der Präsentation interessieren.
Hier muß erreicht werden, daß der Leser erfährt, daß er Frameinhalte liest. Auf behutsame Weise geht es so:

<script language="JavaScript">
   if (top.frames.length==0)
      document.write("Diese Seite ist Teil einer Frame-Struktur. Bitte rufen Sie die <a href='home.htm'>Titelseite</a> auf!");
</script>

Wenn dieses Script im Head untergebracht wird, erscheint der Text mit dem Link am oberen Bildrand, noch vor der Seitenüberschrift. Dem Leser bleibt es überlassen, ob er die Frames aufruft.
Etwas brachialer geht es naürlich auch.
Hier würde in jedem Falle der Anwahl irgendeiner Seite die gesamte Framestruktur errichtet und mit den Start-Seiten geladen:

<script language=JavaScript>
   if (top.frames.length==0) location.replace("start.htm")
</script>

Dabei entsteht aber das ärgerliche Problem, daß man die richtige thematische Seite, die die Suchmaschine anbot, zunächst wieder verliert und man sich müsam wieder zu ihr durchklicken muß. Viel schöner wäre es, man erhielte zwar die Navigationshilfen der Framestruktur, landete aber genau auf der gewählten Seite.
Um dieses zu realisieren, muß während der Umleitung der gewünschte Seitenname "gemerkt" werden. Über den Ladevorgang hinweg kann JavaScript selbst sich nichts merken.
Man könnte dieses Problem umgehen, aber soweit ich sehe, nur mit einem Cookie. Da sich Cookies wegschalten lassen bzw. erst dumme Fragen stellen, ob etc..., funktioniert es so nicht oder sie nerven.
Eine Lösung, die zwar umständlich ist, immerhin aber funktioniert, habe ich hier angewandt. Es wird zu jeder Seite der Präsentation eine eigene Kopie des Framesets erzeugt, in der anstelle der allerersten die gewünschte Seite angezeigt wird.
Zu einer hypothetischen Seite "seite100.htm" wird also eine Kopie des Framesets erzeugt, die "seite100_s.htm" heisse. Jetzt die Einträge:

Im <head> von seite100.htm steht:
<script language=JavaScript>
    if (top.frames.length==0) location.replace("seite100_s.htm")
</script>
das Frameset in seite100_s.htm könnte so aussehen:
<frameset cols = "20%,*" border="0" framespacing="0">
    <frame src="index.htm" name= "links">
    <frame src="seite100.htm" name= "rechts">
</frameset>

 

Mehrere Dateien gleichzeitig laden

Framespezifisch ist ein in HTML nur etwas umständlich lösbares Problem (vgl. HTML-Kurs), die Veränderung von zwei oder mehr Frameinhalten auf einen Rutsch. Da dies oft benötigt wird, gebe ich in Kurzfassung einen geeigneten Code an. Für das einfache Neuladen zweier oder mehrerer Seiten in bestimmte Fenster (hier fr_eins und fr_zwei genannt) definiert man im head eine Funktion:

<script language="JavaScript">
   function Wechsel()
   {
      parent.fr_eins.location.href="seite1.htm";
      parent.fr_zwei.location.href="seite2.htm";
      ...
   }
</script>

Diese Funktion wird mit einem Event (z.B. onClick) aufgerufen. Professioneller läßt sich die Aufruffunktion mit Parametern für die Dateinamen und die Fensternummern gestalten. Dann können sich viele Aufrufe der immer gleichen Funktion bedienen. Komplett nachzulesen ist dieses Beispiel in der Referenz "selfhtml", auf die ich (nicht nur) hier gerne verweise.