Im dritten Teil folgt nun die Konstruktor-Funktion, die das Kernstück unseres ganzen Scripts bildet, denn das Framework ist - wie der Name schon sagt - nur der Rahmen drumherum, der die einzelnen Fader verwaltet, dier Konstruktor-Funktion dagegen ist jedoch die "Fabrik", in der einzelne Fader-Objekte hergestellt werden.
Wieder ein paar Überlegungen, bevor wir unsere Konstruktor-Funktion aufbauen:
1.) Eigenschaften: a) Alle unsere über die init()-Funktion übergebenen Eigenschaften müssen verarbeitet werden. b) Sollten manche Eigenschaften nicht übergeben worden sein, dann gelten die Voreinstellungen aus unserem FaderFramework-Objekt (wie z.B. "viewTime", "fadeStep", "autostart" oder "random"). c) Unser Fader benötigt eine Playlist (ein Array - Eigenschaft "playList"), denn die Bilder sollen ja auch zufällig wiedergegeben werden. d) Wenn eine Playlist abläuft, dann brauchen wir einen Zeiger auf das aktuell angezeigte Bild, damit wir das vorhergehende ausblenden können: "counter". e) Bei einer zufälligen Wiedergabe sollten wir nach einem Durchlauf eine neue Playlist erstellen, da sonst der Zufall sehr regelmäßig würde. f) Wenn wir eine neue Playlist erstellen, dann fehlt uns die Möglichkeit, das "alte Bild" auszublenden, da wir in der neuen Playlist nicht mehr wissen, welches das alte Bild war. Daher brauchen wir auch die alte Playlist: "oldPlayList". g) Wir wollen unsere Slideshow anhalten können. Dazu brauchen wir eine Eigenschaft "stopped", die von unseren Funktionen berücksichtigt wird. h) Unser Fader läuft in einem <span>-Element ab. Dieses Element speichern wir unter der Eigenschaft "element".
2.) Funktionen (Methoden): a) fade() wird unsere Überblendungsfunktion werden. Sie blendet das aktuelle Bild (auf das unser Zähler zeigt) ein und blendet das alte Bild (also das, worauf der Zähler vorher gezeigt hat) aus. b) next() wird unsere Funktion, um einen Bilderwechsel anzustoßen. Sie erhöht den Zeiger (oder veranlasst, dass eine neue Playlist erzeugt wird, mit dem Zeiger wieder auf Null) und ruft fade() auf. Bei angehaltenem Fader darf diese Funktion aber kein nächstes Bild anzeigen lassen. Es sei denn wir möchten das sozusagen "gewaltsam" für einen einzelnen Schritt. Dazu benötigt sie einen zu übergebenden Parameter der "true" sein muss. Fehlt er, dann ist das im Prinzip dasselbe, als hätten wir "false" übergeben. c) stop() wird eine Funktion, die die Eigenschaft "stopped" auf "true" setzt. Dadurch wird die Funktion next() ausgebremst. Eine bereits angefangene Überblendung soll aber zu Ende ablaufen. Daher wird fade() diese Eigenschaft ignorieren. d) start() ist das Gegenstück zu stop() und setzt die Eigenschaft "stopped" auf "false". Außerdem startet sie die Slideshow, indem sie auch next() aufruft. e) createPlaylist() verwenden wir, um eine Playlist zu generieren.
3.) Die Herstellung eines Faders a) Ein Fader wird ja mit seiner ID unter FaderFramework.faders abgelegt werden. Das darf nur erfolgen, wenn folgende Bedingungen erfüllt sind: - Es wurde eine ID übermittelt. - Es existiert ein HTML-Element mit der angegebenen ID im Dokument. - Es existiert noch kein Fader mit dieser ID. - Es sind mindestens zwei Bilder zum Überblenden vorhanden. b) Bei der erfolgreichen Herstellung eines Faders muss das originale <img />-Element im Dokument durch ein <span>-Element ersetzt werden, welches wir ja unter "element" als Eigenschaft des Faders abspeichern.
Diese Überlegungen setzen wir in den einzelnen Funktionen um. Beginnen wir mit der einfachsten, mit stop():
this.stop = function () {
this.stopped = true;
};
Das war ja einfach. Schauen wir uns die nächst kompliziertere an, start():
this.start = function () {
this.stopped = false;
this.next();
};
Aha. Jetzt bezieht sich start() irgendwie auf next(). Schauen wir uns next() an:
this.next = function (single) {
// "single" ist true oder false und dient dazu, einen einmaligen Wechsel zu ermöglichen, ohne eine Slideshow zu starten. Wird kein Parameter übergeben, dann wird single nicht als true interpretiert.
if (single) {
this.stopped = true;
}
// wurde der Fader angehalten?
if (this.stopped && !single) {
return; // Ja -> keinen Bildwechsel durchführen!
}
// Counter weiterzählen (oder zurücksetzen)
this.counter = (this.counter < this.playList.length -1) ? this.counter +1 : 0;
// Neue Playlist fällig?
if (this.counter == 0) {
// neue Playlist generieren
this.oldPlayList = this.playList; // aktuelle Playlist speichern
this.createPlayList(); // neue aktuelle Playlist erstellen
}
// Fading einleiten
this.fade();
};
Bevor wir zum Interessantesten kommen, hier die Funktion zum Generieren einer Playlist:
// Playlist generieren (enthält nur die Nummern der Bilder)
this.createPlayList = function () {
this.playList = new Array();
if (this.random) {
// zufällige Reihenfolge
while (this.playList.length < this.images.length) {
vorhanden = false; // Zufallszahl bereits vorhanden?
r = Math.floor(Math.random() * (this.images.length));
for (i = 0; i < this.playList.length; i++) {
if (r == this.playList[i]) {
vorhanden = true;
}
}
if (!vorhanden) {
this.playList[this.playList.length] = r;
}
}
} else {
// geordnete Reihenfolge
for (i = 0; i < this.images.length; i++) {
this.playList[i] = i;
}
}
};
Und jetzt kommt der Fading-Vorgang:
// Fade-Funktion für den Bilderwechsel (jeder Aufruf entspricht einem Fading-Schritt)
this.fade = function (step) {
var imgs = new Array(), v;
// Wenn kein Wert übertragen wurde, dann muss das Fading von vorne durchgeführt werden
step = (!step) ? 0 : step;
// Das letzte Bild steht in der Liste vor dem aktuellen (falls dieses ganz am Anfang steht, gilt das letzte der alten Playlist)
imgs[0] = (this.counter == 0) ? this.images[this.oldPlayList[this.oldPlayList.length -1]] : this.images[this.playList[this.counter -1]];
// Das neue Bild ist das, auf welches der Counter zeigt
imgs[1] = this.images[this.playList[this.counter]];
for (i = 0; i < imgs.length; i++) {
v = (i == 0) ? (100 - step) : step;
imgs[i].style.opacity = v/100;
// IE?
if (imgs[i].style.filter != "undefined") {
imgs[i].style.filter = "alpha(opacity=" + v + ")";
}
}
step += this.fadeStep;
if (step <= 100) {
// nächsten Fade-Schritt ausführen
window.setTimeout(""
+ "FaderFramework.faders."
+ this.id
+ ".fade("
+ step
+ ");",
1);
} else {
// Bildübergang abgeschlossen -> nach der Pause nächstes Bild
window.setTimeout(""
+ "FaderFramework.faders."
+ this.id
+ ".next();",
this.viewTime);
}
};
Jetzt brauchen wir im Konstruktor nur noch regeln, dass das originale HTML-Element mit der übertragenen ID (das <img />-Element) mit unserem <span>-Element ersetzt wird.
Fader: function (einstellungen) {
/*
In diesem Konstruktor verweist "this" immer auf das zu erzeugende Objekt - vorausgesetzt,
dieser Konstruktor wird mit dem Schlüsselwort "new" aufgerufen, z.B. var a = new this.Fader()
*/
// wie "einstellungen" aussehen muss, siehe Funktion "init"!
var className, imgs, i, r, vorhanden;
// Darf eventuell kein Fader eingerichtet werden?
if (
// keine ID (oder ein Leerstring) übergeben
!einstellungen.id
||
// kein HTML-Element mit dieser ID vorhanden
!document.getElementById(einstellungen.id)
||
// für diese ID ist bereits ein Fader eingerichtet
FaderFramework.faders[einstellungen.id]
||
// weniger als zwei Bilder angegeben
einstellungen.images.length < 2
) {
// also gibt es keinen Fader für diesen init-Aufruf
return false;
}
// Einstellungen des Faders vornehmen
this.id = einstellungen.id;
this.images = new Array(); // Bilder werden hier nicht als Zeichenketten, sondern später als HTML-Elementobjekte abgelegt...
this.random = einstellungen.random ? einstellungen.random : FaderFramework.random;
this.autostart = (typeof(einstellungen.autostart) != "undefined") ? einstellungen.autostart : FaderFramework.autostart;
this.viewTime = einstellungen.viewTime ? einstellungen.viewTime : FaderFramework.viewTime;
this.fadeStep = einstellungen.fadeStep ? einstellungen.fadeStep : FaderFramework.fadeStep;
this.stopped = false; // hiermit kann später der Fader angehalten werden
this.playList = new Array(); // Wiedergabeliste
this.oldPlayList = [0]; // vorherige Wiedergabeliste (besteht aus einem einzigen Bild)
this.counter = 0; // aktuell angezeigtes Bild (Zähler für Playlist)
// DOM-Baum des HTML-Dokumentes auf den Fader vorbereiten
// <span>-Element als Container erzeugen und mit der Fader-Klasse ausrüsten
this.element = document.createElement("span");
this.element.className = FaderFramework.className;
// vor das ursprüngliche Bild setzen
i = document.getElementById(this.id); // ursprüngliches Bild
i.parentNode.insertBefore(this.element, i);
// ursprüngliches Bild entfernen
i.parentNode.removeChild(i);
// Bilder aus der Liste zu echten Bildobjekten machen und ins <span>-Element einhängen
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 = "";
// Alle Bilder, außer dem ersten, müssen positioniert werden, damit sie nicht neben oder unter dem ersten angezeigt werden.
if (i > 0) {
this.images[i].className = "next";
// Volle Durchsichtigkeit einstellen (erstes Bild soll ja gleich angezeigt werden
this.images[i].style.opacity = 0;
// IE?
if (this.images[i].style.filter != "undefined") {
this.images[i].style.filter = "alpha(opacity=0)";
}
}
// einhängen
this.element.appendChild(this.images[i]);
}
/*
Funktionen (Methoden) des Faders definieren!
*/
// wurde oben bereits behandelt
// Playlist erzeugen
this.createPlayList();
// fertigen Fader zurückgeben
return this;
}
Damit ist unser Fader-Bauplan im Prinzip fertig und unsere onload-Funktion kann ihn benutzen, um die mit init()-Angeforderten Fader auch zu erstellen.
Unser fertiges JavaScript kommt im nächsten Post, denn ich bin der Forensoftware wieder etwas zu geschwätzig. ;-)
Liebe Grüße,
Felix Riesterer.
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)