285 lines
11 KiB
JavaScript
285 lines
11 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');
|
|
const editPresetsButton = document.getElementById('edit-presets-button');
|
|
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);
|
|
|
|
// Event-Listener für den "Presets bearbeiten"-Button
|
|
editPresetsButton.addEventListener('click', () => {
|
|
toggleEditMode();
|
|
const isPressed = editPresetsButton.getAttribute('aria-pressed') === 'true';
|
|
editPresetsButton.setAttribute('aria-pressed', !isPressed);
|
|
});
|
|
}
|
|
|
|
// === Funktion: URL-Validierung ===
|
|
function isValidHttpUrl(url) {
|
|
try {
|
|
const parsedUrl = new URL(url);
|
|
return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Funktion zum Ein- und Ausblenden der Bearbeitungsbuttons
|
|
function toggleEditMode() {
|
|
const presetItems = document.querySelectorAll('.preset-item');
|
|
presetItems.forEach(item => {
|
|
const buttons = item.querySelectorAll('.edit-button, .delete-button, .move-button');
|
|
buttons.forEach(button => button.classList.toggle('hidden'));
|
|
});
|
|
}
|
|
|
|
// === 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 hidden" aria-label="Verschieben" title="Verschieben"><i class="fas fa-arrows-alt" style="color:grey"></i></button>
|
|
<button class="edit-button hidden" aria-label="Bearbeiten" title="Bearbeiten"><i class="fas fa-edit" style="color:grey"></i></button>
|
|
<button class="delete-button hidden" aria-label="Löschen" title="Löschen"><i class="fas fa-trash-alt" style="color:grey"></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
|
|
});
|
|
}
|
|
});
|