1
00:00:02,390 --> 00:00:05,730
With event propagation, you can do quite interesting things,

2
00:00:05,750 --> 00:00:11,120
specifically you can implement a pattern which is also called event delegation,

3
00:00:11,150 --> 00:00:14,370
let me show you an example. Let's say in events.html,

4
00:00:14,480 --> 00:00:20,210
so in our little demo file here, we have an unordered list here or any kind of list data,

5
00:00:20,210 --> 00:00:24,420
that's where this pattern typically shines, with a couple of list elements in there,

6
00:00:24,470 --> 00:00:25,620
item one and

7
00:00:25,810 --> 00:00:30,260
then we also have more items - two, three, four and five.

8
00:00:30,350 --> 00:00:38,480
Now I'll quickly add some style so that we can have some output there or that we see this at least a bit and

9
00:00:38,480 --> 00:00:47,270
I'll style each list item to simply have a padding of 1rem and to have a border of one pixel solid

10
00:00:47,750 --> 00:00:55,900
and then some other color here and the unordered list will get a list style of none to remove the bullet

11
00:00:55,900 --> 00:00:56,530
points.

12
00:00:56,590 --> 00:01:02,140
So some basic styling you can add to events.css and then this basic list here which I added to

13
00:01:02,140 --> 00:01:03,510
my HTML file.

14
00:01:03,520 --> 00:01:07,350
Now if we reload this, we see this list down there.

15
00:01:07,600 --> 00:01:12,690
Now we want to be able to click on these items and color the clicked item red,

16
00:01:12,790 --> 00:01:14,300
let's say that's our goal here,

17
00:01:14,320 --> 00:01:22,150
if it is red already, we want to remove the color. Well for that, let's go to events.js and now of course

18
00:01:22,150 --> 00:01:24,440
we've got two possible approaches.

19
00:01:24,460 --> 00:01:33,190
One is that we select all list items and we add multiple listeners, so we could get all list items here

20
00:01:33,190 --> 00:01:43,570
with document query selector all, select all li's and then use list items, forEach for example

21
00:01:43,570 --> 00:01:51,160
to go through them or use a for/of loop of course and then on each list item, we can add an event listener,

22
00:01:52,390 --> 00:02:00,190
for click event and then have a function in there where we get the event object and then in here,

23
00:02:00,190 --> 00:02:05,530
we can say event target and then let's a class list because event target is a DOM element,

24
00:02:05,590 --> 00:02:09,540
so we have the class list property available even though my IDE doesn't know it

25
00:02:09,730 --> 00:02:17,010
and then here we simply toggle the highlight class let's say and now we just have to add this highlight

26
00:02:17,020 --> 00:02:21,980
class to events.css, like this and there,

27
00:02:22,000 --> 00:02:30,870
let's say we have a background color of red and a text color of white then. So this is something we can

28
00:02:30,870 --> 00:02:36,580
do, define this highlight class, register multiple click listeners on all the elements

29
00:02:36,660 --> 00:02:41,600
and now if we save and reload, we should be able to click them and toggle our colors here.

30
00:02:41,610 --> 00:02:42,870
Now that is working,

31
00:02:42,870 --> 00:02:46,110
however this approach has a couple of disadvantages.

32
00:02:46,200 --> 00:02:49,710
For one it's pretty cumbersome to add multiple listeners like this,

33
00:02:50,550 --> 00:02:56,730
additionally it can get bad from a performance and memory perspective because we got a lot of event

34
00:02:56,730 --> 00:02:58,140
listeners out there.

35
00:02:58,470 --> 00:03:04,460
So let's have a look at the alternative which uses this delegate pattern, this delegate approach. There

36
00:03:05,070 --> 00:03:11,640
instead of adding multiple listeners on each list item, we take advantage of event propagation, of the

37
00:03:11,640 --> 00:03:19,100
event bubbling up and therefore we get access to the entire list with document query selector ul,

38
00:03:19,110 --> 00:03:22,290
so with the list that holds the list items.

39
00:03:22,290 --> 00:03:29,190
Now we can register an event listener on that list, so I listen to a click event on the entire list because

40
00:03:29,250 --> 00:03:35,580
since events bubble up, we can also listen to a click on the list when we actually clicked on a list

41
00:03:35,610 --> 00:03:38,610
item because that's how Javascript events behave,

42
00:03:38,760 --> 00:03:50,160
most events at least. So here I can now copy this logic here, this function, copy it in here because I

43
00:03:50,160 --> 00:03:54,530
still want to use the event target and toggle highlight

44
00:03:54,720 --> 00:03:57,560
and that's now by the way also the advantage of event target.

45
00:03:57,660 --> 00:04:04,440
Even if my listener is registered on the list, event target will refer to the actual target on which we

46
00:04:04,440 --> 00:04:05,310
clicked,

47
00:04:05,310 --> 00:04:09,060
which in this example is our list item.

48
00:04:09,070 --> 00:04:14,610
So now if I save that and I reload, I got the same behavior as before

49
00:04:14,890 --> 00:04:21,130
but now with only one event listener instead of multiple event listeners because we're taking advantage

50
00:04:21,130 --> 00:04:27,790
of event propagation and then we're adding a listener on the next higher element which in this case

51
00:04:27,790 --> 00:04:31,440
is the list instead of every child element itself,

