1
00:00:02,270 --> 00:00:05,410
Let's first of all make sure we fully understand what's happening

2
00:00:05,480 --> 00:00:09,870
and for this, I'll again use my buttons however just the first button here which I find with query

3
00:00:09,870 --> 00:00:15,160
selector and then I can add an event listener to it as we did before.

4
00:00:15,220 --> 00:00:22,900
So button add event listener, to a click again and then maybe execute this anonymous function where we

5
00:00:23,260 --> 00:00:28,210
get the event object and where we then console log the event object.

6
00:00:28,210 --> 00:00:35,010
Now I'll not just do it here on the button however, I'll also get access to this div here,

7
00:00:35,040 --> 00:00:42,450
the only div I have on the entire screen, so therefore here I'll get my div with document query selector

8
00:00:42,930 --> 00:00:49,080
for that div tag and also add an event listener on that and it doesn't matter if you registered that

9
00:00:49,080 --> 00:00:52,890
event listener before or after the button event listener.

10
00:00:52,920 --> 00:00:59,490
So here I will also log my event object

11
00:00:59,490 --> 00:01:01,940
and now for us to be able to differentiate them,

12
00:01:01,980 --> 00:01:05,070
here I'll also log clicked div

13
00:01:08,530 --> 00:01:12,750
and then I'll copy that and down there, we can log clicked button.

14
00:01:13,610 --> 00:01:13,860
OK

15
00:01:13,870 --> 00:01:22,030
now with that set up, if I reload and I click on the button here, you see both execute button and then

16
00:01:22,030 --> 00:01:29,140
div. So it executes from inside to outside because as I mentioned, by default all event listeners are

17
00:01:29,140 --> 00:01:34,300
registered in the bubbling phase which means that capturing phase which runs first is totally ignored

18
00:01:34,630 --> 00:01:40,240
but thereafter when the browser checks from inside to outside for that element on which the event occurred,

19
00:01:40,640 --> 00:01:46,000
it first finds that on the element itself, we had a listener, therefore this runs first but then it checks

20
00:01:46,000 --> 00:01:52,030
if there was a listener on the surrounding element, which in this case is the div and there we also had

21
00:01:52,030 --> 00:01:52,540
a listener

22
00:01:52,540 --> 00:01:57,580
so it executes that as well, then the browser by the way also goes onto the body and checks if there we

23
00:01:57,580 --> 00:01:59,450
had a click listener but we don't

24
00:01:59,560 --> 00:02:04,810
so therefore it doesn't execute any code for that because there is no code to execute but it goes

25
00:02:04,810 --> 00:02:10,660
from the element from which the element occurs to all its ancestors and checks for event listeners on

26
00:02:10,660 --> 00:02:11,110
them

27
00:02:11,110 --> 00:02:14,030
and if they are there, it executes them,

28
00:02:14,140 --> 00:02:16,280
this is what the browser does.

29
00:02:16,390 --> 00:02:22,870
Now we could switch to the capturing phase by adding an extra third argument on the event listeners.

30
00:02:22,870 --> 00:02:29,350
So here on the div for example, we could add a third parameter and if we set this to true, the default

31
00:02:29,350 --> 00:02:31,410
is false and therefore doesn't need to be added

32
00:02:31,480 --> 00:02:37,390
but if we set this to true, we're telling the browser this event listener should be part of the capturing

33
00:02:37,390 --> 00:02:38,500
phase.

34
00:02:38,530 --> 00:02:42,610
Now we don't have to switch all event listeners to the capturing phase,

35
00:02:42,700 --> 00:02:48,940
we can just add this one here and now you will see that it will actually run before this button event

36
00:02:48,940 --> 00:02:50,260
listener here runs.

37
00:02:50,260 --> 00:02:55,390
So if I reload now and click this button, you'll see the div was clicked first or the event listener

38
00:02:55,450 --> 00:03:01,510
ran first and then the button, because this listener here triggered in the capturing phase which comes

39
00:03:01,510 --> 00:03:08,380
before the bubbling phase and since we registered this listener for the capturing phase, it executed

40
00:03:08,380 --> 00:03:15,190
its code. So this can be useful if you want to switch the order and you have event listeners on the element

41
00:03:15,190 --> 00:03:21,960
itself but also on some ancestor and for whatever reason, you want to execute the ancestor listener first,

42
00:03:21,970 --> 00:03:27,970
that can be done by passing that extra third argument. Here I'll remove it because I don't want the behavior

43
00:03:27,970 --> 00:03:35,990
here but it is something you could do. Now this entire process of having multiple listeners for the same

44
00:03:35,990 --> 00:03:42,890
event because the event does not just trigger on the element itself but also on ancestors, that's called

45
00:03:42,950 --> 00:03:44,300
propagation,

46
00:03:44,450 --> 00:03:51,560
it means that the event propagates up, it bubbles up or in the capture phase, it kind of goes from outside

47
00:03:51,560 --> 00:03:57,470
to inside but it basically means the event does not just occur on the element itself but also on all

48
00:03:57,470 --> 00:04:00,500
ancestors or at least we can listen on all ancestors,

49
00:04:00,500 --> 00:04:06,160
it occurred on this button but it's listenable on all ancestors because it propagates up,

