Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 <<   zurück
JavaScript und AJAX von Christian Wenz
Das umfassende Handbuch
Buch: JavaScript und AJAX

JavaScript und AJAX
839 S., mit DVD, 39,90 Euro
Galileo Computing
ISBN 3-89842-859-1
gp Kapitel 11 Grafiken
  gp 11.1 Bildlein-Wechsle-Dich
    gp 11.1.1 Zugriff auf Grafiken
  gp 11.2 Animierte JPEGs
    gp 11.2.1 Eine Animation mit JavaScript
    gp 11.2.2 Bilder in den Cache laden
  gp 11.3 Animierte Navigation
    gp 11.3.1 Vorüberlegungen
    gp 11.3.2 Auf- und Zuklappen
    gp 11.3.3 Die einzelnen Menüpunkte
    gp 11.3.4 Verlinkung der Menüpunkte
    gp 11.3.5 Einbau in die HTML-Datei
  gp 11.4 Erweiterung der Navigation
    gp 11.4.1 Vorbereitungen
    gp 11.4.2 Leichte Änderungen
    gp 11.4.3 Doppeltes Mouseover
    gp 11.4.4 Das komplette Beispiel im Überblick
  gp 11.5 Tipps aus der Praxis
    gp 11.5.1 Vorladen – aber richtig
    gp 11.5.2 Ladestand einer Grafik
    gp 11.5.3 Fortschrittsanzeige


Galileo Computing

11.5 Tipps aus der Praxis  downtop

In diesem letzten Abschnitt dieses Kapitels über das Image-Objekt möchte ich Ihnen noch ein paar Tipps aus der Praxis geben, damit Sie Fehlermeldungen vermeiden oder Ihre Seiten mit noch mehr Funktionalität versehen können. Das Image-Objekt wird sehr gern eingesetzt, und ein paar Fehler werden immer wieder gemacht, ein paar Fragen immer wieder gestellt. Die folgenden zwei Abschnitte beantworten hoffentlich die Fragen, die Sie noch haben.


Galileo Computing

11.5.1 Vorladen – aber richtig  downtop

Sie haben sich vielleicht gefragt, warum beim Beispiel zum Vorladen die Funktion preload() nicht mittels <body onload="preload();"> aufgerufen worden ist, sondern noch im <head>-Abschnitt des HTML-Dokuments. Das hat einen einfachen Grund. Gehen Sie von einer langsameren Verbindung oder von einem umfangreichen Dokument aus. Ein Teil des HTML-Dokuments wurde schon übertragen und ist auch schon vom Browser dargestellt worden. Hier ist besonders der Internet Explorer sehr schnell, während manche andere Browser Tabellen erst dann anzeigen, wenn sie vollständig übertragen worden sind. Aber zurück zum Beispiel: Ein Teil der Seite ist also schon geladen und wird dargestellt – und die Event-Handler in diesem Teil sind natürlich aktiv. Wie es der Zufall so will, fährt der Benutzer jetzt schon über eine mit Mouseover versehene Grafik. Im Beispiel von oben würde nun die folgende Funktion aufgerufen werden:

function over() {
   document.grafik.src = img_over.src;
}

Die Variable img_over wird aber erst in der Funktion preload() korrekt gesetzt. Das ist schlecht, wenn die Funktion erst mit dem onload-Event-Handler aufgerufen wird; wie Sie sich erinnern, tritt dieser erst in Aktion, wenn das gesamte HTML-Dokument übertragen worden ist. Es gäbe also in diesem Fall unter Umständen eine Fehlermeldung. Um dies zu vermeiden, rufen Sie Ihre Vorladefunktion noch vor dem ersten <img>-Tag auf!


Galileo Computing

11.5.2 Ladestand einer Grafik  downtop

