jQuery Plugins - Dynamic HTML5 Web Applications with JavaScript and jQuery - HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

Part II Dynamic HTML5 Web Applications with JavaScript and jQuery

Lesson 21 jQuery Plugins

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

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:

· A date-picker component

· A progress bar: Implements the same basic functionality as the HTML5 progress bar, but works in all modern browsers.

· A slider: Implements the same basic functionality as the HTML5 range input field, although again, in a cross-browser manner, and with additional configuration options.

· A spinner component: Implements the same functionality seen on number input fields in Chrome.

· Drag and drop components: These include more advanced features not supported by HTML5, such as the ability to resize components, and the ability to reposition elements onscreen without specifically dropping them on other elements.

jQuery UI also contains more advanced widgets not currently found in HTML5, including the following:

· A tab component: Allows an interface to provide a set of tabs to the user.

· A dialog widget: Provides an implementation of all common varieties of dialog box, such as confirmation, warning, and error dialogs.

· An accordion component: Allows panels to be expanded and collapsed. This has some similarity to the summary/detail tags seen earlier in the book, but allows for many summary/detail blocks to work together, and assumes one detail block will always be expanded. This component is named after its passing resemblance to an accordion musical instrument.

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.

· An 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.

image

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.

Writing a Plugin

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.

image

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:

image

Figure 21.3

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);

Try It

In this Try It, you will use one more feature in the jQuery UI library and write a new plugin of our own.

Lesson Requirements

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.

Step-by-Step

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.

1. The 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" );

2. Load the web page, and click to add a contact. The form should slide down slowly from the top.

3. In order to use jQuery UI effectively, you need to be able to access its documentation. Therefore, open 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 blindeffect and learn about its various options.

4. The form section is hidden with the following code in the 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.

1. Start by creating a new plugin called jquery-tables.js and add the same boilerplate code from jquery-time.js to this.

2. Import the new plugin into contacts.html.

3. Add a method to the plugin called updateFooter. This should accept a single parameter called params.

4. This plugin will operate on tables that contain 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.

5. Within the 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.

6. Update the 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.

image

Figure 21.4

7. The message displayed in the table should be configurable. Therefore, if the 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 messageproperty may be undefined.

8. You can now change the 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)

Reference

Please go to the book's website at www.wrox.com/go/html5jsjquery24hr to view the video for Lesson 21, as well as download the code and resources for this lesson.