In the lessons covered so far in this section, you have learned most of what you need to know to start writing dynamic web applications. This lesson will cover one final subject that can enhance dynamic web applications: jQuery plugins.
One of the reasons jQuery is so popular is that it is very easy to extend with plugins. As a result, a huge number of jQuery plugins are freely available, and these can often be used as an alternative to writing your own code.
In this lesson, you will briefly look at one of the most popular jQuery plugins, called jQuery UI. This plugin provides a set of user interface components, such as date pickers and dialog boxes, and is used extensively, including on some of the Internet's most popular websites.
It is also possible to write your own jQuery plugins. A typical jQuery plugin uses a jQuery selector to identify a set of elements, and then performs an operation on these elements, returning the modified elements as a result.
Although it is obviously possible to modify elements without encapsulating the code in a jQuery plugin, writing plugins provides a convenient mechanism for packaging code.
jQuery UI is probably the most widely used jQuery plugin. This plugin provides a variety of user interface components, all of which work seamlessly across all the most common browsers. jQuery UI can therefore be used to provide polyfills for native HTML5 components, such as date pickers and progress bars.
jQuery UI can be downloaded from http://jqueryui.com
. This website also contains a set of live demos for all the components included in the plugin, along with comprehensive documentation on all components.
Many of the UI components provided by jQueryUI mirror equivalents in HTML5, including the following:
range
input field, although again, in a cross-browser manner, and with additional configuration options.number
input fields in Chrome.jQuery UI also contains more advanced widgets not currently found in HTML5, including the following:
A version of jQuery UI is included with the Lesson 21 resources on the book's website. Because jQuery UI is a large library, it is possible to tailor the download to the specific components needed, and it is also possible to customize the themes of the components (such as colors and fonts) when downloading the library. The version provided contains all components, and the default theme.
The jQuery UI resources comprise the following:
jquery-ui.js
: Contains all the JavaScript code implementing the various components.jquery-ui.css
: Contains the CSS used for styling the components.images
folder: Contains all the images needed by the components. For instance, the date-picker uses arrows for moving between months: These are represented by images.Copy all these resources to the folder containing contacts.html
.
In this section, you will change the date
input field in contacts.html
to use the jQuery UI implementation, rather than the native HTML5 implementation.
To begin, the jQuery UI JavaScript file and CSS file must be imported into the head
of the web page. It is essential that the JavaScript file is imported after the main jQuery file because jQuery UI extends the capabilities of jQuery:
<link rel="stylesheet" type="text/css" href="jquery-ui.css">
<script src="jquery-ui.js"></script>
Next, change the lastContacted
input field from a date-based field to a text-based field:
<input name="lastContacted" type="text" class="validated"/>
Once this is done, all that is required to enable the jQuery UI date-picker on the field is to execute the following code:
$('[name="lastContacted"]').datepicker();
Notice that this begins by selecting an element with a regular jQuery selector, and then calls a datepicker
method on the result. The datepicker
method was provided by the jQuery UI library, but notice that it is available on a regular jQuery selection.
Add this code to the script
block at the bottom of contacts.html
.
If you now open the web page and click in the lastContacted
field, a date-picker will be displayed, as you can see in Figure 21.1.
All jQuery UI components follow this same model: An element (or set of elements) is selected from the DOM and converted into a dynamic component using a method provided by jQuery UI.
jQuery UI components accept a variety of configuration parameters, and in many ways are more flexible than their HTML5 counterparts. Because of the large number of potential parameters (the date-picker itself supports more than 50 different configuration parameters), and the fact that all of these parameters are optional, any parameters required are provided within an object with properties representing the required options.
For instance, the following sets the maximum date the date-picker will accept to today (0 means zero days from today), and the minimum date to 6 months ago (–6m
):
$('[name="lastContacted"]').datepicker({
minDate: "-6m",
maxDate: 0
});
With these parameters set, any dates outside this range will be disabled.
The jQuery UI website contains excellent documentation on all the options available for this component, and all the other components supported by jQuery UI.
You will now switch from using plugins developed by other programmers, to writing your own plugins. The basic premise of a jQuery plugin is that it is passed a selection of elements; it then performs an operation on these elements and (usually) returns the modified elements.
In this section, you will write a plugin that accepts time
elements with a datetime
attribute, and changes the content of the element to contain a more readable representation of the date. Once this is implemented, you will be able to select time
elements and transform them to display the date as you see in Figure 21.2.
Because plugins should be reusable across websites, I recommend that you add them to a new JavaScript file. Start by creating an empty JavaScript file called jquery-time.js
. Place this in the same directory as the other project resources, and import it into contacts.js
(make sure the import occurs after the main jQuery library).
<script src="jquery-time.js"></script>
In order to add a plugin to jQuery, you need to extend the capabilities of jQuery. Specifically, you need to extend an object that can be accessed via jQuery.fn
, and add a new method to it. The boilerplate code for adding a plugin to jQuery therefore looks like this:
(function($) {
$.fn.extend({
setTime: function() {
return this;
},
});
})(jQuery);
This code uses a technique you have not seen previously: It declares an anonymous function that accepts a single parameter (represented by $
). The code then immediately calls this function (on the last line) and passes it the jQuery
function (which is the same function you have been accessing through its $
alias).
This is a great technique when you only want a function to be executed a single time when the web page loads: Because this is an anonymous function, and is not referred to by any variables, it can never be executed again.
Once you have a reference to fn
, you call a method on it called extend
, and pass this an object. This object will contain definitions of the methods you wish to add to jQuery: In this case, a single method will be added called setTime
.
If you reload the web page, you can use this plugin immediately. Figure 21.3 demonstrates an example where you select a time
element from the web page and then call setTime
on the selection:
As you can see, the setTime
method returns the selection it is passed. This is due to the fact that the method returned this
. The this
variable can be used inside a plugin to extract the elements selected, but can also be returned at the end to allow chaining. For example, it is possible to write code such as the following:
> $('time').setTime().parent()
With the plugin skeleton in place, you can start writing the functionality of the plugin. JavaScript does not contain a library for formatting dates, although there are numerous open-source libraries available. You will therefore write your own rudimentary code for date formatting:
(function($) {
$.fn.extend({
setTime: function() {
months = ['January','February', 'March', 'April', 'May', 'June',
'July','August','September','October','November', 'December'];
$.each(this, function(indx, val) {
if ($(val).attr('datetime')) {
var date = new Date($(val).attr('datetime'));
var display = months[date.getMonth()] + ' ';
display += date.getDate() + ', ';
display += date.getFullYear();
$(val).text(display);
}
});
return this;
},
});
})(jQuery);
JavaScript represents the months of the year with the numbers 0–11, so you begin by creating an array that allows you to place a textual representation of each month in an array at its relevant index.
Next, you use the jQuery each
method to iterate through the selected elements. The method then checks to see whether the element has a datetime
attribute: This plugin will be compatible with elements containing the datetime
attribute, and therefore will not do anything if this attribute is missing.
Because the datetime
attribute contains an ISO-compliant representation of a date, it can be converted into a JavaScript Date
object using its constructor. Once a Date
object is created, its component parts (month, day, year) can be accessed through its methods.
The rest of this method uses simple string concatenation to create a textual representation of a date, using the months
array to find the textual representation of the month, and extracting the other important date components with the relevant methods. Once a textual representation of a date is created, it is set on the element using the text
method.
If you load the screen, and ensure the table contains a row with a date in it, you can convert this into a more readable representation with the following call:
> $('time').setTime();
It is also possible to pass parameters to the plugin. As with jQuery UI, it is customary to pass an object with relevant parameters and provide defaults for all parameters. For instance, you may want the user to specify either a short or long form of the date: A short form will only print the first three characters of the month and the last two numbers in the year.
In the following example, the params
object can contain a style
property: If this has a value of short
, the month and year will be truncated.
(function($) {
$.fn.extend({
setTime: function(params) {
months = ['January','February', 'March', 'April', 'May', 'June',
'July','August','September','October','November', 'December'];
$.each(this, function(indx, val) {
if ($(val).attr('datetime')) {
var date = new Date($(val).attr('datetime'));
var m = months[date.getMonth()];
if (params && params.style === 'short') {
m = m.substr(0, 3);
var display = m + ' ';
display += date.getDate() + ', ';
display += (date.getFullYear() % 100);
} else {
var display = m + ' ';
display += date.getDate() + ', ';
display += date.getFullYear();
}
$(val).text(display);
}
});
return this;
},
});
})(jQuery);
This can then be called as follows to use the short
representation:
$('time').setTime({'style':'short'})
The great thing about jQuery plugins is that they are completely reusable on other web pages. Each plugin performs its own specific operation, and provided it is passed elements it is compatible with, it does not need to know anything else about the web page.
You want to ensure that this plugin is called automatically whenever a new row is added to the table so change the save
method to invoke it as follows (the remainder of this function has been excluded for brevity):
row = bind(row, contact);
$(row).find('time').setTime();
$(screen).find('table tbody').append(row);
In this Try It, you will use one more feature in the jQuery UI library and write a new plugin of our own.
You will need the CRM web application from Lesson 20, but it is also assumed you have been following this lesson, and have imported the jQuery UI resources. If not, you need to do this before continuing with the Try It. This lesson can then be completed in a text editor and tested in Chrome.
In addition to providing a set of components, jQuery UI contains a set of more advanced animation effects than are found in jQuery itself. You will therefore use one of these effects when displaying the contacts form.
init
method in contacts.js
adds an event listener for displaying the form that uses the following code:
document.getElementById('contactDetails').style.display = 'block';
This uses the native DOM API: In order to use a jQuery UI effect, change this as follows:
$(screen).find('#contactDetails').toggle( "blind" );
http://api.jqueryui.com/
in your web browser and click the Effects category on the left-hand side. You should be able to find documentation on the blind
effect and learn about its various options.save
method:
$(screen).find('#contactDetails').hide();
This can be replaced with the exact same code used in step 1: Because the toggle
method is being used, a visible element will be automatically hidden.
You will now change the code that populates the contact count in the table footer to operate as a jQuery plugin.
jquery-tables.js
and add the same boilerplate code from jquery-time.js
to this.contacts.html
.updateFooter
. This should accept a single parameter called params
.tfoot
and tbody
children. Therefore, use the each
method to iterate through the selection provided to the plugin, and check that each element has these child elements before processing the element further.if
statement, start by counting how many tr
elements are in the tbody
. Remember that the length
property can be used for ascertaining this. Store the number in a local variable.td
element in the tfoot
to contain the text “X rows in table,” where X is the count retrieved in Step 5.
You should now be able to update the footer by invoking the plugin on the table, as shown in Figure 21.4.
params
object contains a property called message
, use its value instead of “rows in the table.” When writing the code to use this, remember that both the params
object and the message
property may be undefined.updateTableCount
method to use this plugin. I have used the following code:
$(screen).find('table').updateFooter({'message':' contacts displayed'});
The full version of my plugin looks like this:
(function($) {
$.fn.extend({
updateFooter : function(params) {
$.each(this, function(indx, val) {
if ($(val).find('tbody') && $(val).find('tfoot')) {
var count = $(val).find('tbody tr').length;
if (params && params.message) {
$(val).find('tfoot td').text(count + ' ' + params.message);
} else {
$(val).find('tfoot td').text(count + ' rows in the table'),
}
}
});
return this;
},
});
})(jQuery)
3.139.97.53