JQuery_ Novice to Ninja - Earle Castledine [144]
click events fire when the user clicks something, load events fire when an element has loaded … Now we’re going to create an event that fires when the user hovers multiple times over an element. By default, when an element receives three mouseovers, the bound event handler runs, but we’ll see how this can be customized on an element-by-element basis. As with regular events, it’s up to you to specify the code that executes in the event handler.
To create a special event you attach a JavaScript object to the $.event.special namespace. The event system provides four hooks for you to define how the event works. The setup function runs when the event is first bound, the add function runs every time it’s bound, the remove function runs when it’s unbound, and the teardown function runs when the last event is unbound (that is, when no more events of this type remain bound to handlers).
Let’s have a look at the skeleton of our multihover event:
chapter_09/15_special_event/script.js (excerpt)
jQuery.event.special.multihover = {
setup: function(data, namespaces) {
// Do when the first event is bound
},
add: function(handler, data, namespaces) {
// Do every time you bind another event
},
remove: function(namespaces) {
// Do when an event is unbound
},
teardown: function(namespaces) {
// Do when the last event is unbound
},
handler: function(e) {
// Do your logic
}
}
Once you’ve created your event, you can bind it as you would any event. Obviously there’s no shortcut method to bind your custom events, so you have to use the bind method to attach it to page elements:
chapter_09/15_special_event/script.js (excerpt)
$('p').bind('multihover', {times: 4}, function() {
$(this).css('background-color', 'lemonchiffon');
});
We’ve bound our new multihover event to all the paragraphs on the page, and then specified how many times we want to hover over an element before the event fires. We saw in the the section called “Custom Events” that you can pass data to an event with the trigger method, but now we learn that you can also specify data to pass to an event when you bind it as well!
Our special event isn’t going to use the add or remove hooks, because we only want to allow one multihover event to be attached to each element. In the setup hook, we’ll store the required number of hovers on the element itself using the data action. We’ll default to 3 in the absence of a user-specified value. Next up, we bind our custom event handler (which we call jQuery.event.special.handler) to the mouseover event, since we’ll need to perform our logic there to determine when the third hover has taken place:
chapter_09/15_special_event/script.js (excerpt)
setup: function(data, namespaces) {
$(this)
.data('times', data && data.times || 3)
.bind('mouseover', jQuery.event.special.multihover.handler);
},
…
teardown: function(namespaces) {
$(this)
.removeData('times')
.unbind('mouseover', jQuery.event.special.multihover.handler);
Tip: The data Parameter
The data parameter on the bind method is not specific to the special event. It’ll work exactly the same on any of your events, so take advantage of it!
We also undo all this setup in the corresponding teardown handler. Here we remove the data item we added, and unbind the mouseover binding. This tidies everything up. Now we have a new event that calls our custom handler every time a mouseover event occurs, so let’s implement our multihover logic:
chapter_09/15_special_event/script.js (excerpt)
handler: function(e) {
// Do your logic
var times = $(this).data('times') || 0;
times--;
$(this).data('times', times);
if (times <= 0) {
e.type = 'multihover';
jQuery.event.handle.apply(this,arguments);
$(this).unbind('multihover');
}
}
This is the meat of the functionality. We’ve separated it into its own function only to keep it clear—we could have just as easily handled it with an anonymous function.
The multihover logic first subtracts 1 from the times data item.