JavaScript bietet dem Benutzer eine bequeme Möglichkeit festzustellen, wie weit eine Grafik schon geladen ist. Interessant wird das beispielsweise bei der Diashow aus Kapitel 10. Wenn Sie die Diashow über eine langsame Netzwerkverbindung abspielen, kann es sein, dass umfangreiche Grafiken auf den einzelnen Seiten der Show noch nicht vollständig geladen sind, bevor die nächste Seite der Show angezeigt wird. Es wäre hier also praktisch, wenn die Grafiken alle schon vorher im Browsercache wären. Auch beim Beispiel mit der JPEG-Animation aus diesem Kapitel ist das wünschenswert. Wir wollen für das letztere Beispiel eine Lösung konstruieren, die analog auch für das Diashow-Beispiel eingesetzt werden kann.

Der Trick besteht darin, eine Einstiegsseite zu programmieren, auf der alle Grafiken schon einmal geladen werden. Nun könnte man einerseits den Benutzer nach Ablauf einer gewissen Zeitspanne auf die nächste Seite weiterleiten, aber das ist keine sehr flexible Lösung. Bei einer langsamen Verbindung reicht die Zeit nicht aus, und bei einer schnellen Verbindung dauert das Warten zu lange.

Ein erster Ansatz besteht darin, den Event-Handler onload zu benutzen. Den gibt es auch bei Grafiken. Sobald bei jeder Grafik der onload-Event-Handler ausgeführt worden ist, kann auf die nächste Seite weiterverzweigt werden. Zudem sollte man nach einer bestimmten Zeit ohnehin zur nächsten Seite übergehen, um die Geduld des Benutzers nicht allzu sehr zu strapazieren.

<html>
<head>
<meta http-equiv="refresh"
content="30;url=animation.html" />
<!-- nach 30 Sekunden wird die Seite animation.html geladen -->
<title>Animation vorbereiten</title>
<script type="text/javascript"><!--
var geladen = 0;  //Anzahl der fertig geladenen Grafiken
function fertig() {
   geladen++;
   if (geladen==4) { //wenn alle Grafiken geladen sind
      location.href = "animation.html";
   }
}
//--></script>
</head>
<body>
<h3>Animation lädt... Bitte warten...</33>
<img src="ani1.jpg" onload="fertig();" width="1" height="1" />
<img src="ani2.jpg" onload="fertig();" width="1" height="1" />
<img src="ani3.jpg" onload="fertig();" width="1" height="1" />
<img src="ani4.jpg" onload="fertig();" width="1" height="1" />
</body>
</html>

Jedes Mal, wenn eine Grafik fertig geladen worden ist, wird ein Zähler um eins erhöht, und es wird überprüft, ob damit die magische Zahl 4 (die Anzahl der Grafiken) erreicht worden ist.

Dieses Vorgehen funktioniert unter gewissen Umständen nicht – vor allem auf älteren Rechnern mit wenig Speicher. Wenn zwei Grafiken quasi gleichzeitig vollständig geladen worden sind und dadurch die Funktion fertig() zweimal aufgerufen wird, kann es vorkommen, dass einer der Aufrufe verschluckt wird. Wie gesagt, das kommt ganz selten vor, aber es gibt Zeugen ...

Hier hilft Ihnen vielleicht die Eigenschaft complete eines Image-Objekts. Dieses gibt an, ob eine Grafik vollständig geladen worden ist (true) oder nicht (false). In der Funktion fertig() wird also jetzt kein Zähler heraufgesetzt, sondern überprüft, ob alle Grafiken vollständig geladen worden sind. Falls ja, wird zur Animationsseite übergegangen. Auch diese Eigenschaft wird von den verschiedenen Browsern unterschiedlich gut (oder schlecht) unterstützt.

Im folgenden Listing lernen Sie außerdem noch eine Anwendungsmethode für die Event-Handler onabort und onerror kennen. onabort tritt dann in Aktion, wenn der Benutzer das Laden mit der Schaltfläche Stop abbricht; onerror wird aktiv, wenn ein Fehler bei der Übertragung auftritt (beispielsweise, wenn die Grafikdatei nicht existiert).

