* Updated to latest form plugin (2.36), fixing http://plugins.jquery.com/node/11487

This commit is contained in:
Jörn Zaeffferer
2009-11-23 20:36:41 +00:00
parent 7c5d366b08
commit d797e258e8
2 changed files with 506 additions and 664 deletions

View File

@@ -8,6 +8,7 @@
* Added localized methods for DE, NL and PT_BR, removing the dateDE and numberDE methods (use messages_de.js and methods_de.js with date and number methods instead) * Added localized methods for DE, NL and PT_BR, removing the dateDE and numberDE methods (use messages_de.js and methods_de.js with date and number methods instead)
* Fixed remote form submit synchronization, kudos to Matas Petrikas * Fixed remote form submit synchronization, kudos to Matas Petrikas
* Improved interactive select validation, now validating also on click (via option or select, inconsistent across browsers); doesn't work in Safari, which doesn't trigger a click event at all on select elements; fixes http://plugins.jquery.com/node/11520 * Improved interactive select validation, now validating also on click (via option or select, inconsistent across browsers); doesn't work in Safari, which doesn't trigger a click event at all on select elements; fixes http://plugins.jquery.com/node/11520
* Updated to latest form plugin (2.36), fixing http://plugins.jquery.com/node/11487
1.5.5 1.5.5
--- ---

View File

