Ereignisse in JavaScript und interaktive Seiten
AnfängerEinheit 6 von 9 in Kurs: JavaScript – DOM, Ereignisse und asynchroner Code
Was du lernst
- Lass eine Seite reagieren, wenn etwas geschieht: Registriere Listener an Elementen, lies die Angaben des Ereignisobjekts aus und lege fest, wie lange jeder Listener aktiv bleibt.
- Registriere einen Event-Listener an einem ElementNutze
addEventListener, um eine Funktion jedes Mal auszuführen, wenn an einem Element ein Klick, ein Tastendruck, eine Formularaktion oder ein Seitenereignis stattfindet. - Lies die Informationen im Ereignisobjekt ausNutze das Ereignisobjekt, das ein Listener erhält, um herauszufinden, was wo geschehen ist: den Typ, das Ziel, das aktuelle Ziel und ereignisspezifische Details.
- Entferne Event-Listener und steuere ihre AusführungEntferne Listener, die nicht mehr benötigt werden, nutze die Optionen
once,signalundpassiveund löse eigene benutzerdefinierte Ereignisse aus.
- Registriere einen Event-Listener an einem Element
- Erkläre, wie ein Ereignis auf der Seite zu seinem Ziel abwärts und wieder aufwärts gelangt, verhindere das eingebaute Browserverhalten, wenn du es ersetzt, und nutze Bubbling, um viele Elemente mit einem Listener zu verarbeiten.
- Erkläre Bubbling und CapturingBeschreibe die drei Phasen der Ereignisweitergabe und bestimme die Reihenfolge, in der Listener an verschachtelten Elementen ausgeführt werden.
- Verhindere Standardaktionen und stoppe die EreignisweitergabeVerhindere die eingebaute Reaktion des Browsers auf ein Ereignis, wenn dein Code sie ersetzt, und stoppe die weitere Ereignisweitergabe nur, wenn es wirklich nötig ist.
- Verarbeite Ereignisse vieler Elemente mit EreignisdelegationNutze einen Listener an einem gemeinsamen Vorfahrenelement und
event.target.closest(), um Ereignisse vieler Kindelemente zu verarbeiten, auch solcher, die später hinzugefügt werden.
- Erkläre Bubbling und Capturing
- Reagiere auf Tastendrücke, Fokuswechsel, Klicks, Berührungen und Stifteingaben und implementiere eine Ziehinteraktion, die mit jeder Art von Zeiger funktioniert.
- Reagiere auf Tastendrücke und FokuswechselNutze
keydown,keyupund die Fokusereignisse, wähle zwischenevent.keyundevent.codeund erstelle Tastenkombinationen, die den Nutzer nicht behindern. - Verarbeite Klicks, Berührungen und Stifteingaben mit ZeigerereignissenNutze
clickzur Aktivierung und Zeigerereignisse für Drücken, Bewegen und Loslassen mit Maus, Finger oder Stift; lies Koordinaten und Tasten aus und wähle die passenden Hover-Ereignisse. - Implementiere eine Ziehinteraktion mit ZeigerereignissenKombiniere
pointerdown,pointermoveundpointerupmit Zeigererfassung, um ein Element zu bewegen, ermögliche die Bedienung auf Touchscreens und biete eine Möglichkeit, dasselbe ohne Ziehen zu erreichen.
- Reagiere auf Tastendrücke und Fokuswechsel
- Lies Nutzereingaben während des Tippens aus, verarbeite das Absenden von Formularen in JavaScript und prüfe Eingaben mit den Validierungsfunktionen des Browsers und eigenen Regeln mit klaren Fehlermeldungen.
- Lies Formularfelder aus und reagiere während der EingabeLies Textfelder, Zahlen, Kontrollkästchen, Optionsfelder und Auswahllisten aus, nutze die Ereignisse
inputundchangezum richtigen Zeitpunkt und erfasse ein ganzes Formular mitFormData. - Verarbeite das Absenden von Formularen mit JavaScriptReagiere auf das
submit-Ereignis des Formulars, verhindere das Neuladen der Seite, lies die abgesendeten Daten und erkenne, wodurch das Absenden ausgelöst wird. - Nutze die integrierte Validierung des BrowsersBeschreibe Regeln mit HTML-Attributen, lies das Ergebnis im
validity-Objekt aus, prüfe Felder per Code und gestalte ungültige Felder zum richtigen Zeitpunkt. - Schreibe eine benutzerdefinierte Validierung mit klaren FehlermeldungenErgänze Regeln, die HTML-Attribute nicht ausdrücken können, schreibe hilfreiche Meldungen, zeige sie zum richtigen Zeitpunkt an und verknüpfe sie mit ihren Feldern.
- Lies Formularfelder aus und reagiere während der Eingabe
- Erstelle interaktive Elemente, die mit Maus, Tastatur und Screenreader funktionieren: Bevorzuge natives HTML, ergänze bei eigenen Elementen Rollen, Tastaturbedienung und Zustandsangaben und setze den Fokus dorthin, wo Nutzer ihn erwarten.
- Bevorzuge native Elemente und mache eigene Bedienelemente fokussierbarErkenne, was native interaktive Elemente bereits mitbringen und was ein eigenes Bedienelement aus einem
<div>oder<span>ergänzen muss: eine Rolle, Fokussierbarkeit, einen zugänglichen Namen und einen sichtbaren Fokusindikator. - Ergänze eigene Bedienelemente um Tastaturbedienung und ZustandsangabenSorge dafür, dass eigene Schaltflächen, Umschaltflächen, Aufklappbereiche, Kontrollkästchen und Gruppen von Elementen mit der Tastatur funktionieren, und halte ihren ARIA-Zustand mit der sichtbaren Darstellung im Einklang.
- Setze den Fokus bei Seitenänderungen dorthin, wo Nutzer ihn erwartenSetze den Fokus gezielt, wenn Inhalte geöffnet, geschlossen oder entfernt werden oder Fehler anzeigen, und verschiebe ihn nie unerwartet, während Nutzer tippen oder auswählen.
- Bevorzuge native Elemente und mache eigene Bedienelemente fokussierbar
Ereignisse in JavaScript einfach erklärt
1Reagiere mit Event-Listenern auf Ereignisse
Webseiten reagieren durch Funktionen, die für Ereignisse registriert werden. Bei der Einrichtung werden Element und Ereignistyp gewählt; jedes spätere Auftreten liefert ein Ereignisobjekt, das beschreibt, was geschehen ist. Liest ein Listener dieses Objekt aus, kann er auf das richtige Bedienelement reagieren, selbst wenn ein Klick auf einem Symbol darin landet. Mit Listener-Referenzen und Optionen bleibt die Reaktion genau so lange aktiv, wie eine Funktion sie benötigt. Benutzerdefinierte Ereignisse ermöglichen es einem Teil der Seite, einen anderen zu benachrichtigen.
1.1 Listener setzen Aktionen in Code um
Eine Seite kann auf eine Aktion einer Person warten. Ein Ereignis meldet, dass etwas geschehen ist, und ein Event-Listener ist die Funktion, die als Reaktion aufgerufen wird. Die Registrierung eines Listeners richtet diese Reaktion ein; sie führt die Aktion nicht sofort aus.
Füge die Funktion dem Element hinzu
Wähle ein bereits existierendes Element und den exakten Namen des Ereignisses und übergib eine Funktion:
const button = document.querySelector("#like");
let likes = 0;
button.addEventListener("click", function () {
likes = likes + 1;
button.textContent = "Likes: " + likes;
});
Die Auswahl, die Einrichtung der Variablen und die Registrierung laufen, wenn das Skript ausgeführt wird. Jeder spätere Klick führt den Funktionsrumpf aus. Nach drei Klicks zeigt die Schaltfläche „Likes: 3“. Liegt likes außerhalb der Funktion, bleibt die Summe zwischen den Klicks erhalten; mit let likes = 0 innerhalb der Funktion würde sie jedes Mal neu beginnen.
Übergib eine Funktionsreferenz wie showMenu ohne Klammern. In button.addEventListener("click", showMenu()) ruft JavaScript showMenu sofort auf und übergibt den Rückgabewert als Listener. Um später ein Argument zu übergeben, verpacke den Aufruf: button.addEventListener("click", () => showMenu("main"));.
Wähle ein Ereignis, das tatsächlich auftritt
Namen sind Zeichenketten ohne das Präfix „on“, bei denen Groß- und Kleinschreibung beachtet werden. Nutze "click", nicht "Click" oder "onclick". Ein erfundener Name wird ohne Fehler akzeptiert, aber der Browser löst ihn bei einem Klick nicht aus. Zu den häufigen Familien gehören Zeigerereignisse wie pointerdown und pointerup, Tastaturereignisse wie keydown, Formularereignisse wie input und submit sowie Fokusereignisse wie focusin. Bei DOMContentLoaded muss ebenfalls die genaue Groß- und Kleinschreibung beachtet werden.
Richte das richtige Element zum richtigen Zeitpunkt ein
Ein Skript im Head kann ausgeführt werden, bevor eine Schaltfläche existiert. Die Auswahl gibt dann null zurück, und der Aufruf von addEventListener darauf löst einen Fehler aus. Lade ein externes Skript mit defer, setze es hinter das Markup oder registriere die Einrichtung für das Ereignis DOMContentLoaded des Dokuments. Ein später erstelltes Element benötigt nach seiner Erstellung eine Einrichtung oder einen Listener an einem Vorfahrenelement.
querySelectorAll gibt eine NodeList zurück, nicht ein einzelnes Ereignisziel. Registriere Listener an ihren Elementen:
document.querySelectorAll(".tab").forEach((tab) => {
tab.addEventListener("click", selectTab);
});
Lass Listener nebeneinander bestehen
| Methode | Wirkung der Registrierung |
|---|---|
addEventListener("click", fn) | Fügt neben anderen einen Listener hinzu und akzeptiert Optionen. |
button.onclick = fn | Ersetzt den einzelnen Eigenschafts-Handler; weise null zu, um ihn zu entfernen. |
Ein HTML-Attribut onclick | Platziert JavaScript im Markup. |
Listener mit derselben Capture-Einstellung laufen in der Reihenfolge ihrer Registrierung. Am Ereignisziel laufen Capture-Listener vor Listenern ohne Capture. Wird dasselbe Funktionsobjekt mit demselben Typ und derselben Capture-Einstellung erneut hinzugefügt, entsteht keine zweite Kopie.
Wichtige Erkenntnisse
- Übergib die Funktion selbst; nutze einen Wrapper, wenn der spätere Aufruf Argumente benötigt.
- Ereignisnamen müssen exakt geschrieben werden, auch die Groß- und Kleinschreibung muss stimmen.
- Ein Element muss existieren, wenn sein Listener registriert wird.
- Durchlaufe eine NodeList, um Listener an ihren Elementen zu registrieren.
addEventListenererlaubt mehrere Listener; eine Event-Handler-Eigenschaft enthält einen.
1.2 Lies aus, wo ein Ereignis begann
Der Browser übergibt deinem Listener ein Ereignisobjekt. Seine Eigenschaften beschreiben das Ereignis, das diesen konkreten Aufruf ausgelöst hat. Nenne den Parameter event oder e; der Parametername ist deine Wahl.
button.addEventListener("click", (event) => {
console.log(event.type);
console.log(event.currentTarget);
});
Dies gibt während des Listener-Aufrufs "click" und die Schaltfläche aus. Die Ausgabe des ganzen Objekts kann dir helfen, seine anderen Eigenschaften zu entdecken.
Unterscheide den Ursprung vom Listener
Stell dir eine Schaltfläche vor, die ein Bild enthält:
<button id="save" data-id="7">
<img src="disk.svg" alt=""> Save
</button>
| Eigenschaft | Bedeutung | Bei einem Klick auf das Bild |
|---|---|---|
event.target | Wo das Ereignis begann | Das Bild |
event.currentTarget | Wo der laufende Listener registriert wurde | Bei einem Listener an der Schaltfläche: die Schaltfläche |
Ein Klick auf den Text „Save“ macht ebenfalls die Schaltfläche zum Ziel. Der Text ist Teil der Schaltfläche; er wird nicht zu einem eigenen Zielelement.
Dieser Unterschied ist beim Auslesen von Daten wichtig. Das Bild hat nicht das data-id der Schaltfläche, daher ist event.target.dataset.id bei einem Klick auf das Bild undefined. Ein direkt an der Schaltfläche registrierter Listener kann event.currentTarget.dataset.id lesen. Ein Listener an einem größeren Container kann die gewünschte Schaltfläche mit event.target.closest("button") finden und prüfen, ob ein Treffer vorliegt.
Lies die Details dieses Ereignisses
Jedes Ereignis hat einen type, ein target und ein currentTarget. Der boolesche Wert bubbles gibt an, ob es durch die Vorfahren aufwärts weitergegeben wird. cancelable gibt an, ob Code seine Standardaktion verhindern kann, und defaultPrevented hält fest, ob dies geschehen ist. timeStamp hält den Erstellungszeitpunkt des Ereignisses in Millisekunden relativ zum Zeitursprung der Seite fest.
Verschiedene Ereignisfamilien ergänzen nützliche Details. Ein modernes click liefert ein PointerEvent, das Mausereignis-Eigenschaften wie clientX, clientY und button erbt. Ein KeyboardEvent ergänzt key, code und Modifikatortasten-Flags. Ein input-Listener kann mit event.target.value den neuen Text des Feldes lesen.
Bei einem Galerie-Listener kann event.target.tagName "IMG" sein, wenn ein Foto angeklickt wird, oder "DIV", wenn der Zwischenraum angeklickt wird. Behandle den tatsächlich gemeldeten Fall. Geh nicht davon aus, dass jedes Ereignis innerhalb eines Containers von derselben Art von Kindelement stammt.
Nutze den Wert während der Listener läuft
In einem Listener als reguläre Funktion ist this gleich event.currentTarget. Eine Pfeilfunktion übernimmt this aus ihrem umgebenden Code; sie erhält das Element nicht als this. event.currentTarget funktioniert bei beiden Funktionsarten.
Nach der Ereignisauslösung wird currentTarget auf null zurückgesetzt. Eine Konsole kann diesen späteren Wert anzeigen, wenn du ein zuvor ausgegebenes Ereignis aufklappst. Gib event.currentTarget direkt im Listener aus, um das Element während des Aufrufs zu untersuchen.
Wichtige Erkenntnisse
targetbezeichnet den Ursprung des Ereignisses;currentTargetbezeichnet das Element des laufenden Listeners.- Lies Daten von dem Element, dem sie tatsächlich gehören.
- Ereignisfamilien ergänzen Eigenschaften wie Koordinaten, Tastenwerte und Modifikatortasten.
currentTargetist während des Listeners verfügbar und wird danach zunull.
1.3 Steuere die Lebensdauer eines Listeners
Ein Listener sollte so lange aktiv bleiben, wie seine Funktion ihn benötigt. Bewahre bei einer zeitlich begrenzten Tastaturinteraktion die Funktionsreferenz auf, damit der Listener beim Schließen der Interaktion entfernt werden kann.
Entferne dieselbe Funktion
function onKey(event) {
console.log(event.key);
}
document.addEventListener("keydown", onKey);
// When the feature closes:
document.removeEventListener("keydown", onKey);
Beim Entfernen müssen Ereignistyp, Funktionsobjekt und Capture-Einstellung übereinstimmen. Auch eine anonyme Funktion lässt sich entfernen, wenn ihre Referenz gespeichert wird, wie in const handler = () => save();. Ein neu geschriebenes () => save() im Aufruf zum Entfernen erzeugt eine andere Funktion, auch wenn der Code identisch aussieht.
Wähle die Registrierungsoptionen
| Option | Wirkung |
|---|---|
once: true | Entfernt diesen Listener nach seinem ersten Aufruf. |
signal: controller.signal | Entfernt den Listener, wenn dieser Controller abgebrochen wird. |
capture: true | Reagiert auf dem Weg der Capturing-Phase. |
passive: true | Sichert zu, dass der Listener die Standardaktion nicht verhindert. |
Ein einmalig angezeigtes Willkommensbanner kann { once: true } nutzen. Eine Funktion mit mehreren Listenern kann ihnen ein gemeinsames Signal geben:
const controller = new AbortController();
window.addEventListener("pointermove", moveCursor, {
signal: controller.signal
});
window.addEventListener("keydown", onKey, {
signal: controller.signal
});
// Close the feature:
controller.abort();
Der Abbruch entfernt beide Registrierungen. Ein abgebrochener Controller kann nicht zurückgesetzt werden; erstelle für eine neue Lebensdauer einen neuen Controller. Übergib beim Entfernen mit removeEventListener erneut capture: true, wenn es bei der Registrierung verwendet wurde. once, signal und passive gehören nicht zu den Kriterien für das Entfernen.
Der Aufruf von preventDefault() in einem passiven Listener wird ignoriert. Browser machen bestimmte Listener im Zusammenhang mit dem Scrollen an Zielen auf Dokumentebene häufig standardmäßig passiv, darunter Listener für wheel, touchstart und touchmove; nutze dort ausdrücklich { passive: false }, wenn das Verhindern der Standardaktion nötig ist.
Vermeide die Ansammlung von Callbacks
Wenn jeder Klick auf „Start“ einen neuen anonymen Listener am Spielfeld hinzufügt, führt nach zweimaligem Starten ein Klick auf das Spielfeld zwei Callbacks aus. Registriere den Listener am Spielfeld einmal, verwende dasselbe Funktionsobjekt erneut oder brich die vorherige Gruppe ab, bevor du sie ersetzt. Unterschiedliche once-Callbacks können sich dennoch ansammeln, bevor sie ausgelöst werden.
Das Entfernen eines Elements aus der Seite erhält seine Listener. Sie funktionieren, wenn es wieder eingefügt wird, und dispatchEvent() kann sie erreichen, während es losgelöst ist. Das Element kann von der Speicherbereinigung entfernt werden, wenn es und seine Listener nicht mehr erreichbar sind. Ein Listener an window oder document bleibt registriert, bis er ausdrücklich entfernt wird.
Sende ein benutzerdefiniertes Ereignis
const event = new CustomEvent("cart:add", {
detail: { id: 42 },
bubbles: true
});
item.dispatchEvent(event);
Listener lesen event.detail.id. Die Ereignisauslösung ruft die Listener sofort auf, bevor sie zurückkehrt. bubbles: true lässt auch Vorfahrenelemente das Ereignis empfangen. Ein mit dispatchEvent() gesendetes Ereignis hat für isTrusted den Wert false; vom Browser ausgelöste Ereignisse können als vertrauenswürdig gelten, selbst wenn eine API wie focus() sie verursacht hat.
Wichtige Erkenntnisse
- Beim Entfernen müssen Typ, Funktionsidentität und Capture-Einstellung übereinstimmen.
oncebeendet eine Registrierung nach einem Aufruf; der Abbruch eines Signals beendet die zugehörigen Registrierungen.- Ein passiver Listener kann eine Standardaktion nicht verhindern.
- Bei jeder Einrichtung neu hinzugefügte Callbacks können sich ansammeln.
- Beim Entfernen eines Elements aus der Seite bleiben seine Listener erhalten.
- Benutzerdefinierte Ereignisse tragen Daten in
detailund werden synchron ausgelöst.
2Verfolge die Weitergabe von Ereignissen durch die Seite
Verschachtelte Elemente liegen auf demselben Ereignispfad. Ein Klick kann einen Container auf dem Weg zum Ziel passieren und ihn beim Bubbling erneut durchlaufen. Dadurch reicht für eine veränderliche Liste ein Listener aus. Der Ereignispfad erklärt, warum eine Aktion an einem Kindelement auch eine Aktion am Elternelement auslöst. Unterscheide das Verhindern des Browserverhaltens von der Steuerung der Ereignisweitergabe und nutze dann den Ereignisursprung, um zu wählen, welche Aktionen ein gemeinsamer Listener verarbeiten soll.
2.1 Der Weg eines Ereignisses durch verschachtelte Elemente
Ein Klick innerhalb einer Schaltfläche kann auch von ihren Vorfahrenelementen empfangen werden. Ereignisweitergabe ist der Weg des Ereignisses durch den Dokumentbaum. Dieser Weg erklärt sowohl nützliche gemeinsame Listener als auch überraschende zusätzliche Aktionen.
Verfolge drei Phasen
- Capturing: Das Ereignis bewegt sich von
windowdurch die Vorfahren abwärts zum Ziel. - Ziel: Listener werden an dem Element ausgeführt, an dem das Ereignis begann.
- Bubbling: Ein Ereignis mit Bubbling bewegt sich durch die Vorfahren zurück aufwärts bis zu
window.
Die Eigenschaft eventPhase meldet 1 für Capturing, 2 am Ziel und 3 für Bubbling. Ein ohne Optionen registrierter Listener läuft am Ziel oder auf dem Weg der Bubbling-Phase. Ein Listener mit { capture: true } läuft auf dem Weg abwärts, auch am Ziel, wenn er dort registriert ist.
Verfolge einen konkreten Klick
<div id="outer">
<div id="inner">
<button>Go</button>
</div>
</div>
Angenommen, die Schaltfläche und jedes div-Element haben gewöhnliche Klick-Listener, die ihre Namen ausgeben. Ein Klick auf „Go“ gibt „button“, „inner“ und dann „outer“ aus. Ein Klick auf einen leeren Bereich von inner gibt „inner“ und dann „outer“ aus; die Schaltfläche liegt nicht auf dem Pfad dieses Ereignisses.
Füge nun outer einen Capture-Listener hinzu. Ein Klick auf die Schaltfläche gibt zuerst „outer (capture)“ und danach durch die gewöhnlichen Listener „button“, „inner“ und „outer“ aus. Der Capture-Listener erhält den Klick vor den Nachfahren. Nach outer kann das Ereignis durch body, html, document und window weiterlaufen, wenn dort Listener registriert sind.
Es ist ein Ereignis, kein neuer Klick, der an jedem Vorfahrenelement entsteht. target bleibt währenddessen die Schaltfläche. currentTarget ändert sich, während die einzelnen Listener laufen. Auch im äußeren Listener bezeichnet target weiterhin die ursprüngliche Schaltfläche.
Prüfe, welche Ereignisse die Bubbling-Phase durchlaufen
| Mit Bubbling | Ohne Bubbling |
|---|---|
click, input, change, submit | invalid |
keydown, pointerdown | focus, blur |
focusin, focusout | pointerenter, pointerleave |
pointerover, pointerout | mouseenter, mouseleave |
Die Eigenschaft bubbles des Ereignisses zeigt, ob es eine Bubbling-Phase hat. Ereignisse ohne Bubbling können dennoch von einem Capture-Listener an einem Vorfahrenelement beobachtet werden. Um Fokuswechsel über einen gewöhnlichen Container-Listener zu verarbeiten, wähle focusin oder focusout.
Erkläre einen Fehler bei verschachtelten Aktionen
Eine Produktkarte öffnet bei einem Klick eine Detailansicht. Ihre Schaltfläche „Entfernen“ löscht das Produkt. Ein Klick auf diese Schaltfläche löscht es zuerst, erreicht dann den Listener der Karte und öffnet die Detailansicht. Der Ereignispfad erklärt, warum beide Callbacks laufen.
Die Karte kann Klicks zum Entfernen mit if (event.target.closest(".remove")) return; ignorieren. Alternativ kann die Schaltfläche die Ereignisweitergabe stoppen. Das Filtern an der Karte erhält das Ereignis für andere Vorfahrenelemente, die es möglicherweise benötigen.
Wichtige Erkenntnisse
- Die Ereignisweitergabe durchläuft Capturing und die Zielphase und bei Ereignissen mit Bubbling anschließend die Bubbling-Phase.
- Gewöhnliche Listener an Vorfahrenelementen empfangen Klicks auf Nachfahren auf dem Weg aufwärts.
targetbleibt gleich, während sichcurrentTargetändert.- Nutze ein Fokusereignis mit Bubbling oder Capture, um Fokuswechsel von einem Vorfahrenelement aus zu beobachten.
2.2 Eine Aktion verhindern oder die Weitergabe stoppen
Ein Listener kann ändern, was nach einem Ereignis geschieht oder wohin das Ereignis weitergegeben wird. Das sind getrennte Entscheidungen. Das Ereignis eines Links kann die Bubbling-Phase weiter durchlaufen, auch nachdem die Navigation verhindert wurde.
Eine Browseraktion ersetzen
Eine Standardaktion ist ein Verhalten, das der Browser bereitstellt: einem Link folgen, ein Formular absenden, ein Kontrollkästchen umschalten, Text einfügen, mit der Leertaste scrollen oder den Fokus mit Tab verschieben. Nutze preventDefault(), wenn dein Code diese Aktion ersetzt:
help.addEventListener("click", (event) => {
event.preventDefault();
openHelpPanel();
});
Bei einem Link zu /help öffnet dies den Bereich, ohne dorthin zu navigieren. Der Link bietet sein Ziel weiterhin an, wenn JavaScript nicht ausgeführt wird.
Nur bei abbrechbaren Ereignissen lässt sich die Standardaktion verhindern. Prüfe event.cancelable; defaultPrevented hält fest, ob die Aktion erfolgreich verhindert wurde. input tritt auf, nachdem sich der Wert geändert hat, und ist nicht abbrechbar. Ein Aufruf von preventDefault() entfernt dort den eingefügten Text nicht. Ein abbrechbares beforeinput-Ereignis ist die passende Stelle, um eine Bearbeitung abzufangen; das Verhindern eines entsprechenden keydown kann die Standardwirkung dieser Taste verhindern.
Die Ereignisweitergabe getrennt steuern
| Methode | Verhindert die Browseraktion? | Stoppt spätere Listener? |
|---|---|---|
preventDefault() | Ja, wenn das Ereignis abbrechbar und der Listener nicht passiv ist | Nein |
stopPropagation() | Nein | Stoppt die Weitergabe an andere Elemente; Listener an diesem Element laufen weiter |
stopImmediatePropagation() | Nein | Stoppt zusätzlich die verbleibenden Listener an diesem Element |
Ein Link, dessen Listener nur die Ereignisweitergabe stoppt, folgt weiterhin seiner URL. Wird nur die Navigation verhindert, kann ein Klick-Listener am Dokument das Ereignis weiterhin empfangen. Die Rückgabe von false aus einem addEventListener-Callback bewirkt keines von beidem. Eine Event-Handler-Eigenschaft oder ein Inline-Handler kann durch die Rückgabe von false seine Standardaktion verhindern, stoppt damit aber ebenfalls nicht die Ereignisweitergabe.
Gemeinsames Verhalten funktionsfähig halten
Ein Vorfahrenelement kann ein Menü schließen oder Interaktionen zählen. Das Stoppen der Ereignisweitergabe verbirgt das Ereignis vor diesem Code. Oft kann das Vorfahrenelement stattdessen target oder defaultPrevented prüfen.
Zum Beispiel schließt sich ein Menü nur, wenn ein Klick außerhalb sowohl des Menüs als auch des auslösenden Bedienelements liegt:
document.addEventListener("click", (event) => {
if (!menu.contains(event.target) &&
!menuButton.contains(event.target)) {
menu.hidden = true;
}
});
contains() schließt das Element selbst und seine Nachfahren ein. Die Prüfung des auslösenden Bedienelements ist wichtig, weil auch der Klick zum Öffnen durch Bubbling zum Dokument gelangt. Ohne diese zweite Prüfung würde das gerade geöffnete Menü sofort wieder geschlossen.
Nur eine selbst behandelte Aktion verhindern
Prüfe in einem Tastatur-Listener die Taste, bevor du ihre Standardaktion verhinderst. Das Verhindern jeder Taste blockiert die normale Texteingabe und kann verhindern, dass Tab den Fokus verschiebt. In einem passiven Listener wird das Verhindern der Standardaktion vollständig ignoriert.
Wichtige Erkenntnisse
preventDefault()verhindert eine dafür geeignete Standardaktion, ohne die Ereignisweitergabe zu stoppen.stopPropagation()stoppt die Weitergabe, nicht die Standardaktion.stopImmediatePropagation()überspringt zusätzlich die verbleibenden Listener am aktuellen Element.- Bei
inputist es zu spät, um eine Bearbeitung zu verhindern. - Prüfungen auf einen Klick außerhalb müssen sowohl den aufklappenden Bereich als auch sein auslösendes Bedienelement berücksichtigen.
- Verhindere nur die konkreten Tastaturaktionen, die dein Code selbst behandelt.
2.3 Ein Listener für eine veränderliche Liste
Bei der Ereignisdelegation wird ein Listener an einem beständigen Vorfahrenelement registriert und anhand des Ereignisursprungs eine Aktion gewählt. Das ist nützlich, wenn eine Liste viele Einträge hat oder Code nach der Einrichtung neue Einträge erstellt.
Das gewünschte Bedienelement finden
Ein Klick, der die Bubbling-Phase durchläuft, erreicht die Liste unabhängig davon, welcher ihrer Nachfahren angeklickt wurde. Beginne bei event.target, finde das nächste passende Bedienelement und schließe nicht zugehörige Klicks aus:
const list = document.querySelector("#todos");
list.addEventListener("click", (event) => {
const button = event.target.closest(".remove");
if (!button || !list.contains(button)) return;
const item = button.closest("li");
console.log("Removing item " + item.dataset.id);
item.remove();
});
Die Liste enthält Einträge wie <li data-id="7">Buy milk <button class="remove">Remove</button></li>. Der Listener gehört zur Liste, sodass ein neuer Eintrag mit demselben Markup unmittelbar nach dem Einfügen funktioniert.
Verfolge einen Klick auf ein Symbol durch den Code. Das Ziel ist das Symbol, closest(".remove") findet seine Schaltfläche, und button.closest("li") findet den Eintrag. Dessen data-id bezeichnet den Eintrag in der Meldung. Schließlich ändert remove() die Seite.
Beide Prüfungen beibehalten
| Prüfung | Warum sie wichtig ist |
|---|---|
!button | Ein Klick auf einen Zwischenraum in der Liste oder auf gewöhnlichen Eintragstext findet möglicherweise keine Schaltfläche zum Entfernen. |
!list.contains(button) | closest() kann über die Liste hinausgehen und ein passendes äußeres Vorfahrenelement finden. |
Wer nur event.target.matches(".remove") prüft, übersieht Klicks auf Symbole, weil das Symbol selbst nicht zum Selektor passt. closest() prüft das Ziel und geht dessen Vorfahren aufwärts. In einem delegierten Listener ist currentTarget die Liste; es wird nicht zur gefundenen Schaltfläche.
Mehrere Aktionen zuordnen
Mit Datenattributen kann ein Listener an einer Werkzeugleiste zwischen bekannten Aktionen wählen:
const actions = { bold: makeBold, italic: makeItalic,
clear: clearText };
toolbar.addEventListener("click", (event) => {
const button = event.target.closest("button[data-action]");
if (!button || !toolbar.contains(button)) return;
const action = actions[button.dataset.action];
if (typeof action === "function") action();
});
Eine Schaltfläche mit data-action="clear" wählt clearText aus. Die Funktionsprüfung behandelt eine unbekannte Aktion, ohne zu versuchen, undefined aufzurufen.
Ein geeignetes Ereignis wählen
Delegation funktioniert auch mit anderen Ereignissen mit Bubbling, nicht nur mit Klicks. Ein einzelner input-Listener am Formular kann event.target an eine Funktion zur Feldprüfung übergeben. Nutze focusin oder focusout, um Fokuswechsel zu delegieren; gewöhnliche focus- und blur-Ereignisse durchlaufen die Bubbling-Phase nicht. Nutze für Hover-Übergänge over/out-Ereignisse mit Bubbling, wenn Delegation erforderlich ist.
Ein stopPropagation() an einem Nachfahrenelement kann verhindern, dass ein Ereignis den Container erreicht. Wenn ein delegierter Listener nicht aktiv zu sein scheint, prüfe den Ereignistyp, das Ziel, ob der Selektor passt und ob etwas unterhalb des Containers die Weitergabe gestoppt hat.
Wichtige Erkenntnisse
- Registriere den Listener an einem Vorfahrenelement, das Änderungen an seinen Kindelementen überdauert.
closest()findet ein Bedienelement auch dann, wenn ein darin verschachteltes Symbol angeklickt wird.- Schließe fehlende Treffer und Treffer außerhalb des Containers aus.
- Die Delegation erfasst automatisch passende Kindelemente, die später hinzugefügt werden.
- Mit Datenattributen kann ein gemeinsamer Listener bekannten Aktionen zugeordnet werden.
- Delegation benötigt ein Ereignis, das das Vorfahrenelement erreicht.
3Verarbeite Tastatur- und Zeigereingaben
Eine Interaktion kann über Tasten, eine Maus, einen Finger oder einen Stift erfolgen. Das gewählte Ereignis bestimmt, ob du eine Aktivierung, einen geänderten Textwert oder die Bewegung eines bestimmten Zeigers erhältst. Koordinatensysteme und gespeicherte Startpositionen machen Ziehinteraktionen berechenbar. Fokus und alternative Bedienelemente sorgen dafür, dass dieselbe Seite auch nutzbar bleibt, wenn jemand mit der Tastatur navigiert oder keine Ziehbewegung ausführen kann.
3.1 Tasten, Text und Fokus
Tastatureingaben gehen an das fokussierte Element, das als document.activeElement verfügbar ist, und durchlaufen anschließend die Bubbling-Phase. Ein Dokument-Listener kann daher Tastenereignisse aus Feldern und anderen Bedienelementen empfangen. Diese Reichweite macht Tastenkombinationen nützlich, bedeutet aber auch, dass sie beim Tippen stören können.
Die Eigenschaft nach ihrer Bedeutung wählen
| Eigenschaft | Meldet | Beispiel |
|---|---|---|
key | Den erzeugten Wert unter Berücksichtigung von Layout und Modifikatortasten | "a", "A", "Enter", " " |
code | Die physische Tastenposition | "KeyA", "Enter", "Space" |
Auf einer AZERTY-Tastatur erzeugt die Position, die auf einer US-Tastatur mit Q beschriftet ist, key "a" und code "KeyQ". Nutze key für die Bedeutung, etwa Escape zum Schließen oder einen Buchstaben als Kurzbefehl. Nutze code für feste Positionen, etwa Bewegungstasten in einem Spiel. Der key der Leertaste ist ein einzelnes Leerzeichen, nicht "Space".
keydown wird beim ersten Drücken ausgelöst und kann wiederholt werden, solange die Taste gedrückt bleibt. Bei wiederholten Aufrufen gilt event.repeat === true. keyup wird beim Loslassen ausgelöst. Nutze keydown statt des veralteten Ereignisses keypress.
Einen Kurzbefehl gezielt behandeln
document.addEventListener("keydown", (event) => {
if ((event.ctrlKey || event.metaKey) &&
event.key.toLowerCase() === "s") {
event.preventDefault();
saveDraft();
}
});
Dies behandelt Strg+S und Command+S. Die Umwandlung in Kleinbuchstaben erlaubt auch "S". Das Verhindern der Standardaktion ersetzt die Aktion „Seite speichern“ des Browsers nur bei der passenden Tastenkombination. Weitere Modifikatortasten-Flags sind shiftKey und altKey.
Überspringe bei einem seitenweiten Kurzbefehl mit einem einzelnen Buchstaben Eingabekontexte, bevor du die Aktion ausführst:
if (event.target.matches("input, textarea, select") ||
event.target.isContentEditable) return;
if (event.repeat) return;
Die erste Prüfung schützt die Texteingabe. Die zweite sorgt dafür, dass eine Aktion pro physischem Tastendruck einmal läuft. Verhindere Tab nicht auf der ganzen Seite; damit navigieren Tastaturnutzer weiter.
Text nach seiner Änderung auslesen
Bei einer gewöhnlichen druckbaren Taste ist die Reihenfolge keydown, beforeinput, input und dann keyup. Das Lesen von value bei keydown liefert den Wert, bevor dieses Zeichen eingefügt wurde. Nutze input für eine Textvorschau oder einen Zeichenzähler. Es erfasst auch Bearbeitungen wie Einfügen und Diktieren, die keinen entsprechenden Tastendruck benötigen.
Fokuswechsel beobachten
focus und blur melden das Erhalten und Verlieren des Fokus, ohne die Bubbling-Phase zu durchlaufen. focusin und focusout durchlaufen sie, sodass ein Formular seine Felder mit einem Listener beobachten kann. relatedTarget bezeichnet das andere am Wechsel beteiligte Element oder null, wenn es keines gibt.
password.addEventListener("focus", () => {
hint.hidden = false;
});
password.addEventListener("blur", () => {
hint.hidden = true;
});
Der Hinweis ist verfügbar, wenn das Feld den Fokus erhält, auch über Tab. Der Aufruf von element.focus() verschiebt den Fokus per Code; die nächste Tastatureingabe geht dann an dieses Element.
Wichtige Erkenntnisse
- Nutze
keyfür die erzeugte Bedeutung undcodefür die physische Position. - Schütze seitenweite Buchstabenkurzbefehle vor Auslösung bei Texteingaben und vor unerwünschten Wiederholungen.
- Nutze
input, um auf bearbeiteten Text zu reagieren, auch beim Einfügen. focusinundfocusoutdurchlaufen die Bubbling-Phase;focusundblurnicht.relatedTargetmeldet das andere Ziel oder den anderen Ursprung des Fokuswechsels.
3.2 Aktivierung und Zeigerbewegung
Eine Person kann eine Maus, einen Finger, einen Stift oder eine Tastatur nutzen. Wähle das Ereignis passend zur benötigten Interaktion. click steht für eine Aktivierung; Zeigerereignisse beschreiben Drücken, Bewegen und Loslassen.
Aktionen über die Tastatur zugänglich halten
Eine native Schaltfläche löst click aus, wenn sie mit Enter oder der Leertaste aktiviert wird. Ein fokussierter Link tut dies bei Enter. Wird eine Aktion nur an pointerdown oder mousedown gebunden, werden diese Tastaturaktivierungen nicht erfasst. Nutze click für Aktionen wie das Öffnen eines Bereichs; nutze pointerdown, wenn eine Aktion beim Drücken beginnen muss, etwa beim Ziehen.
Ein Zeigerklick folgt auf ein Drücken und Loslassen. Geschehen diese auf unterschiedlichen Elementen, kann der Klick deren nächstes gemeinsames Vorfahrenelement zum Ziel haben. dblclick folgt auf zwei schnelle Klicks; event.detail zählt schnelle aufeinanderfolgende Klicks. auxclick behandelt Klicks mit einer anderen als der primären Taste. contextmenu kann durch einen sekundären Klick, langes Berühren oder einen Menübefehl der Tastatur ausgelöst werden.
Eine Zeigerereignisfamilie nutzen
pointerdown, pointermove, pointerup und pointercancel decken Maus, Berührung und Stift ab. pointerType bezeichnet das Gerät als "mouse", "touch" oder "pen"; pointerId unterscheidet aktive Zeiger, auch zwei Finger.
Ältere Maus- und Berührungsereignisfamilien existieren weiterhin. Browser können nach Zeigerereignissen Mausereignisse zur Kompatibilität auslösen. Die Registrierung von pointerdown und mousedown für dieselbe Aktion kann sie daher zweimal ausführen.
Koordinaten passend zur Aufgabe wählen
| Koordinaten | Ursprung |
|---|---|
clientX, clientY | Linke obere Ecke des sichtbaren Viewports |
pageX, pageY | Linke obere Ecke des Dokuments, unter Berücksichtigung des Scrollens |
offsetX, offsetY | Innerer Rand des Innenabstands des Zielelements |
Ist das Dokument um 300 px nach unten gescrollt und liegt ein Klick 100 px unterhalb des oberen Viewportrands, ist clientY 100 und pageY 400. Verwende beim Berechnen einer Bewegung beide Positionen im selben Koordinatensystem. Wechselt das verschachtelte Ziel, kann sich auch der Ursprung der Offset-Koordinaten ändern.
button meldet, welche Taste bei einem Down- oder Up-Ereignis ihren Zustand geändert hat: 0 primär, 1 Mitte, 2 sekundär. buttons meldet die aktuell gedrückte Kombination: Die primäre Taste trägt 1 bei, die sekundäre 2 und die mittlere 4. Somit bedeutet buttons === 3, dass die primäre und die sekundäre Taste gedrückt sind; es bedeutet nicht, dass die mittlere Taste ihren Zustand geändert hat.
Hover-Verhalten für ein ganzes Bedienelement wählen
Over/out-Ereignisse durchlaufen die Bubbling-Phase und können ausgelöst werden, wenn der Zeiger die Grenze eines Kindelements überquert. Enter/leave-Ereignisse durchlaufen die Bubbling-Phase nicht und beschreiben das Betreten oder Verlassen des gesamten Elements einschließlich seiner Kindelemente. Ein Hinweisfeld kann mit pointerenter und pointerleave das Flackern an den Grenzen von Kindelementen vermeiden.
Nutzer von Touchscreens und Tastaturen führen keinen Hover aus. Biete wesentliche Informationen auch bei Klick oder Fokus an. Für einen visuellen Hover-Effekt ohne zusätzliches Verhalten ist CSS :hover einfacher als ein Listener.
Wichtige Erkenntnisse
- Nutze
clickzur Aktivierung, auch bei nativer Tastaturaktivierung. - Zeigerereignisse decken Maus, Berührung und Stift mit einer Ereignisfamilie ab.
- Wähle für Berechnungen Koordinaten aus demselben Koordinatensystem.
buttonbezeichnet eine Änderung;buttonsmeldet die gedrückte Kombination.- Enter/leave behandeln ein Element und seine Kindelemente als Ganzes.
- Wesentliche Informationen müssen auch ohne Hover zugänglich sein.
3.3 Eine Ziehinteraktion, die dem Zeiger folgt
Eine Ziehinteraktion muss Informationen über mehrere Ereignisse hinweg speichern. Speichere die Startkoordinaten des Zeigers und die Startposition des Elements. Jede Bewegung wendet dann die Differenz zu diesem Startpunkt an, sodass das Element nicht springt, um seine Ecke unter den Zeiger zu setzen.
Die Verschiebung berechnen
Eine Box beginnt bei left: 100px; top: 50px. Der Zeiger beginnt bei den Viewport-Koordinaten 220, 140 und bewegt sich zu 260, 125. Die horizontale Änderung beträgt 40 px; die vertikale Änderung beträgt −15 px. Addierst du diese Änderungen zur Startposition der Box, erhältst du left: 140px; top: 35px.
Nutze für beide Zeigerpositionen einheitlich Client-Koordinaten. Allgemein berechnest du die Startposition des Elements plus die Verschiebung des Zeigers. Addiere nicht jede vollständige Verschiebung zur bereits aktualisierten Position der Box, denn dadurch würdest du frühere Bewegungen erneut zählen.
Einen Zeiger speichern und erfassen
Für eine absolut positionierte Box ohne Außenabstand innerhalb eines relativ positionierten Containers:
let start = null;
box.addEventListener("pointerdown", (event) => {
if (start || event.button !== 0) return;
start = { id: event.pointerId, x: event.clientX,
y: event.clientY, left: box.offsetLeft,
top: box.offsetTop };
box.setPointerCapture(event.pointerId);
});
box.addEventListener("pointermove", (event) => {
if (!start || event.pointerId !== start.id) return;
box.style.left = start.left +
(event.clientX - start.x) + "px";
box.style.top = start.top +
(event.clientY - start.y) + "px";
});
function endDrag(event) {
if (start && event.pointerId === start.id) start = null;
}
box.addEventListener("pointerup", endDrag);
box.addEventListener("pointercancel", endDrag);
Die gespeicherte ID weist Bewegungen und das Loslassen eines zweiten Zeigers zurück. offsetLeft und offsetTop liefern Startpositionen als Zahlen; Stile benötigen den Zusatz "px".
Die Zeigererfassung sorgt dafür, dass nachfolgende Ereignisse dieses Zeigers weiterhin an die Box gerichtet werden, selbst wenn er sich außerhalb der Box bewegt. Der Browser beendet die Erfassung nach dem Loslassen oder Abbrechen des Zeigers. releasePointerCapture(id) kann sie früher beenden.
Die Übernahme durch den Browser behandeln
Eine Berührungsgeste kann zum Scrollen oder Zoomen der Seite werden und dadurch pointercancel auslösen. Beende die Ziehinteraktion dort ebenso wie bei pointerup; andernfalls kann ein veralteter Zustand die Box später weiterbewegen. Setze touch-action: none vor der Interaktion auf die Ziehfläche, um die Geste dafür zu reservieren. Beschränke die Regel auf diese Fläche, damit der Rest der Seite scrollen kann.
Nutze user-select: none auf der Ziehfläche, um das Markieren von Text zu vermeiden. Setze draggable="false" auf ihre Bilder, um das native Ziehen von Bildern zu verhindern.
Eine andere Möglichkeit zum Bewegen anbieten
Biete für ein fokussiertes Bedienelement das Bewegen per Tastatur sowie anklickbare oder antippbare Schaltflächen zum Bewegen an. Pfeiltasten allein bieten keine Einzelzeiger-Alternative zum Ziehen. Das WCAG-2.2-Erfolgskriterium 2.5.7 verlangt eine solche Alternative, außer wenn das Ziehen wesentlich oder unverändertes Browserverhalten ist. Native Schaltflächen zum Bewegen können sowohl Tastatur- als auch Zeigernutzern dienen.
Die separate HTML Drag and Drop API nutzt dragstart, dragover und drop, um Daten wie Dateien zu übertragen. Ihre Ereignisfolge unterscheidet sich von dieser zeigerbasierten Positionsänderung.
Wichtige Erkenntnisse
- Berechne jede Position aus dem gespeicherten Startwert plus der Verschiebung des Zeigers.
- Erfasse und verfolge die ID des aktiven Zeigers.
- Beende die Ziehinteraktion sowohl bei
pointerupals auch beipointercancel. - Wende Regeln für Berührung und Textauswahl auf die Ziehfläche an.
- Biete Tastaturbedienung und eine anklickbare oder antippbare Alternative an.
4Verarbeite Formulare und validiere Eingaben vor dem Absenden
Formulare vereinen verschiedene Arten von Zuständen: Text, Zahlenwerte, angekreuzte Optionen und mehrfach vorkommende Namen. Lies diese Werte beim richtigen Ereignis und verarbeite anschließend das Absenden des Formulars als eine Aktion. HTML-Validierungsregeln decken häufige Anforderungen ab, während JavaScript Beziehungen zwischen Feldern und klarere Rückmeldungen ergänzt. Ein nützliches Formular erhält die Eingaben des Nutzers, erklärt jede Korrektur und setzt den Fokus dorthin, wo die nächste Bearbeitung erfolgen soll.
4.1 Lies Werte aus, wenn sie sich ändern
Formularfelder stellen unterschiedliche Arten von Zuständen bereit. Der value eines Textfeldes ist eine Zeichenkette; checked eines Kontrollkästchens ist ein boolescher Wert. Das Lesen der richtigen Eigenschaft ist der erste Schritt zu zuverlässigen Berechnungen und Vorschauen.
Zahlen gezielt umwandeln
Selbst <input type="number"> hat einen value als Zeichenkette. Bei dem Text "3" ergibt das Addieren von 1 "31". Number(input.value) + 1 ergibt 4. Ein Zahlenfeld stellt außerdem valueAsNumber bereit.
Eine leere Eingabe erfordert eine eigene Entscheidung. Number("") ergibt 0, wodurch eine fehlende Mengenangabe wie eine tatsächliche Null aussehen kann. Prüfe zuerst input.value === "" oder nutze valueAsNumber, das bei einem leeren Zahlenfeld NaN ergibt. Prüfe dieses Ergebnis mit Number.isNaN().
Den ausgewählten Zustand auslesen
| Bedienelement | Auszulesende Eigenschaft |
|---|---|
| Textfeld, Textbereich, Auswahlliste | value |
| Zahlenfeld für Berechnungen | valueAsNumber oder einen nicht leeren value umwandeln |
| Kontrollkästchen | checked für den Ein-/Aus-Zustand |
Optionsfeldgruppe namens size | form.elements.size.value für den ausgewählten Wert |
Der value eines Kontrollkästchens ist sein festgelegter Text für die Übermittlung oder "on", wenn keiner angegeben ist. Er zeigt nicht an, ob es angekreuzt ist. Eine Auswahlliste meldet den Wert der gewählten Option. Um das ausgewählte Optionsfeld selbst zu finden, suche nach input[name="size"]:checked.
Das Ereignis passend zur Aktualisierung wählen
input meldet Änderungen durch den Nutzer unmittelbar, einschließlich Tippen und Einfügen. change meldet eine übernommene Auswahl: nachdem ein geändertes Textfeld den Fokus verliert oder sofort, wenn ein Kontrollkästchen, Optionsfeld oder eine Auswahlliste geändert wird.
message.addEventListener("input", () => {
counter.textContent = 280 - message.value.length +
" characters left";
});
Nach „Hello“ wurden fünf Zeichen verbraucht und der Zähler zeigt „275 characters left“. Ein keydown-Listener würde laufen, bevor das neue Zeichen in den Wert gelangt, und das Einfügen über ein Menü nicht erfassen. Eine Zuweisung an message.value per Code löst weder input noch change aus; rufe die Aktualisierungsfunktion zusätzlich direkt auf.
Die benannten Felder eines Formulars erfassen
form.elements.email.value greift über Name oder ID auf ein Bedienelement zu. Nutze form.elements["first-name"] für einen Namen mit Bindestrich. Beim Absenden werden Namen verwendet: Eine ID allein nimmt ein Feld nicht in die Daten auf.
const data = new FormData(form);
const email = data.get("email");
const topics = data.getAll("topics");
FormData erfasst die aktuellen geeigneten Name-Wert-Paare. Nicht angekreuzte Kontrollkästchen, deaktivierte Bedienelemente und Felder ohne Namen werden ausgelassen. get() gibt den ersten Wert für einen Namen zurück; getAll() erhält wiederholte Werte, etwa mehrere angekreuzte Themen. Dateifelder können Dateiobjekte liefern; gewöhnliche Textfelder liefern Zeichenketten.
Object.fromEntries(data) ist bei unterschiedlichen Namen praktisch, behält bei wiederholten Namen aber nur das letzte Paar. Wähle getAll(), wenn jede Auswahl wichtig ist. Da input die Bubbling-Phase durchläuft, kann ein Formular-Listener event.target lesen, um das jeweils geänderte Feld zu aktualisieren.
Wichtige Erkenntnisse
- Wandle die Zeichenkette eines Feldes vor Berechnungen um und behandle ein leeres Zahlenfeld gesondert.
- Lies den Zustand eines Kontrollkästchens aus
checked. - Nutze
inputfür unmittelbare Bearbeitungen undchangefür übernommene Auswahlen. FormDataenthält geeignete benannte Bedienelemente, nicht jedes Bedienelement.getAll()erhält Werte bei wiederholten Namen; die Umwandlung in ein Objekt tut das nicht.- Eine Wertzuweisung per Code löst keine Bearbeitungsereignisse aus.
4.2 Verarbeite das Absenden des Formulars
Das Absenden gehört zum Formular. Reagiere auf sein submit-Ereignis, um einen Klick auf eine Absende-Schaltfläche, Enter in einem einzeiligen Feld und ein per Skript aufgerufenes requestSubmit() auf einem Weg zu verarbeiten.
Navigation durch eine Seitenaktualisierung ersetzen
Normalerweise sendet ein Formular Daten an seine action-URL und lädt die Antwort. Ohne eine angegebene Aktion ist die aktuelle Seite das Ziel. Die Standardmethode GET fügt die Daten in die URL ein. Um die aktuelle Seite mit JavaScript zu aktualisieren, verhindere diese Standardaktion:
const form = document.querySelector("#new-todo");
form.addEventListener("submit", (event) => {
event.preventDefault();
const data = new FormData(form);
const title = data.get("title").trim();
if (title === "") return;
addTodo(title);
form.reset();
});
Dieses Formular hat ein aktiviertes Textfeld namens title. Der Listener entfernt umgebende Leerzeichen, ignoriert ein leeres Ergebnis, fügt einen Eintrag hinzu und setzt die Felder auf ihre Anfangswerte zurück. reset() bedeutet nicht immer, dass ein Feld leer wird; ein Bedienelement mit einem Anfangswert kehrt zu diesem Wert zurück.
Wenn der Eintrag kurz erscheint und beim Neuladen der Seite verschwindet, prüfe, ob preventDefault() fehlt. Ein Klick-Listener allein an der Schaltfläche ist nicht die richtige Stelle für die Formularverarbeitung, insbesondere wenn das Formular auf einem anderen Weg abgesendet wird.
Erkennen, was das Absenden auslöst
Implizites Absenden durch Enter kann auf die aktivierte standardmäßige Absende-Schaltfläche klicken. Enter in einem Textbereich fügt einen Zeilenumbruch ein. Eine Schaltfläche innerhalb eines Formulars ist standardmäßig eine Absende-Schaltfläche, wenn ihr Typ weggelassen wird. Eine Schaltfläche „Passwort anzeigen“ sollte daher ausdrücklich type="button" verwenden.
Bei mehreren Absende-Schaltflächen bezeichnet event.submitter die verwendete Schaltfläche. Bei Wegen ohne bestimmte Schaltfläche kann der Wert null sein, daher sollte der Code ihn vor dem Lesen prüfen:
const button = event.submitter;
const intent = button ? button.value : "save";
const data = button ? new FormData(form, button) :
new FormData(form);
Eine benannte Absende-Schaltfläche wie name="intent" value="publish" steuert dieses Paar bei, wenn sie an FormData übergeben wird. Ein Aufruf von FormData(form) allein enthält das Name-Wert-Paar einer Absende-Schaltfläche nicht.
Den Validierungsweg beibehalten
| Absendeweg | Automatische Validierung | submit-Listener |
|---|---|---|
Aktivierung einer Absende-Schaltfläche oder requestSubmit() | Läuft, sofern sie nicht durch Validierungsattribute übersprungen wird | Läuft, wenn die Validierung es erlaubt |
form.submit() | Wird übersprungen | Wird übersprungen |
Die integrierte Validierung läuft vor dem submit-Ereignis. Ist ein Pflichtfeld leer und fällt deshalb durch die Prüfung, meldet der Browser das Problem und löst submit nicht aus. Eine benutzerdefinierte Prüfung nur innerhalb dieses Listeners läuft bei diesem fehlgeschlagenen Versuch nicht. novalidate am Formular schaltet den automatischen Validierungsschritt ab.
Nutze requestSubmit(), wenn Code den normalen Weg über Validierung und submit-Ereignis benötigt. Es fordert das Absenden an, ohne einen Schaltflächenklick auszulösen. Übergib eine bestimmte Absende-Schaltfläche an requestSubmit(button), wenn deren Absendeeinstellungen gelten sollen.
Wichtige Erkenntnisse
- Verarbeite
submitam Formular und decke damit das Absenden durch Nutzer und per Skript ab. - Verhindere das standardmäßige Absenden, wenn JavaScript die Navigation ersetzt.
- Gib Formularschaltflächen, die nicht absenden,
type="button". - Nutze
submitter, um Absende-Schaltflächen zu unterscheiden, und nimm bei Bedarf ihre Daten auf. - Die Validierung erfolgt vor
submit;requestSubmit()erhält diesen Weg. submit()umgeht die Validierung und das submit-Ereignis.reset()stellt die Anfangswerte wieder her.
4.3 Lass HTML Validierungsregeln beschreiben
HTML kann viele Eingaberegeln ohne eine benutzerdefinierte JavaScript-Prüfung beschreiben. Der Browser prüft diese Regeln beim Absenden und stellt die Ergebnisse für deinen Code bereit. Beginne mit den Regeln, die zu den benötigten Daten passen.
Eine Validierungsregel wählen
| Attribut | Regel |
|---|---|
required | Ein Wert oder eine erforderliche Auswahl muss angegeben werden. |
type="email" oder "url" | Der Wert muss die erwartete Syntax haben. |
min, max, step | Zahlen- oder Datumswerte müssen zu den Schranken und Schritten passen. |
minlength, maxlength | Vom Nutzer eingegebener Text muss eine Längenregel erfüllen. |
pattern | Ein nicht leerer Textwert muss vollständig zu einem Ausdruck passen. |
Bei pattern="[0-9]{5}" besteht „12345“; „1234“, „123456“ und „12345a“ fallen durch. Das Muster umfasst den ganzen Wert, nicht irgendeine passende Teilzeichenkette. Eine leere Eingabe überspringt die Musterprüfung, ergänze daher required, wenn das Auslassen nicht erlaubt ist.
Die E-Mail-Validierung prüft die Syntax, nicht ob ein Postfach existiert. Sowohl „ann@example.com“ als auch „ann@example“ bestehen die E-Mail-Regel des Browsers, während „ann.example.com“ sie nicht besteht. Ein zusätzliches Muster kann ein genaueres Format verlangen, wenn die Anwendung es benötigt.
Den Grund für das Fehlschlagen auslesen
Das validity-Objekt eines Feldes enthält boolesche Flags. valueMissing, typeMismatch, patternMismatch, tooShort und tooLong beschreiben fehlenden oder fehlerhaft geformten Text. rangeUnderflow, rangeOverflow und stepMismatch beschreiben numerische Einschränkungen. badInput deckt Eingaben ab, die der Browser nicht in einen brauchbaren Wert umwandeln kann, und customError hält eine benutzerdefinierte Validierungsmeldung fest. valid ist wahr, wenn keine Regel verletzt wird.
Bei einem Zahlenfeld mit min="0" max="10" step="2" liegt 12 über dem Maximum, 7 passt nicht zur erlaubten Schrittweite und 6 besteht die Prüfung. Mehr als ein Flag kann wahr sein; geh nicht davon aus, dass jedes ungültige Feld genau ein Problem hat.
Ohne Anzeige prüfen oder sichtbar melden
checkValidity() gibt einen booleschen Wert zurück und löst an ungültigen Bedienelementen invalid aus, ohne die Browsermeldung anzuzeigen. reportValidity() prüft ebenfalls und meldet das Problem zusätzlich dem Nutzer. Rufe eine der Methoden an einem Feld oder Formular auf. validationMessage liefert die Meldung in der Sprache des Browsers. Das Ereignis invalid durchläuft die Bubbling-Phase nicht.
Textlängenregeln gelten für vom Nutzer eingegebenen Text. Die Zuweisung input.value = "ab" im Code setzt tooShort nicht allein deshalb auf wahr, weil minlength 3 ist. maxlength verhindert normalerweise außerdem, dass der Nutzer über die festgelegte Länge hinaus weitere Zeichen eingibt.
Fehler zu einem hilfreichen Zeitpunkt anzeigen
:invalid gilt sofort, sodass ein unberührtes Pflichtfeld bereits dazu passt. :user-invalid wartet auf eine Nutzerinteraktion oder einen Absendeversuch und kann ein frühzeitig rot markiertes Feld vermeiden. Erkläre den Fehler neben der visuellen Gestaltung auch mit Text.
novalidate überspringt die automatische Validierung des Formulars beim Absenden; formnovalidate überspringt sie für eine Absende-Schaltfläche. Die Attribute entfernen weder Regeln noch deaktivieren sie checkValidity(). Browserprüfungen helfen Nutzern, Fehler zu korrigieren; der Server muss empfangene Daten erneut validieren, weil eine Anfrage die Seite umgehen kann.
Wichtige Erkenntnisse
- Nutze HTML-Validierungsregeln für Pflichtwerte, Syntax, Bereiche, Schritte, Länge und Muster.
- Ein Muster muss zum gesamten nicht leeren Wert passen; nutze
required, um leere Eingaben abzulehnen. - Lies
validity-Flags aus, um den Grund für eine fehlgeschlagene Feldprüfung zu erkennen. checkValidity()prüft;reportValidity()zeigt zusätzlich eine Rückmeldung an.- Attribute zum Überspringen der Validierung lassen die Validierungs-API nutzbar.
- Validiere empfangene Daten auch auf dem Server.
4.4 Benutzerdefinierte Regeln und nützliche Fehlermeldungen
Eine Regel, die zwei Felder betrifft, benötigt Code. Zum Beispiel muss eine Bestätigung mit einem Passwort übereinstimmen oder ein Enddatum nach einem Startdatum liegen. Trenne die Regel davon, wie und wann ihr Fehler angezeigt wird.
Einen benutzerdefinierten Fehler setzen und löschen
Eine nicht leere Zeichenkette, die an setCustomValidity() übergeben wird, markiert das Feld als ungültig und setzt customError. Die Übergabe von "" löscht diesen benutzerdefinierten Fehler; required, pattern oder andere Regeln können weiterhin verletzt sein.
function checkMatch() {
const matches = confirm.value === password.value;
confirm.setCustomValidity(matches ? "" :
"The passwords do not match.");
}
password.addEventListener("input", checkMatch);
confirm.addEventListener("input", checkMatch);
Prüfe beide Abhängigkeiten erneut. Eine Änderung des ersten Passworts kann dazu führen, dass eine zuvor korrekte Bestätigung nicht mehr übereinstimmt. Eine Meldung, die nie gelöscht wird, hält das Feld ungültig, nachdem die Person die Abweichung korrigiert hat. Führe auch die anfängliche Prüfung aus, wenn Felder bereits mit Werten beginnen können.
Datumsfelder liefern ISO-Zeichenketten wie "2026-03-10", unabhängig vom angezeigten lokalen Datumsformat. Nicht leere Werte aus diesen Bedienelementen lassen sich als Text vergleichen. Wenn die Regel verlangt, dass das Ende nach dem Anfang liegt, lehne end.value <= start.value ab, einschließlich der Gleichheit. Behandle fehlende Datumsangaben mit required oder einer gesonderten Prüfung auf leere Werte.
Die nächste hilfreiche Handlung erklären
Eine Meldung sollte das Problem und seine Korrektur benennen. Sage bei einer fehlenden E-Mail-Adresse „Gib deine E-Mail-Adresse ein.“ Sage bei fehlerhaftem E-Mail-Text „Gib eine E-Mail-Adresse in der Form name@example.com ein.“ Erhalte den eingegebenen Wert, damit die Person ihn bearbeiten kann.
Ein Pflichtfeld für den Namen akzeptiert Leerzeichen, weil sie eine nicht leere Zeichenkette bilden. Prüfe name.value.trim() === "", wenn umgebende Leerraumzeichen nicht zählen sollen. Lösche diesen benutzerdefinierten Fehler, sobald aussagekräftiger Text vorliegt.
Meldungen mit Bedienelementen verknüpfen
<label for="email">Email</label>
<input id="email" name="email" type="email"
required aria-describedby="email-error">
<p id="email-error"></p>
Platziere den Fehler in diesem Absatz und setze aria-invalid="true", solange das Feld einen Fehler hat. Lösche den Text und entferne aria-invalid oder setze es nach der Korrektur auf "false". aria-describedby verknüpft die Erklärung für assistive Technologien mit dem Feld. Nutze Text; ein roter Rahmen allein kann nicht allen vermitteln, was fehlgeschlagen ist.
Den Validierungsablauf wählen
Ergänze für vollständig benutzerdefinierte Meldungen novalidate und nutze einen submit-Listener am Formular. Aktualisiere benutzerdefinierte Regeln, prüfe die Gültigkeit der Felder, schreibe ihre Meldungen und verhindere das Absenden, wenn eine Prüfung fehlschlägt. Setze den Fokus auf das erste ungültige Feld oder eine verlinkte Fehlerübersicht. Wenn JavaScript auch das erfolgreiche Absenden lokal verarbeitet, verhindere auch diese Standardaktion des Absendens.
Vermeide es, unvollständigen E-Mail-Text bei jedem anfänglichen Tastendruck als Fehler zu melden. Eine nützliche Abfolge ist, Fehler nach dem Fokusverlust oder dem Absenden anzuzeigen und einen bereits gemeldeten Fehler dann bei input erneut zu prüfen.
Wichtige Erkenntnisse
- Nicht leere benutzerdefinierte Meldungen machen ein Feld ungültig;
""löscht nur diesen benutzerdefinierten Fehler. - Prüfe jedes Feld erneut, von dem eine feldübergreifende Regel abhängt.
- Lehne bei einer strikten Datumsreihenfolge sowohl Gleichheit als auch ein früheres Ende ab.
- Erkläre eine Korrektur in Textform und verknüpfe sie mit dem Feld.
- Entferne nach der Korrektur sichtbare Fehler und den ARIA-Fehlerzustand.
- Eine benutzerdefinierte Rückmeldung beim Absenden benötigt einen ausdrücklichen Ablauf für Gültigkeitsprüfung und Fokus.
5Erstelle eigene Bedienelemente, die alle nutzen können
Die Wahl eines nativen Elements liefert einen großen Teil des Verhaltens eines Bedienelements, bevor ein Listener geschrieben wird. Eigene Bedienelemente brauchen dieselbe Sorgfalt: einen klaren Namen, Tastaturzugang, sichtbaren Fokus und einen Zustand, der mit der Ausgabe assistiver Technologien übereinstimmt. Gruppen benötigen eine vorhersehbare Bewegung zwischen ihren Elementen. Wenn Inhalte geöffnet, geschlossen oder entfernt werden, kann der Nutzer dank eines bewusst gewählten Fokusziels die Interaktion fortsetzen, ohne die Seite erneut durchsuchen zu müssen.
5.1 Beginne mit einem nativen Bedienelement
Ein Bedienelement braucht mehr als eine Reaktion auf Klicks. Menschen müssen es finden, erreichen, seinen Zweck verstehen, es bedienen und sehen können, wo der Fokus liegt. Natives HTML stellt einen großen Teil dieses Verhaltens bereits bereit.
Das passende Element für die Aufgabe wählen
Nutze einen <button> für eine Aktion, ein <a href> für die Navigation und ein beschriftetes Formularfeld für Eingaben. <details> mit <summary> stellt einen Aufklappbereich bereit. Gestalte diese Elemente mit CSS passend zur Seite. Eine fokussierte Schaltfläche wird ohne zusätzlichen Tastatur-Listener durch Enter oder die Leertaste aktiviert.
Ein div-Element mit Klick-Listener hat weder die eingebaute Semantik noch das Tastaturverhalten einer Schaltfläche. role="button" ändert, was assistive Technologien ausgeben, macht es aber weder fokussierbar noch wandelt es Tastendrücke in Klicks um.
| Anforderung | Native Schaltfläche | Eigenes div-Element als Schaltfläche |
|---|---|---|
| Rolle | Eingebaut | role="button" ergänzen. |
| Tastaturfokus | Eingebaut | tabindex="0" ergänzen. |
| Enter und Leertaste | Eingebaut | Tastaturbedienung ergänzen. |
| Zugänglicher Name | Meist ihr Text | Aussagekräftigen Text oder einen ARIA-Namen bereitstellen. |
| Verhalten bei Deaktivierung | disabled | aria-disabled im Code prüfen. |
Die Fokusreihenfolge vorhersehbar halten
tabindex="0" nimmt ein Element in der normalen Dokumentreihenfolge in die Tab-Reihenfolge auf. tabindex="-1" erlaubt das Fokussieren per Code, ohne einen Tab-Stopp hinzuzufügen. Positive Werte setzen Elemente vor die übliche Reihenfolge und sind schwer zu pflegen; vermeide sie.
Keine der beiden Einstellungen ergänzt ein Aktivierungsverhalten. Eine fokussierbare eigene Schaltfläche benötigt weiterhin einen Listener für die Tastaturbedienung. Eine Rolle, ein Tab-Stopp und ein Callback lösen unterschiedliche Teile der Interaktion.
Jedem Bedienelement einen Namen geben
Ein Screenreader nutzt einen zugänglichen Namen, um Bedienelemente zu unterscheiden. Eine Textschaltfläche kann ihren sichtbaren Text nutzen. Ein Textfeld oder eine Auswahlliste benötigt eine zugeordnete Beschriftung, etwa <label for="email">Email</label> zusammen mit id="email". aria-labelledby kann auf sichtbaren Text an anderer Stelle verweisen; aria-label kann einen Namen bereitstellen, wenn es keinen geeigneten sichtbaren Text gibt.
Eine Schließen-Schaltfläche, die nur ein Symbol enthält, kann so aussehen: <button type="button" aria-label="Close">×</button>. Der Name beschreibt die Aktion, statt den Nutzer die Bedeutung des Symbols erschließen zu lassen.
Den Zustand anzeigen und durchsetzen
Halte einen Fokusindikator sichtbar. Wenn du die Standardumrandung ersetzt, biete mit :focus-visible einen klaren Ersatz an, zum Beispiel outline: 3px solid #1a73e8. Entfernst du sie ohne Ersatz, bleibt die Position des Tastaturnutzers verborgen.
Eine native deaktivierte Schaltfläche verlässt die Tab-Reihenfolge und kann nicht normal aktiviert werden. aria-disabled="true" teilt nur die Nichtverfügbarkeit mit. Die Klick- und Tastaturaktion eines eigenen Bedienelements muss diesen Zustand prüfen und zurückkehren, ohne etwas auszuführen. Eine zentrale Prüfung in der Aktivierungsfunktion hält beide Eingabewege konsistent.
Wichtige Erkenntnisse
- Nutze ein natives Element, das zur Aktion oder Eingabe passt.
- Eine ARIA-Rolle liefert Semantik, kein Verhalten.
- Nutze
tabindex="0"für normalen Zugang über Tab und-1für Fokus nur per Code. - Stelle einen zugänglichen Namen und einen sichtbaren Fokusindikator bereit.
- Setze
aria-disabledim Aktivierungscode durch.
5.2 Tastaturverhalten und Zustand zusammenhalten
Ein eigenes Bedienelement sollte unabhängig von der Art seiner Aktivierung dasselbe Ergebnis liefern. Halte die Aktion in einer Funktion, leite Tastatur- und Zeigerbedienung an sie weiter und aktualisiere den Zustand, den sowohl die Gestaltung als auch assistive Technologien auslesen.
Einer eigenen Schaltfläche Tastaturaktivierung geben
fakeButton.addEventListener("click", activate);
fakeButton.addEventListener("keydown", (event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
activate();
}
});
Dies gilt für eine eigene fokussierbare Schaltfläche. Das Verhindern der Standardaktion der Leertaste verhindert, dass die Seite während der Aktion scrollt. Eine native Schaltfläche erzeugt bei Tastaturaktivierung bereits Klicks. Ein zweiter Weg über die Tastatur kann die Aktion dort daher zweimal ausführen.
Den zum Bedienelement passenden Zustand wählen
| Bedienelement | Zustand |
|---|---|
| Umschaltfläche mit gleichbleibender Beschriftung | aria-pressed="true" oder "false" |
| Schaltfläche zum Öffnen eines Aufklappbereichs | aria-expanded="true" oder "false" |
| Eigenes Kontrollkästchen oder eigener Schalter | aria-checked="true" oder "false" |
Eine Umschaltfläche „Stummschalten“ behält diese Beschriftung und ändert aria-pressed. Ändert die Gestaltung die Aktionsbeschriftung zu „Stummschaltung aufheben“, lass aria-pressed weg. Ein Kontrollkästchen nutzt role="checkbox" und die Leertaste zum Umschalten; ein Schalter nutzt role="switch" für den Ein-/Aus-Zustand.
Attribute enthalten Zeichenketten. Vergleiche getAttribute("aria-expanded") mit "true", nicht mit dem booleschen Wert true:
detailsButton.addEventListener("click", () => {
const open = detailsButton.getAttribute(
"aria-expanded") === "true";
detailsButton.setAttribute("aria-expanded", String(!open));
panel.hidden = open;
});
War open wahr, ist der neue Zustand falsch und der Bereich wird ausgeblendet. aria-controls kann den Bereich über seine ID bezeichnen. Die nativen Elemente <details> und <summary> bieten das Verhalten eines Aufklappbereichs ohne dieses Skript.
Nutze das Zustandsattribut als Quelle für die Gestaltung, etwa [aria-pressed="true"], damit sich der sichtbare und der ausgegebene Zustand gemeinsam ändern. Schließe aufklappende Bereiche mit Escape und gib den Fokus an ihr auslösendes Bedienelement zurück.
Einer Gruppe einen Tab-Stopp geben
Registerkarten, Werkzeugleisten und Optionsfeldgruppen nutzen Tab, um in die Gruppe hinein oder aus ihr heraus zu gelangen, und Pfeiltasten, um sich darin zu bewegen. Roving tabindex hält das aktuelle Element bei 0 und die anderen Elemente bei -1. Setze bei einer Bewegung das alte Element auf -1, das neue auf 0 und fokussiere das neue Element.
Bei drei Elementen führt rechts von Index 2 mit (2 + 1) % 3 zurück zu 0. Links von 0 nutzt (0 - 1 + 3) % 3, um zu 2 zu gelangen. Addiere die Länge vor der Restoperation, weil -1 % 3 in JavaScript −1 ist.
Prüfe mit der Tastatur: Erreiche das Bedienelement, sieh den Fokus, aktiviere es mit den passenden Tasten, bewege dich innerhalb einer Gruppe und schließe einen aufklappenden Bereich mit Escape. Prüfe bei jeder Änderung den sichtbaren Zustand und den ARIA-Zustand.
Wichtige Erkenntnisse
- Leite Klick, Enter und Leertaste bei einer eigenen Schaltfläche an eine Aktion weiter.
- Native Schaltflächen bieten bereits eine Klickaktivierung über die Tastatur.
- Wähle
aria-pressed,aria-expandedoderaria-checkedpassend zum jeweiligen Zustand. - Vergleiche ARIA-Werte als Zeichenketten und aktualisiere die Gestaltung anhand desselben Zustands.
- Roving tabindex gibt einer Gruppe einen Tab-Stopp und ermöglicht die Bewegung mit Pfeiltasten.
- Escape schließt einen aufklappenden Bereich und stellt den Fokus auf sein auslösendes Bedienelement wieder her.
5.3 Verschiebe den Fokus bei Änderungen an der Seite
Der Fokus bestimmt, wohin die nächste Tastaturaktion geht. Verschwindet das fokussierte Bedienelement, kann der Nutzer seine Position verlieren. Behandle den Fokus als Teil der Seitenaktualisierung, besonders beim Öffnen eines Dialogs, beim Löschen eines Eintrags oder beim Melden eines Fehlers.
Einen Dialog öffnen und zum auslösenden Bedienelement zurückkehren
Merke dir vor dem Öffnen das fokussierte Element. Setze den Fokus in die neue Interaktion und stelle ihn beim Schließen wieder her:
let opener;
openButton.addEventListener("click", () => {
opener = document.activeElement;
dialog.showModal();
});
dialog.addEventListener("close", () => {
if (opener && opener.isConnected) opener.focus();
});
showModal() an einem nativen Dialog setzt den Fokus hinein und macht den Rest der Seite inaktiv, sodass er nicht angeklickt oder fokussiert werden kann, solange der modale Dialog geöffnet ist. Escape löst normalerweise ein cancel-Ereignis aus, gefolgt vom Schließen und einem close-Ereignis. Ein cancel-Listener kann das Schließen verhindern, wenn die Anwendung dieses Verhalten benötigt.
Wähle im Dialog eine sinnvolle anfängliche Fokusposition, etwa sein erstes relevantes Bedienelement. Bei einem eigenen aufklappenden Bereich muss Code den Fokus gezielt verschieben. Existiert das ursprüngliche auslösende Bedienelement nicht mehr, wähle stattdessen ein sinnvolles Bedienelement in der Nähe, statt ein losgelöstes Element zu fokussieren.
Ein sinnvolles Ziel fokussierbar machen
Eine Überschrift oder Fehlerübersicht ist normalerweise nicht fokussierbar. Gib ihr tabindex="-1", bevor du .focus() aufrufst. Sie kann dann gezielt den Fokus erhalten, ohne bei der normalen Tab-Navigation zu einem zusätzlichen Stopp zu werden. Nutze 0 nur, wenn sie in diese normale Reihenfolge gehört.
Die Position nach dem Löschen erhalten
Bevor du einen Listeneintrag entfernst, dessen Löschschaltfläche den Fokus hat, finde das nächste sinnvolle Ziel. Fokussiere die Schaltfläche des nächsten Eintrags; gibt es keinen nächsten Eintrag, nutze die Schaltfläche des vorherigen. Wird die Liste leer, fokussiere ihre Überschrift mit tabindex="-1".
Wenn du das Ziel vor dem Entfernen findest, geht die Beziehung zu benachbarten Einträgen nicht verloren. Setze den Fokus nicht nach jedem Löschen an den Anfang des Dokuments; die Person sollte in der Nähe der Änderung weiterarbeiten können.
Den Fokus innerhalb einer fortlaufenden Interaktion halten
Ein aufklappender Bereich kann sich schließen, wenn der Fokus seinen gesamten Bereich verlässt. Das Ereignis focusout, das die Bubbling-Phase durchläuft, liefert das Ziel:
menu.addEventListener("focusout", (event) => {
if (!menu.contains(event.relatedTarget)) {
menu.hidden = true;
}
});
Eine Bewegung zwischen zwei Menüelementen schließt das Menü nicht, weil das Ziel innerhalb bleibt. Ein Ziel mit dem Wert null liegt ebenfalls außerhalb; contains(null) ist falsch. Gib den Fokus nicht automatisch an das auslösende Bedienelement zurück, wenn der Nutzer bewusst zu einem anderen Bedienelement der Seite gewechselt ist.
Änderungen vorhersehbar machen
Setze nach einer fehlgeschlagenen benutzerdefinierten Formularvalidierung den Fokus auf das erste ungültige Feld oder eine Fehlerübersicht, die zu den Fehlern verlinkt. Die integrierte Validierung fokussiert bereits ein ungültiges Feld. Halte den Fehlertext verfügbar, damit die Person weiß, was sie korrigieren muss.
Springe nicht zu einem neuen Feld, während der Nutzer tippt, und navigiere nicht, sobald sich eine Auswahlliste ändert. Lass eine eindeutige Aktion die Änderung bestätigen. Fokusbewegungen sollten eine bewusste Handlung oder die Behebung eines Fehlers unterstützen und die normale Eingabe nicht unterbrechen.
Wichtige Erkenntnisse
- Merke dir das auslösende Bedienelement und stelle beim Schließen eines Dialogs den Fokus auf ein verfügbares Ziel wieder her.
- Nutze
tabindex="-1"für eine Überschrift oder Übersicht, die per Code fokussiert wird. - Fokussiere nach dem Löschen einen benachbarten Eintrag oder die Überschrift der leeren Liste.
- Nutze
relatedTarget, um Fokusbewegungen innerhalb eines aufklappenden Bereichs von dessen Verlassen zu unterscheiden. - Fokussiere nach einer fehlgeschlagenen Validierung ein Fehlerziel; vermeide unerwartete Fokussprünge.
Ereignisse in JavaScript: Beispiele
1Erstelle und untersuche Event-Listener
13 Schritte
- 1EinführungLass eine Schaltfläche reagieren
Ein Listener verbindet ein Ereignis mit einer Funktion. Erstelle einen kleinen Zähler, indem du die Schaltfläche auswählst, ihre Aktion registrierst und den Zählerstand zwischen Aufrufen erhältst. Untersuche dann einen verschachtelten
clickund steuere die Lebensdauer des Listeners.Achte auf den Unterschied zwischen Einrichtungscode, der jetzt läuft, und dem Callback, den der Browser aufruft, wenn das gewählte Ereignis eintritt.
- 2BeispielSpeichere den Zählerstand außerhalb des Callbacks
Wähle die vorhandene Schaltfläche aus und speichere ihren Zählerstand vor der Registrierung:
const button = document.querySelector("#like"); let likes = 0; button.addEventListener("click", () => { likes = likes + 1; button.textContent = "Likes: " + likes; });Jeder Aufruf erhöht den vorherigen Zählerstand. Nach drei Klicks lautet die Beschriftung „Likes: 3“. Ein innerhalb des Callbacks deklarierter Zähler würde bei jedem Aufruf neu beginnen.
- 3TippÜbergib die Aktion, ohne sie aufzurufen
addEventListener("click", showMenu)übergibt eine Funktion zur späteren Verwendung.showMenu()würde sie während der Einrichtung aufrufen. Wenn Argumente benötigt werden, nutze() => showMenu("main").Lade das Skript, nachdem die Schaltfläche existiert, etwa mit
defer, und beachte die exakte Schreibweise des Ereignisses. Ein Listener für"Click"empfängt keine gewöhnlichen"click"-Ereignisse. - 4HerausforderungKorrigiere eine Registrierung
Eine Schaltfläche soll bei jeder Aktivierung den Tipps-Bereich öffnen. Die Einrichtung nutzt derzeit
button.addEventListener("click", openTips()). Was sollte sich ändern und warum?---reveal---
Übergib
openTipsohne Klammern. Damit stellst du den Callback bereit, der bei einem späterenclicklaufen soll. Der Aufruf vonopenTips()während der Einrichtung öffnet den Bereich sofort und übergibt sein Ergebnis, statt die Aktion für das Ereignis bereitzuhalten. - 5ErklärungLies die beiden Elementeigenschaften
Bei einer Schaltfläche, die ein Bild enthält, macht ein Klick auf das Bild dieses zum
target. Im Listener der Schaltfläche istcurrentTargetdie Schaltfläche.targetgibt an, wo das Ereignis begann; anders alstargetbezeichnet das aktuelle Ziel das Element, an dem dieser Callback registriert wurde. Dieser Unterschied erklärt, warum das Lesen desdataseteiner Schaltfläche übertargetfehlschlagen kann, wenn derclickauf ihrem Bild landet. - 6BeispielLies die Daten der zugehörigen Schaltfläche
Angenommen,
buttonhatdata-id="7"und enthält ein Symbol:button.addEventListener("click", (event) => { console.log(event.currentTarget.dataset.id); });Das Ergebnis ist sowohl bei einem
clickauf das Symbol als auch bei einemclickauf den Hintergrund der Schaltfläche"7". Derselbe Ausdruck funktioniert in einem Listener als Pfeilfunktion oder reguläre Funktion. Dasthiseiner Pfeilfunktion bezeichnet nicht automatisch die Schaltfläche. - 7HerausforderungBestimme das Element des Listeners
Ein Abschnitt enthält eine Schaltfläche mit einem span-Element. Ein
click-Listener ist nur am Abschnitt registriert, und das span-Element wird angeklickt. Was bezeichnentargetundcurrentTargetwährend dieses Callbacks?---reveal---
targetbezeichnet das span-Element, an dem das Ereignis begann.currentTargetbezeichnet den Abschnitt, an dem der Listener registriert wurde. Der Ursprung des Ereignisses wird nicht durch das Vorfahrenelement ersetzt, das es empfängt. - 8ErklärungBewahre die Referenz zum Entfernen auf
Zum Entfernen werden derselbe Ereignistyp, dasselbe Callback-Objekt und dieselbe Capture-Einstellung benötigt:
const handler = () => closePanel(); button.addEventListener("click", handler); button.removeEventListener("click", handler);Eine anonyme Funktion kann entfernt werden, wenn sie auf diese Weise gespeichert wird. Ein neu geschriebenes
() => closePanel()im Aufruf zum Entfernen erzeugt ein anderes Objekt und passt nicht zur früheren Registrierung. - 9VerbindungBeende mehrere Registrierungen gemeinsam
Eine vorübergehend aktive Funktion kann ein Signal eines
AbortControlleran mehrere Registrierungen übergeben. Der Aufruf voncontroller.abort()entfernt diese Listener, einschließlich gespeicherter oder anonymer Callbacks.Nutze für eine weitere Lebensdauer einen neuen Controller. Für eine einzelne einmalige Reaktion entfernt
{ once: true }diese Registrierung nach ihrer Ausführung. Keine der beiden Optionen verhindert, dass sich unterschiedliche Callbacks ansammeln, bevor ihre Lebensdauer endet. - 10HerausforderungUntersuche eine wiederholte Einrichtung
Das Öffnen eines Bereichs registriert jedes Mal einen neuen anonymen Tastatur-Listener am Dokument. Das Schließen blendet den Bereich aus, lässt den Listener aber bestehen. Nach dreimaligem Öffnen löst eine Taste drei Aktionen aus. Wie lässt sich der Lebenszyklus korrigieren?
---reveal---
Entferne die Registrierungen, wenn der Bereich geschlossen wird, etwa indem du ihr gemeinsames Signal abbrichst, und erstelle beim erneuten Öffnen einen neuen Controller. Alternativ kannst du einen Callback speichern und dieselbe Referenz entfernen. Das Ausblenden des Bereichs entfernt keinen Dokument-Listener.
- 11KernaussageSende eine Benachrichtigung sofort
Um anderen Code zu benachrichtigen, erstelle ein
CustomEventmit seinen Daten indetail. Setzebubbles: true, wenn Vorfahrenelemente es empfangen sollen:item.dispatchEvent(new CustomEvent("cart:add", { detail: { id: 42 }, bubbles: true }));Die Listener laufen, bevor der Aufruf zurückkehrt. Das ausgelöste Ereignis hat für
isTrustedden Wert falsch. Es ist eine Benachrichtigung, die dein Code sendet, keine Aufforderung an den Browser, auf eine Nutzeraktion zu warten. - 12HerausforderungKombiniere Ursprung und Lebensdauer
Der
click-Handler einer Schaltfläche nutzt deren eigenesdata-keyund soll nur bei der ersten Aktivierung reagieren. Die Schaltfläche enthält ein SVG-Symbol. Mit welcher Eigenschaft und welcher Option erfüllst du beide Anforderungen?---reveal---
Lies
event.currentTarget.dataset.keyim direkten Listener der Schaltfläche und registriere ihn mit{ once: true }. Die Eigenschaft bezeichnet die zugehörige Schaltfläche auch bei einemclickauf das Symbol. Die Option entfernt diese Registrierung nach ihrem ersten Aufruf. - 13ZusammenfassungPrüfe einen Listener an drei Stellen
Wenn eine Interaktion fehlschlägt, untersuche die Einrichtung, die Daten des Callbacks und seine Lebensdauer. Bestätige, dass das Element existiert und der Ereignisname exakt ist; prüfe
targetundcurrentTargetwährend des Aufrufs; suche dann nach fehlendem Entfernen oder wiederholter Registrierung. Diese Prüfungen unterscheiden einen Listener, der nie ein Ereignis empfängt, von einem, der es korrekt empfängt, aber auf das falsche Element einwirkt.
2Verfolge Ereignisse und delegiere Aktionen
13 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungVerfolge einen Klick durch eine Karte
- 2BeispielLies den Weg aufwärts
- 3ErklärungErgänze den Weg abwärts
- 4HerausforderungVerfolge einen kleineren Baum
- 5ErklärungErsetze die Navigation
- 6KernaussageDas Stoppen der Weitergabe ist eine andere Entscheidung
- 7HerausforderungHalte einen Beobachter am Elternelement aktiv
- 8ErklärungVerschiebe den Listener zur Liste
- 9BeispielFinde und prüfe die Schaltfläche zum Entfernen
- 10HerausforderungVerarbeite ein verschachteltes Symbol
- 11TippNutze ein Ereignis, das den Container erreicht
- 12HerausforderungHalte Öffnen und Schließen getrennt
- 13ZusammenfassungWähle für jede Aktion die passende Stelle
3Verarbeite Tasten und implementiere eine Ziehinteraktion
16 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungWähle die richtige Eingabeebene
- 2ErklärungUnterscheide Bedeutung und Position
- 3TippSchütze die Texteingabe und behandle Wiederholungen
- 4HerausforderungWähle ein Ereignis für eine Vorschau
- 5VerbindungErfasse mit der Aktivierung auch die Tastatur
- 6BeispielRechne zwischen Koordinatensystemen um
- 7HerausforderungUntersuche einen Klick auf einer gescrollten Seite
- 8KernaussageMach Hover nicht zum einzigen Zugangsweg
- 9BeispielBerechne eine Ziehbewegung
- 10ErklärungSpeichere den Start und erfasse den Zeiger
- 11BeispielWende die Verschiebung bei jeder Bewegung an
- 12TippBeende die Interaktion auch bei Übernahme durch den Browser
- 13HerausforderungBestimme eine fortgesetzte Ziehbewegung
- 14VerbindungBiete Bewegung ohne Ziehen an
- 15HerausforderungUntersuche zwei Fehler beim Ziehen
- 16ZusammenfassungWähle das Ereignis passend zur Aufgabe
4Erstelle eine vollständige Formularinteraktion
16 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungVerfolge ein Formular von der Bearbeitung bis zum Absenden
- 2BeispielLies eine Zahl ohne Konkatenation
- 3ErklärungLies Auswahlen und wiederholte Namen
- 4HerausforderungErhalte jedes ausgewählte Thema
- 5ErklärungVerarbeite das Absenden am Formular
- 6BeispielLies, füge hinzu und setze zurück
- 7HerausforderungBehalte den normalen Absendeweg bei
- 8BeispielLies unabhängige Regelverletzungen aus
- 9KernaussageEin Muster verlangt keinen Wert
- 10HerausforderungPrüfe einen Bereich mit Schrittweite
- 11ErklärungErgänze eine Regel, die zwei Felder verbindet
- 12TippTrenne Gültigkeit und Zeitpunkt der Fehlermeldung
- 13HerausforderungKorrigiere eine veraltete Datumsregel
- 14VerbindungÜbernimm Verantwortung beim Überspringen der Browserrückmeldung
- 15HerausforderungVervollständige den Korrekturablauf
- 16ZusammenfassungPrüfe sowohl gültige als auch ungültige Wege
5Erstelle Bedienelemente und erhalte die Tastaturposition
14 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungMach eine Interaktion über die Tastatur nutzbar
- 2ErklärungNutze das Verhalten, das HTML bereits bietet
- 3TippLege die Fokussierbarkeit für den vorgesehenen Weg fest
- 4HerausforderungKorrigiere eine nicht erreichbare Aktion
- 5BeispielNutze eine gemeinsame Aktivierungsfunktion
- 6ErklärungDrücke die richtige Art von Zustand aus
- 7HerausforderungKehre einen Aufklappbereich korrekt um
- 8BeispielVerschiebe einen Tab-Stopp innerhalb einer Gruppe
- 9VerbindungMerke dir, woher ein Dialog geöffnet wurde
- 10BeispielLass eine interne Fokusbewegung innerhalb bleiben
- 11HerausforderungWähle den Fokus nach dem Entfernen
- 12HerausforderungVerfolge die Aktualisierung einer Gruppe
- 13HerausforderungHalte einen aufklappenden Bereich vorhersehbar
- 14ZusammenfassungTeste die vollständige Bedienabfolge
Ereignisse in JavaScript: Übungsaufgaben
Set 1: Verfolge verschachtelte Aktionen und Delegation10 Übungsfragen
Frage 1 von 10
Antwort zeigenAntwort ausblenden
Frage 2 von 10
Antwort zeigenAntwort ausblenden
Frage 3 von 10
focus-Listener, aber das Fokussieren seines input-Kindelements ruft ihn nicht auf. Wie kann das Formular den Fokus von Nachfahren ohne Capture beobachten?Antwort zeigenAntwort ausblenden
focusin gelangt vom input-Element durch Bubbling zum Formular, sodass ein gewöhnlicher Formular-Listener es beobachten kann. focus und blur durchlaufen die Bubbling-Phase nicht. Eine Listener-Option kann nicht ändern, ob das Browserereignis die Bubbling-Phase durchläuft; das Lesen einer Eigenschaft in einem Callback, der nie läuft, kann das fehlende Ereignis nicht ersetzen.Frage 4 von 10
event.stopPropagation() auf. Was geschieht mit seiner normalen Navigation?Antwort zeigenAntwort ausblenden
preventDefault() in einem dafür geeigneten Listener, wenn Code die Navigation durch eine Aktion auf der Seite ersetzt.Frage 5 von 10
preventDefault() auf. Ein gewöhnlicher submit-Listener existiert auch an einem umgebenden Abschnitt. Was kann der Listener des Abschnitts beobachten?Antwort zeigenAntwort ausblenden
Frage 6 von 10
Antwort zeigenAntwort ausblenden
Frage 7 von 10
Antwort zeigenAntwort ausblenden
closest() beginnt beim angeklickten SVG und geht aufwärts zur Schaltfläche. matches() prüft nur das SVG und kann daher das umgebende Bedienelement nicht finden. Auch die Suche abwärts mit querySelector() geht in die falsche Richtung, wenn die Schaltfläche das Ereignisziel enthält.Frage 8 von 10
Antwort zeigenAntwort ausblenden
Frage 9 von 10
closest(".action") innerhalb eines Containers, der in einem äußeren .action-Element liegt. Ein Klick auf einen Zwischenraum findet dieses äußere Element. Welche Prüfung beschränkt die Verarbeitung auf den Container?Antwort zeigenAntwort ausblenden
closest() kann über den Container des Listeners hinausgehen und ein äußeres Vorfahrenelement zurückgeben. Nutze nach der Prüfung auf einen fehlenden Treffer container.contains(match), um dieses Ergebnis auszuschließen. Die Prüfung currentTarget === container würde jedes Ereignis in diesem Listener ausschließen, auch gültige Klicks auf seine eigenen Kindelemente.Frage 10 von 10
closest(".remove") und Prüfungen auf Zugehörigkeit. Neue Schaltflächen funktionieren, außer in einer Zeile, deren Symbol-Listener stopPropagation() aufruft. Der Innenabstand der Schaltfläche in derselben Zeile funktioniert. Warum tritt dieser Unterschied auf?Antwort zeigenAntwort ausblenden
closest() kann ein Symbol als Ziel verarbeiten, hilft aber nicht, wenn ein delegierter Callback das Ereignis nie erhält.Set 2: Richte Event-Listener ein und untersuche sie10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
showHints nur bei ihrer Aktivierung aufrufen. Welche Registrierung erreicht das?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
addEventListener. Welche Änderung beim Laden lässt die Auswahl warten, bis das HTML geparst ist?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
const items = document.querySelectorAll(".choice"); items.addEventListener("click", choose);. Alle Auswahlmöglichkeiten existieren bereits. Warum schlägt das fehl und wie sollte die Einrichtung geändert werden?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
button.onclick = first; button.onclick = second;. Was geschieht, wenn die Schaltfläche einmal angeklickt wird?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
target und currentTarget während dieses Listeners?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
<button data-code="r8"><span>Run</span></button> liest event.target.dataset.code. Warum kann das undefined zurückgeben und welcher Ausdruck liest im direkten Listener den Code der Schaltfläche?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
currentTarget: null. Wie kann die Entwicklerin oder der Entwickler das Element des Listeners während des Aufrufs untersuchen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
{ capture: true } registriert. Derselbe Typ und dieselbe Funktion werden an removeEventListener übergeben, aber ohne drittes Argument. Warum bleibt der Callback bestehen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
board.addEventListener("click", () => mark()). Nach zweimaligem Beginnen setzt ein Klick auf das Spielfeld zwei Markierungen. Welche Änderung an der Einrichtung verhindert diese Ansammlung?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
Eine ansonsten leere Schaltfläche erhält diese Registrierungen und wird dann zweimal angeklickt. Wie oft läuft log insgesamt?
button.addEventListener("click", log, { once: true });
button.addEventListener("click", log);
button.addEventListener("click", log, true);
button.removeEventListener("click", log);
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 3: Verarbeite Tastatur-, Zeiger- und Zieheingaben10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
keydown. Welche Änderung behebt beide Probleme?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
pointerdown. Welches Ereignis sollte die Aktion verarbeiten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
clientY 75. Wie lautet seine vertikale Koordinate relativ zum Dokument?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
pointerout. Welches Ereignis erkennt das Verlassen der ganzen Karte besser?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
left: 65px; top: 90px. Ihr Zeiger beginnt bei den Client-Koordinaten 180, 210 und bewegt sich zu 155, 245. Welche Position sollte die Box erreichen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 4: Lies Formulardaten und untersuche die Validierung10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
"6". Was ergibt input.value + 2?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
topic mit den Werten "art" und "code" in Dokumentreihenfolge, ein nicht angekreuztes topic mit dem Wert "music" und eine deaktivierte benannte Notiz. Was gibt new FormData(form).getAll("topic") zurück und warum ist die Umwandlung in ein Objekt riskant?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
form.submit() auf und der Listener des Formulars, der die Navigation verhindert, läuft nie. Welcher Aufruf stellt den erwarteten Ablauf wieder her und was geschieht, bevor das Feld korrigiert ist?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
pattern="[A-Z]{3}". Besteht ein leerer Wert diese Musterprüfung?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
min="2" max="14" step="4". Der Nutzer gibt 12 ein. Welche Prüfung schlägt fehl?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
novalidate und prüft beim Absenden die Felder in Dokumentreihenfolge. Sein Mengenfeld ist ein Pflichtfeld mit min="2" max="14" step="4"; es enthält nun 10 und eine alte benutzerdefinierte Meldung wurde mit setCustomValidity("") gelöscht. Das nächste Feld ist ein leeres E-Mail-Pflichtfeld. Was sollte diesen Absendeversuch blockieren und den Fokus erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
end.value < start.value ab und läuft nur bei Änderungen am Enddatum. Welche zwei Änderungen beheben die verbleibenden feldübergreifenden Fehler?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 5: Ermögliche Tastaturbedienung und erhalte den Fokus10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
role="button" und einen Klick-Listener. Was stellt die Rolle selbst bereit?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
activate() weiter. Sie hat aria-disabled="true". Die Funktion beginnt mit if (button.getAttribute("aria-disabled") === true) return;, dennoch führen beide Wege die Aktion aus. Welche Korrektur setzt die Deaktivierung durch und erlaubt zugleich beim Zeichenkettenwert „false“ die Aktion?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
aria-expanded="true" und einen sichtbaren Bereich. Sein Klick-Handler liest den alten aufgeklappten Zustand. Wie sollte der nächste Zustand aussehen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
tabindex="-1". Die fokussierte Löschschaltfläche im letzten Eintrag entfernt diesen; später wird auch der verbleibende Eintrag gelöscht. Welche Fokusfolge unterstützt die weitere Tastaturbedienung?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Hängst du bei deiner eigenen Aufgabe fest? Hausaufgabenhilfe
Schlüsselbegriffe
A
AbortController
abort() aufgerufen wird.Absende-Schaltfläche
event.submitter bereitgestellt wird, wenn eine bestimmte Schaltfläche diesen Weg ausgelöst hat.Aktivierung
click dargestellt.click, egal ob sie mit der Leertaste oder der Maus gedrückt wird.aria-describedby
aria-describedby verknüpft ein Bedienelement mit beschreibendem Text, indem es die IDs der Elemente aufführt, die diesen Text enthalten.email-error, damit assistive Technologien den Fehler mit ihm verknüpfen können.aria-invalid
aria-invalid teilt mit, dass der eingegebene Wert eines Bedienelements einen Fehler enthält; Code muss es aktualisieren, wenn sich der Fehler ändert.aria-invalid="true", während seine Korrekturmeldung direkt am Feld angezeigt wird.ARIA-Rolle
role="button" benötigt weiterhin Code für die Aktivierung und einen passenden Tab-Stopp.ARIA-Zustand
aria-checked-Wert des Schalters wird aktualisiert, wenn sich seine sichtbare Ein-/Aus-Darstellung ändert.Aufklappbereich
aria-expanded mit.Auslösendes Bedienelement
B
Benutzerdefinierte Validierung
setCustomValidity() gesetzte Regel, bei der eine nicht leere Meldung das Bedienelement als ungültig markiert.Bubbling
bubbles-Wert wahr ist.input-Ereignis eines Feldes als Kindelement gelangt durch Bubbling zu einem Listener am umgebenden Formular.C
cancelable
cancelable ist ein boolescher Wert, der angibt, ob ein Ereignis das Verhindern seiner Standardaktion durch preventDefault() erlaubt.input-Ereignis meldet eine bereits vorgenommene Bearbeitung, daher ist seine Eigenschaft cancelable falsch.Capturing-Phase
change-Ereignis
change-Ereignis meldet eine übernommene Änderung durch den Nutzer, etwa das Verlassen eines bearbeiteten Textfeldes oder die Auswahl eines neuen Zustands bei einem Kontrollkästchen oder einer Auswahlliste.change aus, wenn der Nutzer es für das nächste Bedienelement verlässt.checked
checked ist der boolesche Zustand, der unabhängig vom Übermittlungswert angibt, ob ein Kontrollkästchen oder Optionsfeld ausgewählt ist.checkbox.checked, um zu entscheiden, ob ein optionaler Abschnitt angezeigt wird.checkValidity
checkValidity() gibt zurück, ob die Regeln erfüllt sind, und löst bei Fehlern invalid-Ereignisse aus, ohne eine Browserrückmeldung anzuzeigen.closest
closest() prüft ein Element und dann seine Vorfahren auf den nächsten Selektortreffer und gibt null zurück, wenn keiner existiert.closest("button") die umgebende Aktionsschaltfläche.code
code bezeichnet eine physische Tastenposition unabhängig von dem Zeichen, das das aktuelle Tastaturlayout erzeugt.code, wenn seine Bewegungssteuerung an festen physischen Positionen bleiben soll.Constraint-Validierung
contains
contains() prüft, ob ein Knoten das Element selbst oder einer seiner Nachfahren ist, und gibt einen booleschen Wert zurück.list.contains(button), bevor er die Aktion der Schaltfläche zulässt.currentTarget
currentTarget bezeichnet das Objekt, dessen Listener läuft, und wird nach Ende der Ereignisauslösung auf null zurückgesetzt.currentTarget die Daten dieser Schaltfläche lesen.CustomEvent
detail tragen und für Bubbling zu Vorfahrenelementen konfiguriert werden kann."cart:add" mit seiner Eintragskennung in detail des Ereignisses aus.D
Datenattribut
data- beginnt und Anwendungsinformationen speichert, die über das dataset eines Elements verfügbar sind.data-action="clear" als button.dataset.action, um eine bekannte Aktion auszuwählen.defaultPrevented
defaultPrevented ist ein boolescher Wert, der festhält, ob die Standardaktion eines Ereignisses erfolgreich verhindert wurde.defaultPrevented prüfen, bevor er entscheidet, wie ein Klick behandelt wird.Dokumentkoordinaten
pageX und pageY unter Berücksichtigung des Scrollens von der linken oberen Ecke des Dokuments aus gemessen werden.pageY 400.E
Einzelzeiger-Alternative
Entfernen führender und nachgestellter Leerraumzeichen
name.value.trim() === "" erkennt einen Namen, der ausschließlich aus Leerzeichen besteht.Ereignis
click-Ereignis lässt die Seite reagieren, wenn eine Person die Weiter-Schaltfläche der Galerie aktiviert.Ereignisdelegation
Ereignisobjekt
key des empfangenen Ereignisses, um zu entscheiden, ob ein Bereich geschlossen wird.Ereignisweitergabe
Event-Handler-Eigenschaft
onclick, die einen Ereignis-Callback enthält und ihn bei einer erneuten Zuweisung ersetzt.button.onclick ersetzt den früheren Handler dieser Eigenschaft.Event-Listener
F
Fehlerübersicht
Fokus
document.activeElement verfügbar ist.search.focus() leitet das nächste eingegebene Zeichen in das Suchfeld.Fokusindikator
:focus-visible-Umrandung zeigt, welche Schaltfläche der Werkzeugleiste die nächste Tastenaktion erhält.Fokusmanagement
FormData
data.getAll("topics") alle ausgewählten Werte gemeinsam ab.Funktionsreferenz
openPanel registriert die Funktion; die Übergabe von openPanel() ruft sie während der Einrichtung auf.I
Inaktiver Hintergrund
input-Ereignis
input-Ereignis meldet eine Bearbeitung durch den Nutzer, nachdem sich der Wert eines Bedienelements geändert hat, einschließlich Textbearbeitungen ohne physischen Tastendruck.input-Listener einen Zähler.K
key
key meldet den von einer Taste erzeugten Wert unter Berücksichtigung des Tastaturlayouts und von Modifikatortasten wie der Umschalttaste.key-Wert eines Buchstabens von "a" zu "A" ändern, während seine Position gleich bleibt.keydown
keydown-Ereignis meldet einen Tastendruck vor dessen normaler Bearbeitungswirkung und kann sich wiederholen, solange die physische Taste gedrückt bleibt.keydown auf Escape, bevor er den offenen Bereich schließt.L
Listener-Identität
M
Modaler Dialog
showModal() öffnet den nativen Dialog und setzt den Fokus in seinen Inhalt.Modifikatortasten-Flag
ctrlKey oder metaKey zusammen mit dem Buchstaben S.N
Natives Bedienelement
novalidate
novalidate überspringt beim Absenden die automatische Constraint-Validierung und lässt Regeln und Validierungsmethoden verfügbar.novalidate, damit sein submit-Listener jedes Feld selbst prüfen kann.O
once
once veranlasst die automatische Entfernung dieser Registrierung nach ihrem ersten Aufruf für den ausgewählten Ereignistyp.once: true für den Klick nutzen, der es für diese Lebensdauer schließt.P
Passiver Event-Listener
preventDefault() in einem passiven Berührungs-Listener stoppt das Scrollen des Browsers nicht.pattern
pattern definiert für unterstützte Textfelder eine Regel als regulären Ausdruck, der zum gesamten Wert passen muss und nur bei nicht leerem Wert angewendet wird.required, um ein leeres Feld abzulehnen.pointercancel
pointercancel-Ereignis meldet, dass der Browser die Zeigerinteraktion abgebrochen hat, sodass eine Ziehinteraktion ihren aktiven Zustand löschen muss.pointercancel beenden.pointerId
pointerId bezeichnet während einer Interaktion einen einzelnen Zeiger, sodass gleichzeitige Kontakte getrennt verarbeitet werden können.preventDefault
preventDefault() verhindert in einem nicht passiven Listener die Standardaktion eines dafür geeigneten Ereignisses, ohne dessen Weitergabe zu stoppen.preventDefault() auf, bevor er ohne Navigation einen lokalen Eintrag hinzufügt.Prüfung auf einen Klick außerhalb
R
relatedTarget
relatedTarget bezeichnet das andere an einem Fokuswechsel beteiligte Element oder ist null, wenn kein solches Element verfügbar ist.focusout-Listener eines Menüs prüft, ob das Ziel innerhalb des Menüs bleibt.reportValidity
reportValidity() prüft Regeln und fordert den Browser zusätzlich auf, für nicht behandelte Fehler eine Validierungsrückmeldung anzuzeigen.reportValidity() auf, um dem Nutzer beim Finden eines ungültigen Feldes zu helfen.requestSubmit
requestSubmit() fordert das Absenden eines Formulars über den normalen Weg mit Validierung und submit-Ereignis an, ohne einen Schaltflächenklick auszulösen.form.requestSubmit() auf, damit die Validierung und der submit-Listener des Formulars weiterhin laufen.Roving tabindex
S
Standardaktion
stopImmediatePropagation
stopImmediatePropagation() stoppt die Ereignisweitergabe und überspringt zusätzlich verbleibende Listener, die am aktuellen Ereignisziel registriert sind.stopPropagation
stopPropagation() verhindert, dass ein Ereignis zu weiteren Elementen gelangt, während andere Listener auf seinem aktuellen Element aktiv bleiben.submit-Ereignis
submit-Ereignis ist ein abbrechbares Formularereignis, das beim normalen Absendeweg ausgelöst wird, nachdem die automatische Validierung das Absenden erlaubt hat.submit-Listener eines Formulars verarbeitet ein gültiges Absenden, indem er lokal einen Eintrag hinzufügt und die Navigation verhindert.Synchrone Ereignisauslösung
dispatchEvent() laufen, bevor die Methode die Kontrolle an den aufrufenden Code zurückgibt.dispatchEvent() ausgegebene Meldung erscheint nach den Meldungen seiner Listener.T
tabindex
tabindex steuert die Teilnahme an der normalen Tab-Reihenfolge und die Fokussierbarkeit per Code, wobei 0 in der normalen Reihenfolge liegt und −1 außerhalb davon.tabindex="-1", damit Code sie fokussieren kann, ohne einen regulären Tab-Stopp hinzuzufügen.target
target bezeichnet den Ursprung des Ereignisses, der ein verschachteltes Element innerhalb des Bedienelements sein kann, dessen Aktion verarbeitet wird.target des Klicks.Tastenbitmaske
buttons des Ereignisses kombiniert.buttons 3 und kombiniert damit die Flags 1 und 2.touch-action
touch-action legt fest, welche Berührungsgesten des Browsers erlaubt sind, wenn eine Geste auf einem Element beginnt.touch-action: none auf der Ziehfläche reserviert die Bewegung in diesem Bereich für die Ziehinteraktion.U
Umschaltfläche
aria-pressed den aktuellen Zustand meldet.aria-pressed-Wert zwischen wahr und falsch wechselt.V
ValidityState
validity eines Bedienelements bereitgestellte Objekt mit booleschen Flags, die verletzte Regeln bezeichnen.stepMismatch melden, obwohl sie zwischen Minimum und Maximum liegt.value
value stellt den aktuellen Wert eines Formularfeldes als Text bereit, auch bei Zahlenfeldern, deren numerischer Inhalt noch umgewandelt werden muss."8" benötigt eine Umwandlung, bevor Code einen numerischen Wert addiert.valueAsNumber
valueAsNumber liest den numerischen Wert eines unterstützten Eingabefeldes direkt und gibt NaN zurück, wenn kein brauchbarer Zahlenwert vorliegt.NaN, was Code mit Number.isNaN() erkennt.Viewport-Koordinaten
clientX und clientY von der linken oberen Ecke des sichtbaren Bereichs aus gemessen werden.Z
Zeigerereignis
pointermove-Listener kann Bewegungen einer Maus oder eines Berührungskontakts auslesen.Zeigererfassung
Ziehzustand
Zielphase
eventPhase 2.Zugänglicher Name
aria-label="Close", um die Wirkung des Symbols anzugeben.Zurücksetzen des Formulars
form.reset() die anfänglichen Feldwerte des Formulars wieder her.Zusammengesetztes Bedienelement
Über diese Einheit
Erstelle deine eigenen Lernmaterialien
Mach aus deinen Notizen, Folien und Dokumenten Lernleitfäden, Übungsfragen, Karteikarten und 6 weitere Tools.