Teil von SELFHTML aktuell Teil von Artikel Teil von JavaScript Teil von Fader-Framework

Geänderter Ansatz bei der Fader-Erzeugung

nach unten Geänderter Ansatz bei der Fader-Erzeugung
nach unten Neue Initialisierungsweise
nach unten Bild in Fader umwandeln
nach unten Angepasster Fader-Konstruktor
nach unten Endlose Slideshow

Geänderter Ansatz bei der Fader-Erzeugung

Wenn das Fader-Script unabhängig davon sein soll, ob bereits alle Bilder einer Slideshow im Dokument vorhanden sind oder nicht, dann muss es so gestaltet sein, dass es die Informationen über die anzuzeigenden Bilder auf andere Weise erhält. Dazu wird nun der Parameter, der an den Konstruktor übergeben wird, etwas erweitert, indem er nicht nur die ID des ursprünglichen HTML-Elements enthält, sondern gleich auch eine Liste mit den Pfaden (URLs) der Bilder.

nach obennach unten

Neue Initialisierungsweise

Der Parameter, der dem Konstruktor übermittelt wird, soll nun mehrere Informationen enthalten. Dabei bietet es sich an, ihn in ein Objekt umzubauen. Das sieht dann so aus:

Beispiel:

var meinFader = new Fader({
    id: "fader_test_1",
    images: ["images/pic1.jpg", "images/pic2.jpg"]
});

Erläuterung:

Der Variablen meinFader wird das Objekt zugewiesen, das der Konstruktor Fader als Rückgabewert zurückgibt. Beim Aufruf des Konstruktors wird ein Objekt als Parameter übergeben, das als Seite Objekt-Literal notiert ist. Dieses Objekt enthält zwei Eigenschaften, nämlich id und images. In der Eigenschaft id steht eben die ID des ursprünglichen HTML-Elements, das in einen Fader umgewandelt werden soll. In der Eigenschaft images steht ein Array notiert, das die Bildpfade der in der Slideshow anzuzeigenden Bilder enthält. Auch dieser Array ist in der Kurzschreibweise als Array-Literal notiert.

Beachten Sie:

Wenn man ein Objekt-Literal notiert, dann schreibt man innerhalb eines geschweiften Klammernpaares eine Aufzählung von Eigenschaften und Methoden, die jeweils durch ein Komma voneinander abgetrennt werden. Dabei darf nach der letzten Eigenschaft bzw. Methode aber kein Komma mehr stehen, da es sonst in einigen Browsern zu Fehlermeldungen und einem Abbruch des Scripts kommt. Deshalb steht am Ende der Zeile mit images kein Komma, und vor der schließenden eckigen Klammer, die das Array definiert, auch keines.

nach obennach unten

Bild in Fader umwandeln

Das Fader-Script soll zwei Einsatzzwecken dienen: Einer Slideshow für eine Bildergalerie, und einer Slideshow als schmückendes visuelles Element einer Seitengestaltung. In beiden Fällen muss im Dokument bereits ein Bild-Element vorhanden sein, das als "Ersatz" dient, falls ein Fader nicht erstellt werden kann - z.B. weil JavaScript im Browser des Besuchers nicht verfügbar oder deaktiviert ist. Dieses Bild-Element muss nun eine ID haben, über die es in einen Fader umgebaut werden kann. Dieses ursprüngliche Bild kann jedoch nicht als Container für die Slideshow herhalten, da ein Bild keine weiteren Kindelemente enthalten kann. Deshalb muss es durch etwas Geeignetes ersetzt werden.

Als Ersatz für das ursprüngliche Bild kommt sinvollerweise ein <span>-Element zum Einsatz, das anstelle des ursprünglichen Bildes in das HTML-Dokument eingesetzt wird. Dieses <span>-Element ist ebenso ein Inline-Element wie das ursprüngliche Bild es gewesen ist, sodass die Logik der Dokumentstruktur nicht gestört wird.

Der Vorgang des Ersetzens geht so:

Beispiel:

Beispiel-Seite Anzeigebeispiel: So sieht's aus

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>Bild mit span-Element ersetzen</title>
    <script type="text/javascript">
        function ersetze (id) {
            var original = document.getElementById(id);
            var span;

            if (original) {
                span = document.createElement("span");
                span.appendChild(document.createTextNode("span-Element"));
                original.parentNode.replaceChild(span, original);
            }
        };
    </script>
    <style type="text/css">
        span { border: 1px solid red; }
    </style>
