Signatur
Beschreibung
ToggleEvent erbt von Event. Der Browser erzeugt dieses Objekt, wenn ein Element mit dem Attribut popover ein- oder ausgeblendet wird. Neuere Browser nutzen es auch für <details> und <dialog>. Dabei gibt es zwei Ereignisse:
beforetogglewird synchron vor dem Zustandswechsel ausgelöst. Beim Öffnen (newState === "open") ist das Ereignis abbrechbar:preventDefault()verhindert, dass das Popover angezeigt wird.togglewird asynchron nach dem Zustandswechsel ausgelöst und lässt sich nicht abbrechen. Mehrere schnell aufeinanderfolgende Wechsel fasst der Browser zu einem Ereignis zusammen.oldStateist dann der erste undnewStateder letzte Zustand.
Die zwei zusätzlichen Eigenschaften oldState und newState haben jeweils den Wert "open" oder "closed". So kann man ohne eigene Zustandsverwaltung reagieren: Daten erst beim Öffnen laden, Animationen starten, Analyse-Ereignisse senden oder den Fokus zurücksetzen.
Die Handler registriert man mit element.addEventListener("toggle", handler) bzw. "beforetoggle" oder über die Eigenschaften element.ontoggle und element.onbeforetoggle. Mit dem Konstruktor new ToggleEvent(type, options) lassen sich auch eigene Ereignisse erzeugen, zum Beispiel für Tests.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses, üblicherweise "toggle" oder "beforetoggle". |
|
| $options | object | {} | Optionales Objekt mit allen Optionen von EventInit (bubbles, cancelable, composed) sowie zusätzlich:
|
Beispiele
Auf das Öffnen und Schließen eines Popovers reagieren
// HTML: <button popovertarget="menu">Menü</button>
// <div id="menu" popover>…</div>
const menu = document.getElementById('menu');
menu.addEventListener('toggle', (event) => {
console.log(`Wechsel: ${event.oldState} → ${event.newState}`);
if (event.newState === 'open') {
menu.querySelector('a')?.focus();
}
});
menu.showPopover();
Öffnen mit beforetoggle verhindern und Inhalte nachladen
const panel = document.getElementById('info-panel');
let isLoggedIn = false;
panel.onbeforetoggle = async (event) => {
if (event.newState !== 'open') return;
if (!isLoggedIn) {
event.preventDefault(); // Popover wird nicht angezeigt
console.log('Bitte zuerst anmelden.');
return;
}
// Inhalte erst beim Öffnen laden
const response = await fetch('/api/info');
panel.textContent = await response.text();
};
panel.showPopover();
Eigenes ToggleEvent erzeugen (z. B. für Tests)
const details = document.createElement('details');
details.addEventListener('toggle', (event) => {
console.log(event instanceof ToggleEvent, event.oldState, event.newState);
});
const synthetic = new ToggleEvent('toggle', {
oldState: 'closed',
newState: 'open'
});
details.dispatchEvent(synthetic);
console.log(details.open); // Zustand ändert sich dadurch nicht
Listener wieder entfernen
const tooltip = document.getElementById('tooltip');
const logToggle = (event) => {
console.log('Tooltip ist jetzt', event.newState);
};
tooltip.addEventListener('toggle', logToggle);
// Später, z. B. beim Abbau einer Komponente:
tooltip.removeEventListener('toggle', logToggle);
// oder bei Nutzung der Eigenschaft: tooltip.ontoggle = null;
// Wichtig · Fallstricke
- Nur beim Öffnen abbrechbar:
preventDefault()wirkt nur beibeforetogglemitnewState === "open". Das Schließen eines Popovers lässt sich damit nicht verhindern. toggleläuft asynchron und wird zusammengefasst: Wird ein Popover schnell geöffnet und wieder geschlossen, kommt eventuell nur eintogglemitoldState === newStatean. Für synchrone Logik istbeforetogglebesser geeignet.- Kein Bubbling: Beide Ereignisse steigen nicht im DOM-Baum auf. Eine Ereignisdelegation am Elternelement funktioniert nur mit
addEventListener(..., { capture: true }). - Selbst erzeugte Ereignisse ändern keinen Zustand:
dispatchEvent(new ToggleEvent(...))öffnet oder schließt kein Element. Das geht nur mitshowPopover(),hidePopover(),togglePopover()oder dem Attributopen. - Kompatibilität: Für Popover wird
ToggleEventseit 2024 in allen großen Browsern unterstützt (Baseline). Bei<details>lieferten ältere Browser fürtogglenur ein einfachesEventohneoldState/newState.beforetoggle/toggleauf<dialog>und die Eigenschaftsource(das auslösende Element) sind neu und noch nicht überall verfügbar. Deshalb vorher prüfen, z. B. mit'newState' in event.