Wer mich ein bisschen kennt, weiß dass ich so ziemlich jeden Song von der bästen Bänd der Welt auswendig kann. Aber auch, dass ich noch nie mit einem Fan-Shirt gesehen wurde. Nicht einmal auf Konzerten!
Das liegt daran, dass die Auswahl im offiziellen Die Ärzte Fanshop für Frauen sehr mau ausfällt. Das heißt: Es gibt genau EIN Unisex-Shirt. Also habe ich einfach selber ein paar Designs erstellt, und die gibt’s hier for free zum Herunterladen: https://fän-stuff.de/
Die Website dazu habe ich natürlich selber geschrieben – mit schönem, sauberen Code. Es gibt sogar eine Songzeile des Tages, die (wie der Name vermuten lässt) sich jeden Tag ändert.
Jekyll mit Liquid-Logik
Im ersten Anlauf habe ich das Ganze rein statisch mit Jekyll und einem feinen Liquid-Hack gelöst. Dafür habe ich zuerst eine Datei mit Songzeilen erstellt. In _data/sprueche.yml
sieht der Eintrag für einen Song so aus:
- text: 'Die Welt gehört dir: Was wirst du mit ihr machen?'
title: 'Himmelblau'
url: 'https://www.bademeister.com/songs/himmelblau'
Der Trick: ich nutze das Datum als Index, modulo der Anzahl der Sprüche. In meiner index.html
nutze ich dafür den folgenden Code-Schnipsel:
{% assign sprueche = site.data.sprueche %}
{% assign today = site.time | date: "%j" %} {# Tag im Jahr: 1 bis 366 #}
{% assign index = today | modulo: sprueche.size %}
<p>{{ sprueche[index] }}</p>
site.time | date: "%j"
→ gibt mir den aktuellen Tag im Jahr (z. B. Tag 172).modulo: sprueche.size
→ sorgt dafür, dass ich nicht aus Versehen aus der Liste herausfalle.sprueche[index]
→ holt den passenden Spruch.
Das funktioniert super, allerdings mit einem kleinen Haken.
Dann doch JavaScript
Letztlich habe ich es doch auf die klassische Art mit JavaScript gelöst.
Warum? Weil GitHub Pages statisch ist, das heißt: Es wird immer dieselbe HTML-Seite ausgeliefert. Und da Jekyll nur beim Build rendert (also z. B. beim Pushen oder Deployen), bleibt die Songzeile des Tages über die ganze Zeit hinweg gleich, solange bis ich manuell pushe. Nicht ganz das, was ich mir vorgestellt hatte.
Mit JavaScript kann ich das direkt im Browser erledigen. Die Seite fragt dann lokal beim Laden: Hey, du, welcher Tag ist heute? und wählt on the fly einen passenden Song aus der Liste aus.
Die Funktionen im Detail
pickSong(songliste)
Diese Funktion sorgt dafür, dass täglich ein anderer Song basierend auf dem aktuellen Datum angezeigt wird.
Dazu wird erst das heutige Datum ermittelt und mit dem Jahresanfang (dem 0. Januar) verglichen. Daraus ergibt sich, wie viele Tage seit Jahresbeginn vergangen sind. Diese Tageszahl wird dann als Basis genommen, um einen Eintrag aus der Songliste auszuwählen.
Damit nicht aus Versehen ein ungültiger Eintrag aus der Liste geholt wird, wird ein kleiner Trick genutzt: Der aktuelle Tag im Jahr wird durch die Anzahl der Songs geteilt, und nur der Rest der Division wird verwendet (das nennt man modulo).
Wenn heute der 172. Tag im Jahr ist und du 20 Songs hast, dann:
172 % 20 = 12
Das ist das gleiche wie 172 / 20 = 8 Rest 12
Also wird einfach der Song an Stelle 12 angezeigt.
So wird sichergestellt, dass der Index immer innerhalb der Songliste bleibt (weil das Ergebnis nie größer sein kann als die Anzahl an Songs).
function pickSong(songliste) {
const heute = new Date();
const jahresbeginn = new Date(heute.getFullYear(), 0, 0);
const differenz = heute - jahresbeginn;
const tagDesJahres = Math.floor(differenz / 1000 / 60 / 60 / 24);
const index = tagDesJahres % songliste.length;
return songliste[index];
}
placeSongInHtml(song)
Diese Funktion sorgt dafür, dass die ausgewählte Songzeile im HTML landet und sichtbar auf der Website erscheint. Oder ganz knapp: Die Funktion packt die Daten an die richtigen Stellen.
Dafür nimmt sie ein song
-Objekt entgegen (mit text
, title
und url
) und verteilt diese Infos in die passenden HTML-Elemente:
- Der Songtext wird in das Element mit der ID
songzeile-text
geschrieben. - Der Titel des Songs kommt in das Element mit der ID
songzeile-title
. - Und der Link, z. B. zur Quelle oder zum Song selbst, wird im Element mit der ID
songzeile-link
hinterlegt.
function placeSongInHtml(song) {
document.getElementById('songzeile-text').textContent = song.text;
document.getElementById('songzeile-link').href = song.url;
document.getElementById('songzeile-title').textContent = song.title;
}
Und so kommt alles zusammen
Die Datei mit den Songzeilen wird per fetch()
vom Server geladen:
fetch('/songs.json');
Sobald die Datei erfolgreich geladen wurde, wird sie mit .json()
umgewandelt. Das ist wichtig damit wir sie überhaupt weiterverarbeiten können:
.then(function (response) {
return response.json();
})
Wenn das Parsen geklappt hat, wird die pickSong
-Funktion aufgerufen:
.then(pickSong)
Und ganz zum Schluss sorgt placeSongInHtml
dafür, dass der ausgewählte Song hübsch im HTML angezeigt wird:
.then(placeSongInHtml);
Also: Erst laden, dann umwandeln, dann auswählen, dann anzeigen. Alles Schritt für Schritt und super lesbar verkettet durch .then(...)
.
Falls du dich fragst, was es mit diesen .then(...)
-Ketten eigentlich auf sich hat: Das gehört zur sogenannten Promise-Logik in JavaScript.
Das ist eine elegante Art, asynchrone Abläufe Schritt für Schritt abzuarbeiten.
Jedes .then(...)
wartet auf den vorherigen Schritt und führt dann etwas aus. Ein bisschen verwirrend, doch keine Sorge: genau dazu gibt’s demnächst einen eigenen Blogbeitrag.
Was ich außerdem gelernt habe
Umlaute im Domainnamen machen Ärger. Wenn die URL also bei dir im Browser irgendwie komisch aussieht: sei unbesorgt, das ist keine billige Phishing-Seite 🐳 Nein, das liegt daran, dass sie automatisch in Punycode übersetzt wird. Das ist eine spezielle Kodierung. Sie erlaubt Umlaute und andere Sonderzeichen darzustellen. Denn das klassische Domain-Name-System (DNS) unterstützt nur ASCII-Zeichen (also Buchstaben a bis z, Zahlen und einige wenige Sonderzeichen).
In Punycode übersetzt wird fän-stuff.de zu xn–fn-stuff-0za.de
Gibt’s hier auch Ärzte-Fans? 👀