</head><body>
    <h1>Bild mit span-Element ersetzen</h1>
    <p>Ist das ein Bild? <img src="images/fliegen4.jpg" alt="Flugzeug" id="fliegen"></p>
    <p><a href="javascript:ersetze('fliegen')">ersetzen</a></p>
</body></html>

Erläuterung:

Die Funktion ersetze nimmt einen Parameter id entgegen, der das zu ersetzende HTML-Element bezeichnet. Dieses Element wird in der Variablen original gespeichert. Sollte kein solches Element existieren, wird der if-Zweig ignoriert und die Funktion beendet.

Wenn ein passendes HTML-Element (hier das Bild) gefunden wurde, dann wird in der Variablen span ein neues <span>-Element angelegt. Mittels bereichsübergreifende Seite appendChild wird diesem <span>-Element ein neuer Textknoten hinzugefügt, der hier direkt im Funktionsaufruf mittels bereichsübergreifende Seite document.createTextNode erzeugt wird. Dieses Vorgehen dient dazu, dass in das neu erzeugte <span>-Element etwas Textinhalt kommt, um es im Beispiel besser sehen zu können. Des Weiteren wurde im Dokument ein <style>-Bereich notiert, der weitere visuelle Hervorhebungen (einen roten Rahmen) für das <span>-Element bewirkt.

Über sein Eltern-Element (parentNode) wird das originale HTML-Element durch das neu erzeugte <span>-Element im Dokument ersetzt, was über die Methode bereichsübergreifende Seite replaceChild des Elternelements geschieht.

Beachten Sie:

Solche Manipulationen am DOM-Baum des HTML-Dokuments sind erst dann möglich, wenn die zu manipulierenden Elemente auch tatsächlich zum Zeitpunkt des Funktionsaufrufes im Dokument existieren. Aus diesem Grund ist es mehr als ratsam, solche Manipulationen erst nach dem abgeschlossenen Ladevorgang durchzuführen! Daher kann die Funktion ersetze auch erst nach dem vollständigen Laden fehlerfrei Arbeiten.

nach obennach unten

Angepasster Fader-Konstruktor

Dieser Ersetzungsmechanismus kann nun in den Konstruktor aufgenommen werden.

Das <span>-Element, das die Bilder für die Slideshow enthält, wird in einer Eigenschaft des Fader-Objektes abgespeichert, um später leichter darauf zugreifen zu können. Diese Eigenschaft nennen wir sinnvollerweise element.

Nachdem das <span>-Element erstellt wurde, können auch die Bilder aus den übermittelten Pfadangaben nacheinander erzeugt und in dieses <span>-Element eingefügt werden.

Beispiel:

Beispiel-Seite Anzeigebeispiel: So sieht's aus

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>Angepasster Fader-Konstruktor</title>
    <script type="text/javascript">
        function Fader(einstellungen) {
            if (!einstellungen.id || !document.getElementById(einstellungen.id)
                || einstellungen.images.length < 2) {

                return new Boolean(false);
            }

            var i, original = document.getElementById(einstellungen.id);

            this.id = einstellungen.id;
            this.images = new Array();
            this.counter = 0;

            this.element = document.createElement("span");
            this.element.className = "fader";
            original.parentNode.replaceChild(this.element, original);

            for (i = 0; i < einstellungen.images.length; i++) {
                this.images[i] = document.createElement("img");
                this.images[i].src = einstellungen.images[i];
                this.images[i].alt = "Bild";

                if (i > 0) {
                    this.images[i].className = "next";
                    this.images[i].style.opacity = "0";
                    this.images[i].style.filter = "alpha(opacity=0)"; // IE?
                }

                this.element.appendChild(this.images[i]);
            }

            this.fade = function (step) {
                ...
            };

            this.next = function () {
                ...
            };
        }

        function erstelleFader () {
            var einstellungen = {
                id: "slideshow",
                images: ["images/fliegen1.jpg", "images/fliegen2.jpg","images/fliegen3.jpg",
                         "images/fliegen4.jpg", "images/fliegen5.jpg", "images/fliegen6.jpg"]
            };

            if (!window.meine_slideshow) {
                window.meine_slideshow = new Fader(einstellungen);
            }
        }
    </script>
    <style type="text/css">
        .next { position: absolute; top: 0; left: 0; opacity: 0; filter:alpha(opacity=0); }
        .fader { position: relative; display: inline-block; }
        .fader img { vertical-align: top; }
    </style>
