vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Tag 12

JavaScript und Frames

Ein wichtiges Thema haben wir bei unser Erkundung der Möglichkeiten von JavaScript bisher ganz ausgelassen: die Programmierung mit Frameseiten und Frames. Wie Sie aus Kapitel 3 wissen, besteht eine Frameseite aus einer <frameset>-Definition, in der die Aufteilung des Browsers in Frames festgelegt wird. In diese Frames werden dann jeweils eigene Webseiten geladen. Das Skripting für die einzelnen Frames unterscheidet sich dabei nicht von dem Skripting für normale Webseiten. Lediglich in Fällen wo man per JavaScript von einem Frame aus auf einen anderen Frame zugreifen will, sind einige Besonderheiten zu beachten.

Die Themen im Einzelnen:

12.1 Frame-Navigation mit JavaScript

Der Schlüssel für die JavaScript-Programmierung mit Frames ist das Array frames[].

Das frames-Array

Wenn der Browser eine Webseite mit Frames lädt, legt er unter dem window-Objekt der Frameseite eine Array-Eigenschaft frames[] an. Über diese Array-Eigenschaft kann man via JavaScript-Code auf die einzelnen Frames zugreifen.

Schauen Sie sich einmal folgende Frame-Aufteilung aus.

<frameset rows="100,*">
<frame name="Banner" scrolling="no" noresize="noresize">

<frameset cols="150,*">
<frame name="Inhalt" noresize="noresize">
<frame name="Hauptframe">
</frameset>
</frameset>

Nach dem Laden einer Webseite mit dieser Frame-Aufteilung sind die Frames Banner, Inhalt und Hauptframe in der Reihenfolge ihrer Definition in dem frames-Objekt der Webseite eingetragen:

frames[0] repräsentiert den Frame Banner

frames[1] repräsentiert den Frame Inhalt

frames[2] repräsentiert den Frame Hauptframe

Wenn die Frames eindeutige Namen haben, kann man auch direkt über diese Namen auf die Frames zugreifen

So könnten Sie beispielsweise die Anfangsseiten für die einzelnen Frames per JavaScript- Code laden.

Frame-Programmierung in der Frameseite

Wurde die Frameseite in den Internet Explorer oder den Netscape 6-Browser geladen, kann man nach dem Laden der Frameseite bereits auf die einzelnen Frames zugreifen. Mit dem folgenden Code könnte man beispielsweise die Anfangsseiten für die oben vorgestellte Frame-Aufteilung laden. Sie müssen die init()-Funktion nur als Ereignisbehandlungsfunktion für das onload-Ereignis des ersten <frameset>-Tags einrichten.

<script type="text/javascript">
function init()
{
frames[0].location.href = "banner.html";
frames[1].location.href = "hallo.html";
frames[2].location.href = "leer.html";
}
</script>

Statt frames[0] könnten Sie in obigem Code übrigens auch window.frames[0], window.Banner oder einfach nur Banner schreiben.

Grundsätzlich sollten Sie die Webseiten für die Frames aber auf normalem Wege, das heißt über die src-Eigenschaft der <frame>-Tags, laden. Schon allein aus Rücksicht auf den Netscape Navigator, der in der Frameseite keinen Zugriff auf die Frames erlaubt.

Wichtiger und interessanter ist die Frame-Programmierung für die Webseiten der einzelnen Frames.

Frame-Programmierung in den Webseiten der Frames

Um von einem Frame aus auf einen anderen Frame zugreifen zu können, müssen Sie zuerst irgendwie an das frames-Array der übergeordneten Frameseite herankommen. Diese wird von dem parent-Objekt repräsentiert.

Das parent-Objekt

Mit Hilfe des parent-Objekts können Sie auf das frames-Array der übergeordneten Frameseite zugreifen. Das parent-Objekt bezieht sich immer auf die ganze Frameseite (und nicht etwa auf die innerste Frameset-Deklaration).

