JQuery_ Novice to Ninja - Earle Castledine [136]
To demonstrate, let’s try exposing a setup event (which will run after the mouseover handlers are attached), and a complete event (which will run after the final animate action concludes):
chapter_09/04_plugin_callbacks/jquery.highlightonce.js (excerpt)
$.fn.highlightOnce.defaults = {
color : '#fff47f',
duration : 'fast',
setup : null,
complete: null
};
The callback functions shouldn’t do anything by default, so we’ll set them to null. When the time comes to run the callbacks, there are a few possible ways of proceeding. If our callback needs to run in the place of a jQuery callback, we can simply provide the function passed in by our users to the jQuery action. Otherwise, we’ll need to call the function manually at the appropriate location:
chapter_09/04_plugin_callbacks/jquery.highlightonce.js (excerpt)
$(this)
.data('original-color', $(this).css('background-color'))
.css('background-color', options.color)
.one('mouseenter', function() {
$(this).animate(
{'background-color': $(this).data('original-color')},
options.duration,
options.complete
);
});
// Fire the setUp callback
$.isFunction(options.setup) && options.setup.call(this);
Above we can see both types of callbacks. The complete callback handler is easy: the effect is completed when the animate action is finished, and the animate action accepts a callback function itself, so we just pass the function along. No such luck with the setup handler, though—we’ll have to fire that one ourselves. We turn to jQuery and a dash of advanced JavaScript to execute the code. First, we check to see if the callback is a function with the handy $.isFunction jQuery action that returns a Boolean value: true if the callback is a function, false if it’s not. If it’s the latter (which is most likely because the user left the defaults as they were, in which case it will still be null), there’s no point trying to execute it!
Tip: More Utility Functions
In addition to $.isFunction, jQuery also provides the following functions: $.isArray (for testing if a variable is an array), $.isPlainObject (for simple JavaScript objects), and $.isEmptyObject (for an object that has no properties). These functions provide you with a number of ways to ascertain the nature and properties of a JavaScript construct.
If the callback has been defined, we need to run it. There are several ways to run a JavaScript function, and the easiest is to just call it: options.setup(). This will run fine, but the problem is that it’s called in the scope of the default object, instead of in the scope of the event’s target element (as we’re used to). So the callback function would be unable to determine which DOM element it was dealing with. To remedy this, we use the JavaScript method call. The first parameter you pass to call will override this in the method you’re calling. In our example, we pass in this, which is the DOM element we want.
With the scope corrected, we can now use $(this) inside the complete event handler to slide up the element once the effect is done and dusted:
chapter_09/04_plugin_callbacks/script.js (excerpt)
$('p')
.hide()
.highlightOnce({
color: '#FFA86F',
complete: function() {
$(this).slideUp();
}
})
.slideDown();
jQuery-style Callback
You might have noticed that the jQuery callbacks seem better integrated than our plugin’s named events. For example, in the hide action, you can specify the callback function as either the first (and only) parameter, or you can include the speed parameter and then the callback function. It’s unnecessary to include a key/value pair as we did above. What’s the secret? It turns out to be a little bit of a JavaScript hack. If you detect that the first parameter is a function, rather than an object, you can assume that only a callback has been specified, so you shift the parameters over.
Here’s a (truncated) example from the jQuery core library, part of the Ajax load action. The params parameter is optional, so if it isn’t supplied the second