With that jQuery.fn.println function defined, we can now invoke a println() method on any jQuery object:
$("#debug").println("x = ", x, "; y = ", y);
It is common practice to add new methods to jQuery.fn. If you
use the each() method to “manually” iterate through the elements in a jQuery object and perform some kind of operation
on them, consider whether it might make sense to refactor your
code so that the each() invocation is moved into an extension
method. If you follow basic modular coding practices when
writing your extension, and abide by a few jQuery-specific
conventions, you can call your extension a plugin and share it
with others. These are the jQuery plugin conventions to be
aware of:
• Don’t rely on the $ identifier: the including page may have
called jQuery.noConflict(), and $() may no longer be a
synonym for the jQuery() function. In short plugins like
the one shown above, you can just use jQuery instead of
$. If you are writing a longer extension, you are likely to
wrap it all within one anonymous function to avoid the
creation of global variables. If you do so, you can use the
idiom of passing the jQuery as an argument to your
anonymous function and receiving that value in a parameter named $:
(function($) { // An function with parameter named $
// Put your plugin code here
}(jQuery)); // Pass the jQuery object to the function
• If your extension method does not return a value of its
own, be sure to return a jQuery object that can be used in
a method chain. Usually this will just be the this object,
which you can return unmodified. In the example above,
the method ended with the line return this;. The method
could have been made slightly shorter (and less readable)
following another jQuery idiom: returning the result of
the each() method. Then the println() method would
have included the code return this.each(function()
{...});.
104 | Chapter 9: Extending jQuery with Plugins
• If your extension method has more than a couple of parameters or configuration options, allow the user to pass
options in the form of an object (as we saw with the
animate() method in “Custom Animations” on page 53,
and the jQuery.ajax() function in “The jQuery.ajax()
Function” on page 72).
• Don’t pollute the jQuery method namespace. Wellbehaved jQuery plugins define the smallest number of
methods consistent with a usable API. It is common for
jQuery plugins to define only a single method in
jQuery.fn. This one method takes a string as its first argument and interprets that string as the name of a function
to pass its remaining arguments to. When you are able to
limit your plugin to a single method, the name of that
method should be the same as the name of the plugin. If
you must define more than one method, use the plugin
name as a prefix for each of your method names.
• If your plugin binds event handlers, put all of those handlers in an event namespace (see “Advanced Event Handler Registration” on page 37). Use your plugin name as
the namespace name.
• If your plugin uses the data() method to associate data
with elements, place all of your data values in a single object, and store that object as a single value, giving it the
same name as your plugin.
• Save your plugin code in a file with a name of the form
“jquery.plugin.js”, replacing plugin with the name of your
plugin.
A plugin can add new utility functions to jQuery by adding
them to the jQuery object itself. For example:
// This method prints its arguments (using the println()
// plugin method) to the element with id "debug". If no
// such element exists, it is created and added.
jQuery.debug = function() {
// Find the #debug element
var elt = jQuery("#debug");
// Create and insert it if necessary
if (elt.length === 0) {
Extending jQuery with Plugins | 105
elt = jQuery("
" +
"
Debugging Output
");
jQuery(document.body).append(elt);
};
}
// Output the arguments to it
elt.println.apply(elt, arguments);
In addition to defining new methods, it is also possible to extend other parts of the jQuery library. In Chapter 5, for example, we saw that it is possible to add new effect duration names
(in addition to “fast” and “slow”) by adding properties to
jQuery.fx.speeds, and that it is possible to add new easing
functions by adding them to jQuery.easing. Plugins can even
extend the jQuery CSS selector engine! You can add new pseudoclass filters (like :first and :input) by adding properties to
the jQuery.expr[':'] object. Here is an example that defines a
new :draggable filter, which returns only elements that have a
draggable=true attribute:
jQuery.expr[':'].draggable = function(e) {
return e.draggable === true;
};
With this selector defined, we can select draggable images with
$("img:draggable") instead of the more verbose $("img[drag
gable=true]").
As you can see from the code above, a custom selector function
is passed a candidate DOM element as its first argument. It
should return true if the element matches the selector, and
false otherwise. Many custom selectors need only the one element argument, but they are actually invoked with four arguments. The second argument is an integer index that gives
the element’s position within an array of candidate elements.
That array is passed as the fourth argument, and your selector
must not modify it. The third argument is interesting: it is the
array result of a call to the RegExp.exec() method. The fourth
element of this array (at index 3) is the value, if any, within
parentheses after the pseudoclass filter. The parentheses and
any quotes inside are stripped, leaving only the argument
string. Here, for example, is how you could implement
106 | Chapter 9: Extending jQuery with Plugins
a :data(x) pseudoclass that returns true only for arguments
that have an HTML5 data-x attribute:
jQuery.expr[':'].data = function(e, idx, match, array) {
return e.hasAttribute("data-" + match[3]);
};
Extending jQuery with Plugins | 107
CHAPTER 10
The jQuery UI Library
jQuery limits itself to providing core DOM, CSS, event handling, and Ajax functionality. These provide an excellent
foundation for building higher-level abstractions, such as user
interface widgets, and the jQuery UI library does just that. Full
coverage of jQuery UI is beyond the scope of this book, but
this chapter offers a simple overview. You can find the library
and its documentation at http://jqueryui.com.
As its name implies, jQuery UI defines a number of user interface widgets: auto-completion input fields, date pickers for entering dates, accordions and tabs for organizing information,
sliders and progress bars for visually displaying numbers, and
modal dialogs for urgent communication with the user. In addition to these widgets, jQuery UI implements more general
“interactions”, which allow any document element to be easily
made draggable, droppable, resizable, selectable, or sortable.
Finally, jQuery UI adds a number of new visual effects methods
(including the ability to animate colors) to those offered by
jQuery itself, and defines lots of new easing functions as well.
Think of jQuery UI as a bunch of related jQuery plugins packed
into a single JavaScript file. To use it, simply include the jQuery
UI script into your web page after including the jQuery code.
The Download page at http://jqueryui.com allows you to select
the components you plan to use, and will build a custom
109
download bundle for you that may reduce your page load times
compared to the full jQuery UI library.
jQuery UI is fully themeable, and its themes take the form of
CSS files. So in addition to loading the jQuery UI JavaScript
code into your web pages, you’ll have to include the CSS file
for your selected theme as well. The jQuery UI website features
a number of prebuilt themes and also a “ThemeRoller” page
that allows you to customize and download your own theme.
jQuery UI widgets and interactions are structured as jQuery
plugins, and each defines a single jQuery method. Typically,
when you call this method on an existing document element,
it transforms that element into the widget. For example, to alter
a text input field so that it pops up a date picker widget when
clicked or focused, simply call the datepicker() method with
code like this:
// Make input.date tags into date picker widgets
$("input.date").datepicker();
In order to make full use of a jQuery UI widget, you must be
familiar with three things: its configuration options, its methods, and its events. All jQuery UI widgets are configurable, and
some have many configuration options. You can customize the
behavior and appearance of your widgets by passing an options
object (like the animations options object passed to
animate()) to the widget method.
jQuery UI widgets usually define at least a handful of “methods” for interacting with the widget. In order to avoid a proliferation of jQuery methods, however, jQuery UI widgets do
not define their “methods” as true methods. Each widget has
only a single method (like the datepicker() method in the example above). When you want to call a “method” of the
widget, you pass the name of the desired “method” to the single
true method defined by the widget. To disable a date picker
widget, for example, you don’t call disableDatepicker();
instead, you call datepicker("disable").
110 | Chapter 10: The jQuery UI Library