Betrachten wie noch einmal die Frame-Aufteilung aus den vorangehenden Abschnitten:

<frameset rows="100,*">
<frame name="Banner" scrolling="no" noresize="noresize">

<frameset cols="150,*">
<frame name="Inhalt" noresize="noresize">
<frame name="Hauptframe">
</frameset>
</frameset>

Stellen wir uns weiter vor, wir bearbeiten gerade den HTML-Code einer Webseite, die im Frame Inhalt angezeigt wird und wir wollen aus einer JavaScript-Funktion heraus auf den Frame Hauptframe zugreifen. Dazu greifen wir zuerst mit parent auf die übergeordnete Frameseite und dann über das frames-Array oder den Namen des Frames auf den gewünschten Frame zu:

parent.frames[2]
parent.Hauptframe

Ein typisches Einsatzgebiet für den frameübergreifenden Zugriff mit JavaScript ist die Aktualisierung zweier oder mehrerer Frames beim Anklicken eines Hyperlinks (siehe 12.2).

Verschachtelte Frameseiten

Was macht man, wenn verschachtelte Frameseiten vorliegen?

Vorsicht, wir reden hier nicht davon, dass wie im obigen Beispiel zwei oder mehr Frameset-Deklarationen ineinander verschachtelt werden, sondern davon, dass eine eigene Frameseite als Webseite in einen Frame einer anderen Frameseite geladen wird. Das wird zwar nicht oft vorkommen, aber ein wenig Grundlagenforschung kann nicht schaden.

Angenommen die erste Frameseite hat drei Frames 1, 2 und 3. Die zweite Frameseite enthält zwei Frames A und B und wird in den Frame 3 der ersten Frameseite geladen:

Abbildung 12.1:  Zwei verschachtelte Frameseiten

Wie kann man nun aus dem Frame A eine neue Webseite in den Frame 1 laden?

Zuerst springt man mit parent zur übergeordneten Frameseite von Frame A. Damit befinden wir uns jetzt in einem Frame der oberen Frameseite. Ein weiterer Aufruf von parent führt uns zu dieser Frameseite und ihrem frames-Array, über das wir auf Frame 1 zugreifen können:

parent.parent.frame[0]

Alternativ hätte man mit top auch gleich zur obersten Webseite im Browser springen können.

12.2 JavaScript-unterstützte Frame-Hyperlinks

Ein typisches Problem von Frame-Designs ist, dass man mit einem normalen Hyperlink immer nur einen Frame aktualisieren kann (eine neue Webseite in einen Frame laden kann). In einfachen Designs, wie zum Beispiel der Aufteilung in Banner, Inhalt und Hauptframe, ist dies grundsätzlich kein Problem: bei einem Klick auf einen Hyperlink im Inhalt-Frame braucht man nur die gewünschte Webseite in den Hauptframe zu laden.

Anders sieht es aus, wenn eine zweischichtige Navigationsstruktur aufbauen. Nehmen wir an, Sie erstellen eine Webseite, auf der Sie verschiedene Länder vorstellen. Sie bauen eine Frameseite mit drei Frames auf.

Listing 12.1: frameseite.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>Frameseite</title>
</head>

<frameset rows="100,*">
<frame name="Banner" src="banner.html"
scrolling="no" noresize="noresize">

<frameset cols="150,*">
<frame name="Inhalt" src="leer.html" noresize="noresize">
<frame name="Hauptframe" src="leer.html" >
</frameset>
</frameset>

<noframes>
<p>Sorry, dies ist eine Frameseite und Ihr Browser unterstützt
offensichtlich keine Frames</p>
</noframes>

</frameset>
</html>

Im »Banner«-Frame werden Links der ersten Ebene angezeigt. Über diese Links kann der Webbesucher einen Kontinent auswählen.

Im Inhalt-Frame werden Links der zweiten Ebene angezeigt. Über diese Links kann der Webbesucher die verschiedenen Länder eines Kontinents auswählen.