</head><body>
    <h1>Angepasster Fader-Konstruktor</h1>
    <p>Der Fader: <img src="images/fliegen4.jpg" alt="" id="slideshow"></p>
    <p>Fader <a href="javascript:erstelleFader()">erzeugen</a> und
        <a href="#" onclick="if (window.meine_slideshow){ meine_slideshow.next();
        this.onclick = function () { return false; }; } return false;">starten</a></p>
</body></html>

Erläuterung:

Die Funktion erstelleFader benutzt den Konstruktor Fader und übergibt ihm ein Objekt, das zwei Eigenschaften besitzt: id und images. Die Eigenschaft id enthält die ID des Bild-Elementes, das der Konstruktor durch ein <span>-Element ersetzt. Dieses <span>-Element wird dann mit Bildelementen befüllt, die dynamisch aus den Pfadangaben des unter images gespeicherten Arrays erstellt werden.

Der Code des Konstruktors ist im Wesentlichen identisch mit der letzten Version. Geänderte bzw. neue Teile sind hervorgehoben.

Der Konstruktor überprüft zuerst, ob im übermittelten Objekt einstellungen eine ID übermittelt wurde, ob es dazu ein passendes HTML-Element im Dokument gibt und ob mindestens zwei Bildpfade im Array images enthalten sind. Wenn eine dieser Bedingungen nicht erfüllt ist, wird der Konstruktor beendet und gibt false zurück, da unter diesen Bedingungen kein Fader erstellt werden kann. Dieses false muss als Objekt zurückgegeben werden, denn ein Konstruktor muss immer ein Objekt zurückgeben. Daher wird es als new Boolean(false), und nicht einfach nur als false notiert. Dieser Unterschied kommt in diesem Beispiel nicht zum tragen, wird aber später in diesem Artikel noch erörtert.

Anschließend ersetzt der Konstruktor das originale HTML-Element durch ein <span>-Element, das die Klasse "fader" erhält.

In der for-Schleife wird die Liste der Bildpfade aus dem Array abgearbeitet, wobei für jeden Pfad mittels document.createElement ein neues <img>-Element erzeugt wird. Dieses wird gleich in this.images abgespeichert wird und es bekommt welches den Bildpfad in sein src-Attribut und als Alternativtext "Bild" eingetragen. Jedes so erzeugte Bild wird mit appendChild ans Ende des <span>-Element des Faders angehängt.

Dabei erhalten die entsprechenden Bildelemente die notwendige Klasse, damit das Positionierungsproblem gelöst werden kann. Das erste Bild bleibt davon - wie in den Beispielen zuvor - natürlich ausgeschlossen.

Mit dem Link "erzeugen" kann der Fader erstellt werden, indem die Funktion erstelleFader aufgerufen wird. Ein mehrmaliges Betätigen wird dadurch abgefangen, indem die Funktion erstelleFader prüft, ob bereits ein entsprechender Fader existiert.

Mit dem Link "starten" wird die next-Methode des Faders aufgerufen und die Animation gestartet. Wie in einem Beispiel zuvor macht sich der Link daraufhin selbst "unschädlich", um JavaScript-Fehler durch erneutes Betätigen zu vermeiden.

Beachten Sie:

Die Erzeugung der Bildelemente innerhalb der for-Schleife wurde so gelöst, dass die Bildelemente unmittelbar in this.images[i] gespeichert wurden. Das hat zum einen den Vorteil, dass das Script an dieser Stelle mit einer lokalen Variable weniger auskommt, und dass die Methode next weiterhin auf die Gesamtanzahl der Bilder im Fader zugreifen kann.

Um eine einheitliche Darstellung in den verschiedenen Browsern zu gewährleisten, waren zusätzliche CSS-Regeln notwendig. Im Opera-Browser wird für das Fader-Element display:inline-block benötigt, da sonst die Darstellung vom gewünschten Ergebnis abweicht. In anderen Browsern hat das Setzen dieser Eigenschaft keinen negativen Effekt.