50
00:04:06,200 --> 00:04:07,100
it bubbles up,

51
00:04:07,100 --> 00:04:09,600
it can be used anywhere above.

52
00:04:09,620 --> 00:04:11,710
Now you can prevent this however.

53
00:04:11,750 --> 00:04:18,050
Let's say we do have an event listener on the div here but we really only want to react to clicks on the

54
00:04:18,050 --> 00:04:21,010
div here, not to clicks on a button in the div,

55
00:04:21,050 --> 00:04:26,600
that could be a requirement you have in an app where you really want to make sure that button clicks don't

56
00:04:26,600 --> 00:04:33,350
trigger the div click listener. To make sure that the click event for the button for example doesn't

57
00:04:33,350 --> 00:04:34,950
propagate anymore,

58
00:04:34,970 --> 00:04:38,360
you can call event.stopPropagation.

59
00:04:38,360 --> 00:04:40,430
That's not the same as prevent default,

60
00:04:40,430 --> 00:04:43,670
prevent default stops the default behavior

61
00:04:43,730 --> 00:04:49,190
the browser might perform upon such an event, for a click event on a button, we have no default behavior

62
00:04:49,370 --> 00:04:51,460
for a click event on a link for example,

63
00:04:51,470 --> 00:04:56,860
we would have one, there the browser would leave the page and go to that links destination.

64
00:04:57,260 --> 00:05:00,420
Stop propagation does nothing with the default behavior,

65
00:05:00,440 --> 00:05:02,660
the default behavior still executes,

66
00:05:02,660 --> 00:05:09,020
so for a form for example, the form would still be submitted but it stops the propagation which means

67
00:05:09,440 --> 00:05:16,040
any other listeners for the same type of event on some ancestor elements will not trigger their event

68
00:05:16,040 --> 00:05:18,190
listeners for this event.

69
00:05:18,200 --> 00:05:19,790
So now you will see that clicked

70
00:05:19,790 --> 00:05:24,620
div will not be printed to the console when we click on a button.

71
00:05:24,650 --> 00:05:29,060
So if I reload and I click on a button, we only see the clicked button event listener,

72
00:05:29,060 --> 00:05:33,880
I have to click somewhere else on the div to trigger that div click listener.

73
00:05:34,460 --> 00:05:37,080
So that's what stop propagation does,

74
00:05:37,100 --> 00:05:40,190
you also have stop immediate propagation,

75
00:05:40,190 --> 00:05:44,270
that is useful if you have multiple event listeners on the same element,

76
00:05:44,360 --> 00:05:50,900
so if we had more event listeners on the button, then after the first event listener, the other button

77
00:05:50,900 --> 00:05:51,490
listeners,

78
00:05:51,560 --> 00:05:57,620
so the other listeners on the same element also wouldn't run anymore. With just stop propagation, all

79
00:05:57,620 --> 00:06:03,080
button event listeners would execute and only ancestor element clicked listeners would not execute.

80
00:06:03,080 --> 00:06:08,600
That's the difference here and just as prevent default, this can be a very useful tool to make sure that

81
00:06:08,600 --> 00:06:11,660
you can handle the events in exactly the way you want.

82
00:06:11,720 --> 00:06:14,040
So you learned about stop propagation,

83
00:06:14,090 --> 00:06:17,330
it's important to understand that not all events propagate.

84
00:06:17,450 --> 00:06:22,850
Again, common sense is a good starting point to find out whether an event propagates or not,

85
00:06:23,000 --> 00:06:28,220
for a click, it makes more sense, when we click something we could also want to listen to a click on a

86
00:06:28,220 --> 00:06:32,400
parent element. For a hovering over something, it makes less sense.

87
00:06:32,510 --> 00:06:39,230
If I add mouse enter here to my button and also

88
00:06:41,830 --> 00:06:45,210
to my div and I reload,

89
00:06:45,360 --> 00:06:47,000
you see now I entered the div,

90
00:06:47,000 --> 00:06:52,020
so yes I'm still printing clicked div but it happens because of me hovering over it,

91
00:06:52,190 --> 00:06:59,320
now I hover over the button and therefore you see indeed, I only trigger clicked button and not the div

92
00:06:59,350 --> 00:07:00,250
as well,

93
00:07:00,250 --> 00:07:07,720
that first output here was from when we reach the div for the first time. So mouse, mouse enter, mouse move events

94
00:07:07,750 --> 00:07:09,420
typically don't propagate,

95
00:07:09,580 --> 00:07:14,900
if you're not sure whether they propagate or not, whether they bubble up, you can always just print the

96
00:07:14,900 --> 00:07:19,090
event object and have a look at it because you will find a bubbles property in there and as you see,

97
00:07:19,090 --> 00:07:20,010
it says false here

98
00:07:20,020 --> 00:07:26,470
which means this does not bubble up and hence you don't have to call stop propagation because it won't

99
00:07:26,470 --> 00:07:28,060
propagate anyways and

100
00:07:28,060 --> 00:07:33,430
there are a couple of events, drag events for example for drag and drop which don't propagate up because

101
00:07:33,430 --> 00:07:37,450
that typically would lead to an undesired behavior.
