Signatur
Beschreibung
Das Ereignis compositionend gehört zu den Kompositionsereignissen (compositionstart, compositionupdate, compositionend). Es wird ausgelöst, sobald eine Eingabemethode (IME) die Zusammensetzung von Text beendet. Das passiert z. B. bei der Eingabe von Chinesisch, Japanisch oder Koreanisch, bei Akzentzeichen über Tottasten, bei der Sprachdiktierfunktion oder bei Autokorrektur auf Mobilgeräten. Beendet wird die Sitzung, wenn der Nutzer einen Kandidaten bestätigt, die Komposition abbricht (etwa mit Esc) oder der Fokus wechselt.
Der Handler erhält ein CompositionEvent. Die Eigenschaft data enthält den endgültig übernommenen Text. Bei einem Abbruch ist sie meist ein leerer String. Das Ereignis bubbelt, lässt sich aber nicht abbrechen: preventDefault() hat keine Wirkung.
Der wichtigste Anwendungsfall: Logik, die an input- oder keydown-Ereignissen hängt (Live-Suche, Validierung, Tastenkürzel, Zeichenzähler), soll während der Komposition pausieren und erst nach compositionend mit dem fertigen Text laufen. Sonst verarbeitet die Anwendung unfertige Zwischenstände wie „k“, „ka“, „かん“ statt des gewünschten „漢字“.
Registrieren lässt sich das Ereignis mit addEventListener("compositionend", …) oder über die Eigenschaft oncompositionend. Die Eigenschaft ist allerdings nicht in allen Browsern als IDL-Attribut vorhanden, deshalb ist addEventListener die sicherere Wahl.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "compositionend". |
|
| $handler Pflicht | (event: CompositionEvent) => void | Callback, der ein CompositionEvent erhält. Wichtige Eigenschaften: event.data (übernommener Text, bei Abbruch meist ""), event.locale (veraltet, meist leer), event.target. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie { once: true }, { capture: true } oder { signal } zum späteren Entfernen über einen AbortController. |
Beispiele
Übernommenen IME-Text protokollieren
const input = document.querySelector('#name');
input.addEventListener('compositionstart', () => {
console.log('Komposition gestartet');
});
input.addEventListener('compositionend', (event) => {
// event.data enthält den bestätigten Text
console.log(`Übernommen: "${event.data}"`);
});
Live-Suche erst nach abgeschlossener Komposition auslösen
const search = document.querySelector('#search');
let composing = false;
const runSearch = async (term) => {
if (!term) return;
const res = await fetch(`/api/search?q=${encodeURIComponent(term)}`);
const hits = await res.json();
console.log(`${hits.length} Treffer für "${term}"`);
};
search.addEventListener('compositionstart', () => { composing = true; });
search.addEventListener('compositionend', (event) => {
composing = false;
// In manchen Browsern kommt kein weiteres input-Event, daher hier explizit suchen
runSearch(event.target.value);
});
search.addEventListener('input', (event) => {
// Zwischenstände der IME ignorieren
if (composing || event.isComposing) return;
runSearch(event.target.value);
});
Enter-Taste nicht während der Komposition abschicken
const chat = document.querySelector('#chat-input');
chat.addEventListener('keydown', (event) => {
// Enter bestätigt bei IMEs oft nur den Kandidaten, das ist kein Absenden
if (event.key === 'Enter' && !event.isComposing && event.keyCode !== 229) {
event.preventDefault();
console.log('Nachricht gesendet:', chat.value);
chat.value = '';
}
});
chat.addEventListener('compositionend', (event) => {
console.log('Kandidat bestätigt:', event.data);
});
Handler per on-Property setzen und wieder entfernen
const field = document.querySelector('textarea');
const onEnd = (event) => {
console.log('Fertig:', event.data);
};
// Variante 1: addEventListener / removeEventListener
field.addEventListener('compositionend', onEnd);
field.removeEventListener('compositionend', onEnd);
// Variante 2: on-Property (wo unterstützt)
field.oncompositionend = onEnd;
field.oncompositionend = null; // entfernt den Handler
// Variante 3: mit AbortController
const controller = new AbortController();
field.addEventListener('compositionend', onEnd, { signal: controller.signal });
controller.abort();
// Wichtig · Fallstricke
- Nicht abbrechbar:
compositionendist nicht cancelable. Wer die Eingabe blockieren will, brauchtbeforeinput, das ist aber während einer Komposition ebenfalls eingeschränkt. - Reihenfolge ist browserabhängig: Chrome und Firefox lösen nach
compositionendkein weiteresinput-Ereignis mitisComposing === falseaus, Safari schickt dagegencompositionendvor dem letztenkeydown. Daher die Logik sowohl incompositionendals auch ininput(mitisComposing-Prüfung) unterbringen. - Enter bei IMEs: In Safari hat das
keydownfür die bestätigende Enter-Taste nachcompositionendisComposing === false. Die zusätzliche Prüfung aufkeyCode === 229ist ein verbreiteter Workaround. - Abbruch: Bei Abbruch (Esc, Fokuswechsel) ist
event.datameist leer. Das kann je nach IME aber auch anders sein. Zuverlässiger ist es, den aktuellen Wert vonevent.target.valuezu lesen. - Nicht nur Asien: Komposition entsteht auch durch Tottasten (z. B.
^+e= „ê“), Android-Tastaturen mit Wortvorschlägen und Diktierfunktionen. Auf Android laufen oft alle Eingaben über Kompositionsereignisse. - Ziel: Das Ereignis tritt nur an editierbaren Elementen auf (
<input>,<textarea>,contenteditable) und bubbelt bis zumdocument. - Kompatibilität:
addEventListenermitcompositionendfunktioniert in allen modernen Browsern. Das IDL-Attributoncompositionendfehlt in einigen Browsern, deshalbaddEventListenerbevorzugen.