3 * version: 2.94 (13-DEC-2011)
4 * @requires jQuery v1.3.2 or later
6 * Examples and documentation at: http://malsup.com/jquery/form/
7 * Dual licensed under the MIT and GPL licenses:
8 * http://www.opensource.org/licenses/mit-license.php
9 * http://www.gnu.org/licenses/gpl.html
16 Do not use both ajaxSubmit and ajaxForm on the same form. These
17 functions are intended to be exclusive. Use ajaxSubmit if you want
18 to bind your own submit handler to the form. For example,
20 $(document).ready(function() {
21 $('#myForm').bind('submit', function(e) {
22 e.preventDefault(); // <-- important
29 Use ajaxForm when you want the plugin to manage all the event binding
32 $(document).ready(function() {
33 $('#myForm').ajaxForm({
38 When using ajaxForm, the ajaxSubmit function will be invoked for you
39 at the appropriate time.
43 * ajaxSubmit() provides a mechanism for immediately submitting
44 * an HTML form using AJAX.
46 $.fn
.ajaxSubmit = function(options
) {
47 // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
49 log('ajaxSubmit: skipping submit process - no element selected');
53 var method
, action
, url
, $form
= this;
55 if (typeof options
== 'function') {
56 options
= { success
: options
};
59 method
= this.attr('method');
60 action
= this.attr('action');
61 url
= (typeof action
=== 'string') ? $.trim(action
) : '';
62 url
= url
|| window
.location
.href
|| '';
64 // clean url (don't include hash vaue)
65 url
= (url
.match(/^([^#]+)/)||[])[1];
68 options
= $.extend(true, {
70 success
: $.ajaxSettings
.success
,
71 type
: method
|| 'GET',
72 iframeSrc
: /^https/i.test(window
.location
.href
|| '') ? 'javascript:false' : 'about:blank'
75 // hook for manipulating the form data before it is extracted;
76 // convenient for use with rich editors like tinyMCE or FCKEditor
78 this.trigger('form-pre-serialize', [this, options
, veto
]);
80 log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
84 // provide opportunity to alter form data before it is serialized
85 if (options
.beforeSerialize
&& options
.beforeSerialize(this, options
) === false) {
86 log('ajaxSubmit: submit aborted via beforeSerialize callback');
90 var traditional
= options
.traditional
;
91 if ( traditional
=== undefined ) {
92 traditional
= $.ajaxSettings
.traditional
;
95 var qx
,n
,v
,a
= this.formToArray(options
.semantic
);
97 options
.extraData
= options
.data
;
98 qx
= $.param(options
.data
, traditional
);
101 // give pre-submit callback an opportunity to abort the submit
102 if (options
.beforeSubmit
&& options
.beforeSubmit(a
, this, options
) === false) {
103 log('ajaxSubmit: submit aborted via beforeSubmit callback');
107 // fire vetoable 'validate' event
108 this.trigger('form-submit-validate', [a
, this, options
, veto
]);
110 log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
114 var q
= $.param(a
, traditional
);
116 q
= ( q
? (q
+ '&' + qx
) : qx
);
118 if (options
.type
.toUpperCase() == 'GET') {
119 options
.url
+= (options
.url
.indexOf('?') >= 0 ? '&' : '?') + q
;
120 options
.data
= null; // data is null for 'get'
123 options
.data
= q
; // data is the query string for 'post'
127 if (options
.resetForm
) {
128 callbacks
.push(function() { $form
.resetForm(); });
130 if (options
.clearForm
) {
131 callbacks
.push(function() { $form
.clearForm(options
.includeHidden
); });
134 // perform a load on the target only if dataType is not provided
135 if (!options
.dataType
&& options
.target
) {
136 var oldSuccess
= options
.success
|| function(){};
137 callbacks
.push(function(data
) {
138 var fn
= options
.replaceTarget
? 'replaceWith' : 'html';
139 $(options
.target
)[fn
](data
).each(oldSuccess
, arguments
);
142 else if (options
.success
) {
143 callbacks
.push(options
.success
);
146 options
.success = function(data
, status
, xhr
) { // jQuery 1.4+ passes xhr as 3rd arg
147 var context
= options
.context
|| options
; // jQuery 1.4+ supports scope context
148 for (var i
=0, max
=callbacks
.length
; i
< max
; i
++) {
149 callbacks
[i
].apply(context
, [data
, status
, xhr
|| $form
, $form
]);
153 // are there files to upload?
154 var fileInputs
= $('input:file:enabled[value]', this); // [value] (issue #113)
155 var hasFileInputs
= fileInputs
.length
> 0;
156 var mp
= 'multipart/form-data';
157 var multipart
= ($form
.attr('enctype') == mp
|| $form
.attr('encoding') == mp
);
159 var fileAPI
= !!(hasFileInputs
&& fileInputs
.get(0).files
&& window
.FormData
);
160 log("fileAPI :" + fileAPI
);
161 var shouldUseFrame
= (hasFileInputs
|| multipart
) /*&& !fileAPI*/; /* fileAPI bug sous tous les navs dans cette version */
163 // options.iframe allows user to force iframe mode
164 // 06-NOV-09: now defaulting to iframe mode if file input is detected
165 if (options
.iframe
!== false && (options
.iframe
|| shouldUseFrame
)) {
166 // hack to fix Safari hang (thanks to Tim Molendijk for this)
167 // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
168 if (options
.closeKeepAlive
) {
169 $.get(options
.closeKeepAlive
, function() {
177 else if ((hasFileInputs
|| multipart
) && fileAPI
) {
178 options
.progress
= options
.progress
|| $.noop
;
185 // fire 'notify' event
186 this.trigger('form-submit-notify', [this, options
]);
189 // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
190 function fileUploadXhr(a
) {
191 var formdata
= new FormData();
193 for (var i
=0; i
< a
.length
; i
++) {
194 if (a
[i
].type
== 'file')
196 formdata
.append(a
[i
].name
, a
[i
].value
);
199 $form
.find('input:file:enabled').each(function(){
200 var name
= $(this).attr('name'), files
= this.files
;
202 for (var i
=0; i
< files
.length
; i
++)
203 formdata
.append(name
, files
[i
]);
207 if (options
.extraData
) {
208 for (var k
in options
.extraData
)
209 formdata
.append(k
, options
.extraData
[k
])
214 var s
= $.extend(true, {}, $.ajaxSettings
, options
, {
221 s
.context
= s
.context
|| s
;
224 var beforeSend
= s
.beforeSend
;
225 s
.beforeSend = function(xhr
, o
) {
227 if(xhr
.upload
) { // unfortunately, jQuery doesn't expose this prop (http://bugs.jquery.com/ticket/10190)
228 xhr
.upload
.onprogress = function(event
) {
229 o
.progress(event
.position
, event
.total
);
233 beforeSend
.call(o
, xhr
, options
);
238 // private function for handling file uploads (hat tip to YAHOO!)
239 function fileUploadIframe(a
) {
240 var form
= $form
[0], el
, i
, s
, g
, id
, $io
, io
, xhr
, sub
, n
, timedOut
, timeoutHandle
;
241 var useProp
= !!$.fn
.prop
;
245 // ensure that every serialized input is still enabled
246 for (i
=0; i
< a
.length
; i
++) {
247 el
= $(form
[a
[i
].name
]);
248 el
.prop('disabled', false);
251 for (i
=0; i
< a
.length
; i
++) {
252 el
= $(form
[a
[i
].name
]);
253 el
.removeAttr('disabled');
258 if ($(':input[name=submit],:input[id=submit]', form
).length
) {
259 // if there is an input with a name or id of 'submit' then we won't be
260 // able to invoke the submit fn on the form (at least not x-browser)
261 alert('Error: Form elements must not have name or id of "submit".');
265 s
= $.extend(true, {}, $.ajaxSettings
, options
);
266 s
.context
= s
.context
|| s
;
267 id
= 'jqFormIO' + (new Date().getTime());
268 if (s
.iframeTarget
) {
269 $io
= $(s
.iframeTarget
);
270 n
= $io
.attr('name');
272 $io
.attr('name', id
);
277 $io
= $('<iframe name="' + id
+ '" src="'+ s
.iframeSrc
+'" />');
278 $io
.css({ position
: 'absolute', top
: '-1000px', left
: '-1000px' });
283 xhr
= { // mock object
289 getAllResponseHeaders: function() {},
290 getResponseHeader: function() {},
291 setRequestHeader: function() {},
292 abort: function(status
) {
293 var e
= (status
=== 'timeout' ? 'timeout' : 'aborted');
294 log('aborting upload... ' + e
);
296 $io
.attr('src', s
.iframeSrc
); // abort op in progress
298 s
.error
&& s
.error
.call(s
.context
, xhr
, e
, status
);
299 g
&& $.event
.trigger("ajaxError", [xhr
, s
, e
]);
300 s
.complete
&& s
.complete
.call(s
.context
, xhr
, e
);
305 // trigger ajax global events so that activity/block indicators work like normal
306 if (g
&& ! $.active
++) {
307 $.event
.trigger("ajaxStart");
310 $.event
.trigger("ajaxSend", [xhr
, s
]);
313 if (s
.beforeSend
&& s
.beforeSend
.call(s
.context
, xhr
, s
) === false) {
323 // add submitting element to data if we know it
327 if (n
&& !sub
.disabled
) {
328 s
.extraData
= s
.extraData
|| {};
329 s
.extraData
[n
] = sub
.value
;
330 if (sub
.type
== "image") {
331 s
.extraData
[n
+'.x'] = form
.clk_x
;
332 s
.extraData
[n
+'.y'] = form
.clk_y
;
337 var CLIENT_TIMEOUT_ABORT
= 1;
338 var SERVER_ABORT
= 2;
340 function getDoc(frame
) {
341 var doc
= frame
.contentWindow
? frame
.contentWindow
.document
: frame
.contentDocument
? frame
.contentDocument
: frame
.document
;
345 // Rails CSRF hack (thanks to Yvan Barthelemy)
346 var csrf_token
= $('meta[name=csrf-token]').attr('content');
347 var csrf_param
= $('meta[name=csrf-param]').attr('content');
348 if (csrf_param
&& csrf_token
) {
349 s
.extraData
= s
.extraData
|| {};
350 s
.extraData
[csrf_param
] = csrf_token
;
353 // take a breath so that pending repaints get some cpu time before the upload starts
354 function doSubmit() {
355 // make sure form attrs are set
356 var t
= $form
.attr('target'), a
= $form
.attr('action');
358 // update form attrs in IE friendly way
359 form
.setAttribute('target',id
);
361 form
.setAttribute('method', 'POST');
364 form
.setAttribute('action', s
.url
);
367 // ie borks in some cases when setting encoding
368 if (! s
.skipEncodingOverride
&& (!method
|| /post/i.test(method
))) {
370 encoding
: 'multipart/form-data',
371 enctype
: 'multipart/form-data'
377 timeoutHandle
= setTimeout(function() { timedOut
= true; cb(CLIENT_TIMEOUT_ABORT
); }, s
.timeout
);
380 // look for server aborts
381 function checkState() {
383 var state
= getDoc(io
).readyState
;
384 log('state = ' + state
);
385 if (state
.toLowerCase() == 'uninitialized')
386 setTimeout(checkState
,50);
389 log('Server abort: ' , e
, ' (', e
.name
, ')');
391 timeoutHandle
&& clearTimeout(timeoutHandle
);
392 timeoutHandle
= undefined;
396 // add "extra" data to form if provided in options
397 var extraInputs
= [];
400 for (var n
in s
.extraData
) {
402 $('<input type="hidden" name="'+n
+'">').attr('value',s
.extraData
[n
])
407 if (!s
.iframeTarget
) {
408 // add iframe to doc and submit the form
409 $io
.appendTo('body');
410 io
.attachEvent
? io
.attachEvent('onload', cb
) : io
.addEventListener('load', cb
, false);
412 setTimeout(checkState
,15);
416 // reset attrs and remove "extra" input elements
417 form
.setAttribute('action',a
);
419 form
.setAttribute('target', t
);
421 $form
.removeAttr('target');
423 $(extraInputs
).remove();
431 setTimeout(doSubmit
, 10); // this lets dom updates render
434 var data
, doc
, domCheckCount
= 50, callbackProcessed
;
437 if (xhr
.aborted
|| callbackProcessed
) {
444 log('cannot access response document: ', ex
);
447 if (e
=== CLIENT_TIMEOUT_ABORT
&& xhr
) {
448 xhr
.abort('timeout');
451 else if (e
== SERVER_ABORT
&& xhr
) {
452 xhr
.abort('server abort');
456 if (!doc
|| doc
.location
.href
== s
.iframeSrc
) {
457 // response not received yet
461 io
.detachEvent
? io
.detachEvent('onload', cb
) : io
.removeEventListener('load', cb
, false);
463 var status
= 'success', errMsg
;
469 var isXml
= s
.dataType
== 'xml' || doc
.XMLDocument
|| $.isXMLDoc(doc
);
471 if (!isXml
&& window
.opera
&& (doc
.body
== null || doc
.body
.innerHTML
== '')) {
472 if (--domCheckCount
) {
473 // in some browsers (Opera) the iframe DOM is not always traversable when
474 // the onload callback fires, so we loop a bit to accommodate
475 log('requeing onLoad callback, DOM not available');
479 // let this fall through because server response could be an empty document
480 //log('Could not access iframe DOM after mutiple tries.');
481 //throw 'DOMException: not available';
484 //log('response detected');
485 var docRoot
= doc
.body
? doc
.body
: doc
.documentElement
;
486 xhr
.responseText
= docRoot
? docRoot
.innerHTML
: null;
487 xhr
.responseXML
= doc
.XMLDocument
? doc
.XMLDocument
: doc
;
490 xhr
.getResponseHeader = function(header
){
491 var headers
= {'content-type': s
.dataType
};
492 return headers
[header
];
494 // support for XHR 'status' & 'statusText' emulation :
496 xhr
.status
= Number( docRoot
.getAttribute('status') ) || xhr
.status
;
497 xhr
.statusText
= docRoot
.getAttribute('statusText') || xhr
.statusText
;
500 var dt
= (s
.dataType
|| '').toLowerCase();
501 var scr
= /(json|script|text)/.test(dt
);
502 if (scr
|| s
.textarea
) {
503 // see if user embedded response in textarea
504 var ta
= doc
.getElementsByTagName('textarea')[0];
506 xhr
.responseText
= ta
.value
;
507 // support for XHR 'status' & 'statusText' emulation :
508 xhr
.status
= Number( ta
.getAttribute('status') ) || xhr
.status
;
509 xhr
.statusText
= ta
.getAttribute('statusText') || xhr
.statusText
;
512 // account for browsers injecting pre around json response
513 var pre
= doc
.getElementsByTagName('pre')[0];
514 var b
= doc
.getElementsByTagName('body')[0];
516 xhr
.responseText
= pre
.textContent
? pre
.textContent
: pre
.innerText
;
519 xhr
.responseText
= b
.textContent
? b
.textContent
: b
.innerText
;
523 else if (dt
== 'xml' && !xhr
.responseXML
&& xhr
.responseText
!= null) {
524 xhr
.responseXML
= toXml(xhr
.responseText
);
528 data
= httpData(xhr
, dt
, s
);
531 status
= 'parsererror';
532 xhr
.error
= errMsg
= (e
|| status
);
536 log('error caught: ',e
);
538 xhr
.error
= errMsg
= (e
|| status
);
542 log('upload aborted');
546 if (xhr
.status
) { // we've set xhr.status
547 status
= (xhr
.status
>= 200 && xhr
.status
< 300 || xhr
.status
=== 304) ? 'success' : 'error';
550 // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
551 if (status
=== 'success') {
552 s
.success
&& s
.success
.call(s
.context
, data
, 'success', xhr
);
553 g
&& $.event
.trigger("ajaxSuccess", [xhr
, s
]);
556 if (errMsg
== undefined)
557 errMsg
= xhr
.statusText
;
558 s
.error
&& s
.error
.call(s
.context
, xhr
, status
, errMsg
);
559 g
&& $.event
.trigger("ajaxError", [xhr
, s
, errMsg
]);
562 g
&& $.event
.trigger("ajaxComplete", [xhr
, s
]);
564 if (g
&& ! --$.active
) {
565 $.event
.trigger("ajaxStop");
568 s
.complete
&& s
.complete
.call(s
.context
, xhr
, status
);
570 callbackProcessed
= true;
572 clearTimeout(timeoutHandle
);
575 setTimeout(function() {
578 xhr
.responseXML
= null;
582 var toXml
= $.parseXML
|| function(s
, doc
) { // use parseXML if available (jQuery 1.5+)
583 if (window
.ActiveXObject
) {
584 doc
= new ActiveXObject('Microsoft.XMLDOM');
589 doc
= (new DOMParser()).parseFromString(s
, 'text/xml');
591 return (doc
&& doc
.documentElement
&& doc
.documentElement
.nodeName
!= 'parsererror') ? doc
: null;
593 var parseJSON
= $.parseJSON
|| function(s
) {
594 return window
['eval']('(' + s
+ ')');
597 var httpData = function( xhr
, type
, s
) { // mostly lifted from jq1.4.4
599 var ct
= xhr
.getResponseHeader('content-type') || '',
600 xml
= type
=== 'xml' || !type
&& ct
.indexOf('xml') >= 0,
601 data
= xml
? xhr
.responseXML
: xhr
.responseText
;
603 if (xml
&& data
.documentElement
.nodeName
=== 'parsererror') {
604 $.error
&& $.error('parsererror');
606 if (s
&& s
.dataFilter
) {
607 data
= s
.dataFilter(data
, type
);
609 if (typeof data
=== 'string') {
610 if (type
=== 'json' || !type
&& ct
.indexOf('json') >= 0) {
611 data
= parseJSON(data
);
612 } else if (type
=== "script" || !type
&& ct
.indexOf("javascript") >= 0) {
622 * ajaxForm() provides a mechanism for fully automating form submission.
624 * The advantages of using this method instead of ajaxSubmit() are:
626 * 1: This method will include coordinates for <input type="image" /> elements (if the element
627 * is used to submit the form).
628 * 2. This method will include the submit element's name/value data (for the element that was
629 * used to submit the form).
630 * 3. This method binds the submit() method to the form for you.
632 * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
633 * passes the options argument along after properly binding events for submit elements and
636 $.fn
.ajaxForm = function(options
) {
637 // in jQuery 1.3+ we can fix mistakes with the ready state
638 if (this.length
=== 0) {
639 var o
= { s
: this.selector
, c
: this.context
};
640 if (!$.isReady
&& o
.s
) {
641 log('DOM not ready, queuing ajaxForm');
643 $(o
.s
,o
.c
).ajaxForm(options
);
647 // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
648 log('terminating; zero elements found by selector' + ($.isReady
? '' : ' (DOM not ready)'));
652 return this.ajaxFormUnbind().bind('submit.form-plugin', function(e
) {
653 if (!e
.isDefaultPrevented()) { // if event has been canceled, don't proceed
655 $(this).ajaxSubmit(options
);
657 }).bind('click.form-plugin', function(e
) {
658 var target
= e
.target
;
660 if (!($el
.is(":submit,input:image"))) {
661 // is this a child element of the submit el? (ex: a span within a button)
662 var t
= $el
.closest(':submit');
670 if (target
.type
== 'image') {
671 if (e
.offsetX
!= undefined) {
672 form
.clk_x
= e
.offsetX
;
673 form
.clk_y
= e
.offsetY
;
674 } else if (typeof $.fn
.offset
== 'function') { // try to use dimensions plugin
675 var offset
= $el
.offset();
676 form
.clk_x
= e
.pageX
- offset
.left
;
677 form
.clk_y
= e
.pageY
- offset
.top
;
679 form
.clk_x
= e
.pageX
- target
.offsetLeft
;
680 form
.clk_y
= e
.pageY
- target
.offsetTop
;
684 setTimeout(function() { form
.clk
= form
.clk_x
= form
.clk_y
= null; }, 100);
688 // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
689 $.fn
.ajaxFormUnbind = function() {
690 return this.unbind('submit.form-plugin click.form-plugin');
694 * formToArray() gathers form element data into an array of objects that can
695 * be passed to any of the following ajax functions: $.get, $.post, or load.
696 * Each object in the array has both a 'name' and 'value' property. An example of
697 * an array for a simple login form might be:
699 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
701 * It is this array that is passed to pre-submit callback functions provided to the
702 * ajaxSubmit() and ajaxForm() methods.
704 $.fn
.formToArray = function(semantic
) {
706 if (this.length
=== 0) {
711 var els
= semantic
? form
.getElementsByTagName('*') : form
.elements
;
716 var i
,j
,n
,v
,el
,max
,jmax
;
717 for(i
=0, max
=els
.length
; i
< max
; i
++) {
724 if (semantic
&& form
.clk
&& el
.type
== "image") {
725 // handle image inputs on the fly when semantic == true
726 if(!el
.disabled
&& form
.clk
== el
) {
727 a
.push({name
: n
, value
: $(el
).val(), type
: el
.type
});
728 a
.push({name
: n
+'.x', value
: form
.clk_x
}, {name
: n
+'.y', value
: form
.clk_y
});
733 v
= $.fieldValue(el
, true);
734 if (v
&& v
.constructor == Array
) {
735 for(j
=0, jmax
=v
.length
; j
< jmax
; j
++) {
736 a
.push({name
: n
, value
: v
[j
]});
739 else if (v
!== null && typeof v
!= 'undefined') {
740 a
.push({name
: n
, value
: v
, type
: el
.type
});
744 if (!semantic
&& form
.clk
) {
745 // input type=='image' are not found in elements array! handle it here
746 var $input
= $(form
.clk
), input
= $input
[0];
748 if (n
&& !input
.disabled
&& input
.type
== 'image') {
749 a
.push({name
: n
, value
: $input
.val()});
750 a
.push({name
: n
+'.x', value
: form
.clk_x
}, {name
: n
+'.y', value
: form
.clk_y
});
757 * Serializes form data into a 'submittable' string. This method will return a string
758 * in the format: name1=value1&name2=value2
760 $.fn
.formSerialize = function(semantic
) {
761 //hand off to jQuery.param for proper encoding
762 return $.param(this.formToArray(semantic
));
766 * Serializes all field elements in the jQuery object into a query string.
767 * This method will return a string in the format: name1=value1&name2=value2
769 $.fn
.fieldSerialize = function(successful
) {
771 this.each(function() {
776 var v
= $.fieldValue(this, successful
);
777 if (v
&& v
.constructor == Array
) {
778 for (var i
=0,max
=v
.length
; i
< max
; i
++) {
779 a
.push({name
: n
, value
: v
[i
]});
782 else if (v
!== null && typeof v
!= 'undefined') {
783 a
.push({name
: this.name
, value
: v
});
786 //hand off to jQuery.param for proper encoding
791 * Returns the value(s) of the element in the matched set. For example, consider the following form:
794 * <input name="A" type="text" />
795 * <input name="A" type="text" />
796 * <input name="B" type="checkbox" value="B1" />
797 * <input name="B" type="checkbox" value="B2"/>
798 * <input name="C" type="radio" value="C1" />
799 * <input name="C" type="radio" value="C2" />
802 * var v = $(':text').fieldValue();
803 * // if no values are entered into the text inputs
805 * // if values entered into the text inputs are 'foo' and 'bar'
808 * var v = $(':checkbox').fieldValue();
809 * // if neither checkbox is checked
811 * // if both checkboxes are checked
814 * var v = $(':radio').fieldValue();
815 * // if neither radio is checked
817 * // if first radio is checked
820 * The successful argument controls whether or not the field element must be 'successful'
821 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
822 * The default value of the successful argument is true. If this value is false the value(s)
823 * for each element is returned.
825 * Note: This method *always* returns an array. If no valid value can be determined the
826 * array will be empty, otherwise it will contain one or more values.
828 $.fn
.fieldValue = function(successful
) {
829 for (var val
=[], i
=0, max
=this.length
; i
< max
; i
++) {
831 var v
= $.fieldValue(el
, successful
);
832 if (v
=== null || typeof v
== 'undefined' || (v
.constructor == Array
&& !v
.length
)) {
835 v
.constructor == Array
? $.merge(val
, v
) : val
.push(v
);
841 * Returns the value of the field element.
843 $.fieldValue = function(el
, successful
) {
844 var n
= el
.name
, t
= el
.type
, tag
= el
.tagName
.toLowerCase();
845 if (successful
=== undefined) {
849 if (successful
&& (!n
|| el
.disabled
|| t
== 'reset' || t
== 'button' ||
850 (t
== 'checkbox' || t
== 'radio') && !el
.checked
||
851 (t
== 'submit' || t
== 'image') && el
.form
&& el
.form
.clk
!= el
||
852 tag
== 'select' && el
.selectedIndex
== -1)) {
856 if (tag
== 'select') {
857 var index
= el
.selectedIndex
;
861 var a
= [], ops
= el
.options
;
862 var one
= (t
== 'select-one');
863 var max
= (one
? index
+1 : ops
.length
);
864 for(var i
=(one
? index
: 0); i
< max
; i
++) {
868 if (!v
) { // extra pain for IE...
869 v
= (op
.attributes
&& op
.attributes
['value'] && !(op
.attributes
['value'].specified
)) ? op
.text
: op
.value
;
883 * Clears the form data. Takes the following actions on the form's input fields:
884 * - input text fields will have their 'value' property set to the empty string
885 * - select elements will have their 'selectedIndex' property set to -1
886 * - checkbox and radio inputs will have their 'checked' property set to false
887 * - inputs of type submit, button, reset, and hidden will *not* be effected
888 * - button elements will *not* be effected
890 $.fn
.clearForm = function(includeHidden
) {
891 return this.each(function() {
892 $('input,select,textarea', this).clearFields(includeHidden
);
897 * Clears the selected form elements.
899 $.fn
.clearFields
= $.fn
.clearInputs = function(includeHidden
) {
900 var re
= /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
901 return this.each(function() {
902 var t
= this.type
, tag
= this.tagName
.toLowerCase();
903 if (re
.test(t
) || tag
== 'textarea' || (includeHidden
&& /hidden/.test(t
)) ) {
906 else if (t
== 'checkbox' || t
== 'radio') {
907 this.checked
= false;
909 else if (tag
== 'select') {
910 this.selectedIndex
= -1;
916 * Resets the form data. Causes all form elements to be reset to their original value.
918 $.fn
.resetForm = function() {
919 return this.each(function() {
920 // guard against an input with the name of 'reset'
921 // note that IE reports the reset function as an 'object'
922 if (typeof this.reset
== 'function' || (typeof this.reset
== 'object' && !this.reset
.nodeType
)) {
929 * Enables or disables any matching elements.
931 $.fn
.enable = function(b
) {
932 if (b
=== undefined) {
935 return this.each(function() {
941 * Checks/unchecks any matching checkboxes or radio buttons and
942 * selects/deselects and matching option elements.
944 $.fn
.selected = function(select
) {
945 if (select
=== undefined) {
948 return this.each(function() {
950 if (t
== 'checkbox' || t
== 'radio') {
951 this.checked
= select
;
953 else if (this.tagName
.toLowerCase() == 'option') {
954 var $sel
= $(this).parent('select');
955 if (select
&& $sel
[0] && $sel
[0].type
== 'select-one') {
956 // deselect all other options
957 $sel
.find('option').selected(false);
959 this.selected
= select
;
965 $.fn
.ajaxSubmit
.debug
= false;
967 // helper fn for console logging
969 if (!$.fn
.ajaxSubmit
.debug
)
971 var msg
= '[jquery.form] ' + Array
.prototype.join
.call(arguments
,'');
972 if (window
.console
&& window
.console
.log
) {
973 window
.console
.log(msg
);
975 else if (window
.opera
&& window
.opera
.postError
) {
976 window
.opera
.postError(msg
);