This week, we'll attack something more useful – a plug-in to submit a regular form via AJAX.
01: Create the API
If you've read the other articles you know that when designing a plug-in, deciding how it's used is often the first step. You can then program to the API you've created. We want to make sure to provide some callbacks, specify the action, and the submission type. Our invocation will look like this:
$('#form-element').ajaxify({ method : 'post', action : 'process.php', onSuccess : function() {}, onSubmit : function() {}, onError : function() {} }
method: This option will be "GET", "POST" or blank. If it's left blank, the plug-in will check for the method attribute of the form tag. If there's no method in the HTML it will default to GET (as per HTML spec.).
action: The action is the URL receiving the data. If left blank, the plug-in will pull the information from the form's action attribute.
onSuccess, onError: These are event handlers for the form submission. If they are left blank, they'll default to an empty function.
onSubmit: This one is important because you may still want to do some validation before submitting the form. The onSubmit option should return true to allow the form to submit, and false to prevent it. If the user doesn't define this callback, it will automatically return true.
02: Setting Up the Defaults
You could probably write this next bit of code yourself, based on the explanations above. Here are the default values for our options (along with the first few lines of plug-in code):
(function($) { $.fn.ajaxify = function(options) { // Defaults and options var defaults = { method : '', action : '', onSuccess : function() {}, onSubmit : function() { return true }, onError : function() {} }; var opts = $.extend({}, defaults, options);
03: The Main $.each Loop
In most plug-ins, the $.each loop is the major part of the program. In this case its only going to set one event handler, and then we're going to do all the work inside that event handler.
this.each(function() { $(this).bind('submit', function(event) {
04: The Event Handler
The event handler has a lot to do. The first thing it's responsible for is preventing the form from doing the thing it normally does (submitting) -- we're going to handle that! We're also going to be using the 'this' variable a bit, and need it available inside closures. So the first two lines of our handler are
FORM = $(this); event.preventDefault();
// Mimic the normal onSubmit handler if(!opts.onSubmit.call(FORM[0])) { return; }
Before actually making the AJAX submission, the proper method needs to be determined (GET or POST) and the action (the target URL).
// Determine the method && action var method = opts.method || FORM.attr('method') || 'GET'; var action = opts.action || FORM.attr('action');
The first line checks if opts.method exists, and that its not empty. If it doesn't pass, it checks if the form has a method attribute with a non-empty value. If both of those checks fail, it ends up returning "GET" which is the default value we wish to use.
Action works the same way. If the opts.action doesn’t exist or is empty, it returns the value of the form's action tag.
05: AJAX Submission
jQuery takes almost all the pain out of AJAX. Here's a basic XMLHTTP request with the form data:
$.ajax({ type : method, url : action, data : FORM.serialize(), success : function(data) { opts.onSuccess.call(FORM[0], data); }, error : function() { opts.onError.call(FORM[0]); } });
Here's an explanation of the parameters:
type: Equivalent to the method attribute of the form.
url: Equivalent to the action attribute of the form
data: This should be a query string of data to submit. Here we're using some jQuery magic to create that string. The .seralize() method is called on a jQuery form reference, and creates a query string from all successful controls found.
success: A callback, expects a function, and is passed the data returned from the remote server. In our case, we're using the jQuery callback to invoke our plug-in's callback.
error: Just like success, this is a callback, and we're using it to call our own callback.
And that's it. Don't forget to return the jQuery object at the end to allow chaining. Here's our entire plug-in:
(function($) { $.fn.ajaxify = function(options) { // Defaults and options var defaults = { method : '', action : '', onSuccess : function() {}, onSubmit : function() { return true }, onError : function() {} }; var opts = $.extend({}, defaults, options); this.each(function() { $(this).bind('submit', function(event) { event.preventDefault(); // Increase readability && scope FORM = $(this); // Mimic the normal onSubmit handler if(!opts.onSubmit.call(FORM[0])) { return; } // Determine the method && action var method = opts.method || FORM.attr('method') || 'GET'; var action = opts.action || FORM.attr('action'); // Submit the form via ajax, with appropriate callback $.ajax({ type : method, url : action, data : FORM.serialize(), success : function(data) { opts.onSuccess.call(FORM[0], data); }, error : function() { opts.onError.call(FORM[0]); } }); }); }); // allow chaining return this; } })(jQuery);
06: Using the Plug-In
To use the plug-in, the code should be inside a document.ready block. First we'll invoke the plug-in itself:
$('#ajaxify').ajaxify({ onSubmit : myOnSubmit, onSuccess : myOnSuccess, onError : myOnError });
function myOnSubmit() { var FORM = $(this); var valid = true; FORM.find('input').css('border-color', '#F0F0F0'); FORM.find('input').each(function() { if($(this).val() == '') { $(this).css('border-color', 'red'); valid = false; } }); return valid; }
Next we use an $.each to iterate over the form's inputs. I would not recommend actually using this function for form validation -- its just checking that each field has something, anything inside it. If its empty, the border is colored and the valid flag is set to false.
Finally we return value of valid from the function.
Our other two call backs are very simple.
function myOnSuccess(msg) { alert("The server said " + msg); } function myOnError() { alert("There was an error"); }
Because this requires a server side script to run successfully, I've posted a demo you can view:
Live Demo
Source code: ajaxify.zip
Conclusion
With this plug-in, you can easily add AJAX to any form on your site. A handy tool to have laying about! In our next tutorial, we'll look at using a plug-in someone else wrote -- the jQuery-UI project's auto-complete widget.