bos@574: /* bos@574: * jQuery Form Plugin bos@574: * @requires jQuery v1.1 or later bos@574: * bos@574: * Examples at: http://malsup.com/jquery/form/ bos@574: * Dual licensed under the MIT and GPL licenses: bos@574: * http://www.opensource.org/licenses/mit-license.php bos@574: * http://www.gnu.org/licenses/gpl.html bos@574: * bos@574: * Revision: $Id$ bos@574: */ bos@574: (function($) { bos@574: /** bos@574: * ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX. bos@574: * bos@574: * ajaxSubmit accepts a single argument which can be either a success callback function bos@574: * or an options Object. If a function is provided it will be invoked upon successful bos@574: * completion of the submit and will be passed the response from the server. bos@574: * If an options Object is provided, the following attributes are supported: bos@574: * bos@574: * target: Identifies the element(s) in the page to be updated with the server response. bos@574: * This value may be specified as a jQuery selection string, a jQuery object, bos@574: * or a DOM element. bos@574: * default value: null bos@574: * bos@574: * url: URL to which the form data will be submitted. bos@574: * default value: value of form's 'action' attribute bos@574: * bos@574: * type: The method in which the form data should be submitted, 'GET' or 'POST'. bos@574: * default value: value of form's 'method' attribute (or 'GET' if none found) bos@574: * bos@574: * data: Additional data to add to the request, specified as key/value pairs (see $.ajax). bos@574: * bos@574: * beforeSubmit: Callback method to be invoked before the form is submitted. bos@574: * default value: null bos@574: * bos@574: * success: Callback method to be invoked after the form has been successfully submitted bos@574: * and the response has been returned from the server bos@574: * default value: null bos@574: * bos@574: * dataType: Expected dataType of the response. One of: null, 'xml', 'script', or 'json' bos@574: * default value: null bos@574: * bos@574: * semantic: Boolean flag indicating whether data must be submitted in semantic order (slower). bos@574: * default value: false bos@574: * bos@574: * resetForm: Boolean flag indicating whether the form should be reset if the submit is successful bos@574: * bos@574: * clearForm: Boolean flag indicating whether the form should be cleared if the submit is successful bos@574: * bos@574: * bos@574: * The 'beforeSubmit' callback can be provided as a hook for running pre-submit logic or for bos@574: * validating the form data. If the 'beforeSubmit' callback returns false then the form will bos@574: * not be submitted. The 'beforeSubmit' callback is invoked with three arguments: the form data bos@574: * in array format, the jQuery object, and the options object passed into ajaxSubmit. bos@574: * The form data array takes the following form: bos@574: * bos@574: * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] bos@574: * bos@574: * If a 'success' callback method is provided it is invoked after the response has been returned bos@574: * from the server. It is passed the responseText or responseXML value (depending on dataType). bos@574: * See jQuery.ajax for further details. bos@574: * bos@574: * bos@574: * The dataType option provides a means for specifying how the server response should be handled. bos@574: * This maps directly to the jQuery.httpData method. The following values are supported: bos@574: * bos@574: * 'xml': if dataType == 'xml' the server response is treated as XML and the 'success' bos@574: * callback method, if specified, will be passed the responseXML value bos@574: * 'json': if dataType == 'json' the server response will be evaluted and passed to bos@574: * the 'success' callback, if specified bos@574: * 'script': if dataType == 'script' the server response is evaluated in the global context bos@574: * bos@574: * bos@574: * Note that it does not make sense to use both the 'target' and 'dataType' options. If both bos@574: * are provided the target will be ignored. bos@574: * bos@574: * The semantic argument can be used to force form serialization in semantic order. bos@574: * This is normally true anyway, unless the form contains input elements of type='image'. bos@574: * If your form must be submitted with name/value pairs in semantic order and your form bos@574: * contains an input of type='image" then pass true for this arg, otherwise pass false bos@574: * (or nothing) to avoid the overhead for this logic. bos@574: * bos@574: * bos@574: * When used on its own, ajaxSubmit() is typically bound to a form's submit event like this: bos@574: * bos@574: * $("#form-id").submit(function() { bos@574: * $(this).ajaxSubmit(options); bos@574: * return false; // cancel conventional submit bos@574: * }); bos@574: * bos@574: * When using ajaxForm(), however, this is done for you. bos@574: * bos@574: * @example bos@574: * $('#myForm').ajaxSubmit(function(data) { bos@574: * alert('Form submit succeeded! Server returned: ' + data); bos@574: * }); bos@574: * @desc Submit form and alert server response bos@574: * bos@574: * bos@574: * @example bos@574: * var options = { bos@574: * target: '#myTargetDiv' bos@574: * }; bos@574: * $('#myForm').ajaxSubmit(options); bos@574: * @desc Submit form and update page element with server response bos@574: * bos@574: * bos@574: * @example bos@574: * var options = { bos@574: * success: function(responseText) { bos@574: * alert(responseText); bos@574: * } bos@574: * }; bos@574: * $('#myForm').ajaxSubmit(options); bos@574: * @desc Submit form and alert the server response bos@574: * bos@574: * bos@574: * @example bos@574: * var options = { bos@574: * beforeSubmit: function(formArray, jqForm) { bos@574: * if (formArray.length == 0) { bos@574: * alert('Please enter data.'); bos@574: * return false; bos@574: * } bos@574: * } bos@574: * }; bos@574: * $('#myForm').ajaxSubmit(options); bos@574: * @desc Pre-submit validation which aborts the submit operation if form data is empty bos@574: * bos@574: * bos@574: * @example bos@574: * var options = { bos@574: * url: myJsonUrl.php, bos@574: * dataType: 'json', bos@574: * success: function(data) { bos@574: * // 'data' is an object representing the the evaluated json data bos@574: * } bos@574: * }; bos@574: * $('#myForm').ajaxSubmit(options); bos@574: * @desc json data returned and evaluated bos@574: * bos@574: * bos@574: * @example bos@574: * var options = { bos@574: * url: myXmlUrl.php, bos@574: * dataType: 'xml', bos@574: * success: function(responseXML) { bos@574: * // responseXML is XML document object bos@574: * var data = $('myElement', responseXML).text(); bos@574: * } bos@574: * }; bos@574: * $('#myForm').ajaxSubmit(options); bos@574: * @desc XML data returned from server bos@574: * bos@574: * bos@574: * @example bos@574: * var options = { bos@574: * resetForm: true bos@574: * }; bos@574: * $('#myForm').ajaxSubmit(options); bos@574: * @desc submit form and reset it if successful bos@574: * bos@574: * @example bos@574: * $('#myForm).submit(function() { bos@574: * $(this).ajaxSubmit(); bos@574: * return false; bos@574: * }); bos@574: * @desc Bind form's submit event to use ajaxSubmit bos@574: * bos@574: * bos@574: * @name ajaxSubmit bos@574: * @type jQuery bos@574: * @param options object literal containing options which control the form submission process bos@574: * @cat Plugins/Form bos@574: * @return jQuery bos@574: */ bos@574: $.fn.ajaxSubmit = function(options) { bos@574: if (typeof options == 'function') bos@574: options = { success: options }; bos@574: bos@574: options = $.extend({ bos@574: url: this.attr('action') || window.location, bos@574: type: this.attr('method') || 'GET' bos@574: }, options || {}); bos@574: bos@574: // hook for manipulating the form data before it is extracted; bos@574: // convenient for use with rich editors like tinyMCE or FCKEditor bos@574: var veto = {}; bos@574: $.event.trigger('form.pre.serialize', [this, options, veto]); bos@574: if (veto.veto) return this; bos@574: bos@574: var a = this.formToArray(options.semantic); bos@574: if (options.data) { bos@574: for (var n in options.data) bos@574: a.push( { name: n, value: options.data[n] } ); bos@574: } bos@574: bos@574: // give pre-submit callback an opportunity to abort the submit bos@574: if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this; bos@574: bos@574: // fire vetoable 'validate' event bos@574: $.event.trigger('form.submit.validate', [a, this, options, veto]); bos@574: if (veto.veto) return this; bos@574: bos@574: var q = $.param(a);//.replace(/%20/g,'+'); bos@574: bos@574: if (options.type.toUpperCase() == 'GET') { bos@574: options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; bos@574: options.data = null; // data is null for 'get' bos@574: } bos@574: else bos@574: options.data = q; // data is the query string for 'post' bos@574: bos@574: var $form = this, callbacks = []; bos@574: if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); bos@574: if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); bos@574: bos@574: // perform a load on the target only if dataType is not provided bos@574: if (!options.dataType && options.target) { bos@574: var oldSuccess = options.success || function(){}; bos@574: callbacks.push(function(data) { bos@574: if (this.evalScripts) bos@574: $(options.target).attr("innerHTML", data).evalScripts().each(oldSuccess, arguments); bos@574: else // jQuery v1.1.4 bos@574: $(options.target).html(data).each(oldSuccess, arguments); bos@574: }); bos@574: } bos@574: else if (options.success) bos@574: callbacks.push(options.success); bos@574: bos@574: options.success = function(data, status) { bos@574: for (var i=0, max=callbacks.length; i < max; i++) bos@574: callbacks[i](data, status, $form); bos@574: }; bos@574: bos@574: // are there files to upload? bos@574: var files = $('input:file', this).fieldValue(); bos@574: var found = false; bos@574: for (var j=0; j < files.length; j++) bos@574: if (files[j]) bos@574: found = true; bos@574: bos@574: if (options.iframe || found) // options.iframe allows user to force iframe mode bos@574: fileUpload(); bos@574: else bos@574: $.ajax(options); bos@574: bos@574: // fire 'notify' event bos@574: $.event.trigger('form.submit.notify', [this, options]); bos@574: return this; bos@574: bos@574: bos@574: // private function for handling file uploads (hat tip to YAHOO!) bos@574: function fileUpload() { bos@574: var form = $form[0]; bos@574: var opts = $.extend({}, $.ajaxSettings, options); bos@574: bos@574: var id = 'jqFormIO' + $.fn.ajaxSubmit.counter++; bos@574: var $io = $('