JavaScript/Tutorials/Ereignisverarbeitung

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Mit JavaScript könnnen Sie interaktive Webseiten erstellen, die auf Benutzeraktionen wie Eingaben, Klicks und Wischgesten (aber auch auf interne Meldungen, wie dem vollständigen Laden der Seite oder der Verbindung zum Netzwerk) reagieren.

In diesem Tutorial sehen Sie, mit welchen Techniken Sie diese Ereignisse (engl. Events) überwachen und verarbeiten können.

Event-Handling[Bearbeiten]

Ein HTML-Dokument wird vom Browser geladen, geparst und bleibt dann unverändert im Browser, bis das Fenster geschlossen wird. JavaScript wird zwar ebenso geladen, bietet dann aber eine Interaktivität, mit der der Nutzer das Dokument ändern kann. Dabei werden drei Phasen unterschieden:

  1. Phase Eins: Das Dokument wird empfangen und geparst
    Dabei wird das JavaScript erstmals ausgeführt.
    • Objekte und Funktionen werden dabei definiert, sodass sie für die spätere Nutzung zur Verfügung stehen.
    • Nicht alle notierten Funktionen werden dabei bereits aufgerufen.
    • Zu diesem Zeitpunkt hat das Script noch keinen vollständigen Zugriff auf das Dokument.
  2. Phase Zwei: Das Dokument ist fertig geladen
    Der vollständige Zugriff auf das Dokument über das DOM ist erst jetzt möglich.
    • Registrieren von Event-Handlern: Das Script spricht vorhandene Elementknoten an und fügt ihnen sogenannte Event-Handler mit Handler-Funktionen hinzu.
    • Inhalt oder Darstellung bestehender Elemente können verändert und dem Dokument neue Elemente hinzugefügt werden (siehe DOM-Manipulation).
  3. Phase Drei: Der Anwender bedient das Dokument und das Script reagiert darauf
    Wenn die überwachten Ereignisse an den entsprechenden Elementen im Dokument passieren, werden die entsprechenden Handler-Funktionen ausgeführt.

traditionelles Event-Handling[Bearbeiten]

Es gibt noch viele Script-Beispiele und Tutorials im Netz, in denen Event-Handler als HTML-Eventattribute direkt in das HTML-Dokument geschrieben werden.

Beispiel: obsolete Methode mit HTML-Eventattributen
<button onclick="alert('Hallo Welt!');">Drück mich! </button>
Empfehlung: Eventhandler sollte man in der Regel nicht im HTML selbst notieren, sondern mittels Javascript dynamisch an Elemente binden. Dies folgt der Tugend des unobtrusive JavaScript, denn nur aktiv JavaScript ausführende Browser sollen auch mit JavaScript-Code konfrontiert werden.

Diese Schreibweise mit der Vorsilbe on- wurde auch im traditionellen Event-Handling verwendet. Sie ist Englisch und steht für bei: onclick (engl. bei einem Klick).

Beispiel: traditionelles Event-Handling ansehen …
<!DOCTYPE html>
<html lang="de">
<head>
<script>
  window.onload = start;

  function start() {
    document.querySelector('#interaktiv').onclick = klickverarbeitung;
  }

  function klickverarbeitung() {
    document.querySelector('output').innerText += ' Huhu, das ist von Javascript eingefügter Text.';
  }
</script>
</head>
<body>
  <h1>Beispiel für traditionelles Event-Handling</h1>
  <button id="interaktiv">Klick mich!</button>
  <output></output>
</body>
</html>
Da sich der Script-Bereich im head des Dokuments befindet, sind die mit JavaScript angesprochenen Elemente beim Parsen des Skripts noch nicht vorhanden.

Deshalb wird an das globale Window-Objekt mit der Punkt-Notation ein load-Event angehängt, das die Funktion start aufruft.

In der Funktion start erhält der Button, der mit querySelector über seine id interaktiv aufgerufen wird, ein Klick-Event zugewiesen, das onclick (engl. bei einem Klick) die Funktion klickverarbeitung aufruft. Diese weist dem output-Element, das mit querySelector ermittelt wurde, mittels innerText die Zeichenkette zu.

Diese traditionelle Methode scheint sehr einfach, hat jedoch einige Nachteile. So kann man jeweils nur ein Event an Elemente hängen - weitere überschreiben bestehende Event-Handler. Deshalb hat sich eine fortgeschrittene Ereignisvarbeitung mit addEventListener durchgesetzt.

Empfehlung: Vermeiden Sie auf jeden Fall das Hinzufügen von Eventhandlern mit der Punktnotation, wie es in älteren Scripten noch zu sehen ist. Auch wenn es auf den ersten Blick schneller und einfacher scheint, verstößt man so gegen die Trennung von Inhalt und Verhalten und selbst bei kleineren Projekten wird der Code schnell unübersichtlich, wie Sie in diesem Beispiel aus den Jahr 2000 sehen können.

Event-Handler registrieren: addEventListener[Bearbeiten]

Heutzutage hat sich eine einfache Methode Event-Handler dynamisch an Elemente zu hängen, durchgesetzt:

Beispiel: fortgeschrittenes Event-Handling ansehen …
document.addEventListener('DOMContentLoaded', function () {
 
  document.querySelector('#interaktiv').addEventListener('click', klickverarbeitung);
 
  function klickverarbeitung () {
    document.querySelector('output').innerText += ' Huhu, das ist von Javascript eingefügter Text. \n';
  }
	  
});
Das Beispiel entspricht im HTML-Aufbau und Funktion dem ersten Beispiel.

Da sich der Script-Bereich im head des Dokuments befindet, sind die mit JavaScript angesprochenen Elemente beim Parsen des Skripts noch nicht vorhanden.