Im Hauptframe-Frame werden die Seiten zu den Kontinenten und Ländern angezeigt.

Wenn die Webseite geladen wird, sollen die Frames Inhalt und Hauptframe noch leer bleiben (oder irgendeinen Begrüßungstext anzeigen). Lediglich im Banner-Frame sollen bereits die Links für die Kontinente angeboten werden (siehe Abbildung 12.2).

Abbildung 12.2:  frameseite.html direkt nach dem Aufruf

Klickt der Besucher auf einen der Kontinente-Links sollen sowohl der Inhaltframe als auch der Hauptframe aktualisiert werden. Im Inhalt-Frame soll das Verzeichnis der Länder für den Kontinent angezeigt werden, im Hauptframe soll eine Landkarte des Kontinents angezeigt werden. Mit normalen Hyperlinks ist dies nicht zu bewerkstelligen. Also behilft man sich mit einer JavaScript-Funktion.

Zuerst verbinden wir die Anker-Elemente der Kontinente-Schaltflächen mit einer JavaScript-Funktion namens hyperlinks().

<table width="600" border="0" cellspacing="10px">
<tr>
<td><a href="javascript: hyperlinks(0)">
¬<img src="button1.jpg" alt="Amerika" /></a></td>
<td><a href="javascript: hyperlinks(1)">
¬<img src="button2.jpg" alt="Asien" /></a></td>
<td><a href="javascript: hyperlinks(2)">
¬<img src="button3.jpg" alt="Europa" /></a></td>
</tr>
</table>

Für jeden Link übergeben wir eine andere Kennnummer, damit wir in der Funktion unterscheiden können, für welchen Link die Funktion aufgerufen wurde.

In der Funktion selbst spalten wir den Code mit Hilfe einer switch-Anweisung auf und laden je nach angeklickter Schaltfläche die zugehörigen Webseiten in die Frames Inhalt und Hauptframe.

function hyperlinks(quelle)
{
switch (quelle)
{
case 0: parent.Inhalt.location.href = "inhaltamerika.html";
parent.Hauptframe.location.href = "halloamerika.html";
break;
case 1: parent.Inhalt.location.href = "inhaltasien.html";
parent.Hauptframe.location.href = "halloasien.html";
break;
case 2: parent.Inhalt.location.href = "inhalteuropa.html";
parent.Hauptframe.location.href = "halloeuropa.html";
break;
}
}

Der vollständige Code der Seite banner.html sieht damit wie folgt aus:

Listing 12.2: banner.html - Mit einem Link mehrere Webseiten in Frames laden

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Banner</title>

<style type="text/css">
<!--
img { border: 0; }
-->
</style>

<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script type="text/javascript">

function hyperlinks(quelle)
{
switch (quelle)
{
case 0: parent.Inhalt.location.href = "inhaltamerika.html";
parent.Hauptframe.location.href = "halloamerika.html";
break;
case 1: parent.Inhalt.location.href = "inhaltasien.html";
parent.Hauptframe.location.href = "halloasien.html";
break;
case 2: parent.Inhalt.location.href = "inhalteuropa.html";
parent.Hauptframe.location.href = "halloeuropa.html";
break;
}
}
</script>
</head>

<body>
<table width="600" border="0" cellspacing="10px">
<tr>
<td><a href="javascript: hyperlinks(0)"><img src="button1.jpg" alt="Amerika" /></a></td>
<td><a href="javascript: hyperlinks(1)"><img src="button2.jpg" alt="Asien" /></a></td>
<td><a href="javascript: hyperlinks(2)"><img src="button3.jpg" alt="Europa" /></a></td>
</tr>
</table>


</body>
</html>

Abbildung 12.3:  Die Webseite nach Klick auf den Asien-Schalter

12.3 Zugriff auf HTML-Elemente in Frames