52
00:04:31,480 --> 00:04:34,100
this is the event delegation pattern.

53
00:04:34,200 --> 00:04:41,220
Now this event delegation pattern can become problematic if we have a more complex structure.

54
00:04:41,440 --> 00:04:45,060
Let's say here for our list items, they are not simple like this,

55
00:04:45,070 --> 00:04:55,920
instead inside of li, we got a h2 tag which wraps our item one text here and then next to that

56
00:04:55,950 --> 00:04:56,470
or below that,

57
00:04:56,470 --> 00:04:59,520
we also got a paragraph with some text.

58
00:04:59,550 --> 00:05:02,300
Now let's say we have a couple of those items here,

59
00:05:03,180 --> 00:05:08,370
so I'll just quickly copy and paste them and change the numbers here so that we can differentiate them

60
00:05:09,730 --> 00:05:11,220
and auto format

61
00:05:11,260 --> 00:05:14,290
and now if we reload, we have a problem, if I click on the title,

62
00:05:14,320 --> 00:05:14,490
yes

63
00:05:14,500 --> 00:05:17,810
now you see this gets the red background, not the entire element.

64
00:05:17,920 --> 00:05:22,660
If I click somewhere else, the entire element might get this or just a paragraph.

65
00:05:22,720 --> 00:05:27,250
So now because we were referring to event target, we have a problem,

66
00:05:27,370 --> 00:05:32,020
we have a problem because event target is the actual DOM element on which we clicked

67
00:05:32,080 --> 00:05:34,270
and that's the lowest possible element,

68
00:05:34,510 --> 00:05:40,300
so that's either our h2 tag or if we clicked outside of h2 and outside of paragraph, it's the

69
00:05:40,300 --> 00:05:45,330
entire list item or it's just a paragraph or whatever else we might have in there,

70
00:05:45,370 --> 00:05:50,680
so just coloring or using event target is not helping us here.

71
00:05:50,710 --> 00:05:56,880
Now we also do have another property available and that is event.currentTarget.

72
00:05:57,160 --> 00:05:59,380
This is different from event target,

73
00:05:59,410 --> 00:06:05,590
let's see if that helps us. If we reload and I click somewhere on the h2 tag,

74
00:06:05,740 --> 00:06:12,940
well event current target is the entire unordered list here because current target, unlike target is

75
00:06:12,940 --> 00:06:18,010
not the actual element on which you clicked but the element on which you added the listener.

76
00:06:18,010 --> 00:06:24,190
So current target here always refers to the list element because that's where we register our listener.

77
00:06:24,280 --> 00:06:27,310
So that can also be useful sometimes but here it isn't,

78
00:06:27,340 --> 00:06:29,960
it's still not the element on which we clicked,

79
00:06:30,040 --> 00:06:34,060
it's still not the list item, it's just a list which also is not what you need.

80
00:06:35,100 --> 00:06:41,820
Well we can use a combination of event target and DOM traversal which I covered earlier in the course,

81
00:06:41,820 --> 00:06:46,080
in the DOM module to get access to the list item.

82
00:06:46,080 --> 00:06:48,150
What do we know about event target?

83
00:06:48,150 --> 00:06:53,430
Well we know it's inside of our list and if we have a look at our list, we see it's definitely somewhere

84
00:06:53,430 --> 00:06:55,260
inside of the list item,

85
00:06:55,260 --> 00:06:55,490
right,

86
00:06:55,500 --> 00:06:58,830
because we have just the list and the list items.

87
00:06:58,830 --> 00:07:01,780
So we know it's inside of our list item,

88
00:07:01,780 --> 00:07:06,870
hence it's either the h2 tag, the paragraph or the list item itself.

89
00:07:06,880 --> 00:07:13,420
Now you learned about a specific method that can help us here and that would be on event target which

90
00:07:13,420 --> 00:07:16,810
is some DOM object inside of our list,

91
00:07:16,810 --> 00:07:25,470
the closest method. Closest exists on all DOM objects and it traverses up in the ancestor tree

92
00:07:25,780 --> 00:07:31,990
and there you can select the closest element with a certain CSS selector, you could select by ID, by

93
00:07:31,990 --> 00:07:33,960
class or just by tag

94
00:07:34,120 --> 00:07:36,770
and in this case I'm looking for the closest li.

95
00:07:36,880 --> 00:07:43,090
The cool thing is closest does include this element on what you call it itself.

96
00:07:43,090 --> 00:07:50,350
So if we clicked on the list item itself, this will give us the list item itself, if we clicked on some

97
00:07:50,400 --> 00:07:53,020
h2 tag inside of the list item,

98
00:07:53,020 --> 00:07:57,020
this will give us the closest li ancestor which is this list item.

99
00:07:57,040 --> 00:08:01,840
So it always gives us the closest list item which is exactly what we need here

100
00:08:02,050 --> 00:08:08,230
and therefore here, we can now call class list toggle on the closest list item

101
00:08:08,230 --> 00:08:15,820
and now this will work because now, no matter where we click, you see I always select the entire list

102
00:08:15,850 --> 00:08:18,220
item and color the entire list item.

103
00:08:18,220 --> 00:08:24,760
So this is now the perfect event delegation pattern because now we delegate our event and we still make

104
00:08:24,760 --> 00:08:30,490
sure we worked with the right element, with a combination of event target and DOM traversal.