Für CSS-Fortgeschrittene: Damit absolut positionierte Kindelemente (die Bilder) im Opera auch tatsächlich korrekt (in diesem Fall an der linken oberen Ecke) ausgerichtet werden, benötigt entweder das erste Kindelement oder aber das Elternelement die Eigenschaft display:block, sonst stimmt absolute Position nicht - dieses Opera-Verhalten ist offensichtlich ein Bug. Da aber das Fader-Element inline dargestellt werden soll (da es wie das ursprüngliche Bildelement im Elementfluss verbleiben soll), wurde ersatzweise inline-block als display-Wert verwendet. Somit bildet das Element keinen Block, aber Opera behandelt es hinsichtlich der Positionierung als Block-Element. Auch wenn die Notwendigkeit dieser Korrektur nicht einleuchtet, führt display:inline-block zur gewünschten Darstellung im Opera, und damit muss man sich zum gegenwärtigen Zeitpunkt wohl begnügen.

Im Firefox dagegen werden die Bilder nur dann passgenau übereinander abgebildet, wenn für Bilder im Fader-Element vertical-align:top eingestellt ist. Das hat zur Folge, dass große Bilder im Fließtext immer mit ihrer Oberkante an der Oberkante der jeweiligen Textzeile ausgerichtet werden. Alternativ könnte man hier selbstverständlich auch die Unterkante nehmen, indem man nicht top:0, sondern bottom:0 notiert, und dann analog auch vertical-align:bottom festlegt. Da andere Browser damit keine Probleme haben, wurden diese CSS-Eigenschaften in den CSS-Code aufgenommen.

Dieses Beispiel orientiert sich an dem Einsatzzweck "illustrierendes Gestaltungselement", da es die Bilder neu erzeugt und ins Dokument schreibt, diese zuvor jedoch nicht vorhanden waren. Wenn man eine bestehende Bildergalerie mit dieser Slideshow ausrüsten möchte, dann wäre es sicherlich sinnvoller, in der Funktion erstelleFader die bereits vorhandenen Bilder zu ermitteln, ihre Bildpfade zu speichern und die Bilder selbst aus dem Dokument zu entfernen, um erst dann den Fader erstellen zu lassen.

nach obennach unten

Endlose Slideshow

Der bisherige Aufbau des Faders erlaubt noch keine endlose Wiederholung der Bilder, da ein Übergang vom letzten Bild zum ersten Bild mit dem bisherigen Vorgehen so nicht möglich ist. Es gäbe dazu zwei Lösungswege:

  1. Man lässt parallel zum Einblenden des neuen Bildes das alte Bild einfach ausblenden.
  2. Oder man hat nur ein Bild im Fader, um jedesmal vor einer Überblendung das neue Bild hinter das alte in das Dokument einzufügen, die Überblendung durchzuführen, und anschließend das alte Bild aus dem Dokument zu entfernen.

In diesem Artikel der anscheinend kompliziertere zweite Ansatz verfolgt, der jedoch später eine größere Übersichtlichkeit im Code zur Folge haben wird.

Da im vorherigen Beispiel Referenzen auf die Bild-Elemente in der Eigenschaft this.images abgelegt wurden (sie wurden benötigt, um die Gesamtanzahl der Bilder zu ermitteln), können diese Referenzen genutzt werden, um die Bilder dynamisch in das Fader-Element einzuhängen und daraus wieder zu entfernen. Es ist nämlich so, dass aus dem Dokument entfernte HTML-Elemente nicht unbedingt "verloren" sind, solange eine Referenz auf sie irgendwo gespeichert wurde. Dann sind sie nämlich nur nicht im DOM-Baum eingehängt, wohl aber noch im Speicher des Browser vorhanden, sodass sie später wieder eingehängt werden können.

Slideshow mit Bildertausch

Beispiel-Seite Anzeigebeispiel: So sieht's aus

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>Endlose Slideshow</title>
    <script type="text/javascript">
        function Fader(einstellungen) {
            ...
            for (i = 0; i < einstellungen.images.length; i++) {
                this.images[i] = document.createElement("img");
                this.images[i].src = einstellungen.images[i];
                this.images[i].alt = "Bild";

                if (i == 0) {
                    this.element.appendChild(this.images[i]);
                }
            }

            this.fade = function (step) {
                var fader = this, imgs = this.element.getElementsByTagName("img");

                step = step || 0;

                imgs[1].style.opacity = step/100;
                imgs[1].style.filter = "alpha(opacity=" + step + ")"; // IE?

                step = step + 2;

                if (step <= 100) {
                    window.setTimeout(function () { fader.fade(step); }, 1);
                } else {
                    imgs[1].className = "";
                    this.element.removeChild(imgs[0]);
                    window.setTimeout(function () { fader.next(); }, 2000);
                }
            };

            this.next = function () {
                this.counter = (this.counter < this.images.length -1) ? this.counter +1 : 0;

                this.element.appendChild(this.images[this.counter]);
                this.images[this.counter].className = "next";
                this.fade();
            };
        }

        function erstelleFader () {
            ...
        }
    </script>
    <style type="text/css">
        ...
    </style>