@@ -1,209 +1,113 @@
/* /*
* jQuery Form Plugin * jQuery Form Plugin
* @requires jQuery v1.1 or later * version: 2.36 (07-NOV-2009)
* @requires jQuery v1.2.6 or later
* *
* Examples at: http://malsup.com/jquery/form/ * Examples and documentation at: http://malsup.com/jquery/form/
* Dual licensed under the MIT and GPL licenses: * Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php * http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
*
* Revision: $Id: jquery.form.js 3028 2007-08-31 13:37:36Z joern.zaefferer $
*/ */
(function($) { ;(function($) {
/*
Usage Note:
-----------
Do not use both ajaxSubmit and ajaxForm on the same form. These
functions are intended to be exclusive. Use ajaxSubmit if you want
to bind your own submit handler to the form. For example,
$(document).ready(function() {
$('#myForm').bind('submit', function() {
$(this).ajaxSubmit({
target: '#output'
});
return false; // <-- important!
});
});
Use ajaxForm when you want the plugin to manage all the event binding
for you. For example,
$(document).ready(function() {
$('#myForm').ajaxForm({
target: '#output'
});
});
When using ajaxForm, the ajaxSubmit function will be invoked for you
at the appropriate time.
*/
/** /**
* ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX. * ajaxSubmit() provides a mechanism for immediately submitting
* * an HTML form using AJAX.
* ajaxSubmit accepts a single argument which can be either a success callback function
* or an options Object. If a function is provided it will be invoked upon successful
* completion of the submit and will be passed the response from the server.
* If an options Object is provided, the following attributes are supported:
*
* target: Identifies the element(s) in the page to be updated with the server response.
* This value may be specified as a jQuery selection string, a jQuery object,
* or a DOM element.
* default value: null
*
* url: URL to which the form data will be submitted.
* default value: value of form's 'action' attribute
*
* type: The method in which the form data should be submitted, 'GET' or 'POST'.
* default value: value of form's 'method' attribute (or 'GET' if none found)
*
* data: Additional data to add to the request, specified as key/value pairs (see $.ajax).
*
* beforeSubmit: Callback method to be invoked before the form is submitted.
* default value: null
*
* success: Callback method to be invoked after the form has been successfully submitted
* and the response has been returned from the server
* default value: null
*
* dataType: Expected dataType of the response. One of: null, 'xml', 'script', or 'json'
* default value: null
*
* semantic: Boolean flag indicating whether data must be submitted in semantic order (slower).
* default value: false
*
* resetForm: Boolean flag indicating whether the form should be reset if the submit is successful
*
* clearForm: Boolean flag indicating whether the form should be cleared if the submit is successful
*
*
* The 'beforeSubmit' callback can be provided as a hook for running pre-submit logic or for
* validating the form data. If the 'beforeSubmit' callback returns false then the form will
* not be submitted. The 'beforeSubmit' callback is invoked with three arguments: the form data
* in array format, the jQuery object, and the options object passed into ajaxSubmit.
* The form data array takes the following form:
*
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
*
* If a 'success' callback method is provided it is invoked after the response has been returned
* from the server. It is passed the responseText or responseXML value (depending on dataType).
* See jQuery.ajax for further details.
*
*
* The dataType option provides a means for specifying how the server response should be handled.
* This maps directly to the jQuery.httpData method. The following values are supported:
*
* 'xml': if dataType == 'xml' the server response is treated as XML and the 'success'
* callback method, if specified, will be passed the responseXML value
* 'json': if dataType == 'json' the server response will be evaluted and passed to
* the 'success' callback, if specified
* 'script': if dataType == 'script' the server response is evaluated in the global context
*
*
* Note that it does not make sense to use both the 'target' and 'dataType' options. If both
* are provided the target will be ignored.
*
* The semantic argument can be used to force form serialization in semantic order.
* This is normally true anyway, unless the form contains input elements of type='image'.
* If your form must be submitted with name/value pairs in semantic order and your form
* contains an input of type='image" then pass true for this arg, otherwise pass false
* (or nothing) to avoid the overhead for this logic.
*
*
* When used on its own, ajaxSubmit() is typically bound to a form's submit event like this:
*
* $("#form-id").submit(function() {
* $(this).ajaxSubmit(options);
* return false; // cancel conventional submit
* });
*
* When using ajaxForm(), however, this is done for you.
*
* @example
* $('#myForm').ajaxSubmit(function(data) {
* alert('Form submit succeeded! Server returned: ' + data);
* });
* @desc Submit form and alert server response
*
*
* @example
* var options = {
* target: '#myTargetDiv'
* };
* $('#myForm').ajaxSubmit(options);
* @desc Submit form and update page element with server response
*
*
* @example
* var options = {
* success: function(responseText) {
* alert(responseText);
* }
* };
* $('#myForm').ajaxSubmit(options);
* @desc Submit form and alert the server response
*
*
* @example
* var options = {
* beforeSubmit: function(formArray, jqForm) {
* if (formArray.length == 0) {
* alert('Please enter data.');
* return false;
* }
* }
* };
* $('#myForm').ajaxSubmit(options);
* @desc Pre-submit validation which aborts the submit operation if form data is empty
*
*
* @example
* var options = {
* url: myJsonUrl.php,
* dataType: 'json',
* success: function(data) {
* // 'data' is an object representing the the evaluated json data
* }
* };
* $('#myForm').ajaxSubmit(options);
* @desc json data returned and evaluated
*
*
* @example
* var options = {
* url: myXmlUrl.php,
* dataType: 'xml',
* success: function(responseXML) {
* // responseXML is XML document object
* var data = $('myElement', responseXML).text();
* }
* };
* $('#myForm').ajaxSubmit(options);
* @desc XML data returned from server
*
*
* @example
* var options = {
* resetForm: true
* };
* $('#myForm').ajaxSubmit(options);
* @desc submit form and reset it if successful
*
* @example
* $('#myForm).submit(function() {
* $(this).ajaxSubmit();
* return false;
* });
* @desc Bind form's submit event to use ajaxSubmit
*
*
* @name ajaxSubmit
* @type jQuery
* @param options object literal containing options which control the form submission process
* @cat Plugins/Form
* @return jQuery
*/ */
$.fn.ajaxSubmit = function(options) { $.fn.ajaxSubmit = function(options) {
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
if (!this.length) {
log('ajaxSubmit: skipping submit process - no element selected');
return this;
}
if (typeof options == 'function') if (typeof options == 'function')
options = { success: options }; options = { success: options };
var url = $.trim(this.attr('action'));
if (url) {
// clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/)||[])[1];
}
url = url || window.location.href || '';
options = $.extend({ options = $.extend({
url: this.attr('action') || window.location, url: url,
type: this.attr('method') || 'GET' type: this.attr('method') || 'GET',
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, options || {}); }, options || {});
// hook for manipulating the form data before it is extracted; // hook for manipulating the form data before it is extracted;
// convenient for use with rich editors like tinyMCE or FCKEditor // convenient for use with rich editors like tinyMCE or FCKEditor
var veto = {}; var veto = {};
$.event.trigger('form.pre.serialize', [this, options, veto]); this.trigger('form-pre-serialize', [this, options, veto]);
if (veto.veto) return this; if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
return this;
}
// provide opportunity to alter form data before it is serialized
if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
log('ajaxSubmit: submit aborted via beforeSerialize callback');
return this;
}
var a = this.formToArray(options.semantic); var a = this.formToArray(options.semantic);
if (options.data) { if (options.data) {
for (var n in options.data) options.extraData = options.data;
for (var n in options.data) {
if(options.data[n] instanceof Array) {
for (var k in options.data[n])
a.push( { name: n, value: options.data[n][k] } );
}
else
a.push( { name: n, value: options.data[n] } ); a.push( { name: n, value: options.data[n] } );
} }
}
// give pre-submit callback an opportunity to abort the submit // give pre-submit callback an opportunity to abort the submit
if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this; if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
log('ajaxSubmit: submit aborted via beforeSubmit callback');
return this;
}
// fire vetoable 'validate' event // fire vetoable 'validate' event
$.event.trigger('form.submit.validate', [a, this, options, veto]); this.trigger('form-submit-validate', [a, this, options, veto]);
if (veto.veto) return this; if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
return this;
}
var q = $.param(a);//.replace(/%20/g,'+'); var q = $.param(a);
if (options.type.toUpperCase() == 'GET') { if (options.type.toUpperCase() == 'GET') {
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
@@ -220,9 +124,6 @@ $.fn.ajaxSubmit = function(options) {
if (!options.dataType && options.target) { if (!options.dataType && options.target) {
var oldSuccess = options.success || function(){}; var oldSuccess = options.success || function(){};
callbacks.push(function(data) { callbacks.push(function(data) {
if (this.evalScripts)
$(options.target).attr("innerHTML", data).evalScripts().each(oldSuccess, arguments);
else // jQuery v1.1.4
$(options.target).html(data).each(oldSuccess, arguments); $(options.target).html(data).each(oldSuccess, arguments);
}); });
} }
@@ -231,7 +132,7 @@ $.fn.ajaxSubmit = function(options) {
options.success = function(data, status) { options.success = function(data, status) {
for (var i=0, max=callbacks.length; i < max; i++) for (var i=0, max=callbacks.length; i < max; i++)
callbacks[i](data, status, $form); callbacks[i].apply(options, [data, status, $form]);
}; };
// are there files to upload? // are there files to upload?
@@ -241,36 +142,59 @@ $.fn.ajaxSubmit = function(options) {
if (files[j]) if (files[j])
found = true; found = true;
if (options.iframe || found) // options.iframe allows user to force iframe mode var multipart = false;
// var mp = 'multipart/form-data';
// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
// options.iframe allows user to force iframe mode
// 06-NOV-09: now defaulting to iframe mode if file input is detected
if ((files.length && options.iframe !== false) || options.iframe || found || multipart) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive)
$.get(options.closeKeepAlive, fileUpload);
else
fileUpload(); fileUpload();
}
else else
$.ajax(options); $.ajax(options);
// fire 'notify' event // fire 'notify' event
$.event.trigger('form.submit.notify', [this, options]); this.trigger('form-submit-notify', [this, options]);
return this; return this;
// private function for handling file uploads (hat tip to YAHOO!) // private function for handling file uploads (hat tip to YAHOO!)
function fileUpload() { function fileUpload() {
var form = $form[0]; var form = $form[0];
var opts = $.extend({}, $.ajaxSettings, options);
var id = 'jqFormIO' + $.fn.ajaxSubmit.counter++; if ($(':input[name=submit]', form).length) {
var $io = $('<iframe id="' + id + '" name="' + id + '" />'); alert('Error: Form elements must not be named "submit".');
return;
}
var opts = $.extend({}, $.ajaxSettings, options);
var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
var id = 'jqFormIO' + (new Date().getTime());
var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ opts.iframeSrc +'" />');
var io = $io[0]; var io = $io[0];
var op8 = $.browser.opera && window.opera.version() < 9;
if ($.browser.msie || op8) io.src = 'javascript:false;document.write("");';
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
var xhr = { // mock object var xhr = { // mock object
aborted: 0,
responseText: null, responseText: null,
responseXML: null, responseXML: null,
status: 0, status: 0,
statusText: 'n/a', statusText: 'n/a',
getAllResponseHeaders: function() {}, getAllResponseHeaders: function() {},
getResponseHeader: function() {}, getResponseHeader: function() {},
setRequestHeader: function() {} setRequestHeader: function() {},
abort: function() {
this.aborted = 1;
$io.attr('src', opts.iframeSrc); // abort op in progress
}
}; };
var g = opts.global; var g = opts.global;
@@ -278,33 +202,78 @@ $.fn.ajaxSubmit = function(options) {
if (g && ! $.active++) $.event.trigger("ajaxStart"); if (g && ! $.active++) $.event.trigger("ajaxStart");
if (g) $.event.trigger("ajaxSend", [xhr, opts]); if (g) $.event.trigger("ajaxSend", [xhr, opts]);
if (s.beforeSend && s.beforeSend(xhr, s) === false) {
s.global && $.active--;
return;
}
if (xhr.aborted)
return;
var cbInvoked = 0; var cbInvoked = 0;
var timedOut = 0; var timedOut = 0;
// add submitting element to data if we know it
var sub = form.clk;
if (sub) {
var n = sub.name;
if (n && !sub.disabled) {
options.extraData = options.extraData || {};
options.extraData[n] = sub.value;
if (sub.type == "image") {
options.extraData[name+'.x'] = form.clk_x;
options.extraData[name+'.y'] = form.clk_y;
}
}
}
// take a breath so that pending repaints get some cpu time before the upload starts // take a breath so that pending repaints get some cpu time before the upload starts
setTimeout(function() { setTimeout(function() {
$io.appendTo('body');
// jQuery's event binding doesn't work for iframe events in IE
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
// make sure form attrs are set // make sure form attrs are set
var encAttr = form.encoding ? 'encoding' : 'enctype'; var t = $form.attr('target'), a = $form.attr('action');
var t = $form.attr('target');
// update form attrs in IE friendly way
form.setAttribute('target',id);
if (form.getAttribute('method') != 'POST')
form.setAttribute('method', 'POST');
if (form.getAttribute('action') != opts.url)
form.setAttribute('action', opts.url);
// ie borks in some cases when setting encoding
if (! options.skipEncodingOverride) {
$form.attr({ $form.attr({
target: id, encoding: 'multipart/form-data',
method: 'POST', enctype: 'multipart/form-data'
action: opts.url
}); });
form[encAttr] = 'multipart/form-data'; }
// support timout // support timout
if (opts.timeout) if (opts.timeout)
setTimeout(function() { timedOut = true; cb(); }, opts.timeout); setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
// add "extra" data to form if provided in options
var extraInputs = [];
try {
if (options.extraData)
for (var n in options.extraData)
extraInputs.push(
$('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
.appendTo(form)[0]);
// add iframe to doc and submit the form
$io.appendTo('body');
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
form.submit(); form.submit();
$form.attr('target', t); // reset target }
finally {
// reset attrs and remove "extra" input elements
form.setAttribute('action',a);
t ? form.setAttribute('target', t) : $form.removeAttr('target');
$(extraInputs).remove();
}
}, 10); }, 10);
var domCheckCount = 50;
function cb() { function cb() {
if (cbInvoked++) return; if (cbInvoked++) return;
@@ -315,27 +284,47 @@ $.fn.ajaxSubmit = function(options) {
if (timedOut) throw 'timeout'; if (timedOut) throw 'timeout';
// extract the server response from the iframe // extract the server response from the iframe
var data, doc; var data, doc;
doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
log('isXml='+isXml);
if (!isXml && (doc.body == null || doc.body.innerHTML == '')) {
if (--domCheckCount) {
// in some browsers (Opera) the iframe DOM is not always traversable when
// the onload callback fires, so we loop a bit to accommodate
cbInvoked = 0;
setTimeout(cb, 100);
return;
}
log('Could not access iframe DOM after 50 tries.');
return;
}
xhr.responseText = doc.body ? doc.body.innerHTML : null; xhr.responseText = doc.body ? doc.body.innerHTML : null;
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
xhr.getResponseHeader = function(header){
var headers = {'content-type': opts.dataType};
return headers[header];
};
if (opts.dataType == 'json' || opts.dataType == 'script') { if (opts.dataType == 'json' || opts.dataType == 'script') {
// see if user embedded response in textarea
var ta = doc.getElementsByTagName('textarea')[0]; var ta = doc.getElementsByTagName('textarea')[0];
data = ta ? ta.value : xhr.responseText; if (ta)
if (opts.dataType == 'json') xhr.responseText = ta.value;
eval("data = " + data);
else
$.globalEval(data);
}
else if (opts.dataType == 'xml') {
data = xhr.responseXML;
if (!data && xhr.responseText != null)
data = toXml(xhr.responseText);
}
else { else {
data = xhr.responseText; // account for browsers injecting pre around json response
var pre = doc.getElementsByTagName('pre')[0];
if (pre)
xhr.responseText = pre.innerHTML;
} }
} }
else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
xhr.responseXML = toXml(xhr.responseText);
}
data = $.httpData(xhr, opts.dataType);
}
catch(e){ catch(e){
ok = false; ok = false;
$.handleError(opts, xhr, 'error', e); $.handleError(opts, xhr, 'error', e);
@@ -369,7 +358,6 @@ $.fn.ajaxSubmit = function(options) {
}; };
}; };
}; };
$.fn.ajaxSubmit.counter = 0; // used to create unique iframe ids
/** /**
* ajaxForm() provides a mechanism for fully automating form submission. * ajaxForm() provides a mechanism for fully automating form submission.
@@ -382,107 +370,47 @@ $.fn.ajaxSubmit.counter = 0; // used to create unique iframe ids
* used to submit the form). * used to submit the form).
* 3. This method binds the submit() method to the form for you. * 3. This method binds the submit() method to the form for you.
* *
* Note that for accurate x/y coordinates of image submit elements in all browsers
* you need to also use the "dimensions" plugin (this method will auto-detect its presence).
*
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
* passes the options argument along after properly binding events for submit elements and * passes the options argument along after properly binding events for submit elements and
* the form itself. See ajaxSubmit for a full description of the options argument. * the form itself.
*
*
* @example
* var options = {
* target: '#myTargetDiv'
* };
* $('#myForm').ajaxSForm(options);
* @desc Bind form's submit event so that 'myTargetDiv' is updated with the server response
* when the form is submitted.
*
*
* @example
* var options = {
* success: function(responseText) {
* alert(responseText);
* }
* };
* $('#myForm').ajaxSubmit(options);
* @desc Bind form's submit event so that server response is alerted after the form is submitted.
*
*
* @example
* var options = {
* beforeSubmit: function(formArray, jqForm) {
* if (formArray.length == 0) {
* alert('Please enter data.');
* return false;
* }
* }
* };
* $('#myForm').ajaxSubmit(options);
* @desc Bind form's submit event so that pre-submit callback is invoked before the form
* is submitted.
*
*
* @name ajaxForm
* @param options object literal containing options which control the form submission process
* @return jQuery
* @cat Plugins/Form
* @type jQuery
*/ */
$.fn.ajaxForm = function(options) { $.fn.ajaxForm = function(options) {
return this.ajaxFormUnbind().submit(submitHandler).each(function() { return this.ajaxFormUnbind().bind('submit.form-plugin', function() {
// store options in hash $(this).ajaxSubmit(options);
this.formPluginId = $.fn.ajaxForm.counter++; return false;
$.fn.ajaxForm.optionHash[this.formPluginId] = options; }).bind('click.form-plugin', function(e) {
$(":submit,input:image", this).click(clickHandler); var target = e.target;
}); var $el = $(target);
}; if (!($el.is(":submit,input:image"))) {
// is this a child element of the submit el? (ex: a span within a button)
$.fn.ajaxForm.counter = 1; var t = $el.closest(':submit');
$.fn.ajaxForm.optionHash = {}; if (t.length == 0)
return;
function clickHandler(e) { target = t[0];
var $form = this.form; }
$form.clk = this; var form = this;
if (this.type == 'image') { form.clk = target;
if (target.type == 'image') {
if (e.offsetX != undefined) { if (e.offsetX != undefined) {
$form.clk_x = e.offsetX; form.clk_x = e.offsetX;
$form.clk_y = e.offsetY; form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
var offset = $(this).offset(); var offset = $el.offset();
$form.clk_x = e.pageX - offset.left; form.clk_x = e.pageX - offset.left;
$form.clk_y = e.pageY - offset.top; form.clk_y = e.pageY - offset.top;
} else { } else {
$form.clk_x = e.pageX - this.offsetLeft; form.clk_x = e.pageX - target.offsetLeft;
$form.clk_y = e.pageY - this.offsetTop; form.clk_y = e.pageY - target.offsetTop;
} }
} }
// clear form vars // clear form vars
setTimeout(function() { $form.clk = $form.clk_x = $form.clk_y = null; }, 10); setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
};
function submitHandler() {
// retrieve options from hash
var id = this.formPluginId;
var options = $.fn.ajaxForm.optionHash[id];
$(this).ajaxSubmit(options);
return false;
};
/**
* ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
*
* @name ajaxFormUnbind
* @return jQuery
* @cat Plugins/Form
* @type jQuery
*/
$.fn.ajaxFormUnbind = function() {
this.unbind('submit', submitHandler);
return this.each(function() {
$(":submit,input:image", this).unbind('click', clickHandler);
}); });
};
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
return this.unbind('submit.form-plugin click.form-plugin');
}; };
/** /**
@@ -495,21 +423,6 @@ $.fn.ajaxFormUnbind = function() {
* *
* It is this array that is passed to pre-submit callback functions provided to the * It is this array that is passed to pre-submit callback functions provided to the
* ajaxSubmit() and ajaxForm() methods. * ajaxSubmit() and ajaxForm() methods.
*
* The semantic argument can be used to force form serialization in semantic order.
* This is normally true anyway, unless the form contains input elements of type='image'.
* If your form must be submitted with name/value pairs in semantic order and your form
* contains an input of type='image" then pass true for this arg, otherwise pass false
* (or nothing) to avoid the overhead for this logic.
*
* @example var data = $("#myForm").formToArray();
* $.post( "myscript.cgi", data );
* @desc Collect all the data from a form and submit it to the server.
*
* @name formToArray
* @param semantic true if serialization must maintain strict semantic ordering of elements (slower)
* @type Array<Object>
* @cat Plugins/Form
*/ */
$.fn.formToArray = function(semantic) { $.fn.formToArray = function(semantic) {
var a = []; var a = [];
@@ -525,8 +438,10 @@ $.fn.formToArray = function(semantic) {
if (semantic && form.clk && el.type == "image") { if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true // handle image inputs on the fly when semantic == true
if(!el.disabled && form.clk == el) if(!el.disabled && form.clk == el) {
a.push({name: n, value: $(el).val()});
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
}
continue; continue;
} }
@@ -540,70 +455,28 @@ $.fn.formToArray = function(semantic) {
} }
if (!semantic && form.clk) { if (!semantic && form.clk) {
// input type=='image' are not found in elements array! handle them here // input type=='image' are not found in elements array! handle it here
var inputs = form.getElementsByTagName("input"); var $input = $(form.clk), input = $input[0], n = input.name;
for(var i=0, max=inputs.length; i < max; i++) { if (n && !input.disabled && input.type == 'image') {
var input = inputs[i]; a.push({name: n, value: $input.val()});
var n = input.name;
if(n && !input.disabled && input.type == "image" && form.clk == input)
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
} }
} }
return a; return a;
}; };
/** /**
* Serializes form data into a 'submittable' string. This method will return a string * Serializes form data into a 'submittable' string. This method will return a string
* in the format: name1=value1&amp;name2=value2 * in the format: name1=value1&amp;name2=value2
*
* The semantic argument can be used to force form serialization in semantic order.
* If your form must be submitted with name/value pairs in semantic order then pass
* true for this arg, otherwise pass false (or nothing) to avoid the overhead for
* this logic (which can be significant for very large forms).
*
* @example var data = $("#myForm").formSerialize();
* $.ajax('POST', "myscript.cgi", data);
* @desc Collect all the data from a form into a single string
*
* @name formSerialize
* @param semantic true if serialization must maintain strict semantic ordering of elements (slower)
* @type String
* @cat Plugins/Form
*/ */
$.fn.formSerialize = function(semantic) { $.fn.formSerialize = function(semantic) {
//hand off to jQuery.param for proper encoding //hand off to jQuery.param for proper encoding
return $.param(this.formToArray(semantic)); return $.param(this.formToArray(semantic));
}; };
/** /**
* Serializes all field elements in the jQuery object into a query string. * Serializes all field elements in the jQuery object into a query string.
* This method will return a string in the format: name1=value1&amp;name2=value2 * This method will return a string in the format: name1=value1&amp;name2=value2
*
* The successful argument controls whether or not serialization is limited to
* 'successful' controls (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
* The default value of the successful argument is true.
*
* @example var data = $("input").formSerialize();
* @desc Collect the data from all successful input elements into a query string
*
* @example var data = $(":radio").formSerialize();
* @desc Collect the data from all successful radio input elements into a query string
*
* @example var data = $("#myForm :checkbox").formSerialize();
* @desc Collect the data from all successful checkbox input elements in myForm into a query string
*
* @example var data = $("#myForm :checkbox").formSerialize(false);
* @desc Collect the data from all checkbox elements in myForm (even the unchecked ones) into a query string
*
* @example var data = $(":input").formSerialize();
* @desc Collect the data from all successful input, select, textarea and button elements into a query string
*
* @name fieldSerialize
* @param successful true if only successful controls should be serialized (default is true)
* @type String
* @cat Plugins/Form
*/ */
$.fn.fieldSerialize = function(successful) { $.fn.fieldSerialize = function(successful) {
var a = []; var a = [];
@@ -622,7 +495,6 @@ $.fn.fieldSerialize = function(successful) {
return $.param(a); return $.param(a);
}; };
/** /**
* Returns the value(s) of the element in the matched set. For example, consider the following form: * Returns the value(s) of the element in the matched set. For example, consider the following form:
* *
@@ -660,30 +532,6 @@ $.fn.fieldSerialize = function(successful) {
* *
* Note: This method *always* returns an array. If no valid value can be determined the * Note: This method *always* returns an array. If no valid value can be determined the
* array will be empty, otherwise it will contain one or more values. * array will be empty, otherwise it will contain one or more values.
*
* @example var data = $("#myPasswordElement").fieldValue();
* alert(data[0]);
* @desc Alerts the current value of the myPasswordElement element
*
* @example var data = $("#myForm :input").fieldValue();
* @desc Get the value(s) of the form elements in myForm
*
* @example var data = $("#myForm :checkbox").fieldValue();
* @desc Get the value(s) for the successful checkbox element(s) in the jQuery object.
*
* @example var data = $("#mySingleSelect").fieldValue();
* @desc Get the value(s) of the select control
*
* @example var data = $(':text').fieldValue();
* @desc Get the value(s) of the text input or textarea elements
*
* @example var data = $("#myMultiSelect").fieldValue();
* @desc Get the values for the select-multiple control
*
* @name fieldValue
* @param Boolean successful true if only the values for successful controls should be returned (default is true)
* @type Array<String>
* @cat Plugins/Form
*/ */
$.fn.fieldValue = function(successful) { $.fn.fieldValue = function(successful) {
for (var val=[], i=0, max=this.length; i < max; i++) { for (var val=[], i=0, max=this.length; i < max; i++) {
@@ -698,24 +546,6 @@ $.fn.fieldValue = function(successful) {
/** /**
* Returns the value of the field element. * Returns the value of the field element.
*
* The successful argument controls whether or not the field element must be 'successful'
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
* The default value of the successful argument is true. If the given element is not
* successful and the successful arg is not false then the returned value will be null.
*
* Note: If the successful flag is true (default) but the element is not successful, the return will be null
* Note: The value returned for a successful select-multiple element will always be an array.
* Note: If the element has no value the return value will be undefined.
*
* @example var data = jQuery.fieldValue($("#myPasswordElement")[0]);
* @desc Gets the current value of the myPasswordElement element
*
* @name fieldValue
* @param Element el The DOM element for which the value will be returned
* @param Boolean successful true if value returned must be for a successful controls (default is true)
* @type String or Array<String> or null or undefined
* @cat Plugins/Form
*/ */
$.fieldValue = function(el, successful) { $.fieldValue = function(el, successful) {
var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
@@ -736,8 +566,9 @@ $.fieldValue = function(el, successful) {
for(var i=(one ? index : 0); i < max; i++) { for(var i=(one ? index : 0); i < max; i++) {
var op = ops[i]; var op = ops[i];
if (op.selected) { if (op.selected) {
// extra pain for IE... var v = op.value;
var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value; if (!v) // extra pain for IE...
v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
if (one) return v; if (one) return v;
a.push(v); a.push(v);
} }
@@ -747,7 +578,6 @@ $.fieldValue = function(el, successful) {
return el.value; return el.value;
}; };
/** /**
* Clears the form data. Takes the following actions on the form's input fields: * Clears the form data. Takes the following actions on the form's input fields:
* - input text fields will have their 'value' property set to the empty string * - input text fields will have their 'value' property set to the empty string
@@ -755,13 +585,6 @@ $.fieldValue = function(el, successful) {
* - checkbox and radio inputs will have their 'checked' property set to false * - checkbox and radio inputs will have their 'checked' property set to false
* - inputs of type submit, button, reset, and hidden will *not* be effected * - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected * - button elements will *not* be effected
*
* @example $('form').clearForm();
* @desc Clears all forms on the page.
*
* @name clearForm
* @type jQuery
* @cat Plugins/Form
*/ */
$.fn.clearForm = function() { $.fn.clearForm = function() {
return this.each(function() { return this.each(function() {
@@ -770,19 +593,7 @@ $.fn.clearForm = function() {
}; };
/** /**
* Clears the selected form elements. Takes the following actions on the matched elements: * Clears the selected form elements.
* - input text fields will have their 'value' property set to the empty string
* - select elements will have their 'selectedIndex' property set to -1
* - checkbox and radio inputs will have their 'checked' property set to false
* - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected
*
* @example $('.myInputs').clearFields();
* @desc Clears all inputs with class myInputs
*
* @name clearFields
* @type jQuery
* @cat Plugins/Form
*/ */
$.fn.clearFields = $.fn.clearInputs = function() { $.fn.clearFields = $.fn.clearInputs = function() {
return this.each(function() { return this.each(function() {
@@ -796,16 +607,8 @@ $.fn.clearFields = $.fn.clearInputs = function() {
}); });
}; };
/** /**
* Resets the form data. Causes all form elements to be reset to their original value. * Resets the form data. Causes all form elements to be reset to their original value.
*
* @example $('form').resetForm();
* @desc Resets all forms on the page.
*
* @name resetForm
* @type jQuery
* @cat Plugins/Form
*/ */
$.fn.resetForm = function() { $.fn.resetForm = function() {
return this.each(function() { return this.each(function() {
@@ -816,4 +619,42 @@ $.fn.resetForm = function() {
}); });
}; };
/**
* Enables or disables any matching elements.
*/
$.fn.enable = function(b) {
if (b == undefined) b = true;
return this.each(function() {
this.disabled = !b;
});
};
/**
* Checks/unchecks any matching checkboxes or radio buttons and
* selects/deselects and matching option elements.
*/
$.fn.selected = function(select) {
if (select == undefined) select = true;
return this.each(function() {
var t = this.type;
if (t == 'checkbox' || t == 'radio')
this.checked = select;
else if (this.tagName.toLowerCase() == 'option') {
var $sel = $(this).parent('select');
if (select && $sel[0] && $sel[0].type == 'select-one') {
// deselect all other options
$sel.find('option').selected(false);
}
this.selected = select;
}
});
};
// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
};
})(jQuery); })(jQuery);