Ijs2019medienpartner.jpg

SELFHTML ist in diesem Jahr Medienpartner der IJC.

Für die Konferenz vom 21. – 25. Oktober 2019 in München verlosen wir ein Freiticket.

Weitere Informationen finden sich im SELFHTML-Forum.

JavaScript/Tutorials/DOM/Ereignisverarbeitung

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Informationen zu diesem Text

Lesedauer
10-15min
Schwierigkeitsgrad
mittel
Vorausgesetztes Wissen
Kenntnisse in
● HTML
● JavaScript

Alle bisherigen Beispiele wurden direkt mit dem Laden des Script ausgeführt. Dies hat aber (noch) nichts mit Interaktivität zu tun. Die Event-API ermöglicht die Überwachung und Behandlung von Ereignissen (Event-Handling). Dies können Klicks mit der Maus, Wischgesten (Swipes) auf einem Touchbildschirm, ankommende Daten aus dem Netzwerk oder Änderungen am DOM sein.

Moderne Scripte durchlaufen deshalb verschiedene Phasen:

  1. Das Dokument wird geladen
  2. JavaScript fügt Event-Handler an Elementknoten an.
  3. Der Anwender bedient das Dokument und das Script reagiert darauf.

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).

window.onload[Bearbeiten]

In diesem Beispiel ist der JavaScript-Code im head des Dokuments gespeichert. Der Zugriff auf das output-Element würde erfolgen, bevor der Absatz im DOM überhaupt vorhanden wäre.

Deshalb wird das Script mit window.onload erst ausgeführt, wenn die Seite im Browser geladen und geparst ist.


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.
Beachten Sie: Eventhandler sind Callbacks. Wenn Sie aus dem Eventhandler heraus auf Variablen zugreifen wollen, die außerhalb der Eventhandler-Funktion definiert sind, beachten Sie bitte die Hinweise zum Umgang mit Callback-Funktionen. Alternativ sollten Sie Bubbling als bessere Alternative in Erwägung ziehen.

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.

auf Klicks reagieren[Bearbeiten]

Bis jetzt wurde unser Programm automatisch immer nach dem Laden der Webseite ausgeführt. Interessant wird es jedoch erst, wenn der Anwender selbständig eingreifen kann und unser Programm reagiert.

Beispiel ansehen …
  <main>
     <button id="button">Drück mich!</button>
     <output></output>
  </main>
In diesem Beispiel sehen Sie einen Button (noch ohne Funktion) und das noch leere output-Element.
Das JavaScript befindet sich in einem script-Element im Head des Dokuments:
document.addEventListener('DOMContentLoaded', function () {
 
  var anzahl = 0;
  var text ='';
 
  document.getElementById('button').addEventListener('click', gedrueckt);
 
  function gedrueckt() {
    anzahl = anzahl + 1; 
 
    if (anzahl < 10) {
      text = 'Sie haben den Button ' + anzahl +'mal gedrückt!';
    }
    else if (anzahl < 15) {
      text = 'Sie haben jetzt bereits ' + anzahl + 'mal geklickt.\n' +
             'Wollen Sie sich nicht einen Kaffee gönnen?';
    }
    else {
      text = 'Jetzt haben Sie schon ' + anzahl + 'mal geklickt - mir wird langweilig.';
    }
    document.querySelector('output').innerText = text;
  }
 
});
Wenn das DOM aufgebaut ist, feuert DOMContentLoaded und führt die anonyme Funktion aus.

Mit der addEventListener-Methode wird eine Ereignisüberwachung an den Button gehängt.

Sobald der Button gedrückt (click) wird, wird die Funktion gedrueckt aufgerufen. Diese erhöht den Zähler um 1 und gibt dann aus, wie oft der Button bereits angeklickt wurde.

Die Ereignisüberwachung anderer Events wie mousemove oder touchstart (dem Berühren eines Touchscreens) kann genauso eingerichtet werden.

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.