CSS, HTML und Javascript mit {stil}

Javascript preventDefault • stopPropagation

Javascript event prevent default

Aktionen als Folge eines Events können noch verhindert werden, wenn das Event schon eingetreten ist:

  • Javascript Event preventDefault übernimmt im DOM die Aufgabe des Aufrufs return false;, um die ursprüngliche Aktion des Browsers bei einem HTML-Element außer Kraft zu setzen.
  • Event stopPropagation verhindert, dass ein Event im DOM-Baum nach oben reist und dabei Aktionen auf anderen Elementen triggert.

Javascript kann Aktionen, die durch ein Event ausgelöst werden, auf zweierlei Weise unterbinden:

  • Event.preventDefault
  • Event.stopPropagation

Einige HTML-Elemente können bei Ereignissen auch ohne Javascript Aktionen durchführen. Ein Klick oder Touch führt z.B. zu einer neuen Seite. Ein Formular wird versendet, wenn der Benutzer auf den Button »Absenden« klickt. preventDefault verhindert, dass die vorgesehene Aktion des HTML-Elements durchgeführt wird.

preventDefault

Typischer Einsatz für evt.preventDefault() sind Formulare, die vor dem Ansenden durch Javascript geprüft werden. Wenn ein Javascript-Event an den submit-Button gebunden ist, muss das normale Verhalten des Buttons unterbunden werden, um das Weiterleiten der Daten an die Anwendung auf dem Server zu blockieren.

Bei einem einfachen Klick-Handler reicht return false.

// Traditionell
elem.onclick = function () {
   // Ereignis behandeln
   return false;
});

// Moderne Browser
elem.addEventListener ('click', function (evt) {
   // Ereignis behandeln
   evt.preventDefault();
});

Wird das Event durch addEventListener (oder attachEvent) getriggert, reicht der Aufruf return false nicht immer aus.

Stattdessen wird preventDefault() in Standard-konformen Browsern aufgerufen. Für IE8 und älter setzt das Script die Boolesche Variable event.returnValue auf false.

DOM: preventDefault()
Kann das Ereignis canceln. Verhindert jegliche Browser-Aktion für das Ereignis, etwa das Laden einer URL, wenn ein Hyperlink geklickt wurde
IE: event.ReturnValue
Keine Methode, sondern eine Boole'sche Eigenschaft, die false gesetzt wird, um die Browser-Aktion für das Element zu canceln.

Wrapper für preventDefault und window.event.returnValue

function stopDefault(evt) {
    if (evt && evt.preventDefault) {
        evt.preventDefault();
    } else if (window.event && window.event.returnValue) {
        window.event.returnValue = false;
    }
}

Event stopPropagation

Bei einem Klick auf einem Button entsteht das Event nicht etwa auf dem Button, sondern Events entstehen immer auf dem window-Element und reisen dann durch den DOM-Baum nach unten (»Capturing Phase). Auf dem Weg nach unten informieren sie jedes HTML-Element: »Hi, hier ist ein Klick! Hast du auf mich gewartet?«.

Dann reist das Event in der Bubbling-Phase wieder nach oben bis zum ROOT. evt.stopPropagation verhindert die Weiterreise des Events.

preventDefault vs stopPropagation

preventDefault für das erste Bild verhindert die vorgegebene Aktion des a-Elements, so dass die Seite nicht über den Link verlassen wird. Das Event trifft aber dennoch auf dem Weg zurück nach oben den Parent Node und wird hier erkannt.

<div id="logo1">
   <a id="thelink1" href="formulare-http.html">
      <img src="logo.png" width="" height="" alt="">
   </a>
</div>
<div id="logo2">
   <a id="thelink2" href="formulare-http.html">
      <img src="logo.png" width="" height="" alt="">
   </a>
</div>

stopPropagation im zweiten Bild verhindert die vorgegebene Aktion des a-Elements nicht. Aber sein Parent Node würde nichts mehr davon mitbekommen.

var link1 = document.querySelector('#link1');
link1.onclick = function (evt) {
   evt.preventDefault();
   console.log('Du gehst hier nicht weg!');
}

thelink1.parentNode.onclick = function ( evt ) {
   console.log ('Das habe ich gehört!');
}
var link2 = document.querySelector('#link2');
link2.onclick = function (evt) {
   evt.stopPropagation();
   console.log('Ich mach trotzdem den Abflug!');
}

thelink2.parentNode.onclick = function ( evt ) {
   console.log ('Davon werde ich nie etwas hören!');
}

In den überwiegenden Situationen brauchen wir preventDefault. Man kann aber durchaus beides zusammenbinden:

evt.stopPropagation().preventDefault();