Über das frames-Array kann man nicht nur neue Webseiten in Frames laden. Man kann auch

Man kann auf das document-Objekt zugreifen? Das sollte uns aufhorchen lassen, wissen wir doch aus Kapitel 10, dass man ausgehend vom document-Objekt auf alle1 HTML-Elemente der Webseite zugreifen kann.

Wir nutzen dies, um in dem nachfolgenden Beispiel vom linken Frame aus die Bilder in den <img>-Tags des rechten Frames zu ändern.

Beginnen wir mit dem Quellode der Frameseite. Diese ist vertikal in zwei Frames aufgeteilt.

Listing 12.3: frameseite.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>Frameseite</title>
</head>

<frameset cols="20%,80%">

<frame name="links" src="links.html">
<frame name="hauptframe" src="hauptseite.html">

<noframes>
<p>Sorry, dies ist eine Frameseite und Ihr Browser unterstützt
offensichtlich keine Frames</p>
</noframes>

</frameset>
</html>

Interessanter als der HTML-Code der Frameseite ist der Code der Webseite für den Hauptframe.

Listing 12.4: hauptseite.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Wechsel Dich!</title>

<style type="text/css">
<!--
#kopf { position: absolute; left: 90px; top: 70px; z-index: 1}
#rumpf { position: absolute; left: 85px; top: 95px; z-index: 0}
-->
</style>

</head>

<body>

<img id="kopf" src="babykopf.gif" />
<img id="rumpf" src="babyrumpf.gif" />

</body>
</html>

Diese Seite enthält nichts weiter als zwei Bilder: eines zeigt einen Babykopf, das andere einen Babykörper. Die <img>-Elemente werden mit Hilfe eines Stylesheets so absolut positioniert, dass der Kopf ordentlich auf dem Rumpf sitzt. Die z-index-Werte sind so gesetzt sind, dass der Kopf das Rumpf-Bild überdeckt (siehe Abbildung 12.4).

Der Hintergrund der GIF-Bilder wurde als transparent abgespeichert (siehe Kapitel 2.5.2). Ansonsten würde der rechteckige Hintergrund des Kopfbildes den oberen Teil des Rumpfes verdecken. Ist der Hintergrund transparent, kann der Rumpf unter dem Hintergrund des überlappenden Kopfbild durchscheinen.

Wenn Sie das Beispiel im Navigator 4 betrachten wollen, müssen Sie die Bilder in <div>-Tags setzen und diese positionieren (vergleiche Kapitel 5.4).

Abbildung 12.4:  Die Frameseite nach dem Laden

Kommen wir zum Code der Webseite für den linken Frame.

Listing 12.5: links.html - HTML-Elemente in anderem Frame manipulieren

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Inhaltsverzeichnis</title>
<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script type="text/javascript">

var koepfe = new Array();
koepfe[0] = "babykopf.gif";
koepfe[1] = "fischerkopf.gif";
koepfe[2] = "kaninkopf.gif";

var koerper = new Array();
koerper[0] = "babyrumpf.gif";
koerper[1] = "fischerrumpf.gif";
koerper[2] = "kaninrumpf.gif";


function kopf()
{
var index = parseInt(Math.random() * 3);
parent.hauptframe.document.images[0].src = koepfe[index];
}
function rumpf()
{
var index = parseInt(Math.random() * 3);
parent.hauptframe.document.images[1].src = koerper[index];
}

</script>
</head>


<body>

<p><a href="javascript: kopf()">Neuer Kopf</a></p>
<p><a href="javascript: rumpf()">Neuer Körper</a></p>

</body>
</html>

Diese Seite enthält zwei Links. Klickt der Besucher der Webseite auf einen dieser Hyperlinks, soll entweder ein neuer Kopf oder ein neuer Körper eingeblendet werden.

Es gibt drei verschiedene Köpfe und zugehörige Körper. Im Header der Webseite werden die Strings mit den URLs der Bilddateien in zwei Arrays koepfe und koerper geladen.