<html>
<head>
<meat http-equiv="refresh"
content="30;url=animation.html" />
<!-- nach 30 Sekunden wird die Seite animation.htm
geladen -->
<title>Animation vorbereiten</title>
<script type="text/javascript"><!--
function fertig() {
   if (document.images[0].complete && document.
   images[1].complete && document.images[2].complete &&
   document.images[3].complete) {
      location.href = "animation.html";
   }
}
function abbruch() {
   alert("Sie wollen das Laden abbrechen? Na gut,
   wir leiten Sie weiter...");
   location.href = "animation.html";
}
function fehler() {
   alert("Beim Laden einer der Grafiken ist ein Fehler
   aufgetreten. Wir leiten Sie trotzdem weiter...");
   location.href = "animation.html";
}
//--></script>
</head>
<body>
<h1>Animation lädt... Bitte warten...</h1>
<img src="ani1.jpg" onload="fertig();"
onAbort="abbruch();" onError="fehler();" width="1" height="1" />
<img src ="ani2.jpg" onload="fertig();"
onAbort="abbruch();" onError="fehler();" width="1" height="1" />
<img src ="ani3.jpg" onload="fertig();"
onAbort="abbruch();" onError="fehler();" width="1" height="1" />
<img src ="ani4.jpg" onload="fertig();"
onAbort="abbruch();" onError="fehler();" width="1" height="1" />
</body>
</html>

Leider wird onerror nicht mitgeteilt, welche der Grafiken beim Laden einen Fehler hatte. Man könnte diese Information aber als Parameter an die Funktion fehler() übergeben.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 11.5     Die Meldung, die erscheint, wenn eine der Grafiken nicht existiert


Galileo Computing

11.5.3 Fortschrittsanzeige  toptop

Flash-Filme können es – mit etwas Mühe. Normale HTML-Seiten können es auch – in der Statuszeile des Browsers. Die Rede ist von Fortschrittsanzeigen, die angeben, wie viel von dem Inhalt einer Seite oder eines Films schon geladen worden ist. In Bezug auf Grafiken ist das mit der complete-Eigenschaft von Grafiken möglich.

Zunächst erstellen wir eine Fortschrittsanzeige, die angibt, wie viele Grafiken der aktuellen Seite bereits übertragen worden sind. Das Vorgehen ist das Folgende:

gp  Eine Funktion durchläuft alle Grafiken in der HTML-Seite und überprüft die complete-Eigenschaft.
gp  Die Anzahl der bereits vollständigen Grafiken wird durch die Anzahl der insgesamt zu ladenden Grafiken geteilt.
gp  Dieser Wert wird in der Statuszeile ausgegeben.
gp  Falls der Wert noch nicht 100  % entspricht, wird die Funktion per Timeout wieder aufgerufen.
function fortschritt() {
   var gesamt = document.images.length;
   var geladen = 0;
   for (var i=0; i<gesamt; i++) {
      if (document.images[i].complete) {
         geladen++;
      }
   }
    if (gesamt > 0) {
      window.status = "Geladen: " +
                      Math.round(100*geladen/gesamt) + "%";
    }
   if (gesamt > geladen) {
      setTimeout("fortschritt();", 500);
   }
}

Beachten Sie, dass Sie die Funktion erst aufrufen dürfen, wenn das HTML-Dokument vollständig geladen worden ist. Nachfolgend sehen Sie ein exemplarisches HTML-Dokument – mit Statusanzeige:

<html>
<head>
<title>Fortschrittsanzeige</title>
<script type="text/javascript"><!--
function fortschritt() {
   var gesamt = document.images.length;
   var geladen = 0;
   for (var i=0; i<gesamt; i++) {
      if (document.images[i].complete) {
         geladen++;
      }
   }
    if (gesamt > 0) {
      window.status = "Geladen: " +
                      Math.round(100*geladen/gesamt) + "%";
    }
   if (gesamt > geladen) {
      setTimeout("fortschritt();", 500);
   }
}
//--></script>
</head>
<body onload="fortschritt();">
<img src="1.png" /><img src="2.png" /><img src="3.png" />
</body>
</html>

Auf der Buch-DVD finden Sie noch eine weitere Datei (warten.php), die jedoch PHP voraussetzt. Anstelle von Grafikdateien lädt dort der JavaScript-Code eine PHP-Datei, die ein paar Sekunden wartet und dann erst die Dateien 1.png bis 3.png lädt. Somit geht die Fortschrittsanzeige nur schrittweise voran, und der Effekt ist besser zu beobachten.

Was für die aktuelle Seite gilt, kann auch für den Rest der Website gelten. Zwar ist es unsinnig, die Grafiken für die gesamte Site im Browser-Cache zu halten, aber zumindest oft verwendete Grafiken sollten Sie möglichst früh laden. Dazu gehören:

gp  das Firmenlogo (es kommt bestimmt auf jeder Seite vor)
gp  Navigationsgrafiken (die auch auf fast jeder Seite verwendet werden)
gp  weitere häufig verwendete Grafiken, zum Beispiel Füllgrafiken

Ein möglicher Ansatz besteht darin, diese Grafiken auf der Startseite des Angebots bereits zu laden und nach dem erfolgten Laden erst den Zugang zum restlichen Angebot zu eröffnen.

Dazu muss die Funktion fortschritt() ein wenig umgeschrieben werden (beziehungsweise eine Funktion programmiert werden, die Ähnliches wie fortschritt() leistet), damit Folgendes gewährleistet ist:

gp  Der Prozentsatz der bereits vollständig geladenen Grafiken der Webseite wird ermittelt.
gp  Dieser Prozentsatz wird zurückgegeben.
gp  Eine Funktion gibt den aktuellen Prozentwert an geeigneter Stelle aus.
gp  Sobald der Prozentwert 100  % beträgt, wird die Hauptseite des Angebots geladen.

Kommen wir zunächst zu der Funktion, die zurückliefert, wie viele der Grafiken der Webseite bereits vollständig geladen worden sind:

function geladen() {
   var gesamt = document.images.length;
   var geladen = 0;
   for (var i=0; i<gesamt; i++) {
      if (document.images[i].complete) {
         geladen++;
      }
    }
   if (gesamt > 0) {
      return geladen/gesamt;
   } else {
      return 1;  // 100 Prozent
   }
}

Die Funktion, die den gerade aktuellen Prozentwert regelmäßig ausgibt und bei 100 Prozent die nächste Seite lädt, ist folgendermaßen aufgebaut:

gp  Zunächst wird mit geladen() ermittelt, wie viele der Grafiken der aktuellen Seite bereits geladen worden sind:
var geladen = Math.round(100 * geladen());
geladen = "Bitte warten ... " + geladen + "%";
gp  Als Nächstes wird der Wert in einem <div>-Element ausgegeben, wobei wir auf DHTML und getElementById() setzen (mehr dazu erfahren Sie in Kapitel 16:
document.getElementById("geladen").innerHTML = geladen;
gp  Sobald 100  % erreicht worden sind, wird die nächste Seite aufgerufen:
if (geladen() == 1) {
   location.href = "homepage.html";
}
gp  Falls 100  % noch nicht erreicht sind, wird der Code per Timeout nach kurzer Zeit wieder aufgerufen.

Im Folgenden ist der komplette Code abgedruckt. Die Weiterleitungs-URL wird in einer globalen Variablen gespeichert, um das Skript leicht anpassen zu können.

<html>
<head>
<title>Fortschrittsanzeige</title>
<script type="text/javascript"><!--
function geladen() {
   var gesamt = document.images.length;
   var geladen = 0;
   for (var i=0; i<gesamt; i++) {
      if (document.images[i].complete) {
         geladen++;
      }
    }
   if (gesamt > 0) {
      return geladen/gesamt;
   } else {
      return 1;  // 100 Prozent
   }
}

var url = "homepage.html";
function warten() {
   var geladenprozent = Math.round(100 * geladen());
   geladenprozent = "Bitte warten ... " + geladenprozent + "%";
   document.getElementById("geladen").innerHTML = geladenprozent;
   if (geladen() == 1) {
      location.href = url;
   } else {
      setTimeout("warten()", 500);
   }
}
//--></script>
</head>
<body onload="warten();">
<div id="geladen" style="position: absolute;">
</div>
<img src="1.png" width="1" height="1" />
<img src="2.png" width="1" height="1" />
<img src="3.png" width="1" height="1" />
</body>
</html>

Beachten Sie, dass die width- und height-Eigenschaften der Grafiken auf "1" gesetzt worden sind, damit die Grafiken dort noch nicht angezeigt werden.

Die Fortschrittsanzeige lässt sich auch grafisch darstellen. Das ist ein wenig komplizierter, und vor allem wird das Ergebnis verfälscht:

gp  Die Grafiken zur Anzeige der Fortschrittsanzeige müssen ebenfalls geladen werden.
gp  Im schlimmsten Fall werden die restlichen Grafiken vor den Grafiken des Fortschrittsbalkens geladen.

Der Rest läuft wie folgt ab:

gp  Es wird eine fünfstufige Fortschrittsanzeige verwendet; jede Grafik entspricht 20 Prozent.
<nobr><img src="rot.png" name="balken1" /><img src="rot.png" name="balken2" />
<img src="rot.png" name="balken3" /><img src="rot.png" name="balken4" />
<img src="rot.png" name="balken5" /></nobr>
gp  Dann wird per Timeout der momentane Ladefortschritt bestimmt.
var geladen = geladen();
gp  Der Ladefortschritt wird (gerundet) durch zwanzig dividiert. In Abhängigkeit von diesem Ergebnis werden entsprechend viele Grafiken von rot auf grün geschaltet.
var fortschritt = Math.round(5*geladen); // *100 / 20
for (var i=1; i<=fortschritt; i++) {
   document.images["balken"+i].src = "gruen.png";
}
gp  Eine weitere Besonderheit: Damit die Fortschrittsanzeige auch komplett bewundert werden kann, erfolgt die Weiterleitung auf die nächste Seite erst nach einer kurzen Verzögerung:
setTimeout("location.href=\"" + url + "\"", 500);

Hier sehen Sie das komplette Skript:

<html>
<head>
<title>Fortschrittsanzeige</title>
<script type="text/javascript"><!--
function geladen() {
   var gesamt = document.images.length;
   var geladen = 0;
   for (var i=0; i<gesamt; i++) {
      if (document.images[i].complete) {
         geladen++;
      }
    }
   if (gesamt > 0) {
      return geladen/gesamt;
   } else {
      return 1;  // 100 Prozent
   }
}

var url = "homepage.html";
function warten() {
   var geladen = geladen();
   var fortschritt = Math.round(5*geladen); // *100 / 20
   for (var i=1; i<=fortschritt; i++) {
      document.images["balken"+i].src = "gruen.png";
   }
   if (geladen() == 1) {
      setTimeout("location.href = \"" + url + "\";", 500);
   } else {
      setTimeout("warten();", 500);
   }
}
//--></script>
</head>
<body onload="warten()">
<nobr><img src="rot.png" name="balken1" /><img src="rot.png" name="balken2" />
<img src="rot.png" name="balken3" /><img src="rot.png" name="balken4" />
<img src="rot.png" name="balken5" /></nobr>
<img src="1.png" width="1" height="1" />
<img src="2.png" width="1" height="1" />
<img src="3.png" width="1" height="1" />
</body>
</html>

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 11.6     Fast alle Grafiken sind schon geladen.

Denken Sie auf jeden Fall daran, dass Sie für Browser ohne Unterstützung des Image-Objekts (das sind eher wenige) oder mit deaktiviertem oder fehlendem JavaScript (das sind schon mehr) auf jeden Fall noch einen Link auf die eigentliche Hauptseite des Angebots zur Verfügung stellen sollten – denn ansonsten bleibt der Benutzer auf der Einstiegsseite hängen.

 <<   zurück
  
  Zum Katalog
Zum Katalog: JavaScript und AJAX
JavaScript und AJAX
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: JavaScript und AJAX - Das Video-Training






 JavaScript und AJAX -
 Das Video-Training


Zum Katalog: Webseiten programmieren und gestalten






 Webseiten
 programmieren
 und gestalten


Zum Katalog: XHTML, HTML und CSS






 XHTML, HTML und CSS


Zum Katalog: CSS-Praxis






 CSS-Praxis


Zum Katalog: AJAX






 AJAX


Zum Katalog: PHP 5 und MySQL 5






 PHP 5 und MySQL 5


Zum Katalog: TYPO3 4.0






 TYPO3 4.0


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de