diff --git a/script.js b/script.js index b5f6e58..ea639a0 100644 --- a/script.js +++ b/script.js @@ -1,107 +1,51 @@ 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 presetModal = document.getElementById('preset-modal'); + const tableBody = document.querySelector('#sortable-tbody'); const editPresetsButton = document.getElementById('edit-presets-button'); - let currentPlayingItem = null; // Speichert das aktuell spielende Element + let currentSound = null; + let presets = []; - // === Abschnitt: Initialisierung === initializeFooter(); + loadPresets(); 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; - } + document.getElementById('current-year').textContent = currentYear; + document.getElementById('server-name').textContent = window.location.hostname; } - // === Funktion: Titel dynamisch ändern === function updateTitle(stationName) { - if (stationName) { - document.title = `${stationName} - Radioplayer mit Presets`; - } else { - document.title = "Radioplayer mit Presets"; - } + document.title = stationName ? `${stationName} - Radioplayer mit Presets` : "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); - }); + editPresetsButton.addEventListener('click', openModal); } - // === Funktion: URL-Validierung === - function isValidHttpUrl(url) { - try { - const parsedUrl = new URL(url); - return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:"; - } catch (e) { - return false; + async function loadPresets() { + presets = JSON.parse(localStorage.getItem('presets')) || []; + if (presets.length === 0) { + try { + const response = await fetch('webradio_presets.json'); + if (!response.ok) throw new Error('Datei konnte nicht geladen werden'); + presets = await response.json(); + localStorage.setItem('presets', JSON.stringify(presets)); + } catch (error) { + alert('Fehler beim Laden der Presets: ' + error.message); + } } + displayPresets(presets); + renderPresets(); + initSortable(); } - // 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')) || []; + function displayPresets(presets) { + presetContainer.innerHTML = ''; presets.forEach(preset => addNewPreset(preset.name, preset.url)); } @@ -109,177 +53,139 @@ document.addEventListener('DOMContentLoaded', function () { const presetItem = document.createElement('div'); presetItem.classList.add('preset-item'); presetItem.dataset.streamUrl = url; - - presetItem.innerHTML = ` -

${name}

-
- - - -
- `; - - 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.innerHTML = `

${name}

`; 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 renderPresets() { + tableBody.innerHTML = ''; + presets.forEach((preset, index) => { + const row = document.createElement('tr'); + row.setAttribute('data-index', index); + row.innerHTML = ` + ☰ + + + + `; + tableBody.appendChild(row); + }); } - 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(); + stopPlayback(); + currentSound = new Howl({ + src: [url], + html5: true, + volume: 0.5, + onplay: () => { + stopButton.classList.remove('hidden'); + updateTitle(item.querySelector('h3').textContent); + currentStationName.textContent = 'Es läuft: ' + item.querySelector('h3').textContent; + }, + onstop: () => { + stopButton.classList.add('hidden'); + currentStationName.textContent = 'Wähle einen Sender aus'; + updateTitle(''); } - 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); + }); + currentSound.play(); } 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'; - } + if (currentSound) { + currentSound.stop(); + currentSound = null; } - - 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); + function openModal() { + presetModal.classList.remove('hidden'); + presetModal.style.display = 'block'; + renderPresets(); + } - const blob = new Blob([json], { type: 'application/json' }); + window.closeModal = function() { + presetModal.classList.add('hidden'); + presetModal.style.display = 'none'; + } + + window.addPreset = function() { + presets.push({ name: 'Neuer Sender', url: '' }); + renderPresets(); + } + + window.changeName = function(index, newName) { + presets[index].name = newName; + } + + window.changeURL = function(index, newURL) { + presets[index].url = newURL; + } + + window.deletePreset = function(index) { + presets.splice(index, 1); + renderPresets(); + } + + window.saveAndClose = function() { + savePresets(); + closeModal(); + location.reload(); + } + + function savePresets() { + localStorage.setItem('presets', JSON.stringify(presets)); + } + + function initSortable() { + const sortable = new Sortable(tableBody, { + handle: '.drag-handle', + animation: 150, + onEnd: function (evt) { + const newOrder = Array.from(tableBody.children).map(row => parseInt(row.getAttribute('data-index'))); + presets = newOrder.map(index => presets[index]); + } + }); + } + + window.exportPreset = function() { + const presetsJSON = JSON.stringify(presets, null, 2); + const blob = new Blob([presetsJSON], { type: 'application/json' }); const url = URL.createObjectURL(blob); - const a = document.createElement('a'); a.href = url; - a.download = 'webradio_presets.json'; + a.download = 'radio_presets.json'; + document.body.appendChild(a); a.click(); - + document.body.removeChild(a); URL.revokeObjectURL(url); } - function importPresets() { + window.importPreset = function() { const input = document.createElement('input'); input.type = 'file'; - input.accept = '.json'; - input.addEventListener('change', (event) => { + input.accept = 'application/json'; + input.onchange = function(event) { const file = event.target.files[0]; if (file) { const reader = new FileReader(); - reader.onload = (e) => { + reader.onload = function(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."); - } + presets = importedPresets; + localStorage.setItem('presets', JSON.stringify(presets)); + renderPresets(); + displayPresets(presets); + location.reload(); } catch (error) { - alert("Fehler beim Importieren: " + error.message); + alert('Fehler beim Importieren der Presets: Ungültige Datei.'); } }; 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 - }); - } });