-
Notifications
You must be signed in to change notification settings - Fork 17
/
event-handling-objekt.html
350 lines (321 loc) · 24.8 KB
/
event-handling-objekt.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>JavaScript: Arbeiten mit dem Event-Objekt</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="js-doku.css">
<style>
#target-area {
border: 1px solid #aaf;
background-color: #f0f0fa;
cursor: pointer;
}
#target-area p,
#target-area ol,
#target-area li,
#target-area strong {
border: 1px solid #aaf;
list-style-position: inside;
}
#target-area,
#target-area p,
#target-area ol,
#target-area li {
margin: 1rem;
}
#target-area p,
#target-area li {
padding: 0.2rem 0.5rem;
}
#target-output {
text-indent: 0;
list-style-position: inside;
background-color: #f0f0f0;
padding: 0.5em;
}
</style>
</head>
<body>
<div id="nav">
<p>Hier entsteht eine <strong>JavaScript-Dokumentation</strong> von <a href="https://molily.de/">molily</a>. Derzeit ist sie noch lückenhaft, wächst aber nach und nach. Kommentare und Feedback werden gerne per <a href="mailto:[email protected]">E-Mail</a> entgegen genommen.</p>
<p class="contents-link"><a href="./">Zum Inhaltsverzeichnis</a></p>
</div>
<h1>JavaScript: Arbeiten mit dem Event-Objekt</h1>
<div class="section" id="event-objekt">
<h2>Zugriff auf das Event-Objekt</h2>
<p>Durch das <a href="event-handling-grundlagen.html#traditionelles-event-handling">Registrieren von Event-Handlern</a> wird die angegebene Funktion immer dann ausgeführt, wenn das jeweilige Ereignis beim jeweiligen Element eintritt. In dieser Handler-Funktion ist es meistens nötig, auf die näheren Umstände des Ereignisses zu reagieren. Beispielsweise sind bei einem Mausklick die Koordinaten des Mauszeigers interessant oder bei einem Tastendruck die gedrückte Taste.</p>
<p>All diese Informationen sind im <dfn>Event-Objekt</dfn> gespeichert. Dieses Objekt repräsentiert das individuelle Ereignis, das der Handler gerade verarbeitet. Es bietet zahlreiche Eigenschaften mit Informationen zum Ereignis und einige Methoden, um das Verhalten des Ereignisses zu steuern. Wenn Sie bei der Ereignis-Verarbeitung diese Daten benötigen, ist der Zugriff auf das Event-Objekt die erste Aufgabe in der Handler-Funktion.</p>
<p>In neueren Browsern gestaltet sich dieser Zugriff einfach: Das Event-Objekt wird der Handler-Funktion automatisch als erster Parameter übergeben. Sie muss dieses nur noch entgegen nehmen. Der Parametername ist dabei frei wählbar. Üblicherweise wird der <a href="syntax.html#bezeichner">Bezeichner</a> <code>event</code> verwendet.</p>
<pre>
function handlerfunktion(event) {
window.alert("Es ist ein Ereignis vom Typ " + event.type + " passiert.");
}
</pre>
<p>Diesen Zugriff auf das Event-Objekt unterstützen alle relevanten Browser. Lediglich ältere Internet Explorer vor Version 9 unterstützen diese Technik nicht. Für diese Browserversionen ist eine Sonderlösung notwendig. Diese Internet-Explorer-Versionen übergeben das Event-Objekt nicht als Parameter an die Handler-Funktion, sondern stellen es unter dem globalen Objekt <code>window.event</code> zur Verfügung. Auch wenn es den Anschein hat, so ist das Event-Objekt dort nicht dauerhaft gespeichert. <code>window.event</code> verweist auf das Event-Objekt des Ereignisses, das gerade verarbeitet wird.</p>
<p>Wenn Sie die besagten älteren Browser unterstützen wollen oder müssen, ist eine Vereinheitlichung notwendig. Diese ist recht einfach: Wir prüfen, ob der Funktion ein Parameter übergeben wurde und somit die lokale Variable <code>event</code> einen Wert hat. Falls dies zutrifft, können wir den Parameter direkt verwenden. Andernfalls speichern wir in der Variable <code>event</code> einen Verweis auf <code>window.event</code>.</p>
<pre>function handlerfunktion(event) {
// Vereinheitlichung:
if (!event) {
// Korrektur für den Internet Explorer < 9
event = window.event;
}
// Browserübergreifender Zugriff:
window.alert("Es ist ein Ereignis vom Typ " + event.type + " passiert.");
}</pre>
<p>Nach der Vereinheitlichung steht das Event-Objekt browserübergreifend in einer Variable zu Verfügung.</p>
<p>Mit <code>if (!event)</code> wird geprüft, ob der Wert der Variablen bei einer Umwandlung in den Typ Boolean den Wert <code>false</code> ergibt. Eine solche Abfrage ist hier möglich, weil <code>event</code> entweder ein Objekt enthält oder, falls der Handler-Funktion nichts übergeben wird, mit dem Wert <code>undefined</code> initialisiert wird. Dieser ergibt in Boolean umgewandelt <code>false</code>.</p>
<p>Eine gleichwertige Kurzschreibweise nutzt den Oder-Operator <code>||</code>. Intern funktioniert dies wie die besagte <code>if</code>-Anweisung. Das Ziel ist ebenfalls vereinheitlichter Zugriff auf das Event-Objekt über die Variable <code>event</code>.</p>
<pre>
function handlerfunktion(event) {
event = event || window.event;
window.alert("Es ist ein Ereignis vom Typ " + event.type + " passiert.");
}
</pre>
<p>Der Oder-Operator <code>||</code> überprüft, ob der Wert links <code>true</code> ergibt, also der Funktionsparameter <code>event</code> bei der Umwandlung in den Typ Boolean den Wert <code>true</code> ergibt. Wenn dies der Fall ist, ergibt der Ausdruck den Wert von <code>event</code> und es wird <code>event = event</code> ausgeführt. Dabei passiert nichts, die Variable wird mit ihrem eigenen Wert überschrieben.</p>
<p>Interessant ist der andere Fall, wenn kein Parameter übergeben wurde. Dann ist das Ergebnis des Ausdrucks der Wert rechts vom <code>||</code>-Operator. Dann wird <code>event = window.event</code> ausgeführt. Durch die Oder-Verzweigung ist das Event-Objekt in jedem Fall in der Variable <code>event</code> gespeichert.</p>
<p>Beide der Schreibweisen erfüllen dieselbe Funktion. Die erste ist klarer und leicht verständlich, die zweite ist kürzer, erfordert jedoch das Verständnis des <code>||</code>-Operators.</p>
</div>
<div class="section" id="standardaktion">
<h2>Unterdrücken der Standardaktion des Ereignisses</h2>
<p>Viele Ereignisse im Dokument haben eigentümliche Auswirkungen. Ein Beispiel: Wenn der Anwender auf einen Link klickt, so tritt ein <code>click</code>-Ereignis ein. Das bringt den Browser dazu, dem Link zu folgen und zum angegebenen Linkziel (der URL) zu navigieren. Das bedeutet, dass der Browser die Ressource vom Webserver herunterlädt und anzeigt. Ein weiteres Beispiel: Wenn der Anwender den Absende-Buttons eines Formulars aktiviert, so tritt ein <code>submit</code>-Ereignis an. Das bringt den Browser dazu, das Formular an den Webserver zu übertragen.</p>
<p>Der Browser behandelt also standardmäßig gewisse Ereignisse und führt die sogenannte <strong>Standardaktion</strong> (englisch <em>default action</em>) aus, ohne dass der Seitenautor eine entsprechende JavaScript-Logik definiert hat.</p>
<p>Beim Unobtrusive JavaScript versieht man z.B. bestehende Links mit einer JavaScript-Logik. Die ursprüngliche Funktionalität des Links will man dann zumeist unterdrücken: Beim Klick auf den Link soll nur das Script ausgeführt werden, nicht mehr das Linkziel angesprungen werden.</p>
<p>Angenommen, wir haben folgenden Link:</p>
<pre><a href="bilder/bild.jpg" id="vollbildlink">Bild in Originalgröße ansehen</a></pre>
<p>Mit JavaScript soll diesem Link nun ein <code>click</code>-Handler hinzugefügt werden, der das verlinkte Bild im aktuellen Dokument einblendet, anstatt das Bild einzeln anzuzeigen. Wie dieses Einblenden umgesetzt wird, interessiert uns an dieser Stelle nicht, sondern nur das Unterdrücken der Standardaktion.</p>
<p>Im traditionellen Event-Handling wird die Standardaktion unterdrückt, indem die Handler-Funktion <code>false</code> als Ergebnis zurückgibt. Am Ende der Funktion wird daher die Anweisung <code>return false;</code> notiert.</p>
<pre>
function zeigeVollbild() {
// Blende das Bild ein, auf das der Link zeigt.
// … (an dieser Stelle uninteressant) …
// Unterdrücke schließlich die Standardaktion:
return false;
}
// Registriere Event-Handler
document.getElementById("vollbildlink").onclick = zeigeVollbild;
</pre>
<p>Beachten Sie, dass mit der <code>return</code>-Anweisung die Funktion beendet wird. Code, der auf diese Anweisung folgt, wird nicht ausgeführt. Es sei denn, die <code>return</code>-Anweisung ist z.B. durch eine <code>if</code>-Anweisung gekapselt und wird nicht in jedem Fall ausgeführt.</p>
<p>Wenn Sie kein <code>return false</code> notieren, führt der Browser automatisch die Standardaktion aus. Sie müssen ihn also nicht mit einem <code>return true</code> oder auf andere Art dazu bringen – sie können die Standardaktion lediglich verhindern.</p>
<p>Neben <code>return false</code> gibt es modernere Techniken, um die Standardaktion zu verhindern. Der DOM-Standard, auf den wir später noch zu sprechen kommen, bietet eine Methode namens <code>preventDefault</code> beim Event-Objekt, mit der sich die Standardaktion unterdrücken lässt. Das obige Beispiel könnte auch folgendermaßen aussehen:</p>
<pre>
function zeigeVollbild(event) {
// Browserübergreifender Zugriff auf das Event-Objekt
if (!event) event = window.event;
// Unterdrücke die Standardaktion durch Aufruf von preventDefault:
event.preventDefault();
// Fehler im Internet Explorer < 9!
// Blende das Bild ein, auf das der Link zeigt.
// … (an dieser Stelle uninteressant) …
};</pre>
<p>Der Vorteil von <code>preventDefault</code> ist, dass es im Gegensatz zu <code>return false</code> auch mitten in der Handler-Funktion aufgerufen werden kann, ohne sie gleich zu beenden. Das Beispiel demonstriert dies.</p>
<p>Der Nachteil ist, dass der Internet Explorer diese standardisierte Methode erst ab Version 9 kennt. Er hat jedoch eine gleichwertige Boolean-Eigenschaft des Event-Objekts namens <code>returnValue</code>. Weist man dieser den Wert <code>false</code> zu, so wird die Standardaktion unterbunden. Um auch ältere Internet Epxlorer zu unterstützen, kann die Existenz der <code>preventDefault</code>-Methode abgefragt werden. Existiert diese nicht, wird alternativ die Eigenschaft <code>returnValue</code> gesetzt:</p>
<pre>function zeigeVollbild(event) {
if (!event) event = window.event;
// Existiert die Methode preventDefault?
if (event.preventDefault) {
// Dann rufe sie auf.
// DOM-Standard
event.preventDefault();
} else {
// Andernfalls setze returnValue.
// Microsoft-Alternative für Internet Explorer < 9
event.returnValue = false;
}
// Blende das Bild ein, auf das der Link zeigt.
// … (an dieser Stelle uninteressant) …
};</pre>
<p>Diese Vorgehensweise sei hier der Vollständigkeit halber erwähnt. Wenn sie Ihnen unnötig kompliziert erscheint, so können Sie sich mit dem herkömmlichen <code>return false</code> zufrieden geben, das die Aufgabe hinreichend erfüllt. Sie müssen allerdings beachten, dass mit <code>return false</code> die Handler-Funktion beendet wird.</p>
</div>
<div class="section" id="bubbling">
<h2>Der Event-Fluss: Bubbling</h2>
<p>Bisher haben wir erfahren, dass Ereignisse bei bestimmten Elementen passieren. Dort können wir sie überwachen, indem wir Handler registrieren. Tritt das Ereignis bei diesem Element ein, wird die Handler-Funktion ausgelöst.</p>
<p>Die Wirklichkeit ist etwas komplizierter. Die Verarbeitung eines Ereignisses verläuft in <strong>drei Phasen</strong>, die nacheinander durchlaufen werden. Davon lernen wir nun eine zweite kennen. Die dritte ist weniger wichtig. Sie wird unter <a href="event-handling-effizient.html#capturing">Capturing</a> beschrieben.</p>
<p>Ein Ereignis passiert bei einem Element, dem sogenannten <strong>Zielelement</strong> (englisch <em>target element</em>), und löst dort alle Handler aus, die für das entsprechende Ereignis registriert wurden. Diese bereits bekannte Phase nennt sich entsprechend <strong>Ziel-Phase</strong>.</p>
<p>Mit dieser Phase ist die Ereignis-Verarbeitung nicht zuende, denn anschließend steigt das Ereignis im DOM-Elementbaum auf: Zum Eltern-Element, dann zu dessen Eltern-Element und so weiter. Dieser Vorgang nennt sich <strong>Bubbling</strong>. Das Wort ist abgleitet von <em lang="en">bubble</em>, Englisch für Blase. Wie Luftblasen im Wasser <strong>steigen Events auf</strong>.</p>
<p>Beim Aufsteigen werden die entsprechenden Handler auch beim Eltern-Element des Zielelements ausgeführt. Dann bei dessen Eltern-Element und so weiter, bis das Ereignis schließlich den obersten <code>document</code>-Knoten erreicht hat.
Das Ereignis bewegt sich also nach oben im Elementbaum, durchläuft alle Vorfahrenelemente des Zielelements und löst auf diesem Weg alle entsprechenden Handler aus. Dieser Vorgang wird entsprechend <strong>Bubbling-Phase</strong> genannt.</p>
<p>Das mag zunächst sehr abstrakt klingen, aber der Sinn und die Funktionsweise des Bubblings sind schnell erfasst. Nehmen wir folgenden HTML-Code:</p>
<pre>
<p id="absatz">
Dies ist ein Beispiel-Element mit einem
<strong id="wichtig">
wichtigen Text
</strong>.
</p>
</pre>
<p>Nehmen wir ferner an, dass das <code>p</code>-Element <a href="#traditionelles-event-handling">auf traditionelle Weise</a> einen <code>click</code>-Handler bekommt:</p>
<pre>
function clickHandler() {
window.alert('Der Absatz wurde geklickt!');
}
document.getElementById('absatz').onclick = clickHandler;
</pre>
<p>Das <code>p</code>-Element wird vom Browser als rechteckige Box dargestellt. Bei einem Klick irgendwo in diese Box soll die Handler-Funktion ausgeführt werden.</p>
<p>Wenn man auf das Wort »Beispiel-Element« klickt, ist das <code>p</code>-Element das Zielelement des Ereignisses. Wenn man hingegen auf »wichtigen Text« klickt, so ist das <code>strong</code>-Element das Zielelement des Ereignisses, nicht das p-Element! Denn dieser Text liegt zuvorderst im <code>strong</code>-Element und nur indirekt im <code>p</code>-Element. Aus Sicht des DOM-Baumes ist der Text ein Textknoten, der ein Kindknoten des <code>strong</code>-Elementknotens ist.</p>
<p>Nichtsdestoweniger erwartet man, dass ein Klick auf die Box des <code>strong</code>-Elements ebenfalls den <code>click</code>-Handler beim <code>p</code>-Element auslöst. Und dies ist auch der Fall – dafür sorgt das <strong>Bubbling</strong>! Das Ereignis, das ursprünglich beim <code>strong</code>-Element passiert ist, steigt nämlich auf, sodass der Handler des <code>p</code>-Elements ausgeführt wird.</p>
<p>Das Bubbling ist also meist erwünscht, damit bei einem Element Ereignisse überwacht werden können, die ursprünglich bei Kindelementen passieren. Wenn Sie aber nicht damit rechnen, dass Ereignisse aufsteigen, so kann das Bubbling zu einiger Verwirrung führen und Sie werden sich wundern, woher plötzlich gewisse Ereignisse stammen.</p>
<p>Nicht alle Ereignisse steigen auf, denn bei manchen Ereignissen wäre es kontraproduktiv, wenn sie zentrale Handler auslösen würden.</p>
</div>
<div class="section" id="currenttarget-target">
<h2>Verarbeitendes Element und Zielelement</h2>
<p>Infolge des Bubblings kann sich das Zielelement, bei dem das Ereignis ursprünglich passiert ist, von dem verarbeitenden Element unterscheiden, dessen Handler aufgerufen wird. Letzteres Element liegt dann im DOM-Elementbaum oberhalb des Zielelements.</p>
<p>In vielen Fällen will man in der Handler-Funktion auf beide beteiligten Elemente zugreifen, sofern sie sich unterscheiden.</p>
<p>Beginnen wir mit dem Zugriff auf das <strong>verarbeitende Element</strong>: Das Element kann in der Handler-Funktion über das Schlüsselwort <code>this</code> angesprochen werden. Die Handler-Funktion wird nämlich im Kontext dieses Elementobjekts ausgeführt.</p>
<p>Das obige Beispiel wird wieder aufgegriffen:</p>
<pre>
<p id="absatz">
Dies ist ein Beispiel-Element mit einem
<strong id="wichtig">
wichtigen Text
</strong>.
</p>
</pre>
<p>Dem Absatz wird wieder ein <code>click</code>-Handler zugewiesen:</p>
<pre>
function clickHandler() {
window.alert("Element vom Typ " + this.nodeName + " wurde geklickt!");
}
document.getElementById("absatz").onclick = clickHandler;
</pre>
<p>Innerhalb der Handler-Funktion können wir über <code>this</code> auf das <code>p</code>-Element zugreifen. Im Beispiel wird auf dessen Eigenschaft <code>nodeName</code> ausgegeben, welche den Elementnamen <code>P</code> enthält.</p>
<p>Der DOM-Standard sieht eine andere Zugriffsweise vor: Das Event-Objekt hat eine Eigenschaft namens <code>currentTarget</code>, die das verarbeitende Element enthält. So wird die Eigenschaft genutzt:</p>
<pre>
function clickHandler(event) {
window.alert("Element vom Typ " + event.currentTarget.nodeName + " wurde geklickt!");
}
</pre>
<p>Der Internet Explorer kennt Eigenschaft <code>currentTarget</code> erst ab Version 9. Das besagte <code>this</code> ist in älteren Internet-Explorer-Versionen die einzige Möglichkeit, auf das fragliche Element zuzugreifen.</p>
<p>Für den Zugriff auf das <strong>Zielelement</strong> besitzt das Event-Objekt die Eigenschaft <code>target</code>. Diese kennen alle modernen Browser.</p>
Der Internet Explorer unterstützt die Eigenschaft <code>target</code> ab Version 9. Ältere Versionen kennen eine gleichwertige Eigenschaft namens <code>srcElement</code>. Mithilfe einer Fähigkeitenweiche können Sie browserübergreifend das Zielelement ansprechen. Wir kennen dieses Vorgehensweise bereits vom Zugriff auf das Event-Objekt.</p>
<pre>
function clickHandler(event) {
if (!event) event = window.event;
// Zugriff auf das Zielelement
if (event.target) {
// W3C-DOM-Standard
var target = event.target;
} else {
// Microsoft-Alternative für Internet Explorer < 9
var target = event.srcElement;
}
window.alert(
'Das Ereignis passierte ursprünglich beim Element ' + target.nodeName +
' und wird vom Element ' + this.nodeName + ' verarbeitet.');
);
}
</pre>
<p>Falls die Eigenschaft <code>target</code> des Event-Objekts gefüllt ist, speichern wir deren Wert in der lokalen Variable <code>target</code>. Andernfalls, das betrifft den Internet Explorer, wird die Eigenschaft <code>srcElement</code> verwendet.</p>
<p>Wie beim Zugriff auf das Event-Objekt erlaubt der <code>||</code>-Operator eine Kurzschreibweise. So kommen wir zu einem Schema, dem viele Handler-Funktionen entsprechen:</p>
<pre>
function clickHandler(event) {
// Vereinheitlichung von Event-Objekt und Zielelement
event = event || window.event;
var target = event.target || event.srcElement;
// Nutzlast
window.alert(
'Das Ereignis passierte ursprünglich beim Element ' + target.nodeName +
' und wird vom Element ' + this.nodeName + ' verarbeitet.');
);
}
</pre>
<div class="section" id="currenttarget-target-beispiel">
<h3>Interaktives Beispiel</h3>
<p>Das folgende Beispiel ist ein <code>div</code>-Element, an dem ein <code>mouseover</code>-Handler registriert wurde. Darin sind verschiedene Elemente verschachtelt. Bewegen Sie die Maus über deren Boxen, so werden <code>mouseover</code>-Ereignisse an diesen ausgelöst. Sie steigen im DOM-Baum auf und werden beim gemeinsamen <code>div</code>-Vorfahrenelement verarbeitet.</p>
<p>Unter dem interaktiven Bereich werden das Zielelement und das verarbeitende Element ausgegeben. Das verarbeite Element ist immer dasselbe, nämlich das <code>div</code>-Element.</p>
<div id="target-area">
<p>Ein einfacher Textabsatz ohne weiteres.</p>
<ol>
<li>Listenelement mit <strong>wichtigem Text</strong>.</li>
<li>Listenelement mit <em>hervorgehobenem</em> Text.</li>
</ol>
</div>
<p id="target-output">Hier erfolgt die Ausgabe.</p>
<script>
(function () {
var targetArea = document.getElementById('target-area');
var output = document.getElementById('target-output');
targetArea.onmouseover = function (event) {
event = event || window.event;
var target = event.target || event.srcElement;
output.innerHTML =
'Das <code>mouseover</code>-Ereignis passierte ursprünglich beim Element ' +
'<strong><code>' + target.nodeName + '</code></strong> und wird vom Element ' +
'<strong><code>' + this.nodeName + '</code></strong> verarbeitet.';
};
})();
</script>
<p>Der JavaScript-Quellcode dieses Beispiels sieht so aus:</p>
<pre>
var targetArea = document.getElementById('target-area');
var output = document.getElementById('target-output');
targetArea.onmouseover = function (event) {
event = event || window.event;
var target = event.target || event.srcElement;
output.innerHTML =
'Das <code>mouseover</code>-Ereignis passierte ursprünglich beim Element ' +
'<strong><code>' + target.nodeName + '</code></strong> und wird vom Element ' +
'<strong><code>' + this.nodeName + '</code></strong> verarbeitet.';
};
</pre>
<p>Der Code geht davon aus, dass zwei Elemente mit den IDs <code>target-area</code> und <code>target-output</code> definiert sind und das Script später im Dokument notiert ist, sodass es Zugriff auf die Elemente hat.</p>
</div>
</div>
<div class="section" id="bubbling-verhindern">
<h2>Kontrolle über den Event-Fluss: Bubbling verhindern</h2>
<p>Es gibt Fälle, in denen das Bubbling nicht gewünscht ist. Beispielsweise wenn zwei verschachtelte Elemente dasselbe Ereignis überwachen, aber nur der Handler des inneren Elements aktiv werden soll. Sie können deshalb das weitere Aufsteigen des Ereignisses im Elementbaum verhindern.</p>
<p>Folgendes bekannte Beispiel mit verschachtelten Elementen soll dies illustrieren:</p>
<pre>
<p id="absatz">
Dies ist ein Beispiel-Element mit einem
<strong id="wichtig">
wichtigen Text
</strong>.
</p>
</pre>
<p>Sowohl beim <code>strong</code>- als auch beim <code>p</code>-Element wird ein <code>click</code>-Handler registriert:</p>
<pre>
function absatzKlick() {
window.alert('Klick auf das p-Element');
}
document.getElementById('absatz').onclick = absatzKlick;
function wichtigKlick() {
window.alert('Klick auf das strong-Element');
}
document.getElementById('wichtig').onclick = wichtigKlick;
</pre>
<p>Bei einem Klick auf die Fläche des <code>strong</code>-Elements (»wichtigen Text«) werden beide Handler-Funktionen ausgeführt, denn das Ereignis steigt vom <code>strong</code>-Element zum <code>p</code>-Element auf.</p>
<p>Dieses Aufsteigen können Sie in der Handler-Funktion <code>wichtigKlick</code> verhindern. Der DOM-Standard definiert dafür die Methode <code>stopPropagation</code> (englisch für stoppe die Verbreitung des Ereignisses) beim Event-Objekt. Ein Aufruf dieser Methode unterbricht den Event-Fluss und verhindert damit das weitere Aufsteigen.</p>
<p>Der Internet Explorer kennt die Methode <code>stopPropagation</code> erst ab Version 9. Ältere Versionen verfügen über eine gleichwertige Boolean-Eigenschaft beim Event-Objekt. Diese trägt den Namen <code>cancelBubble</code> (englisch für breche das Aufsteigen ab). Weisen Sie dieser Eigenschaft den Wert <code>true</code> zu, um das Aufsteigen des Ereignisses abzubrechen.</p>
<p>Wieder einmal nutzen wir eine Fähigkeitenerkennung, die die Verfügbarkeit der standardisierten Methode <code>stopPropagation</code> prüft und im Fehlerfalle auf die Microsoft-Alternative <code>cancelBubble</code> zurückfällt.</p>
<p>Die Handler-Funktion <code>wichtigKlick</code> sieht dann so aus:</p>
<pre>
function wichtigKlick(eventObekt) {
if (!event) event = window.event;
// Stoppe das Aufsteigen des Ereignisses
if (event.stopPropagation) {
// W3C-DOM-Standard
event.stopPropagation();
} else {
// Microsoft-Alternative für Internet Explorer < 9
event.cancelBubble = true;
}
window.alert('Das Aufsteigen des Ereignisses wird unterbunden!');
}
</pre>
<p>Damit können verschachtelte Elemente denselben Ereignistyp überwachen, im Beispiel <code>click</code>. Obwohl das eine Element in dem anderen enthalten ist und üblicherweise in dessen Grenzen dargestellt wird, übernimmt es die Ereignis-Verarbeitung selbstständig. Der Handler des äußeren Elements, im Beispiel <code>absatzKlick</code>, wird nur bei Klicks ausgeführt, die auf seine Fläche zielen, ausgenommen die Fläche des inneren Elements.</p>
</div>
<div class="sequence-navigation">
<p class="next"><a href="event-handling-fortgeschritten.html" rel="next">Fortgeschrittene Ereignis-Verarbeitung</a></p>
<p class="prev"><a href="event-handling-grundlagen.html" rel="prev">Grundlagen der Ereignis-Verarbeitung</a></p>
</div>
<div id="footer">
<p><strong>JavaScript-Dokumentation</strong> · <a href="./">Zum Inhaltsverzeichnis</a></p>
<p>Autor: <a href="https://molily.de/">molily</a> · Kontakt: <a href="mailto:[email protected]">[email protected]</a></p>
<p>Lizenz: <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/de/">Creative Commons Namensnennung - Weitergabe unter gleichen Bedingungen 3.0</a></p>
<p><a href="https://github.com/molily/javascript-einfuehrung">JavaScript-Einführung auf Github</a></p>
<p>Kostenloses Online-Buch und E-Book:<br><a href="https://testing-angular.com" lang="en" hreflang="en">Testing Angular – A Guide to Robust Angular Applications</a> (englisch)</p>
</div>
<script src="js-doku.js"></script>
</body>
</html>