Deshalb wird an das document-Objekt mit der addEventListener-Methode ein Event-Handler angehängt, der beim Feuern des DOMContentLoaded-Events eine anonyme Funktion aufruft, die wiederum dem Button mit der id interaktiv einen Event-Handler zuweist, der bei einem Klick die Funktion klickverarbeitung aufruft.


Das DOMContentLoaded-Event bietet gegenüber dem load-Event einige Vorteile, da es schon beim Laden und Parsen des DOM feuert, wenn evtl. umfangreichere externe Skripte und Ressourcen wie Bilder und Videos noch geladen werden.

Beachten Sie: Es gibt für DOMContentLoaded keine entsprechende Objekteigenschaft, dass heißt, eine Überwachung dieses Ereignisses muss immer mit addEventListener erfolgen.

Mit diesem fortgeschrittenen Event-Handling könnten an ein Element mehrere Event-Handler angehängt werden, die unterschiedliche Aktionen etwa bei Klick, Touch oder dem Auslösen mit einem Stift auslösen.

Event-Handler entfernen: removeEventListener[Bearbeiten]

Einen mit der addEventListener-Methode hinzugefügten Event-Handler können Sie mit der Schwester-Methode removeEventListener wieder entfernen. Die Methode erwartet dieselben Parameter, die addEventListener beim Registrieren bekommen hat: Einen String mit dem Ereignistyp, die zu löschende Handler-Funktion und schließlich einen optionalen Boolean-Wert für die Event-Phase.

Beispiel: Entfernen eines Event-Handlers mit removeEventListener ansehen …
  document.addEventListener('DOMContentLoaded', function () {
 
    document.querySelector('#interaktiv').addEventListener('click', klickverarbeitung);
    document.querySelector('#entferne').addEventListener('click', entferneKlickverarbeitung);
 
    function klickverarbeitung () {
      document.querySelector('output').innerText += ' Huhu, das ist von Javascript eingefügter Text. \n';
      document.querySelector('#entferne').setAttribute('aria-hidden', false);
    }
	
    function entferneKlickverarbeitung () {
      document.querySelector('#interaktiv').removeEventListener('click', klickverarbeitung);	
      document.querySelector('output').innerText += ' Event-Handler wurde entfernt. \n';
    }
	  
  });
Das Beispiel enthält zwei Buttons, von denen nur der linke sichtbar ist. Der "Entferne!"-Button besitzt ein aria-hidden-Attribut und wird durch CSS ausgeblendet.

Innerhalb der Funktion klickverarbeitung wird der bereits bekannte Text eingefügt. In einer weiteren Anweisung wird das ARIA-Attribut mit setAttribute auf false gesetzt und so durch seine CSS-Festlegung sichtbar.

Durch einen Klick auf den "Entferne"-Button wird die Funktion entferneKlickverarbeitung aufgerufen, die mit removeEventListener('click', klickverarbeitung); die Funktionalität des linken Buttons entfernt und eine entsprechende Meldung im output-Element ausgibt.

HTML-Markup[Bearbeiten]

Standardaktionen[Bearbeiten]

Die oben erwähnte Einteilung in statisches HTML und dynamisches JavaScript ist so nicht ganz richtig. Es gibt in HTML neben reinen Textauszeichnungelementen wie einer Überschrift oder einem Textabsatz auch Elemente, die bereits eine browsereigene Funktionalität haben, wie z.B. Verweise, Buttons oder input-Elemente und damit verbundene label. Sie haben ein sogenanntes Standardverhalten (default behavior), d.h. sie sind anklickbar oder mit der Tab-Taste ( ) durchtabbbar. Der Browser behandelt also standardmäßig gewisse Ereignisse und führt die Standardaktion (englisch default action) aus, ohne dass der Seitenautor eine entsprechende JavaScript-Logik definieren musste.

Theoretisch können Sie diese Funktionalität mit jedem Element nachbauen, praktisch machen Sie sich doppelt Arbeit, verkomplizieren das Markup und den Code und erschweren die Zugänglichkeit Ihrer Seite für Screenreader.

Standardaktionen unterdrücken[Bearbeiten]

Teilweise ist es jedoch nicht erwünscht, diese Standardaktionen durchzuführen.

Ein submit-Event, das z.B. durch button type="submit" ausgelöst wird, sendet eingegebene Formulardaten ab und sorgt für einen Reload der Seite. Bei einer browsereigenen Validierung sollen richtig eingegebene Daten jedoch erhalten bleiben, sodass das submit-Event unterdrückt werden muss.

Beispiel
document.addEventListener('unload', function() { 
  return confirm('Sie haben auf dieser Seite eine Antwort verfasst, \
                  sind Sie sicher, dass Sie diese Seite verlassen möchten?') 
});
Wenn die Seite verlassen wird, feuert das unload-Event und eine anonyme Handler-Funktion fragt in einer Bestätigungsbox, ob der Nutzer die Seite wirklich verlassen möchte. Außerdem wäre zu überlegen, ob man bei leeren oder (unberührten) Eingabefeldern die Abfrage nicht weglässt.

Mit preventDefault können Sie die Standardaktion des Browsers unterdrücken, wie z.B. in diesem Beispiel, in dem die verlinkte Großansicht eines Bildes schon innerhalb der Webseite angezeigt wird. Der Klick auf den Link löst das JavasCript, aber kein Navigieren zu einer neuen Ressource aus.

Der Event-Fluss: Bubbling[Bearbeiten]

Verarbeitendes Element und Zielelement[Bearbeiten]

Kontrolle über den Event-Fluss: Bubbling verhindern[Bearbeiten]

Weblinks[Bearbeiten]

Information

Bei diesem Text handelt es sich um eine stark überarbeitete Übernahme aus der Einführung in JavaScript von Mathias Schäfer.