Zufallsheader Augen- und Serverschonend | 28. Januar 2006 um 13:23 Uhr / Programming Webdesign /
Gerade stand ich vor der Aufgabe ein Headerbild per Zufall in eine Seite einzubinden. Ich hätte das auch mittels PHP auf dem Server machen können, das würde aber bedeuten dass sich die Dateien jedes mal ändern und somit das caching ziemlich durcheinander kommt, deshalb habe ich mich für eine JavaScript Lösung entschieden. Es galt dabei aber auch ein paar Probleme zu bewältigen, das größte war die änderung des headers so früh wie möglich zu machen, damit die Seite nicht flackert. Gleichzeitig sollte so wenig code wie möglich dafür verwendet werden.
Der Eventhandler onload fiel damit gleich weg, da dieser sogar auf das fertigladen aller bilder wartet und das dauert einfach zu lange. Ich habe mich also entschieden eine funktion gleich nachdem der relevante code geladen wurde aufzurufen. Die Funktion in eine externe Datei auszulagern war auch nicht sinnvoll, da dann nicht sichergestellt werden kann ob diese schon geladen ist, wenn sie aufgerufen wird. Blieb also nur noch die Notation in der Datei selbst.
Wenn ich sie im <head> Bereich definiert hätte, dann würde alles wunderbar funktionieren, aber ich hätte unnötig zwei mal <script type="text/javascript"><script> drinn, und ich wollte ja Code sparen, da das ganze jedes mal mit heruntergeladen werden muss. Naja lange Rede kurzer Sinn, die Lösung sah für mich dann so aus:
HTML
<div id="head">
<!-- hier kamen noch andere Sachen -->
</div>
<script type="text/javascript">
( function () {
var c = ['a','b','c','d','e','f','g','h','i','j','k'];
document.getElementById('head').className =
c[Math.round(Math.random()*c.length)];
} ) ()
</script>
CSS
#head {
background: url(default.jpg) top left no-repeat white;
/* hier noch alle anderen Styles für #head */
}
#head.a { background: url(1.jpg) top left no-repeat brown; }
#head.b { background: url(2.jpg) top right no-repeat yellow; }
#head.c { background: url(3.jpg) top center repeat-x blue; }
/* und so weiter */
[update:] Ich habe das new function() Konstrukt welches an dieser Stelle falsch war, da es keine anonyme Funktion deklariert hat ersetzt.
Ich definiere und rufe also diese anonyme Funktion sofort auf, wenn sie geladen ist, dadurch, dass sie im Quellcode genau unter dem head DIV ist, wird immer sicher gestellt dass dieser schon geladen ist. Das schöne dabei ist, dass noch bevor der Browser anfängt zu rendern die Klasse für das DIV schon geändert wurde und nunmehr das zufällige Bild geladen wird, ohne vorher das default Bild anzuzeigen. Schöner Nebeneffekt der anonymen Funktion ist auch, dass sie nie in anderen Scripten Unhelt anrichten kann, weil sie den Namespace verunreinigt, sie hat ja keinen Namen. Grundsätzlich könnte man so per Zufall völlig verschiedene Header produzieren, die man mit CSS unterschiedlich stylt.
Der Nachteil eines solchen Vorgehens ist offensichtlich, man schreibt extra Markup nur um das aussehen zu verändern, bzw. um ein Verhalten zu produzieren. Eigentlich sollte man ja die Trennung von strukturiertem Inhalt (Text mit Markup) und der Präsentationslogik (CSS) und Verhalten (JavaScript) nach dem drei Schichten Modell nutzen, manchmal aber ist es sinnvoller da ein bischen zu schummeln ;-). Vor allem wenn das Design für die ganze seite über eine einzelne Template Datei erstellt wird.
Kommentare
Die Kommentare sind für diesen Eintrag geschlossen.




