You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We're all familiar with the basic events — click, mouseover, focus, blur,
12
-
submit, etc. — that we can latch on to as a user interacts with the browser.
13
-
Custom events open up a whole new world of event-driven programming. In this
14
-
chapter, we'll use jQuery's custom events system to make a simple Twitter
15
-
search application.
16
-
17
-
It can be difficult at first to understand why you'd want to use custom events,
18
-
when the built-in events seem to suit your needs just fine. It turns out that
19
-
custom events offer a whole new way of thinking about event-driven JavaScript.
20
-
Instead of focusing on the element that triggers an action, custom events put
21
-
the spotlight on the element being acted upon. This brings a bevy of benefits,
22
-
including:
23
-
24
-
- Behaviors of the target element can easily be triggered by different elements using the same code.
25
-
- Behaviors can be triggered across multiple, similar, target elements at once.
26
-
- Behaviors are more clearly associated with the target element in code, making code easier to read and maintain.
27
-
28
-
Why should you care? An example is probably the best way to explain. Suppose
29
-
you have a lightbulb in a room in a house. The lightbulb is currently turned
30
-
on, and it's controlled by two three-way switches and a clapper:
11
+
We're all familiar with the basic events — click, mouseover, focus, blur, submit, etc. — that we can latch on to as a user interacts with the browser. Custom events open up a whole new world of event-driven programming. In this chapter, we'll use jQuery's custom events system to make a simple Twitter search application.
12
+
13
+
It can be difficult at first to understand why you'd want to use custom events, when the built-in events seem to suit your needs just fine. It turns out that custom events offer a whole new way of thinking about event-driven JavaScript. Instead of focusing on the element that triggers an action, custom events put the spotlight on the element being acted upon. This brings a bevy of benefits, including:
14
+
15
+
* Behaviors of the target element can easily be triggered by different elements using the same code.
16
+
* Behaviors can be triggered across multiple, similar, target elements at once.
17
+
* Behaviors are more clearly associated with the target element in code, making code easier to read and maintain.
18
+
19
+
Why should you care? An example is probably the best way to explain. Suppose you have a lightbulb in a room in a house. The lightbulb is currently turned on, and it's controlled by two three-way switches and a clapper:
31
20
32
21
```
33
22
<div class="room" id="kitchen">
@@ -38,9 +27,7 @@ on, and it's controlled by two three-way switches and a clapper:
38
27
</div>
39
28
```
40
29
41
-
Triggering the clapper or either of the switches will change the state of the
42
-
lightbulb. The switches and the clapper don't care what state the lightbulb is
43
-
in; they just want to change the state.
30
+
Triggering the clapper or either of the switches will change the state of the lightbulb. The switches and the clapper don't care what state the lightbulb is in; they just want to change the state.
44
31
45
32
Without custom events, you might write some code like this:
46
33
@@ -92,11 +79,7 @@ Let's make our example a little more interesting. We'll add another room to our
92
79
<div id="master_switch"></div>
93
80
```
94
81
95
-
If there are any lights on in the house, we want the master switch to turn all
96
-
the lights off; otherwise, we want it to turn all lights on. To accomplish
97
-
this, we'll add two more custom events to the lightbulbs: `turnOn` and
98
-
`turnOff`. We'll make use of them in the `changeState` custom event, and use
99
-
some logic to decide which one the master switch should trigger:
82
+
If there are any lights on in the house, we want the master switch to turn all the lights off; otherwise, we want it to turn all lights on. To accomplish this, we'll add two more custom events to the lightbulbs: `turnOn` and `turnOff`. We'll make use of them in the `changeState` custom event, and use some logic to decide which one the master switch should trigger:
100
83
101
84
```
102
85
$( ".lightbulb" ).on( "changeState", function( e ) {
Note how the behavior of the master switch is attached to the master switch;
129
-
the behavior of a lightbulb belongs to the lightbulbs.
111
+
Note how the behavior of the master switch is attached to the master switch; the behavior of a lightbulb belongs to the lightbulbs.
130
112
131
-
If you're accustomed to object-oriented programming, you may find it useful to
132
-
think of custom events as methods of objects. Loosely speaking, the object to
133
-
which the method belongs is created via the jQuery selector. Binding the
134
-
`changeState` custom event to all `$( ".light" )` elements is akin to having a
135
-
class called `Light` with a method of `changeState`, and then instantiating new
136
-
`Light` objects for each element with a classname of `light`.
113
+
If you're accustomed to object-oriented programming, you may find it useful to think of custom events as methods of objects. Loosely speaking, the object to which the method belongs is created via the jQuery selector. Binding the `changeState` custom event to all `$( ".light" )` elements is akin to having a class called `Light` with a method of `changeState`, and then instantiating new `Light` objects for each element with a classname of `light`.
137
114
138
115
### Recap: `.on()` and `.trigger()`
139
116
140
-
In the world of custom events, there are two important jQuery methods:
141
-
`.on()` and `.trigger()`. In the [Events](/events/) chapter, we saw how to use these
142
-
methods for working with user events; for this chapter, it's important to
143
-
remember two things:
117
+
In the world of custom events, there are two important jQuery methods: `.on()` and `.trigger()`. In the [Events](/events/) chapter, we saw how to use these methods for working with user events; for this chapter, it's important to remember two things:
144
118
145
-
-`.on()` method takes an event type and an event handling function as
146
-
arguments. Optionally, it can also receive event-related data as its second
147
-
argument, pushing the event handling function to the third argument. Any data
148
-
that is passed will be available to the event handling function in the `data`
149
-
property of the event object. The event handling function always receives the
150
-
event object as its first argument.
119
+
*`.on()` method takes an event type and an event handling function as arguments. Optionally, it can also receive event-related data as its second argument, pushing the event handling function to the third argument. Any data that is passed will be available to the event handling function in the `data` property of the event object. The event handling function always receives the event object as its first argument.
151
120
152
-
-`.trigger()` method takes an event type as its argument. Optionally, it can
153
-
also take an array of values. These values will be passed to the event
154
-
handling function as arguments after the event object.
121
+
*`.trigger()` method takes an event type as its argument. Optionally, it can also take an array of values. These values will be passed to the event handling function as arguments after the event object.
155
122
156
-
Here is an example of the usage of `.on()` and `.trigger()` that uses
157
-
custom data in both cases:
123
+
Here is an example of the usage of `.on()` and `.trigger()` that uses custom data in both cases:
To demonstrate the power of custom events, we're going to create a simple tool
174
-
for searching Twitter. The tool will offer several ways for a user to add
175
-
search terms to the display: by entering a search term in a text box, by
176
-
entering multiple search terms in the URL, and by querying Twitter for trending
177
-
terms.
139
+
To demonstrate the power of custom events, we're going to create a simple tool for searching Twitter. The tool will offer several ways for a user to add search terms to the display: by entering a search term in a text box, by entering multiple search terms in the URL, and by querying Twitter for trending terms.
178
140
179
-
The results for each term will be shown in a results container; these
180
-
containers will be able to be expanded, collapsed, refreshed, and removed,
181
-
either individually or all at once.
141
+
The results for each term will be shown in a results container; these containers will be able to be expanded, collapsed, refreshed, and removed, either individually or all at once.
182
142
183
143
When we're done, it will look like this:
184
144
@@ -201,42 +161,23 @@ When we're done, it will look like this:
201
161
</div>
202
162
```
203
163
204
-
This gives us a container (`#twitter`) for our widget, a template for our results
205
-
containers (hidden via CSS), and a simple form where users can input a search
206
-
term. (For the sake of simplicity, we're going to assume that our application
207
-
is JavaScript-only and that our users will always have CSS.)
164
+
This gives us a container (`#twitter`) for our widget, a template for our results containers (hidden via CSS), and a simple form where users can input a search term. (For the sake of simplicity, we're going to assume that our application is JavaScript-only and that our users will always have CSS.)
208
165
209
-
There are two types of objects we'll want to act on: the results containers,
210
-
and the Twitter container.
166
+
There are two types of objects we'll want to act on: the results containers, and the Twitter container.
211
167
212
-
The results containers are the heart of the application. We'll create a plugin
213
-
that will prepare each results container once it's added to the Twitter
214
-
container. Among other things, it will bind the custom events for each
215
-
container and add the action buttons at the top right of each container. Each
216
-
results container will have the following custom events:
168
+
The results containers are the heart of the application. We'll create a plugin that will prepare each results container once it's added to the Twitter container. Among other things, it will bind the custom events for each container and add the action buttons at the top right of each container. Each results container will have the following custom events:
217
169
218
-
-`refresh` — Mark the container as being in the "refreshing" state, and fire
219
-
the request to fetch the data for the search term.
170
+
*`refresh` — Mark the container as being in the "refreshing" state, and fire the request to fetch the data for the search term.
220
171
221
-
-`populate` — Receive the returned JSON data and use it to populate the container.
172
+
*`populate` — Receive the returned JSON data and use it to populate the container.
222
173
223
-
-`remove` — Remove the container from the page after the user verifies the
224
-
request to do so. Verification can be bypassed by passing `true` as the second
225
-
argument to the event handler. The `remove` event also removes the term
226
-
associated with the results container from the global object containing the
227
-
search terms.
174
+
*`remove` — Remove the container from the page after the user verifies the request to do so. Verification can be bypassed by passing `true` as the second argument to the event handler. The `remove` event also removes the term associated with the results container from the global object containing the search terms.
228
175
229
-
-`collapse` — Add a class of collapsed to the container, which will hide the
230
-
results via CSS. It will also turn the container's "Collapse" button into an
231
-
"Expand" button.
176
+
*`collapse` — Add a class of collapsed to the container, which will hide the results via CSS. It will also turn the container's "Collapse" button into an "Expand" button.
232
177
233
-
-`expand` — Remove the collapsed class from the container. It will also turn
234
-
the container's "Expand" button into a "Collapse" button.
178
+
*`expand` — Remove the collapsed class from the container. It will also turn the container's "Expand" button into a "Collapse" button.
235
179
236
-
The plugin is also responsible for adding the action buttons to the container.
237
-
It binds a click event to each action's list item, and uses the list item's
238
-
class to determine which custom event will be triggered on the corresponding
239
-
results container.
180
+
The plugin is also responsible for adding the action buttons to the container. It binds a click event to each action's list item, and uses the list item's class to determine which custom event will be triggered on the corresponding results container.
The Twitter container itself will have just two custom events:
347
288
348
-
-`getResults` — Receives a search term and checks to determine whether there's
349
-
already a results container for the term; if not, adds a results container
350
-
using the results template, set up the results container using the
351
-
`$.fn.twitterResult` plugin discussed above, and then triggers the `refresh`
352
-
event on the results container in order to actually load the results.
353
-
Finally, it will store the search term so the application knows not to
354
-
re-fetch the term.
289
+
*`getResults` — Receives a search term and checks to determine whether there's already a results container for the term; if not, adds a results container using the results template, set up the results container using the `$.fn.twitterResult` plugin discussed above, and then triggers the `refresh` event on the results container in order to actually load the results. Finally, it will store the search term so the application knows not to re-fetch the term.
355
290
356
-
-`getTrends` — Queries Twitter for the top 10 trending terms, then iterates
357
-
over them and triggers the `getResults` event for
358
-
each of them, thereby adding a results container for each term.
291
+
*`getTrends` — Queries Twitter for the top 10 trending terms, then iterates over them and triggers the `getResults` event for each of them, thereby adding a results container for each term.
359
292
360
293
Here's how the Twitter container bindings look:
361
294
@@ -394,14 +327,9 @@ $( "#twitter" ).on( "getResults", function( e, term ) {
394
327
});
395
328
```
396
329
397
-
So far, we've written a lot of code that does approximately nothing, but that's
398
-
OK. By specifying all the behaviors that we want our core objects to have,
399
-
we've created a solid framework for rapidly building out the interface.
330
+
So far, we've written a lot of code that does approximately nothing, but that's OK. By specifying all the behaviors that we want our core objects to have, we've created a solid framework for rapidly building out the interface.
400
331
401
-
Let's start by hooking up our text input and the "Load Trending Terms" button.
402
-
For the text input, we'll capture the term that was entered in the input and
403
-
pass it as we trigger the Twitter container's `getResults` event. Clicking the
404
-
"Load Trending Terms" will trigger the Twitter container's `getTrends` event:
332
+
Let's start by hooking up our text input and the "Load Trending Terms" button. For the text input, we'll capture the term that was entered in the input and pass it as we trigger the Twitter container's `getResults` event. Clicking the "Load Trending Terms" will trigger the Twitter container's `getTrends` event:
By adding a few buttons with the appropriate ID's, we can make it possible to
419
-
remove, collapse, expand, and refresh all results containers at once, as shown
420
-
below. For the remove button, note how we're passing a value of `true` to the
421
-
event handler as its second argument, telling the event handler that we don't
422
-
want to verify the removal of individual containers.
346
+
By adding a few buttons with the appropriate ID's, we can make it possible to remove, collapse, expand, and refresh all results containers at once, as shown below. For the remove button, note how we're passing a value of `true` to the event handler as its second argument, telling the event handler that we don't want to verify the removal of individual containers.
423
347
424
348
```
425
349
$.each([ "refresh", "expand", "collapse" ], function( i, ev ) {
@@ -437,13 +361,4 @@ $( "#remove" ).click(function( e ) {
437
361
438
362
### Conclusion
439
363
440
-
Custom events offer a new way of thinking about your code: they put the
441
-
emphasis on the target of a behavior, not on the element that triggers it. If
442
-
you take the time at the outset to spell out the pieces of your application, as
443
-
well as the behaviors those pieces need to exhibit, custom events can provide a
444
-
powerful way for you to "talk" to those pieces, either one at a time or en
445
-
masse. Once the behaviors of a piece have been described, it becomes trivial to
446
-
trigger those behaviors from anywhere, allowing for rapid creation of and
447
-
experimentation with interface options. Finally, custom events can enhance code
448
-
readability and maintainability, by making clear the relationship between an
449
-
element and its behaviors.
364
+
Custom events offer a new way of thinking about your code: they put the emphasis on the target of a behavior, not on the element that triggers it. If you take the time at the outset to spell out the pieces of your application, as well as the behaviors those pieces need to exhibit, custom events can provide a powerful way for you to "talk" to those pieces, either one at a time or en masse. Once the behaviors of a piece have been described, it becomes trivial to trigger those behaviors from anywhere, allowing for rapid creation of and experimentation with interface options. Finally, custom events can enhance code readability and maintainability, by making clear the relationship between an element and its behaviors.
0 commit comments