Start · Sprachen · JavaScript · Referenz · HTMLElement: drop

HTMLElement: drop

Ereignis

Wird ausgelöst, wenn ein gezogenes Element, eine Textauswahl oder eine Datei auf einem gültigen Ablageziel losgelassen wird.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

element.addEventListener("drop", handler)

Beschreibung

Das drop-Event gehört zur HTML Drag and Drop API. Es wird auf dem Element ausgelöst, über dem der Nutzer die Maustaste loslässt. Voraussetzung: Das Element hat sich vorher als gültiges Ablageziel gemeldet. Das Event-Objekt ist ein DragEvent. Über dessen Eigenschaft dataTransfer erreichen Sie die übertragenen Daten, also Text, URLs, eigene MIME-Typen oder Dateien.

Wichtig: Standardmäßig ist ein Element kein Ablageziel. Damit drop überhaupt ausgelöst wird, müssen Sie im dragover-Handler (und am besten auch in dragenter) event.preventDefault() aufrufen. Fehlt dieser Aufruf, kommt das Event nie an.

Auch im drop-Handler selbst sollten Sie preventDefault() aufrufen. Sonst führt der Browser seine Standardaktion aus: Er öffnet zum Beispiel eine abgelegte Datei oder navigiert zu einem abgelegten Link.

Registrieren können Sie den Handler per addEventListener("drop", …) oder über die Eigenschaft ondrop. Das Event steigt im DOM auf (bubbles) und kann abgebrochen werden (cancelable). Typische Einsatzfälle sind Datei-Upload-Zonen, sortierbare Listen und Kanban-Boards.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Event-Name "drop".
$handler Pflicht (event: DragEvent) => void Callback-Funktion. Sie erhält ein DragEvent mit dataTransfer, clientX/clientY und target.
$options boolean | AddEventListenerOptions false Optionen wie capture, once, passive oder signal. Setzen Sie passive: true hier nicht, sonst ist preventDefault() wirkungslos.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler erhält ein DragEvent.

Beispiele

Datei-Upload-Zone mit addEventListener

const zone = document.querySelector('#dropzone');

// Ohne preventDefault in dragover wird drop nie ausgelöst
zone.addEventListener('dragover', (e) => {
  e.preventDefault();
  e.dataTransfer.dropEffect = 'copy';
  zone.classList.add('aktiv');
});

zone.addEventListener('dragleave', () => zone.classList.remove('aktiv'));

zone.addEventListener('drop', async (e) => {
  e.preventDefault(); // verhindert, dass der Browser die Datei öffnet
  zone.classList.remove('aktiv');

  const dateien = [...e.dataTransfer.files];
  for (const datei of dateien) {
    console.log(`${datei.name} (${datei.size} Bytes)`);
    const form = new FormData();
    form.append('datei', datei);
    await fetch('/upload', { method: 'POST', body: form });
  }
});
bericht.pdf (48213 Bytes)

Listenelemente zwischen Spalten verschieben

document.querySelectorAll('.karte').forEach((karte) => {
  karte.draggable = true;
  karte.addEventListener('dragstart', (e) => {
    e.dataTransfer.setData('text/plain', karte.id);
    e.dataTransfer.effectAllowed = 'move';
  });
});

document.querySelectorAll('.spalte').forEach((spalte) => {
  spalte.addEventListener('dragover', (e) => e.preventDefault());
  spalte.addEventListener('drop', (e) => {
    e.preventDefault();
    const id = e.dataTransfer.getData('text/plain');
    const karte = document.getElementById(id);
    if (karte) {
      spalte.appendChild(karte);
      console.log(`Karte ${id} nach ${spalte.dataset.name} verschoben`);
    }
  });
});
Karte aufgabe-3 nach Erledigt verschoben

ondrop-Eigenschaft und Entfernen des Listeners

const ziel = document.querySelector('#ziel');
ziel.ondragover = (e) => e.preventDefault();
ziel.ondrop = (e) => {
  e.preventDefault();
  console.log('Abgelegt:', e.dataTransfer.getData('text/plain'));
};

// Variante mit addEventListener, die sich wieder entfernen lässt
const beiDrop = (e) => {
  e.preventDefault();
  console.log('Einmaliger Drop');
  ziel.removeEventListener('drop', beiDrop);
};
ziel.addEventListener('drop', beiDrop);

// Handler über die Eigenschaft deaktivieren
// ziel.ondrop = null;
Abgelegt: Hallo Welt Einmaliger Drop

// Wichtig · Fallstricke

  • Häufigster Fehler: Wenn dragover nicht mit preventDefault() abgebrochen wird, wird drop nie ausgelöst.
  • Rufen Sie auch in drop preventDefault() auf. Sonst öffnet der Browser abgelegte Dateien oder Links, besonders in Firefox.
  • Mit dataTransfer.getData() können Sie Daten nur in drop (und in dragstart) lesen. In dragover ist nur dataTransfer.types sichtbar (geschützter Modus).
  • Sicherheit: Abgelegte Inhalte können aus fremden Quellen stammen. Fügen Sie Werte aus getData('text/html') nie ungeprüft per innerHTML ein, sonst droht XSS. Nutzen Sie textContent oder bereinigen Sie das HTML vorher. Prüfen Sie Dateitypen und -größen serverseitig.
  • dragleave wird auch beim Wechsel auf Kindelemente ausgelöst. Hervorhebungen können deshalb flackern. Abhilfe schafft ein Zähler oder pointer-events: none auf den Kindelementen während des Ziehens.
  • Auf Touch-Geräten wird die native Drag-and-Drop-API nur eingeschränkt unterstützt (iOS Safari erst ab Version 11, und nicht in allen Browsern). Planen Sie dort gegebenenfalls eine Umsetzung mit Pointer Events ein.
  • Für Ordner und Dateien liefert dataTransfer.items mit getAsFileSystemHandle() bzw. webkitGetAsEntry() mehr Möglichkeiten als files.