</head><body>
    ...
</body></html>

Erläuterung:

Wie bereits im Kapitel Beispiel zuvor wird mit Hilfe der Funktion erstelleFader ein Bild-Element des Dokuments in einen Fader umgebaut. Wesentliche Teile des Scripts sind identisch geblieben, Abweichungen bzw. Neuerungen sind hervorgehoben.

Im Unterschied zum letzten Beispiel werden nun in der for-Schleife nicht mehr alle dynamisch erzeugten Bild-Elemente ins Fader-Element eingefügt, sondern nur das erste, denn es wird als sofort voll sichtbares Startbild benötigt. Die bisherigen Klassenzuweisungen an die restlichen Bilder werden auch nicht mehr in dieser for-Schleife vorgenommen, da diese nun an anderer Stelle dynamischer gehandhabt werden.

In der fade-Methode des Fader-Objektes wird nun wieder mit einer lokalen Variable imgs gearbeitet, wie es auch in den ersten Beispielen bereits der Fall gewesen ist. Da wir nur noch von zwei Bildelementen ausgehen dürfen, die als Bilderpaar für den Überblendungsvorgang im Fader-Element stehen, kann diese Überblendung auf die selbe einfache Weise erfolgen, wie im Beispiel des Kapitel einfachen Faders zuvor. Daher werden mittels getElementsByTagName die beiden Bild-Elemente des Fader-Elements ermittelt und in imgs abgelegt. Anschließend wird - wie gehabt - immer die Deckkraft des zweiten Bildes erhöht.

Neu in der fade-Methode ist, dass bei Erreichen der vollen Deckkraft des neuen Bildes das alte Bild aus dem Fader-Element mittels removeChild entfernt wird. Außerdem muss dem neuen Bild die Klasse "next" weggenommen werden, da es nicht mehr absolut positioniert werden darf - es ist ja jetzt das erste (und einzige) Bild-Element im Fader-Element, welches regulär im Element-Fluss angezeigt werden soll, wie das ja ohnehin der Normalfall gewesen wäre. Das Entfernen der Klasse geschieht durch die Zuweisung eines Leerstrings als "neuen" Klassennamen.

In der next-Methode wird der Zähler entsprechend um eins weitergezählt bzw. wieder auf Null zurückgestellt. Dazu wird das passende Bild-Element über seine Referenz aus der Liste in this.images mittels appendChild hinten in das Fader-Element eingefügt. Dazu bekommt es auch gleich den Klassennamen "next" zugewiesen, damit es passgenau über das bereits vorhandene Bild positioniert wird. Dann wird - wie gehabt - ein Überblendungsvorgang eingeleitet, indem fade aufgerufen wird.

Falls Ihnen an dieser Stelle die Schreibweise mit dem Fragezeichen aufgefallen ist: Es handelt sich hierbei um eine einfache bereichsübergreifende Seite Entweder-oder-Abfrage.

Beachten Sie:

Wenn man die Methode removeChild benutzt und den Rückgabewert dieser Methode nicht in einer Variablen abspeichert, dann ist das ausgehängte HTML-Elementobjekt für das Script "verloren". In diesem Scriptbeispiel muss der Rückgabewert von removeChild nicht noch extra gespeichert werden, da eine Referenz bereits in this.images vorhanden ist. Solange eine solche Referenz irgendwo existiert, kann das HTML-Element nicht verloren gehen.

weiter Seite Ein Framework zur Verwaltung der Fader-Objekte

zurück Seite Der objektorientierte Ansatz

Teil von SELFHTML aktuell Teil von Artikel Teil von JavaScript Teil von Fader-Framework

© 2008 bereichsübergreifende Seite Impressum, für diese Seite: E-Mail Felix.Riesterer@gmx.net