91 lines
3.8 KiB
JavaScript
91 lines
3.8 KiB
JavaScript
import { queueEntfernen, queueVerschieben } from './player.js';
|
|
|
|
// ─── WARTESCHLANGE BEARBEITEN (Web) ─────────────────────────────────────────
|
|
// Ziehen und Entfernen fuer beide Queue-Listen: die Seitenleiste und die im Now-Playing.
|
|
//
|
|
// Bewusst ueber Zeiger-Ereignisse statt HTML5-Drag-and-Drop: dessen `dragstart` gibt es auf
|
|
// Touch-Geraeten gar nicht, die Warteschlange waere am Handy also unbearbeitbar geblieben.
|
|
// `setPointerCapture` liefert dafuer Maus und Finger ueber denselben Weg.
|
|
|
|
const ZIEH_SCHWELLE = 4; // px, bevor aus einem Tippen ein Ziehen wird
|
|
|
|
export function macheQueueBearbeitbar(listeId) {
|
|
const liste = document.getElementById(listeId);
|
|
if (!liste || liste.dataset.bearbeitbar) return;
|
|
liste.dataset.bearbeitbar = '1';
|
|
|
|
liste.addEventListener('click', (e) => {
|
|
const weg = e.target.closest('.q-del');
|
|
if (!weg) return;
|
|
e.stopPropagation();
|
|
const zeile = weg.closest('[data-qidx]');
|
|
if (zeile) queueEntfernen(Number(zeile.dataset.qidx));
|
|
});
|
|
|
|
liste.addEventListener('pointerdown', (e) => {
|
|
const griff = e.target.closest('.q-grip');
|
|
if (!griff || e.button > 0) return;
|
|
const zeile = griff.closest('[data-qidx]');
|
|
if (!zeile) return;
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
ziehen(liste, zeile, e);
|
|
});
|
|
}
|
|
|
|
function ziehen(liste, zeile, start) {
|
|
const zeilen = [...liste.querySelectorAll('[data-qidx]')];
|
|
const vonIdx = Number(zeile.dataset.qidx);
|
|
const hoehe = zeile.offsetHeight || 1;
|
|
const startY = start.clientY;
|
|
let zielIdx = vonIdx;
|
|
let aktiv = false;
|
|
|
|
const bewegen = (e) => {
|
|
const dy = e.clientY - startY;
|
|
if (!aktiv) {
|
|
if (Math.abs(dy) < ZIEH_SCHWELLE) return;
|
|
aktiv = true;
|
|
zeile.classList.add('q-dragging');
|
|
liste.classList.add('q-dragging-aktiv');
|
|
}
|
|
zeile.style.transform = `translateY(${dy}px)`;
|
|
zielIdx = Math.max(0, Math.min(zeilen.length - 1, vonIdx + Math.round(dy / hoehe)));
|
|
// Die Zeilen zwischen Start und Ziel weichen um eine Zeilenhoehe aus, damit die Luecke
|
|
// dorthin wandert, wo losgelassen wird.
|
|
zeilen.forEach((z, i) => {
|
|
if (z === zeile) return;
|
|
let v = 0;
|
|
if (vonIdx < zielIdx && i > vonIdx && i <= zielIdx) v = -hoehe;
|
|
else if (vonIdx > zielIdx && i >= zielIdx && i < vonIdx) v = hoehe;
|
|
z.style.transform = v ? `translateY(${v}px)` : '';
|
|
});
|
|
};
|
|
|
|
const beenden = () => {
|
|
liste.releasePointerCapture?.(start.pointerId);
|
|
window.removeEventListener('pointermove', bewegen);
|
|
window.removeEventListener('pointerup', beenden);
|
|
window.removeEventListener('pointercancel', beenden);
|
|
zeilen.forEach(z => { z.style.transform = ''; z.classList.remove('q-dragging'); });
|
|
liste.classList.remove('q-dragging-aktiv');
|
|
if (aktiv && zielIdx !== vonIdx) queueVerschieben(vonIdx, zielIdx);
|
|
};
|
|
|
|
try { liste.setPointerCapture(start.pointerId); } catch {}
|
|
window.addEventListener('pointermove', bewegen);
|
|
window.addEventListener('pointerup', beenden);
|
|
window.addEventListener('pointercancel', beenden);
|
|
}
|
|
|
|
/** Griff und Entfernen-Knopf als HTML — in beiden Listen identisch. */
|
|
export const QUEUE_WERKZEUGE =
|
|
'<button class="q-del" title="Aus der Warteschlange entfernen" aria-label="Entfernen">' +
|
|
'<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' +
|
|
'<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>' +
|
|
'</button>' +
|
|
'<span class="q-grip" title="Zum Verschieben ziehen" aria-label="Verschieben">' +
|
|
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' +
|
|
'<line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/></svg>' +
|
|
'</span>';
|