Wir speichern diesmal nur die URL-Strings in den Arrays und nicht wie im Falle der Rollover-Schaltflächen (siehe Kapitel 10.6) gleich die anzuzeigenden Bilder. Der Grund ist, dass sich die in einem Frame geladenen Bilder nicht auf einen anderen Frame übertragen lassen.

In den JavaScript-Funktionen zum Wechseln von Kopf und Rumpf erzeugen wir schließlich eine Zufallszahl zwischen 0 und 2 (einschließlich) und nutzen diese, um den URL-String eines Kopfes/Rumpfes aus dem entsprechenden Array auszuwählen und an das passende <img>-Element im Frame hauptframe zuzuweisen.

Kopf und Rumpf verändern sich nicht bei jedem Klick auf einen der Hyperlinks in linken Frame, da es ja durchaus sein kann, dass bei der zufälligen Auswahl der gerade angezeigte Kopf/Rumpf gezogen wird.

Abbildung 12.5:  Frameseite nach Klick auf "Neuer Körper"

12.4 Zusammenfassung

Heute haben Sie gelernt, wie man mit JavaScript-Code auf die Webseiten anderer Frames zugreift. Der Schlüssel hierzu war das frames-Array, das der Browser beim Laden einer Frameseite anlegt.

Meist geht es darum, von einem Frame A einer Frameseite auf einen Frame B der gleichen Frameseite zuzugreifen. Dazu steigt man zuerst mit Hilfe des parent-Objekts hoch zur Frameseite und steigt dann über das frames-Array und einen Index (oder alternativ über den Namen des Frames, falls ein solcher definiert wurde) hinab zu dem anvisierten Frame.

parent.frames[0]
parent.frameName

Am häufigsten benutzt man diese Technik, um beim Klick auf einen Hyperlink aus einem Frame mehr als zwei Frames zu aktualisieren.

parent.frameB.location.href = "neueseite1.html";
parent.frameC.location.href = "neueseite2.html";

Man kann aber auch über das document-Objekt des Frames auf beliebige HTML-Elemente in der Webseite des Frames zugreifen:

parent.frameName.document.images[1].src = "neuesbild.gif";

12.5 Fragen und Antworten

Frage:
Kann man von einer JavaScript-Funktion, die in der Webseite eines Frames definiert ist, die Frame-Aufteilung auflösen und eine Seite normal in das Browser-Fenster laden?

Antwort:
Ja, das geht! Sie müssen den URL der Webseite nur an das location-Objekt der Frameseite statt an das location-Objekt eines Frames zuweisen:

parent.location.href = "neueseite.html";

Frage:
Kann ich mit JavaScript nachträglich die Größe eines Frames ändern?

Antwort:
Nein!

12.6 Workshop

Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, und Übungen, die Sie anregen sollen, das eben Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Versuchen Sie, das Quiz und die Übungen zu beantworten und zu verstehen, bevor Sie zur Lektion des nächsten Tages übergehen.

Quiz

  1. Wofür steht das JavaScript-Objekt parent?
  2. Wie lädt man von Frame A aus eine neue Webseite in Frame D? (Beide Frames gehören einer gemeinsamen Frameseite an.)

Übungen

  1. Das heutige Thema war weder ausgesprochen schwierig noch umfangreich. Nutzen Sie die Zeit doch für etwas Spaßiges und erweitern Sie die Webseite aus Abschnitt 12.3 um weitere Comic-Figuren (Falls Sie keine Möglichkeit haben, eigene Bilder von Comic-Figuren einzuscannen oder zu beschaffen, finden Sie zwei - bereits in Kopf und Rumpf aufgeteilte - Comic-Figuren auf der Buch-CD. Sie müssen allerdings noch die Transparenz regeln und die Abmaße anpassen, siehe Lösung).



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


1

© Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH