Adventskalender 2. Dezember 2024 - HTML, CSS, JavaScript - der Weihnachtsplayer von Santa Claus
Verfasst: 02.12.2024 06:42:33
In diesem Jahr präsentiere ich euch im Debianforum Adventskalender 2024 im Namen von Santa Claus drei interessante Softwareprodukte und damit Einblicke in die webbasierte Softwareprogrammierung. Der heute vorgestellte Weihnachtsplayer nutzt HTML, CSS, DOM-Strukturen und JavaScript. Der Adventskalender in ein paar Tagen verwendet zusätzlich PHP und die Fetch API zur Interaktion mit einem Webserver, um die Adventskalendertürchen aus der Cloud zu laden. In einem weiteren Türchen stellt euch Santa Claus mit seinem Rentier Rudolph zusammen eine auf Leaflet basierte Navigationssoftware für die Verteilung von Weihnachtsgeschenken mit dem Weihnachtsschlitten vor.
Weihnachtsplayer
Beim Weihnachtsplayer handelt es sich um einen webbasierten Player zum Abspielen von weihnachtlichen Radiostreams. Santa Claus hat nämlich kein Spotify, mocp (moc) oder Audials Play, sondern nur vorausgewählte Internet-Streams mit Weihnachtsliedern in einem Browser mit einer Software, die er selbst geschrieben hat. So kann er die Weihnachtssender mit seinem Browser überall mit hin nehmen. Der Weihnachtsplayer hat einen Lautstärkeregler, jeder Radiostream wird über einen Button repräsentiert und zusätzlich hat Santa Claus einen SleepTimer eingebaut. Aktuell hört er FFN Tannenbaum.
Der Weihnachtsplayer ist wie jedes HTML-Programm aufgebaut. Interessant sind der CSS-Teil, der Haupt-Teil sowie der JavaScript-Teil.
CSS-Teil
CSS definiert diverse Gestaltungselemente wie Typografie, Farbgebung, Schaltflächen und Steuerelemente. Strukturelle Komponenten wie Container sorgen für eine klare Anordnung. Mittels CSS Grid und Media Queries wird eine responsive Darstellung realisiert, die sich unterschiedlichen Bildschirmgrößen anpasst. Als Alternativen hätte Santa Claus auch FlexBox, W3.CSS oder responsive Frameworks wie Bootstrap nutzen können.
Verwendet werden die folgenden CSS-Elemente:
Auf die genauere Konfiguration der einzelnen Elemente möchte Santa Claus nicht eingehen, da das Hauptaugenmerk auf JavaScript gelegt wird. Unterschieden wird vor allen zwischen CSS-Klassen (.) und CSS-Objekte (#). Die Verwendung von CSS-Objekten ist dann sinnvoll, wenn es dieses Objekt genau einmal existiert. Interessant vor allem für die JavaScript-Funktionen sind die Variablen #volume und #volumeControl für den Lautstärkeregler, #timer und #timerControl für den SleepTimer sowie #streamContainer für die Erstellung und Steuerung der Button für die in diesem Beispiel 24 Radio-Streams.
Haupt-Teil
Der Haupt-Teil umfasst das zentrale Container-Objekt #container mit #green-border als grüne Umrandung. Diese grüne Umrandung enthält die Überschrift <h1>, den Lautstärkeregler #volume, die Stream-Button #streamContainer sowie den SleepTimer #timer.
Lautstärkeregler und SleepTimer umfassen einen Bereich von 0 bis 100 (%) bzw. 0 bis 30 (Minuten). Interessanter ist die dynamische Erweiterung des streamContainer durch JavaScript
<ul><li></li></ul> definiert die Radiosender als eine Art Liste. Alternativ hätte Santa Claus jedoch auch <div>, <article>, <section> oder eine eigene CSS-Klasse verwenden können.
<body> enthält abschließend noch das HTML5-Objekt <audio id="audioPlayer"></audio>, welches ein nicht sichtbares Audio-Element ist, welches durch JavaScript erzeugt und gesteuert wird.
DOM
Das Document Object Model (DOM) (Wikipedia) ist eine standardisierte Programmierschnittstelle für HTML- und XML-Dokumente. Es stellt Webseiten als hierarchische, navigierbare Baumstruktur dar. Das DOM fungiert als Bindeglied zwischen statischem HTML und dynamischem JavaScript. Es ermöglicht JavaScript auf alle Elemente zuzugreifen und diese ohne Neuladen der Seite zu manipulieren. Zudem stellt das DOM eine Schnittstelle für Event Listener bereit. Hierdurch können statische Webseiten in interaktive, dynamische Anwendungen umgewandelt werden.
In unserem Programmbeispiel sieht die DOM-Struktur so aus:
Initialisierung JavaScript-Variablen und JavaScript-Objekte:
Zu Beginn werden Variablen initialisiert. audioPlayer, volumeControl, sleepTimer und streamContainer sind hierbei Variablen auf Referenzen von DOM-Elementen oder kürzer DOM-Elemente. audioPlayer ist vom Typ HTMLAudioElement, volumeControl und sleepTimer sind vom Typ HTMLInputElement und streamContainer ist vom Typ HTMLUListElement. Das Programm verwendet globale Variablen wie z. B. den JavaScript-Array STREAMS. Das ist nicht unbedingt Best Practice vereinfacht aber ein wenig den JavaScript-Code.
Hauptprogramm
Das Programm verfügt über insgesamt vier Event Listener. Ein Event Listener wartet auf ein bestimmtes Ereignis (wie einen Mausklick oder eine Tastatureingabe) und führt dann eine definierte Funktion aus, wenn dieses Ereignis eintritt.
Der erste Event Listener wird ausgeführt, wenn DOM vollständig geladen ist ('DOMContentLoaded'). Mit der Funktion SantasCreateStreamButtons() werden die Button erstellt, welches kein Event Listener ist. Anschließend werden die drei weitere Event Listener für den Lautstärkeregler, den SleepTimer-Regler sowie für die Button-Steuerung aktiviert.
Weiter unten gehen wir vor allen auf den letzten Event-Listener ein, da das Click-Event für die Button die Hauptfunktion des Weihnachtsplayers ist. Tritt das Ereignis ein wird an die Funktion SantasStartOrStopStream (event, url) das Event sowie der Wert button.dataset.url also die URL des angeklickten Buttons übergeben.
DOM um Radiosender erweitern
Vor der Aktivierung der drei Event Listener wird mit SantasCreateStreamButtons() der DOM und damit das vom Browser verarbeitete HTML um die einzelnen Streams erweitert.
Wie oben beschrieben ist streamContainer im HTML bzw. DOM definiert:
Über die Variable streamContainer hat JavaScript Zugriff auf diesen Teil der DOM-Struktur. Wie oben beschrieben ist streamContainer vom Typ HTMLUListElement und enthält <ul></ul>. Auf Basis der Streamliste STREAMS wird die DOM-Struktur für <ul></ul> um <li></li> für jeden einzelnen Radiosender erweitert. Die Funktion SantasCreateStreamButtons() durchläuft alle Streams und fügt <li></li> hinzu (streamContainer.appendChild(li) ). Innerhalb von <li></li> ist wiederum ein <button></button> enthalten, welches mit SantasCreateButton(stream) erzeugt wird.
Lautstärke und SleepTimer:
Diese Funktion setzt die Lautstärke
Diese Funktionen aktualisieren bzw. initialisieren den SleepTimer. Um Hintergrundanfragen bei nicht Nichtverwendung des SleepTimers zu unterbinden, wird er in diesen Fall auf „null“ gesetzt. Die Aktualisierung des SleepTimers verfolgt aktuell jede Sekunde. Anzumerken ist, dass setInterval statt requestAnimationFrame verwendet wird, damit der SleepTimer auch bei deaktiviertem Display funktioniert. Die verwendete JavaScript-Funktion „SantasStopAllStreams()“ beim Ablauf des Timers wird weiter unten erklärt.
Starten oder Stoppen von Radio-Streams
Die Funktion SantasStartOrStopStream(event, url) ist die Hauptfunktion des Weihnachtsplayers. Gesteuert durch das Click-Event wird für den Button mit button.dataset.url die URL ermittelt. Egal ob ein Radiosender aktiviert, deaktiviert oder gewechselt wird, werden sicherheitshalber zuvor alle (eigentlich nur ein Stream) über die Funktion SantasStopAllStreams() gestoppt. Wenn zuvor der angeklickte Stream nicht aktiv war, wird er gestartet.
Gesamtcode
Der Gesamtcode aus HTML, CSS und JavaScript stellt einen Radio-Player auf Basis von JavaScript bereit. Die Button des Weihnachtsplayer werden dynamisch aus einer Liste aufgebaut. Die Sender können leicht gestartet, gestoppt und gewechselt werden. Es kann die Lautstärke verändert und ein SleepTimer mit 30 Minuten genutzt werden. Bei Interesse könnt ihr den Gesamtcode 42261 als weihnachtsplayer.html lokal auf eurem Rechner oder auf einen Webserver speichern. Natürlich könnt ihr sowohl die Senderliste als auch das Design anpassen. So kann man z. B. den Player in einen Klassikplayer umbauen, der unterschiedliche Klassiksender spielt siehe Diskussion hier.
Ich hoffe euch hat der Weihnachtsplayer von Santa Claus gefallen. Hört ihr in der Weihnachtszeit Weihnachtslieder? Hört ihr auch Radiosender oder Radio-Streams? Welche Radiosender hört ihr?
Weihnachtsplayer
Beim Weihnachtsplayer handelt es sich um einen webbasierten Player zum Abspielen von weihnachtlichen Radiostreams. Santa Claus hat nämlich kein Spotify, mocp (moc) oder Audials Play, sondern nur vorausgewählte Internet-Streams mit Weihnachtsliedern in einem Browser mit einer Software, die er selbst geschrieben hat. So kann er die Weihnachtssender mit seinem Browser überall mit hin nehmen. Der Weihnachtsplayer hat einen Lautstärkeregler, jeder Radiostream wird über einen Button repräsentiert und zusätzlich hat Santa Claus einen SleepTimer eingebaut. Aktuell hört er FFN Tannenbaum.
Der Weihnachtsplayer ist wie jedes HTML-Programm aufgebaut. Interessant sind der CSS-Teil, der Haupt-Teil sowie der JavaScript-Teil.
Code: Alles auswählen
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Weihnachtsplayer</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Weihnachtsplayer">
<style>
/* CSS-Teil*/
</style>
</head>
<body>
<!—Haupt-Teil -->
<script>
// JavaScript-Teil
</script>
</body>
</html>
CSS definiert diverse Gestaltungselemente wie Typografie, Farbgebung, Schaltflächen und Steuerelemente. Strukturelle Komponenten wie Container sorgen für eine klare Anordnung. Mittels CSS Grid und Media Queries wird eine responsive Darstellung realisiert, die sich unterschiedlichen Bildschirmgrößen anpasst. Als Alternativen hätte Santa Claus auch FlexBox, W3.CSS oder responsive Frameworks wie Bootstrap nutzen können.
Verwendet werden die folgenden CSS-Elemente:
Code: Alles auswählen
:root, *, body, #container, h1, #volume, #timer, #volumeControl, #timerControl, #streamContainer, .button, .button.active, #green-border, @media (min-width: 600px), @media (min-width: 900px), @media (min-width: 1200px)
Auf die genauere Konfiguration der einzelnen Elemente möchte Santa Claus nicht eingehen, da das Hauptaugenmerk auf JavaScript gelegt wird. Unterschieden wird vor allen zwischen CSS-Klassen (.) und CSS-Objekte (#). Die Verwendung von CSS-Objekten ist dann sinnvoll, wenn es dieses Objekt genau einmal existiert. Interessant vor allem für die JavaScript-Funktionen sind die Variablen #volume und #volumeControl für den Lautstärkeregler, #timer und #timerControl für den SleepTimer sowie #streamContainer für die Erstellung und Steuerung der Button für die in diesem Beispiel 24 Radio-Streams.
Haupt-Teil
Der Haupt-Teil umfasst das zentrale Container-Objekt #container mit #green-border als grüne Umrandung. Diese grüne Umrandung enthält die Überschrift <h1>, den Lautstärkeregler #volume, die Stream-Button #streamContainer sowie den SleepTimer #timer.
Code: Alles auswählen
<main id="container">
<div id="green-border">
<h1>🎄 Weihnachtsplayer 🎄</h1>
<div id="volume">
<input type="range" id="volumeControl" min="0" max="100" step="1" value="50">
</div>
<ul id="streamContainer"></ul>
<div id="timer">
<input type="range" id="timerControl" min="0" max="30" step="1" value="0">
</div>
</div>
</main>
<audio id="audioPlayer"></audio>
Code: Alles auswählen
<ul id="streamContainer">
<li><button class="button" data-url="https://0n-christmas.radionetz.de/0n-christmas.aac">0N - Christmas</button></li>
</ul>
<body> enthält abschließend noch das HTML5-Objekt <audio id="audioPlayer"></audio>, welches ein nicht sichtbares Audio-Element ist, welches durch JavaScript erzeugt und gesteuert wird.
DOM
Das Document Object Model (DOM) (Wikipedia) ist eine standardisierte Programmierschnittstelle für HTML- und XML-Dokumente. Es stellt Webseiten als hierarchische, navigierbare Baumstruktur dar. Das DOM fungiert als Bindeglied zwischen statischem HTML und dynamischem JavaScript. Es ermöglicht JavaScript auf alle Elemente zuzugreifen und diese ohne Neuladen der Seite zu manipulieren. Zudem stellt das DOM eine Schnittstelle für Event Listener bereit. Hierdurch können statische Webseiten in interaktive, dynamische Anwendungen umgewandelt werden.
In unserem Programmbeispiel sieht die DOM-Struktur so aus:
Code: Alles auswählen
<!DOCTYPE html>
html (lang="de")
│
├── head
│ │
│ ├── meta (charset="UTF-8")
│ ├── title
│ ├── meta (name="viewport")
│ ├── meta (name="description")
│ │
│ └── style
│ └── (CSS-Regeln)
│
└── body
│
├── main#container
│ │
│ └── div#green-border
│ │
│ ├── h1
│ │
│ ├── div#volume
│ │ └── input#volumeControl
│ │
│ ├── ul#streamContainer
│ │ ├── li
│ │ │ └── button.button
│ │ ├── li
│ │ │ └── button.button
│ │ └── ... (weitere li-Elemente für jeden Stream)
│ │
│ └── div#timer
│ └── input#timerControl
│
├── audio#audioPlayer
│
└── script (defer)
└── (JavaScript-Code)
Initialisierung JavaScript-Variablen und JavaScript-Objekte:
Code: Alles auswählen
<script defer>
const STREAMS = [
{ "name": "0N - Christmas", "url": "https://0n-christmas.radionetz.de/0n-christmas.aac" },
// im Beispiel weitere 22 Streams
{ "name": "Krasse Weihnachten by Rautemusik", "url": "https://rautemusik-de-hz-fal-stream17.radiohost.de/weihnachten" }
];
const INITIAL_VOLUME = 0.5;
const MAX_SLEEP_TIMER = 30;
let currentVolume = INITIAL_VOLUME;
let sleepTimerInterval;
let sleepTimerEndTime;
const audioPlayer = document.getElementById('audioPlayer');
const volumeControl = document.getElementById('volumeControl');
const sleepTimer = document.getElementById('sleepTimer');
const streamContainer = document.getElementById('streamContainer');
volumeControl.value = INITIAL_VOLUME * 100;
sleepTimer.value = 0;
Hauptprogramm
Code: Alles auswählen
document.addEventListener('DOMContentLoaded', () => {
SantasCreateStreamButtons();
volumeControl.addEventListener('input', function() {
SantasSetVolume(this.value);
});
timerControl.addEventListener('input', function() {
SantasSetSleepTimer(parseInt(this.value));
});
streamContainer.addEventListener('click', function(event) {
const button = event.target.closest('.button');
if (button) {
const url = button.dataset.url;
SantasStartOrStopStream(event, url);
}
});
});
Der erste Event Listener wird ausgeführt, wenn DOM vollständig geladen ist ('DOMContentLoaded'). Mit der Funktion SantasCreateStreamButtons() werden die Button erstellt, welches kein Event Listener ist. Anschließend werden die drei weitere Event Listener für den Lautstärkeregler, den SleepTimer-Regler sowie für die Button-Steuerung aktiviert.
Weiter unten gehen wir vor allen auf den letzten Event-Listener ein, da das Click-Event für die Button die Hauptfunktion des Weihnachtsplayers ist. Tritt das Ereignis ein wird an die Funktion SantasStartOrStopStream (event, url) das Event sowie der Wert button.dataset.url also die URL des angeklickten Buttons übergeben.
DOM um Radiosender erweitern
Code: Alles auswählen
function SantasCreateStreamButtons() {
streams.forEach(stream => {
const li = document.createElement('li');
li.appendChild(SantasCreateButton(stream));
streamContainer.appendChild(li);
});
}
function SantasCreateButton(stream) {
const button = document.createElement('button');
button.classList.add('button');
button.dataset.url = stream.url;
button.innerHTML = stream.name.length > 16 ? stream.name.slice(0, 16) + '...' : stream.name;
return button;
}
Wie oben beschrieben ist streamContainer im HTML bzw. DOM definiert:
Code: Alles auswählen
<ul id="streamContainer"></ul>
const streamContainer = document.getElementById('streamContainer');
Code: Alles auswählen
<ul id="streamContainer">
<li><button class="button" data-url="https://0n-christmas.radionetz.de/0n-christmas.aac">0N - Christmas</button></li>
</ul>
Code: Alles auswählen
function SantasSetVolume(value) {
currentVolume = value / 100;
audioPlayer.volume = currentVolume;
}
Code: Alles auswählen
function SantasUpdateSleepTimer() {
if (!sleepTimerEndTime) {
clearInterval(sleepTimerInterval);
sleepTimerInterval = null;
return;
}
const remainingTime = Math.max(0, sleepTimerEndTime - Date.now());
timerControl.value = Math.ceil(remainingTime / 60000);
if (remainingTime <= 0) {
clearInterval(sleepTimerInterval);
sleepTimerInterval = null;
sleepTimerEndTime = null;
SantasStopAllStreams();
timerControl.value = 0;
}
}
function SantasSetSleepTimer(minutes) {
clearInterval(sleepTimerInterval);
sleepTimerInterval = null;
if (minutes === 0) {
sleepTimerEndTime = null;
timerControl.value = 0;
return;
}
sleepTimerEndTime = Date.now() + minutes * 60 * 1000;
sleepTimerInterval = setInterval(SantasUpdateSleepTimer, 1000);
}
Starten oder Stoppen von Radio-Streams
Code: Alles auswählen
function SantasStopAllStreams() {
audioPlayer.pause();
audioPlayer.currentTime = 0;
audioPlayer.src = '';
const buttons = Array.from(document.querySelectorAll('.button'));
buttons.forEach(btn => {
btn.classList.remove('active');
});
}
function SantasStartOrStopStream(event, url) {
const clickedButton = event.target.closest('[data-url]');
const currentButtonPlaying = audioPlayer.src === url && !audioPlayer.paused;
SantasStopAllStreams();
if (!currentButtonPlaying) {
audioPlayer.src = url;
audioPlayer.volume = currentVolume;
audioPlayer.play().then(() => {
clickedButton.classList.add('active');
});
}
}
Gesamtcode
Der Gesamtcode aus HTML, CSS und JavaScript stellt einen Radio-Player auf Basis von JavaScript bereit. Die Button des Weihnachtsplayer werden dynamisch aus einer Liste aufgebaut. Die Sender können leicht gestartet, gestoppt und gewechselt werden. Es kann die Lautstärke verändert und ein SleepTimer mit 30 Minuten genutzt werden. Bei Interesse könnt ihr den Gesamtcode 42261 als weihnachtsplayer.html lokal auf eurem Rechner oder auf einen Webserver speichern. Natürlich könnt ihr sowohl die Senderliste als auch das Design anpassen. So kann man z. B. den Player in einen Klassikplayer umbauen, der unterschiedliche Klassiksender spielt siehe Diskussion hier.
Ich hoffe euch hat der Weihnachtsplayer von Santa Claus gefallen. Hört ihr in der Weihnachtszeit Weihnachtslieder? Hört ihr auch Radiosender oder Radio-Streams? Welche Radiosender hört ihr?