abonnieren.
globe aus Stadt / Land / Fluss schrieb am 28.01.2006
da stellen sich mir nur folgende fragen:
a) wozu dieses new function() { } konstrukt?
b) wird der css part auch im dokument selbst definiert? ist das nicht auch etwas doof?
Jeena Paradies aus Varberg schrieb am 28.01.2006
zu a) damit die das Array c nicht global verfügbar ist und in andere Scripts reinstört ;-) aber jaja ich weiß schon, eigentlich ansonsten überflüssig
zu b) nein, wie kommst du darauf?
Ashura schrieb am 28.01.2006
<div id="head"> document.getElementById('navigation')Fällt dir etwas auf?
Gruß, Ashura
Jeena Paradies aus Varberg schrieb am 28.01.2006
Ah hehe das ist wohl beim übertragen noch geblieben, danke werde ich gleich ändern ;-).
Rolf aus Karlsruhe schrieb am 28.01.2006
Hi Jeena,
schöne Lösung!
Ich hätts mit Ajax (asynchronous javascript + xml) gemacht, Beispiel
http://rolfrost.de/cgi-bin/xmlhttpreq.cgi
Viele Grüße, Rolf
Markus Stange aus Gau-Bischofsheim schrieb am 28.01.2006
Daneben ;)
Dean Edwards hat letztens eine Lösung beschrieben, mit der man das Problem auch umgehen kann. Sie ist vielleicht etwas zu viel des guten, aber dafür hat man wieder die Schichten getrennt.
Sven schrieb am 29.01.2006
Ich frage mich, wieso das insgesamt so kompliziert gemacht wird.
An strategischen Stellen ein passendes document.write, verbunden ggf. mit einem noscript, sollte doch vollkommen ausreichend sein. Beispielsweise einfach dynamisch einen Klassennamen mnit JS auszugeben, und das DIV samt ID statisch sein zu lassen.
Martin schrieb am 29.01.2006
Wenn man HTTP-Redirects benutzt, können die Bilder auch im Cache zwischengespeichert werden. Für die Redirects braucht man nicht mal PHP o. ä., das geht auch mit mod_rewrite, zufällige Bilder mit einer RewriteMap vom Typ rnd, zeitabhängig geht es mittels Auswertung der TIME-Variablen.
Bastian schrieb am 01.02.2006
Hi!
Tschuldigung, aber mag mir jemand beantworten, was das für ein Konstrukt ist?
( funtion() { // mach was } ) ()Anonyme Funktionen, okay. Aber damit komme ich nicht klar.
Wieso steht die Funktion innerhalb von runden Klammern? Wieso dahinter noch mal ein Call-Operator ()?
Die Syntax verwirrt mich total. Ich dachte immer, ich könnte Javascript. Würde mich über eine kurze Erklärung freuen.
Im Übrigen: Wie wird die Funktion hier aufgerufen?
Was ist eigentlich mit Usern, die JS deaktiviert haben? Es sollte einen Noscript-Bereich geben.
Ich hätte wahrscheinlich doch lieber eine serverseitige Lösung genommen, damit es auch ohne JS funktioniert.
Henryk Plötz aus Berlin schrieb am 01.02.2006
Moin,
function() { ... }gibt in Javascript eine Funktion zurück. Man kann das natürlich in eine Variable speichern also
a = function() { ... }und diese dann aufrufen, mit
zum Beispiel. Aber da schon das erste Stückchen Code nur ein Ausdruck ist kann man ihn auch gleich weiterverwenden und direkt aufrufen:
(function() { ... })()Die Klammern um das
function(){ ... }sind nur um das unzweideutig zu machen.
(Vergleiche:
)
Na direkt da, sofort. Und der Witz ist eben dass das eine wirklich anonyme Funktion ist, da wir ihr keinen Namen zuordnen (brauchen).
--
Henryk Plötz
Grüße aus Berlin
wahsaga schrieb am 02.02.2006
Weil du dich in echtem XHTML (als XML ausgeliefert) von document.write verabschieden kannst.
Mathias schrieb am 09.06.2006
Tut mir leid, mich wiederholen zu müssen, aber: fällt dir hier etwas auf?
Gruß, Mathias
Jeena Paradies aus Varberg schrieb am 09.06.2006
Jaja ;-) irgendwann haben wir auf dem Weg zusammen alle Fehler bereinigt (und noch später auch die die ich durch die Bereinigung einbaue ;-) )
Christian schrieb am 13.09.2006
Hmm...das sieht sehr interessant aus soweit... aber kann man das ganze auch anwenden, wenn das Hintergrundbild der ganzen seite per Zufall geändert werden soll? Hab da bisher nur ne reine JavaScript Lösung gefunden, bei der ich in der html Datei das Hintergrundbild angeben muss, aber ich würd das Ganze gerne in einer seperaten css Datei machen...
Jeena Paradies aus Varberg schrieb am 13.09.2006
Ja, das ist kein Problem. Du müsstest dann nur anstatt einem <div> gleich dem Body diese IDs geben.
Christian schrieb am 14.09.2006
verdammt... klar... da hätte ich auch selbst drauf kommen können... Vielen Dank auf jeden Fall
Gunnar Bittersmann schrieb am 11.01.2007
Du hast im Code:
Nein! Erstens erreichst du so keine Gleichverteilung, zweitens kann als Index c.length herauskommen, und der Zugriff auf c[c.length] liefert nichts Sinnvolles. (Die Indizes gehen von 0 bis c.length - 1.)
Richtig wäre:
Steht doch tausendfach im Archiv! ;-)
Gunnar
PS: „Wenn ich sie im <header> Bereich […]“ Du meinst <head>?