3
* version: 3.37.0-2013.07.11
4
* @requires jQuery v1.5 or later
5
* Copyright (c) 2013 M. Alsup
6
* Examples and documentation at: http://malsup.com/jquery/form/
7
* Project repository: https://github.com/malsup/form
8
* Dual licensed under the MIT and GPL licenses.
9
* https://github.com/malsup/form#copyright-and-license
11
/*global ActiveXObject */
18
Do not use both ajaxSubmit and ajaxForm on the same form. These
19
functions are mutually exclusive. Use ajaxSubmit if you want
20
to bind your own submit handler to the form. For example,
22
$(document).ready(function() {
23
$('#myForm').on('submit', function(e) {
24
e.preventDefault(); // <-- important
31
Use ajaxForm when you want the plugin to manage all the event binding
34
$(document).ready(function() {
35
$('#myForm').ajaxForm({
40
You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
41
form does not have to exist when you invoke ajaxForm:
43
$('#myForm').ajaxForm({
48
When using ajaxForm, the ajaxSubmit function will be invoked for you
49
at the appropriate time.
56
feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
57
feature.formdata = window.FormData !== undefined;
59
var hasProp = !!$.fn.prop;
61
// attr2 uses prop when it can but checks the return type for
62
// an expected string. this accounts for the case where a form
63
// contains inputs with names like "action" or "method"; in those
64
// cases "prop" returns the element
65
$.fn.attr2 = function() {
67
return this.attr.apply(this, arguments);
68
var val = this.prop.apply(this, arguments);
69
if ( ( val && val.jquery ) || typeof val === 'string' )
71
return this.attr.apply(this, arguments);
75
* ajaxSubmit() provides a mechanism for immediately submitting
76
* an HTML form using AJAX.
78
$.fn.ajaxSubmit = function(options) {
79
/*jshint scripturl:true */
81
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
83
log('ajaxSubmit: skipping submit process - no element selected');
87
var method, action, url, $form = this;
89
if (typeof options == 'function') {
90
options = { success: options };
92
else if ( options === undefined ) {
96
method = options.type || this.attr2('method');
97
action = options.url || this.attr2('action');
99
url = (typeof action === 'string') ? $.trim(action) : '';
100
url = url || window.location.href || '';
102
// clean url (don't include hash vaue)
103
url = (url.match(/^([^#]+)/)||[])[1];
106
options = $.extend(true, {
108
success: $.ajaxSettings.success,
109
type: method || 'GET',
110
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
113
// hook for manipulating the form data before it is extracted;
114
// convenient for use with rich editors like tinyMCE or FCKEditor
116
this.trigger('form-pre-serialize', [this, options, veto]);
118
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
122
// provide opportunity to alter form data before it is serialized
123
if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
124
log('ajaxSubmit: submit aborted via beforeSerialize callback');
128
var traditional = options.traditional;
129
if ( traditional === undefined ) {
130
traditional = $.ajaxSettings.traditional;
134
var qx, a = this.formToArray(options.semantic, elements);
136
options.extraData = options.data;
137
qx = $.param(options.data, traditional);
140
// give pre-submit callback an opportunity to abort the submit
141
if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
142
log('ajaxSubmit: submit aborted via beforeSubmit callback');
146
// fire vetoable 'validate' event
147
this.trigger('form-submit-validate', [a, this, options, veto]);
149
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
153
var q = $.param(a, traditional);
155
q = ( q ? (q + '&' + qx) : qx );
157
if (options.type.toUpperCase() == 'GET') {
158
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
159
options.data = null; // data is null for 'get'
162
options.data = q; // data is the query string for 'post'
166
if (options.resetForm) {
167
callbacks.push(function() { $form.resetForm(); });
169
if (options.clearForm) {
170
callbacks.push(function() { $form.clearForm(options.includeHidden); });
173
// perform a load on the target only if dataType is not provided
174
if (!options.dataType && options.target) {
175
var oldSuccess = options.success || function(){};
176
callbacks.push(function(data) {
177
var fn = options.replaceTarget ? 'replaceWith' : 'html';
178
$(options.target)[fn](data).each(oldSuccess, arguments);
181
else if (options.success) {
182
callbacks.push(options.success);
185
options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
186
var context = options.context || this ; // jQuery 1.4+ supports scope context
187
for (var i=0, max=callbacks.length; i < max; i++) {
188
callbacks[i].apply(context, [data, status, xhr || $form, $form]);
193
var oldError = options.error;
194
options.error = function(xhr, status, error) {
195
var context = options.context || this;
196
oldError.apply(context, [xhr, status, error, $form]);
200
if (options.complete) {
201
var oldComplete = options.complete;
202
options.complete = function(xhr, status) {
203
var context = options.context || this;
204
oldComplete.apply(context, [xhr, status, $form]);
208
// are there files to upload?
210
// [value] (issue #113), also see comment:
211
// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
212
var fileInputs = $('input[type=file]:enabled[value!=""]', this);
214
var hasFileInputs = fileInputs.length > 0;
215
var mp = 'multipart/form-data';
216
var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
218
var fileAPI = feature.fileapi && feature.formdata;
219
log("fileAPI :" + fileAPI);
220
var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
224
// options.iframe allows user to force iframe mode
225
// 06-NOV-09: now defaulting to iframe mode if file input is detected
226
if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
227
// hack to fix Safari hang (thanks to Tim Molendijk for this)
228
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
229
if (options.closeKeepAlive) {
230
$.get(options.closeKeepAlive, function() {
231
jqxhr = fileUploadIframe(a);
235
jqxhr = fileUploadIframe(a);
238
else if ((hasFileInputs || multipart) && fileAPI) {
239
jqxhr = fileUploadXhr(a);
242
jqxhr = $.ajax(options);
245
$form.removeData('jqxhr').data('jqxhr', jqxhr);
247
// clear element array
248
for (var k=0; k < elements.length; k++)
251
// fire 'notify' event
252
this.trigger('form-submit-notify', [this, options]);
255
// utility fn for deep serialization
256
function deepSerialize(extraData){
257
var serialized = $.param(extraData, options.traditional).split('&');
258
var len = serialized.length;
261
for (i=0; i < len; i++) {
262
// #252; undo param space replacement
263
serialized[i] = serialized[i].replace(/\+/g,' ');
264
part = serialized[i].split('=');
265
// #278; use array instead of object storage, favoring array serializations
266
result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
271
// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
272
function fileUploadXhr(a) {
273
var formdata = new FormData();
275
for (var i=0; i < a.length; i++) {
276
formdata.append(a[i].name, a[i].value);
279
if (options.extraData) {
280
var serializedData = deepSerialize(options.extraData);
281
for (i=0; i < serializedData.length; i++)
282
if (serializedData[i])
283
formdata.append(serializedData[i][0], serializedData[i][1]);
288
var s = $.extend(true, {}, $.ajaxSettings, options, {
292
type: method || 'POST'
295
if (options.uploadProgress) {
296
// workaround because jqXHR does not expose upload property
298
var xhr = $.ajaxSettings.xhr();
300
xhr.upload.addEventListener('progress', function(event) {
302
var position = event.loaded || event.position; /*event.position is deprecated*/
303
var total = event.total;
304
if (event.lengthComputable) {
305
percent = Math.ceil(position / total * 100);
307
options.uploadProgress(event, position, total, percent);
315
var beforeSend = s.beforeSend;
316
s.beforeSend = function(xhr, o) {
319
beforeSend.call(this, xhr, o);
324
// private function for handling file uploads (hat tip to YAHOO!)
325
function fileUploadIframe(a) {
326
var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
327
var deferred = $.Deferred();
330
// ensure that every serialized input is still enabled
331
for (i=0; i < elements.length; i++) {
334
el.prop('disabled', false);
336
el.removeAttr('disabled');
340
s = $.extend(true, {}, $.ajaxSettings, options);
341
s.context = s.context || s;
342
id = 'jqFormIO' + (new Date().getTime());
343
if (s.iframeTarget) {
344
$io = $(s.iframeTarget);
345
n = $io.attr2('name');
347
$io.attr2('name', id);
352
$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
353
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
358
xhr = { // mock object
364
getAllResponseHeaders: function() {},
365
getResponseHeader: function() {},
366
setRequestHeader: function() {},
367
abort: function(status) {
368
var e = (status === 'timeout' ? 'timeout' : 'aborted');
369
log('aborting upload... ' + e);
373
if (io.contentWindow.document.execCommand) {
374
io.contentWindow.document.execCommand('Stop');
379
$io.attr('src', s.iframeSrc); // abort op in progress
382
s.error.call(s.context, xhr, e, status);
384
$.event.trigger("ajaxError", [xhr, s, e]);
386
s.complete.call(s.context, xhr, e);
391
// trigger ajax global events so that activity/block indicators work like normal
392
if (g && 0 === $.active++) {
393
$.event.trigger("ajaxStart");
396
$.event.trigger("ajaxSend", [xhr, s]);
399
if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
411
// add submitting element to data if we know it
415
if (n && !sub.disabled) {
416
s.extraData = s.extraData || {};
417
s.extraData[n] = sub.value;
418
if (sub.type == "image") {
419
s.extraData[n+'.x'] = form.clk_x;
420
s.extraData[n+'.y'] = form.clk_y;
425
var CLIENT_TIMEOUT_ABORT = 1;
426
var SERVER_ABORT = 2;
428
function getDoc(frame) {
429
/* it looks like contentWindow or contentDocument do not
430
* carry the protocol property in ie8, when running under ssl
431
* frame.document is the only valid response document, since
432
* the protocol is know but not on the other two objects. strange?
433
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
438
// IE8 cascading access check
440
if (frame.contentWindow) {
441
doc = frame.contentWindow.document;
444
// IE8 access denied under ssl & missing protocol
445
log('cannot get iframe.contentWindow document: ' + err);
448
if (doc) { // successful getting content
452
try { // simply checking may throw in ie8 under ssl or mismatched protocol
453
doc = frame.contentDocument ? frame.contentDocument : frame.document;
456
log('cannot get iframe.contentDocument: ' + err);
457
doc = frame.document;
462
// Rails CSRF hack (thanks to Yvan Barthelemy)
463
var csrf_token = $('meta[name=csrf-token]').attr('content');
464
var csrf_param = $('meta[name=csrf-param]').attr('content');
465
if (csrf_param && csrf_token) {
466
s.extraData = s.extraData || {};
467
s.extraData[csrf_param] = csrf_token;
470
// take a breath so that pending repaints get some cpu time before the upload starts
471
function doSubmit() {
472
// make sure form attrs are set
473
var t = $form.attr2('target'), a = $form.attr2('action');
475
// update form attrs in IE friendly way
476
form.setAttribute('target',id);
478
form.setAttribute('method', 'POST');
481
form.setAttribute('action', s.url);
484
// ie borks in some cases when setting encoding
485
if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
487
encoding: 'multipart/form-data',
488
enctype: 'multipart/form-data'
494
timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
497
// look for server aborts
498
function checkState() {
500
var state = getDoc(io).readyState;
501
log('state = ' + state);
502
if (state && state.toLowerCase() == 'uninitialized')
503
setTimeout(checkState,50);
506
log('Server abort: ' , e, ' (', e.name, ')');
509
clearTimeout(timeoutHandle);
510
timeoutHandle = undefined;
514
// add "extra" data to form if provided in options
515
var extraInputs = [];
518
for (var n in s.extraData) {
519
if (s.extraData.hasOwnProperty(n)) {
520
// if using the $.param format that allows for multiple values with the same name
521
if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
523
$('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
527
$('<input type="hidden" name="'+n+'">').val(s.extraData[n])
534
if (!s.iframeTarget) {
535
// add iframe to doc and submit the form
536
$io.appendTo('body');
538
io.attachEvent('onload', cb);
540
io.addEventListener('load', cb, false);
542
setTimeout(checkState,15);
547
// just in case form has element with name/id of 'submit'
548
var submitFn = document.createElement('form').submit;
549
submitFn.apply(form);
553
// reset attrs and remove "extra" input elements
554
form.setAttribute('action',a);
556
form.setAttribute('target', t);
558
$form.removeAttr('target');
560
$(extraInputs).remove();
568
setTimeout(doSubmit, 10); // this lets dom updates render
571
var data, doc, domCheckCount = 50, callbackProcessed;
574
if (xhr.aborted || callbackProcessed) {
580
log('cannot access response document');
583
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
584
xhr.abort('timeout');
585
deferred.reject(xhr, 'timeout');
588
else if (e == SERVER_ABORT && xhr) {
589
xhr.abort('server abort');
590
deferred.reject(xhr, 'error', 'server abort');
594
if (!doc || doc.location.href == s.iframeSrc) {
595
// response not received yet
600
io.detachEvent('onload', cb);
602
io.removeEventListener('load', cb, false);
604
var status = 'success', errMsg;
610
var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
612
if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
613
if (--domCheckCount) {
614
// in some browsers (Opera) the iframe DOM is not always traversable when
615
// the onload callback fires, so we loop a bit to accommodate
616
log('requeing onLoad callback, DOM not available');
620
// let this fall through because server response could be an empty document
621
//log('Could not access iframe DOM after mutiple tries.');
622
//throw 'DOMException: not available';
625
//log('response detected');
626
var docRoot = doc.body ? doc.body : doc.documentElement;
627
xhr.responseText = docRoot ? docRoot.innerHTML : null;
628
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
631
xhr.getResponseHeader = function(header){
632
var headers = {'content-type': s.dataType};
633
return headers[header];
635
// support for XHR 'status' & 'statusText' emulation :
637
xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
638
xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
641
var dt = (s.dataType || '').toLowerCase();
642
var scr = /(json|script|text)/.test(dt);
643
if (scr || s.textarea) {
644
// see if user embedded response in textarea
645
var ta = doc.getElementsByTagName('textarea')[0];
647
xhr.responseText = ta.value;
648
// support for XHR 'status' & 'statusText' emulation :
649
xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
650
xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
653
// account for browsers injecting pre around json response
654
var pre = doc.getElementsByTagName('pre')[0];
655
var b = doc.getElementsByTagName('body')[0];
657
xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
660
xhr.responseText = b.textContent ? b.textContent : b.innerText;
664
else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
665
xhr.responseXML = toXml(xhr.responseText);
669
data = httpData(xhr, dt, s);
672
status = 'parsererror';
673
xhr.error = errMsg = (err || status);
677
log('error caught: ',err);
679
xhr.error = errMsg = (err || status);
683
log('upload aborted');
687
if (xhr.status) { // we've set xhr.status
688
status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
691
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
692
if (status === 'success') {
694
s.success.call(s.context, data, 'success', xhr);
695
deferred.resolve(xhr.responseText, 'success', xhr);
697
$.event.trigger("ajaxSuccess", [xhr, s]);
700
if (errMsg === undefined)
701
errMsg = xhr.statusText;
703
s.error.call(s.context, xhr, status, errMsg);
704
deferred.reject(xhr, 'error', errMsg);
706
$.event.trigger("ajaxError", [xhr, s, errMsg]);
710
$.event.trigger("ajaxComplete", [xhr, s]);
712
if (g && ! --$.active) {
713
$.event.trigger("ajaxStop");
717
s.complete.call(s.context, xhr, status);
719
callbackProcessed = true;
721
clearTimeout(timeoutHandle);
724
setTimeout(function() {
727
xhr.responseXML = null;
731
var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
732
if (window.ActiveXObject) {
733
doc = new ActiveXObject('Microsoft.XMLDOM');
738
doc = (new DOMParser()).parseFromString(s, 'text/xml');
740
return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
742
var parseJSON = $.parseJSON || function(s) {
743
/*jslint evil:true */
744
return window['eval']('(' + s + ')');
747
var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
749
var ct = xhr.getResponseHeader('content-type') || '',
750
xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
751
data = xml ? xhr.responseXML : xhr.responseText;
753
if (xml && data.documentElement.nodeName === 'parsererror') {
755
$.error('parsererror');
757
if (s && s.dataFilter) {
758
data = s.dataFilter(data, type);
760
if (typeof data === 'string') {
761
if (type === 'json' || !type && ct.indexOf('json') >= 0) {
762
data = parseJSON(data);
763
} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
775
* ajaxForm() provides a mechanism for fully automating form submission.
777
* The advantages of using this method instead of ajaxSubmit() are:
779
* 1: This method will include coordinates for <input type="image" /> elements (if the element
780
* is used to submit the form).
781
* 2. This method will include the submit element's name/value data (for the element that was
782
* used to submit the form).
783
* 3. This method binds the submit() method to the form for you.
785
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
786
* passes the options argument along after properly binding events for submit elements and
789
$.fn.ajaxForm = function(options) {
790
options = options || {};
791
options.delegation = options.delegation && $.isFunction($.fn.on);
793
// in jQuery 1.3+ we can fix mistakes with the ready state
794
if (!options.delegation && this.length === 0) {
795
var o = { s: this.selector, c: this.context };
796
if (!$.isReady && o.s) {
797
log('DOM not ready, queuing ajaxForm');
799
$(o.s,o.c).ajaxForm(options);
803
// is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
804
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
808
if ( options.delegation ) {
810
.off('submit.form-plugin', this.selector, doAjaxSubmit)
811
.off('click.form-plugin', this.selector, captureSubmittingElement)
812
.on('submit.form-plugin', this.selector, options, doAjaxSubmit)
813
.on('click.form-plugin', this.selector, options, captureSubmittingElement);
817
return this.ajaxFormUnbind()
818
.bind('submit.form-plugin', options, doAjaxSubmit)
819
.bind('click.form-plugin', options, captureSubmittingElement);
822
// private event handlers
823
function doAjaxSubmit(e) {
824
/*jshint validthis:true */
825
var options = e.data;
826
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
828
$(this).ajaxSubmit(options);
832
function captureSubmittingElement(e) {
833
/*jshint validthis:true */
834
var target = e.target;
836
if (!($el.is("[type=submit],[type=image]"))) {
837
// is this a child element of the submit el? (ex: a span within a button)
838
var t = $el.closest('[type=submit]');
839
if (t.length === 0) {
846
if (target.type == 'image') {
847
if (e.offsetX !== undefined) {
848
form.clk_x = e.offsetX;
849
form.clk_y = e.offsetY;
850
} else if (typeof $.fn.offset == 'function') {
851
var offset = $el.offset();
852
form.clk_x = e.pageX - offset.left;
853
form.clk_y = e.pageY - offset.top;
855
form.clk_x = e.pageX - target.offsetLeft;
856
form.clk_y = e.pageY - target.offsetTop;
860
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
864
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
865
$.fn.ajaxFormUnbind = function() {
866
return this.unbind('submit.form-plugin click.form-plugin');
870
* formToArray() gathers form element data into an array of objects that can
871
* be passed to any of the following ajax functions: $.get, $.post, or load.
872
* Each object in the array has both a 'name' and 'value' property. An example of
873
* an array for a simple login form might be:
875
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
877
* It is this array that is passed to pre-submit callback functions provided to the
878
* ajaxSubmit() and ajaxForm() methods.
880
$.fn.formToArray = function(semantic, elements) {
882
if (this.length === 0) {
887
var els = semantic ? form.getElementsByTagName('*') : form.elements;
892
var i,j,n,v,el,max,jmax;
893
for(i=0, max=els.length; i < max; i++) {
896
if (!n || el.disabled) {
900
if (semantic && form.clk && el.type == "image") {
901
// handle image inputs on the fly when semantic == true
903
a.push({name: n, value: $(el).val(), type: el.type });
904
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
909
v = $.fieldValue(el, true);
910
if (v && v.constructor == Array) {
913
for(j=0, jmax=v.length; j < jmax; j++) {
914
a.push({name: n, value: v[j]});
917
else if (feature.fileapi && el.type == 'file') {
920
var files = el.files;
922
for (j=0; j < files.length; j++) {
923
a.push({name: n, value: files[j], type: el.type});
928
a.push({ name: n, value: '', type: el.type });
931
else if (v !== null && typeof v != 'undefined') {
934
a.push({name: n, value: v, type: el.type, required: el.required});
938
if (!semantic && form.clk) {
939
// input type=='image' are not found in elements array! handle it here
940
var $input = $(form.clk), input = $input[0];
942
if (n && !input.disabled && input.type == 'image') {
943
a.push({name: n, value: $input.val()});
944
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
951
* Serializes form data into a 'submittable' string. This method will return a string
952
* in the format: name1=value1&name2=value2
954
$.fn.formSerialize = function(semantic) {
955
//hand off to jQuery.param for proper encoding
956
return $.param(this.formToArray(semantic));
960
* Serializes all field elements in the jQuery object into a query string.
961
* This method will return a string in the format: name1=value1&name2=value2
963
$.fn.fieldSerialize = function(successful) {
965
this.each(function() {
970
var v = $.fieldValue(this, successful);
971
if (v && v.constructor == Array) {
972
for (var i=0,max=v.length; i < max; i++) {
973
a.push({name: n, value: v[i]});
976
else if (v !== null && typeof v != 'undefined') {
977
a.push({name: this.name, value: v});
980
//hand off to jQuery.param for proper encoding
985
* Returns the value(s) of the element in the matched set. For example, consider the following form:
988
* <input name="A" type="text" />
989
* <input name="A" type="text" />
990
* <input name="B" type="checkbox" value="B1" />
991
* <input name="B" type="checkbox" value="B2"/>
992
* <input name="C" type="radio" value="C1" />
993
* <input name="C" type="radio" value="C2" />
996
* var v = $('input[type=text]').fieldValue();
997
* // if no values are entered into the text inputs
999
* // if values entered into the text inputs are 'foo' and 'bar'
1000
* v == ['foo','bar']
1002
* var v = $('input[type=checkbox]').fieldValue();
1003
* // if neither checkbox is checked
1005
* // if both checkboxes are checked
1008
* var v = $('input[type=radio]').fieldValue();
1009
* // if neither radio is checked
1011
* // if first radio is checked
1014
* The successful argument controls whether or not the field element must be 'successful'
1015
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
1016
* The default value of the successful argument is true. If this value is false the value(s)
1017
* for each element is returned.
1019
* Note: This method *always* returns an array. If no valid value can be determined the
1020
* array will be empty, otherwise it will contain one or more values.
1022
$.fn.fieldValue = function(successful) {
1023
for (var val=[], i=0, max=this.length; i < max; i++) {
1025
var v = $.fieldValue(el, successful);
1026
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
1029
if (v.constructor == Array)
1038
* Returns the value of the field element.
1040
$.fieldValue = function(el, successful) {
1041
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
1042
if (successful === undefined) {
1046
if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
1047
(t == 'checkbox' || t == 'radio') && !el.checked ||
1048
(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
1049
tag == 'select' && el.selectedIndex == -1)) {
1053
if (tag == 'select') {
1054
var index = el.selectedIndex;
1058
var a = [], ops = el.options;
1059
var one = (t == 'select-one');
1060
var max = (one ? index+1 : ops.length);
1061
for(var i=(one ? index : 0); i < max; i++) {
1065
if (!v) { // extra pain for IE...
1066
v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
1080
* Clears the form data. Takes the following actions on the form's input fields:
1081
* - input text fields will have their 'value' property set to the empty string
1082
* - select elements will have their 'selectedIndex' property set to -1
1083
* - checkbox and radio inputs will have their 'checked' property set to false
1084
* - inputs of type submit, button, reset, and hidden will *not* be effected
1085
* - button elements will *not* be effected
1087
$.fn.clearForm = function(includeHidden) {
1088
return this.each(function() {
1089
$('input,select,textarea', this).clearFields(includeHidden);
1094
* Clears the selected form elements.
1096
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
1097
var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
1098
return this.each(function() {
1099
var t = this.type, tag = this.tagName.toLowerCase();
1100
if (re.test(t) || tag == 'textarea') {
1103
else if (t == 'checkbox' || t == 'radio') {
1104
this.checked = false;
1106
else if (tag == 'select') {
1107
this.selectedIndex = -1;
1109
else if (t == "file") {
1110
if (/MSIE/.test(navigator.userAgent)) {
1111
$(this).replaceWith($(this).clone(true));
1116
else if (includeHidden) {
1117
// includeHidden can be the value true, or it can be a selector string
1118
// indicating a special test; for example:
1119
// $('#myForm').clearForm('.special:hidden')
1120
// the above would clean hidden inputs that have the class of 'special'
1121
if ( (includeHidden === true && /hidden/.test(t)) ||
1122
(typeof includeHidden == 'string' && $(this).is(includeHidden)) )
1129
* Resets the form data. Causes all form elements to be reset to their original value.
1131
$.fn.resetForm = function() {
1132
return this.each(function() {
1133
// guard against an input with the name of 'reset'
1134
// note that IE reports the reset function as an 'object'
1135
if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
1142
* Enables or disables any matching elements.
1144
$.fn.enable = function(b) {
1145
if (b === undefined) {
1148
return this.each(function() {
1154
* Checks/unchecks any matching checkboxes or radio buttons and
1155
* selects/deselects and matching option elements.
1157
$.fn.selected = function(select) {
1158
if (select === undefined) {
1161
return this.each(function() {
1163
if (t == 'checkbox' || t == 'radio') {
1164
this.checked = select;
1166
else if (this.tagName.toLowerCase() == 'option') {
1167
var $sel = $(this).parent('select');
1168
if (select && $sel[0] && $sel[0].type == 'select-one') {
1169
// deselect all other options
1170
$sel.find('option').selected(false);
1172
this.selected = select;
1178
$.fn.ajaxSubmit.debug = false;
1180
// helper fn for console logging
1182
if (!$.fn.ajaxSubmit.debug)
1184
var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
1185
if (window.console && window.console.log) {
1186
window.console.log(msg);
1188
else if (window.opera && window.opera.postError) {
1189
window.opera.postError(msg);