Skip to content

Commit 08d5893

Browse files
committed
Merge in @bentonam's event delegation article changes.
2 parents 460195c + 22430d4 commit 08d5893

File tree

1 file changed

+81
-42
lines changed

1 file changed

+81
-42
lines changed

page/events/event-delegation.md

Lines changed: 81 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,93 @@
11
---
2-
title : Increasing Performance with Event Delegation
3-
level: beginner
2+
title : Understanding Event Delegation
3+
attribution: jQuery Fundamentals
44
---
5-
You'll frequently use jQuery to add new elements to the page, and when you do,
6-
you may need to bind events to those new elements — events you already bound to
7-
similar elements that were on the page originally. Instead of repeating your
8-
event binding every time you add elements to the page, you can use event
9-
delegation. With event delegation, you bind your event to a container element,
10-
and then when the event occurs, you look to see which contained element it
11-
occurred on. If this sounds complicated, luckily jQuery makes it easy with its
12-
`$.fn.live` and `$.fn.delegate` methods.
13-
14-
While most people discover event delegation while dealing with elements added
15-
to the page later, it has some performance benefits even if you never add more
16-
elements to the page. The time required to bind event handlers to hundreds of
17-
individual elements is non-trivial; if you have a large set of elements, you
18-
should consider delegating related events to a container element.
19-
20-
<div class="note" markdown="1">
21-
### Note
22-
23-
The `$.fn.live` method was introduced in jQuery 1.3, and at that time only
24-
certain event types were supported. As of jQuery 1.4.2, the `$.fn.delegate`
25-
method is available, and is the preferred method.
26-
</div>
27-
28-
```
29-
// Event delegation using `$.fn.delegate`
30-
$('#myUnorderedList').delegate('li', 'click', function(e) {
31-
var $myListItem = $(this);
32-
// ...
5+
6+
Say you have to add new line items to your page, given the following HTML:
7+
```
8+
<html>
9+
<body>
10+
<div id="container">
11+
<ul id="list">
12+
<li>
13+
<a href="#">Item #1</a>
14+
</li>
15+
<li>
16+
<a href="http://somedomain.com">Item #2</a>
17+
</li>
18+
<li>
19+
<a href="#">Item #3</a>
20+
</li>
21+
<li>...</li>
22+
<li>
23+
<a href="http://someotherdomain.com">Item #100</a>
24+
</li>
25+
</ul>
26+
</div>
27+
</body>
28+
</html>
29+
```
30+
31+
We need to attach the same event handler to multiple elements. In this example we want to attach an event that will the log the text of the anchor tag to the console whenever it is clicked.
32+
33+
We can attach a direct bind click event to each `<li>` using the `.on()` method, that will alert the text inside of it by doing the following:
34+
```
35+
// attach a directly bound event
36+
$('#list a').on('click', function(event) {
37+
event.preventDefault();
38+
console.log( $(this).text() );
3339
});
3440
```
3541

42+
While this works perfectly fine, there are drawbacks. Consider this:
43+
```
44+
// add a new element on to our existing list
45+
$('#list').append('<li><a href="http://newsite.com">Item #101</a></li>');
3646
```
37-
// Event delegation using `$.fn.live`
38-
$('#myUnorderedList li').live('click', function(e) {
39-
var $myListItem = $(this);
40-
// ...
47+
If we were to click our newly added item, nothing would happen. This is because of the directly bound event that we attached previously. Direct events are only attached to elements at the time we called the `.on()` method for our existing collection of `<a>`'s, that is only the `<a>`'s that were found when we call `$('#list a')`
48+
49+
## Event Propagation
50+
Understanding how events propagate is an important factor in being able to leverage Event Delegation. Any time an anchor tags is clicked, a *click* event is fired for the:
51+
52+
* `<a>`
53+
* `<li>`
54+
* `<ul>`
55+
* `<div>`
56+
* `<body>`
57+
* `<html>`
58+
* *document* root
59+
60+
Anytime one of these links is clicked you can think of it as if you were clicking the entire document body. This is called *event bubbling* or *event propagation*.
61+
62+
Since we know how events bubble we can created a delegated event that listens for a specific event to happen on our element
63+
```
64+
// attach a delegated event
65+
$('#list').on('click', 'a', function(event){
66+
event.preventDefault();
67+
console.log( $(this).text() );
4168
});
4269
```
70+
Notice for the second parameter to the `.on()` method we are telling it which selector to listen for. Now when a *click* event is triggered on our `<ul>`, our delegated event will check to see if the triggering element matches our selector (`'a'`). If it does, our anonymous function will execute. We have now attached a single *click* event listener to our `<ul>` instead of an unknown number of directly bound events on our `<a>`'s.
4371

44-
### Unbinding Delegated Events
72+
Now lets say that whenever a link is clicked we want to check and see if the `href` attribute starts with "http" and if it does we want to set the `target` attribute to `_blank`.
73+
```
74+
// attach a delegated event
75+
$('#list').on('click', 'a', function(event){
76+
var $elem = $(this);
77+
if( $elem.is('[href^=http]') ){
78+
$elem.attr('target', '_blank');
79+
}
80+
});
81+
```
82+
This simply passes the `.is()` method a selector to see if the element's `href` attributes starts with "http". Also we have removed the `event.preventDefault();` statement, this is because we want the default action to happen (which is to following the `href`)
4583

46-
If you need to remove delegated events, you can't simply unbind them. Instead,
47-
use `$.fn.undelegate` for events connected with `$.fn.delegate`, and `$.fn.die`
48-
for events connected with `$.fn.live`. As with bind, you can optionally pass
49-
in the name of the bound function.
84+
We can actually take this a step further and make our code simpiler and more concise by allowing the selector argument to `.on()` do our logic for us.
5085
```
51-
// Unbinding delegated events
52-
$('#myUnorderedList').undelegate('li', 'click');
53-
$('#myUnorderedList li').die('click');
86+
// attach a delegated event with a more refined selector
87+
$('#list').on('click', 'a[href^=http]', function(event){
88+
$(this).attr('target', '_blank');
89+
});
5490
```
91+
92+
##Summary
93+
Event delegation refers to the process of using event bubbling to handle events at a higher level in the DOM than the element on which the event originated. It allows us to attach a single event listener for elements that exist now or in the future.

0 commit comments

Comments
 (0)