Stopp Button in die Titelzeile verlegt, als Symbol dargestellt und wird nur angezeigt, wenn auch ein Sender abgespielt wird. Header Bereich nur immer fix oben sichtbar.
268 lines
9.7 KiB
JavaScript
268 lines
9.7 KiB
JavaScript
document.addEventListener('DOMContentLoaded', function () {
|
|
// === Abschnitt: Globale Variablen ===
|
|
const presetContainer = document.getElementById('preset-container');
|
|
const newPresetForm = document.getElementById('new-preset-form');
|
|
const newPresetNameInput = document.getElementById('new-preset-name');
|
|
const newPresetUrlInput = document.getElementById('new-preset-url');
|
|
const exportButton = document.getElementById('export-button');
|
|
const importButton = document.getElementById('import-button');
|
|
const loadPresetsLink = document.getElementById('load-presets-link');
|
|
const stopButton = document.querySelector('.stop-button');
|
|
const currentStationName = document.getElementById('current-station-name');
|
|
let currentPlayingItem = null; // Speichert das aktuell spielende Element
|
|
|
|
// === Abschnitt: Initialisierung ===
|
|
initializeFooter();
|
|
initializeEventListeners();
|
|
loadExistingPresets();
|
|
setupSortable();
|
|
|
|
// === Funktion: Footer dynamisch aktualisieren ===
|
|
function initializeFooter() {
|
|
const currentYear = new Date().getFullYear();
|
|
const currentYearElement = document.getElementById('current-year');
|
|
if (currentYearElement) {
|
|
currentYearElement.textContent = currentYear;
|
|
}
|
|
|
|
const serverName = window.location.hostname;
|
|
const serverNameElement = document.getElementById('server-name');
|
|
if (serverNameElement) {
|
|
serverNameElement.textContent = serverName;
|
|
}
|
|
}
|
|
|
|
// === Funktion: Titel dynamisch ändern ===
|
|
function updateTitle(stationName) {
|
|
if (stationName) {
|
|
document.title = `${stationName} - Radioplayer mit Presets`;
|
|
} else {
|
|
document.title = "Radioplayer mit Presets";
|
|
}
|
|
}
|
|
|
|
// === Abschnitt: Event-Listener ===
|
|
function initializeEventListeners() {
|
|
newPresetForm.addEventListener('submit', (event) => {
|
|
event.preventDefault(); // Verhindert die Standardaktion (Seiten-Reload)
|
|
|
|
const presetName = newPresetNameInput.value.trim();
|
|
const presetUrl = newPresetUrlInput.value.trim();
|
|
|
|
if (!presetName || !presetUrl) {
|
|
alert("Bitte geben Sie einen Namen und eine URL ein.");
|
|
return;
|
|
}
|
|
|
|
if (!isValidHttpUrl(presetUrl)) {
|
|
alert("Bitte geben Sie eine gültige HTTP- oder HTTPS-URL ein.");
|
|
return;
|
|
}
|
|
|
|
addNewPreset(presetName, presetUrl);
|
|
savePresetToLocalStorage(presetName, presetUrl);
|
|
|
|
newPresetNameInput.value = '';
|
|
newPresetUrlInput.value = '';
|
|
});
|
|
|
|
exportButton.addEventListener('click', exportPresets);
|
|
importButton.addEventListener('click', importPresets);
|
|
loadPresetsLink.addEventListener('click', loadPresetsFromFile);
|
|
stopButton.addEventListener('click', stopPlayback);
|
|
}
|
|
|
|
// === Funktion: URL-Validierung ===
|
|
function isValidHttpUrl(url) {
|
|
try {
|
|
const parsedUrl = new URL(url);
|
|
return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// === Funktion: Preset-Handling ===
|
|
function loadExistingPresets() {
|
|
const presets = JSON.parse(localStorage.getItem('presets')) || [];
|
|
presets.forEach(preset => addNewPreset(preset.name, preset.url));
|
|
}
|
|
|
|
function addNewPreset(name, url) {
|
|
const presetItem = document.createElement('div');
|
|
presetItem.classList.add('preset-item');
|
|
presetItem.dataset.streamUrl = url;
|
|
|
|
presetItem.innerHTML = `
|
|
<h3>${name}</h3>
|
|
<div class="button-container">
|
|
<button class="move-button"><i class="fas fa-arrows-alt"></i></button>
|
|
<button class="edit-button"><i class="fas fa-edit"></i></button>
|
|
<button class="delete-button"><i class="fas fa-trash-alt"></i></button>
|
|
</div>
|
|
`;
|
|
|
|
presetItem.querySelector('.edit-button').addEventListener('click', (event) => {
|
|
event.stopPropagation();
|
|
editPreset(presetItem, name, url);
|
|
});
|
|
|
|
presetItem.querySelector('.delete-button').addEventListener('click', (event) => {
|
|
event.stopPropagation();
|
|
deletePreset(presetItem);
|
|
});
|
|
|
|
presetItem.addEventListener('click', () => playStream(url, presetItem));
|
|
|
|
presetContainer.appendChild(presetItem);
|
|
}
|
|
|
|
function editPreset(item, currentName, currentUrl) {
|
|
const newName = prompt("Neuer Name:", currentName);
|
|
const newUrl = prompt("Neue URL:", currentUrl);
|
|
|
|
if (newName !== null && newUrl !== null) {
|
|
item.querySelector('h3').textContent = newName;
|
|
item.dataset.streamUrl = newUrl;
|
|
savePresetOrder();
|
|
}
|
|
}
|
|
|
|
function deletePreset(item) {
|
|
if (confirm("Möchten Sie diesen Sender wirklich löschen?")) {
|
|
presetContainer.removeChild(item);
|
|
savePresetOrder();
|
|
}
|
|
}
|
|
|
|
function savePresetToLocalStorage(name, url) {
|
|
const presets = JSON.parse(localStorage.getItem('presets')) || [];
|
|
presets.push({ name, url });
|
|
localStorage.setItem('presets', JSON.stringify(presets));
|
|
}
|
|
|
|
function savePresetOrder() {
|
|
const presetItems = Array.from(presetContainer.children);
|
|
const presets = presetItems.map(item => ({
|
|
name: item.querySelector('h3').textContent,
|
|
url: item.dataset.streamUrl
|
|
}));
|
|
localStorage.setItem('presets', JSON.stringify(presets));
|
|
}
|
|
|
|
// === Funktion: Audio-Handling ===
|
|
function playStream(url, item) {
|
|
if (currentPlayingItem) {
|
|
const currentAudio = currentPlayingItem.querySelector('audio');
|
|
if (currentAudio) {
|
|
currentAudio.pause();
|
|
currentAudio.remove();
|
|
}
|
|
currentPlayingItem.classList.remove('playing');
|
|
}
|
|
|
|
const audioElement = new Audio(url);
|
|
audioElement.autoplay = true;
|
|
audioElement.loop = true;
|
|
audioElement.volume = 0.5;
|
|
audioElement.onerror = () => alert('Fehler beim Laden des Streams: ' + url);
|
|
|
|
item.appendChild(audioElement);
|
|
item.classList.add('playing');
|
|
currentPlayingItem = item;
|
|
currentStationName.textContent = 'Es läuft: ' + item.querySelector('h3').textContent;
|
|
|
|
stopButton.classList.remove('hidden'); // Stopp-Button einblenden
|
|
updateTitle(item.querySelector('h3').textContent);
|
|
}
|
|
|
|
function stopPlayback() {
|
|
if (currentPlayingItem) {
|
|
const audioElement = currentPlayingItem.querySelector('audio');
|
|
if (audioElement) {
|
|
audioElement.pause();
|
|
audioElement.currentTime = 0;
|
|
currentPlayingItem.classList.remove('playing');
|
|
currentPlayingItem = null;
|
|
currentStationName.textContent = 'Wähle einen Sender aus';
|
|
}
|
|
}
|
|
|
|
stopButton.classList.add('hidden'); // Stopp-Button ausblenden
|
|
updateTitle('');
|
|
}
|
|
|
|
// === Funktion: Preset-Import und -Export ===
|
|
function exportPresets() {
|
|
const presets = JSON.parse(localStorage.getItem('presets')) || [];
|
|
const json = JSON.stringify(presets, null, 2);
|
|
|
|
const blob = new Blob([json], { type: 'application/json' });
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = 'webradio_presets.json';
|
|
a.click();
|
|
|
|
URL.revokeObjectURL(url);
|
|
}
|
|
|
|
function importPresets() {
|
|
const input = document.createElement('input');
|
|
input.type = 'file';
|
|
input.accept = '.json';
|
|
input.addEventListener('change', (event) => {
|
|
const file = event.target.files[0];
|
|
if (file) {
|
|
const reader = new FileReader();
|
|
reader.onload = (e) => {
|
|
try {
|
|
const importedPresets = JSON.parse(e.target.result);
|
|
if (Array.isArray(importedPresets)) {
|
|
localStorage.setItem('presets', JSON.stringify(importedPresets));
|
|
presetContainer.innerHTML = '';
|
|
importedPresets.forEach(preset => addNewPreset(preset.name, preset.url));
|
|
alert("Presets erfolgreich importiert.");
|
|
} else {
|
|
throw new Error("Ungültiges Format.");
|
|
}
|
|
} catch (error) {
|
|
alert("Fehler beim Importieren: " + error.message);
|
|
}
|
|
};
|
|
reader.readAsText(file);
|
|
}
|
|
});
|
|
input.click();
|
|
}
|
|
|
|
function loadPresetsFromFile(event) {
|
|
event.preventDefault();
|
|
|
|
fetch('/webradio_presets.json')
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Datei konnte nicht geladen werden');
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
localStorage.setItem('presets', JSON.stringify(data));
|
|
presetContainer.innerHTML = '';
|
|
data.forEach(preset => addNewPreset(preset.name, preset.url));
|
|
alert('Presets erfolgreich geladen.');
|
|
})
|
|
.catch(error => alert('Fehler: ' + error.message));
|
|
}
|
|
|
|
// === Funktion: Sortierbare Presets ===
|
|
function setupSortable() {
|
|
new Sortable(presetContainer, {
|
|
animation: 250,
|
|
ghostClass: 'ghost',
|
|
handle: '.move-button',
|
|
onEnd: savePresetOrder
|
|
});
|
|
}
|
|
});
|