PageSourceSearch

https://yozone.fr/prive/javascript/jquery.form.js

js yozone.fr collected 2026-10-03 17:33:48 UTC 28,454 bytes, 980 lines download raw bytes

1/*!
2 * jQuery Form Plugin
3 * version: 2.94 (13-DEC-2011)
4 * @requires jQuery v1.3.2 or later
5 *
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
10 */
11;(function($) {
12
13/*
14	Usage Note:
15	-----------
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,
19
20	$(document).ready(function() {
21		$('#myForm').bind('submit', function(e) {
22			e.preventDefault(); // <-- important
23			$(this).ajaxSubmit({
24				target: '#output'
25			});
26		});
27	});
28
29	Use ajaxForm when you want the plugin to manage all the event binding
30	for you.  For example,
31
32	$(document).ready(function() {
33		$('#myForm').ajaxForm({
34			target: '#output'
35		});
36	});
37
38	When using ajaxForm, the ajaxSubmit function will be invoked for you
39	at the appropriate time.
40*/
41
42/**
43 * ajaxSubmit() provides a mechanism for immediately submitting
44 * an HTML form using AJAX.
45 */
46$.fn.ajaxSubmit = function(options) {
47	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
48	if (!this.length) {
49		log('ajaxSubmit: skipping submit process - no element selected');
50		return this;
51	}
52	
53	var method, action, url, $form = this;
54
55	if (typeof options == 'function') {
56		options = { success: options };
57	}
58
59	method = this.attr('method');
60	action = this.attr('action');
61	url = (typeof action === 'string') ? $.trim(action) : '';
62	url = url || window.location.href || '';
63	if (url) {
64		// clean url (don't include hash vaue)
65		url = (url.match(/^([^#]+)/)||[])[1];
66	}
67
68	options = $.extend(true, {
69		url:  url,
70		success: $.ajaxSettings.success,
71		type: method || 'GET',
72		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
73	}, options);
74
75	// hook for manipulating the form data before it is extracted;
76	// convenient for use with rich editors like tinyMCE or FCKEditor
77	var veto = {};
78	this.trigger('form-pre-serialize', [this, options, veto]);
79	if (veto.veto) {
80		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
81		return this;
82	}
83
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');
87		return this;
88	}
89
90	var traditional = options.traditional;
91	if ( traditional === undefined ) {
92		traditional = $.ajaxSettings.traditional;
93	}
94	
95	var qx,n,v,a = this.formToArray(options.semantic);
96	if (options.data) {
97		options.extraData = options.data;
98		qx = $.param(options.data, traditional);
99	}
100
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');
104		return this;
105	}
106
107	// fire vetoable 'validate' event
108	this.trigger('form-submit-validate', [a, this, options, veto]);
109	if (veto.veto) {
110		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
111		return this;
112	}
113
114	var q = $.param(a, traditional);
115	if (qx) {
116		q = ( q ? (q + '&' + qx) : qx );
117	}	
118	if (options.type.toUpperCase() == 'GET') {
119		options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
120		options.data = null;  // data is null for 'get'
121	}
122	else {
123		options.data = q; // data is the query string for 'post'
124	}
125
126	var callbacks = [];
127	if (options.resetForm) {
128		callbacks.push(function() { $form.resetForm(); });
129	}
130	if (options.clearForm) {
131		callbacks.push(function() { $form.clearForm(options.includeHidden); });
132	}
133
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);
140		});
141	}
142	else if (options.success) {
143		callbacks.push(options.success);
144	}
145
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]);
150		}
151	};
152
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);
158
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 */
162
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() {
170				fileUploadIframe(a);
171			});
172		}
173  		else {
174			fileUploadIframe(a);
175  		}
176	}
177	else if ((hasFileInputs || multipart) && fileAPI) {
178		options.progress = options.progress || $.noop;
179		fileUploadXhr(a);
180	}
181	else {
182		$.ajax(options);
183	}
184
185	 // fire 'notify' event
186	 this.trigger('form-submit-notify', [this, options]);
187	 return this;
188
189	 // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
190	function fileUploadXhr(a) {
191		var formdata = new FormData();
192
193		for (var i=0; i < a.length; i++) {
194			if (a[i].type == 'file')
195				continue;
196			formdata.append(a[i].name, a[i].value);
197		}
198
199		$form.find('input:file:enabled').each(function(){
200			var name = $(this).attr('name'), files = this.files;
201			if (name) {
202				for (var i=0; i < files.length; i++)
203					formdata.append(name, files[i]);
204			}
205		});
206
207		if (options.extraData) {
208			for (var k in options.extraData)
209				formdata.append(k, options.extraData[k])
210		}
211
212		options.data = null;
213
214		var s = $.extend(true, {}, $.ajaxSettings, options, {
215			contentType: false,
216			processData: false,
217			cache: false,
218			type: 'POST'
219		});
220
221      s.context = s.context || s;
222
223      s.data = null;
224      var beforeSend = s.beforeSend;
225      s.beforeSend = function(xhr, o) {
226          o.data = formdata;
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);
230              };
231          }
232          if(beforeSend)
233              beforeSend.call(o, xhr, options);
234      };
235      $.ajax(s);
236   }
237
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;
242
243		if (a) {
244			if ( useProp ) {
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);
249				}
250			} else {
251				for (i=0; i < a.length; i++) {
252					el = $(form[a[i].name]);
253					el.removeAttr('disabled');
254				}
255			};
256		}
257
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".');
262			return;
263		}
264		
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');
271			if (n == null)
272			 	$io.attr('name', id);
273			else
274				id = n;
275		}
276		else {
277			$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
278			$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
279		}
280		io = $io[0];
281
282
283		xhr = { // mock object
284			aborted: 0,
285			responseText: null,
286			responseXML: null,
287			status: 0,
288			statusText: 'n/a',
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);
295				this.aborted = 1;
296				$io.attr('src', s.iframeSrc); // abort op in progress
297				xhr.error = e;
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);
301			}
302		};
303
304		g = s.global;
305		// trigger ajax global events so that activity/block indicators work like normal
306		if (g && ! $.active++) {
307			$.event.trigger("ajaxStart");
308		}
309		if (g) {
310			$.event.trigger("ajaxSend", [xhr, s]);
311		}
312
313		if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
314			if (s.global) {
315				$.active--;
316			}
317			return;
318		}
319		if (xhr.aborted) {
320			return;
321		}
322
323		// add submitting element to data if we know it
324		sub = form.clk;
325		if (sub) {
326			n = sub.name;
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;
333				}
334			}
335		}
336		
337		var CLIENT_TIMEOUT_ABORT = 1;
338		var SERVER_ABORT = 2;
339
340		function getDoc(frame) {
341			var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
342			return doc;
343		}
344		
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;
351		}
352
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');
357
358			// update form attrs in IE friendly way
359			form.setAttribute('target',id);
360			if (!method) {
361				form.setAttribute('method', 'POST');
362			}
363			if (a != s.url) {
364				form.setAttribute('action', s.url);
365			}
366
367			// ie borks in some cases when setting encoding
368			if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
369				$form.attr({
370					encoding: 'multipart/form-data',
371					enctype:  'multipart/form-data'
372				});
373			}
374
375			// support timout
376			if (s.timeout) {
377				timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
378			}
379			
380			// look for server aborts
381			function checkState() {
382				try {
383					var state = getDoc(io).readyState;
384					log('state = ' + state);
385					if (state.toLowerCase() == 'uninitialized')
386						setTimeout(checkState,50);
387				}
388				catch(e) {
389					log('Server abort: ' , e, ' (', e.name, ')');
390					cb(SERVER_ABORT);
391					timeoutHandle && clearTimeout(timeoutHandle);
392					timeoutHandle = undefined;
393				}
394			}
395
396			// add "extra" data to form if provided in options
397			var extraInputs = [];
398			try {
399				if (s.extraData) {
400					for (var n in s.extraData) {
401						extraInputs.push(
402							$('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
403								.appendTo(form)[0]);
404					}
405				}
406
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);
411				}
412				setTimeout(checkState,15);
413				form.submit();
414			}
415			finally {
416				// reset attrs and remove "extra" input elements
417				form.setAttribute('action',a);
418				if(t) {
419					form.setAttribute('target', t);
420				} else {
421					$form.removeAttr('target');
422				}
423				$(extraInputs).remove();
424			}
425		}
426
427		if (s.forceSync) {
428			doSubmit();
429		}
430		else {
431			setTimeout(doSubmit, 10); // this lets dom updates render
432		}
433
434		var data, doc, domCheckCount = 50, callbackProcessed;
435
436		function cb(e) {
437			if (xhr.aborted || callbackProcessed) {
438				return;
439			}
440			try {
441				doc = getDoc(io);
442			}
443			catch(ex) {
444				log('cannot access response document: ', ex);
445				e = SERVER_ABORT;
446			}
447			if (e === CLIENT_TIMEOUT_ABORT && xhr) {
448				xhr.abort('timeout');
449				return;
450			}
451			else if (e == SERVER_ABORT && xhr) {
452				xhr.abort('server abort');
453				return;
454			}
455
456			if (!doc || doc.location.href == s.iframeSrc) {
457				// response not received yet
458				if (!timedOut)
459					return;
460			}
461			io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
462
463			var status = 'success', errMsg;
464			try {
465				if (timedOut) {
466					throw 'timeout';
467				}
468
469				var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
470				log('isXml='+isXml);
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');
476						setTimeout(cb, 250);
477						return;
478					}
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';
482				}
483
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;
488				if (isXml)
489					s.dataType = 'xml';
490				xhr.getResponseHeader = function(header){
491					var headers = {'content-type': s.dataType};
492					return headers[header];
493				};
494				// support for XHR 'status' & 'statusText' emulation :
495				if (docRoot) {
496					xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
497					xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
498				}
499
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];
505					if (ta) {
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;
510					}
511					else if (scr) {
512						// account for browsers injecting pre around json response
513						var pre = doc.getElementsByTagName('pre')[0];
514						var b = doc.getElementsByTagName('body')[0];
515						if (pre) {
516							xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
517						}
518						else if (b) {
519							xhr.responseText = b.textContent ? b.textContent : b.innerText;
520						}
521					}
522				}
523				else if (dt == 'xml' && !xhr.responseXML && xhr.responseText != null) {
524					xhr.responseXML = toXml(xhr.responseText);
525				}
526
527				try {
528					data = httpData(xhr, dt, s);
529				}
530				catch (e) {
531					status = 'parsererror';
532					xhr.error = errMsg = (e || status);
533				}
534			}
535			catch (e) {
536				log('error caught: ',e);
537				status = 'error';
538				xhr.error = errMsg = (e || status);
539			}
540
541			if (xhr.aborted) {
542				log('upload aborted');
543				status = null;
544			}
545
546			if (xhr.status) { // we've set xhr.status
547				status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
548			}
549
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]);
554			}
555			else if (status) {
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]);
560			}
561
562			g && $.event.trigger("ajaxComplete", [xhr, s]);
563
564			if (g && ! --$.active) {
565				$.event.trigger("ajaxStop");
566			}
567
568			s.complete && s.complete.call(s.context, xhr, status);
569
570			callbackProcessed = true;
571			if (s.timeout)
572				clearTimeout(timeoutHandle);
573
574			// clean up
575			setTimeout(function() {
576				if (!s.iframeTarget)
577					$io.remove();
578				xhr.responseXML = null;
579			}, 100);
580		}
581
582		var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
583			if (window.ActiveXObject) {
584				doc = new ActiveXObject('Microsoft.XMLDOM');
585				doc.async = 'false';
586				doc.loadXML(s);
587			}
588			else {
589				doc = (new DOMParser()).parseFromString(s, 'text/xml');
590			}
591			return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
592		};
593		var parseJSON = $.parseJSON || function(s) {
594			return window['eval']('(' + s + ')');
595		};
596
597		var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
598
599			var ct = xhr.getResponseHeader('content-type') || '',
600				xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
601				data = xml ? xhr.responseXML : xhr.responseText;
602
603			if (xml && data.documentElement.nodeName === 'parsererror') {
604				$.error && $.error('parsererror');
605			}
606			if (s && s.dataFilter) {
607				data = s.dataFilter(data, type);
608			}
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) {
613					$.globalEval(data);
614				}
615			}
616			return data;
617		};
618	}
619};
620
621/**
622 * ajaxForm() provides a mechanism for fully automating form submission.
623 *
624 * The advantages of using this method instead of ajaxSubmit() are:
625 *
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.
631 *
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
634 * the form itself.
635 */
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');
642			$(function() {
643				$(o.s,o.c).ajaxForm(options);
644			});
645			return this;
646		}
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)'));
649		return this;
650	}
651
652	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
653		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
654			e.preventDefault();
655			$(this).ajaxSubmit(options);
656		}
657	}).bind('click.form-plugin', function(e) {
658		var target = e.target;
659		var $el = $(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');
663			if (t.length == 0) {
664				return;
665			}
666			target = t[0];
667		}
668		var form = this;
669		form.clk = target;
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;
678			} else {
679				form.clk_x = e.pageX - target.offsetLeft;
680				form.clk_y = e.pageY - target.offsetTop;
681			}
682		}
683		// clear form vars
684		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
685	});
686};
687
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');
691};
692
693/**
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:
698 *
699 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
700 *
701 * It is this array that is passed to pre-submit callback functions provided to the
702 * ajaxSubmit() and ajaxForm() methods.
703 */
704$.fn.formToArray = function(semantic) {
705	var a = [];
706	if (this.length === 0) {
707		return a;
708	}
709
710	var form = this[0];
711	var els = semantic ? form.getElementsByTagName('*') : form.elements;
712	if (!els) {
713		return a;
714	}
715
716	var i,j,n,v,el,max,jmax;
717	for(i=0, max=els.length; i < max; i++) {
718		el = els[i];
719		n = el.name;
720		if (!n) {
721			continue;
722		}
723
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});
729			}
730			continue;
731		}
732
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]});
737			}
738		}
739		else if (v !== null && typeof v != 'undefined') {
740			a.push({name: n, value: v, type: el.type});
741		}
742	}
743
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];
747		n = input.name;
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});
751		}
752	}
753	return a;
754};
755
756/**
757 * Serializes form data into a 'submittable' string. This method will return a string
758 * in the format: name1=value1&amp;name2=value2
759 */
760$.fn.formSerialize = function(semantic) {
761	//hand off to jQuery.param for proper encoding
762	return $.param(this.formToArray(semantic));
763};
764
765/**
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&amp;name2=value2
768 */
769$.fn.fieldSerialize = function(successful) {
770	var a = [];
771	this.each(function() {
772		var n = this.name;
773		if (!n) {
774			return;
775		}
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]});
780			}
781		}
782		else if (v !== null && typeof v != 'undefined') {
783			a.push({name: this.name, value: v});
784		}
785	});
786	//hand off to jQuery.param for proper encoding
787	return $.param(a);
788};
789
790/**
791 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
792 *
793 *  <form><fieldset>
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" />
800 *  </fieldset></form>
801 *
802 *  var v = $(':text').fieldValue();
803 *  // if no values are entered into the text inputs
804 *  v == ['','']
805 *  // if values entered into the text inputs are 'foo' and 'bar'
806 *  v == ['foo','bar']
807 *
808 *  var v = $(':checkbox').fieldValue();
809 *  // if neither checkbox is checked
810 *  v === undefined
811 *  // if both checkboxes are checked
812 *  v == ['B1', 'B2']
813 *
814 *  var v = $(':radio').fieldValue();
815 *  // if neither radio is checked
816 *  v === undefined
817 *  // if first radio is checked
818 *  v == ['C1']
819 *
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.
824 *
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.
827 */
828$.fn.fieldValue = function(successful) {
829	for (var val=[], i=0, max=this.length; i < max; i++) {
830		var el = this[i];
831		var v = $.fieldValue(el, successful);
832		if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
833			continue;
834		}
835		v.constructor == Array ? $.merge(val, v) : val.push(v);
836	}
837	return val;
838};
839
840/**
841 * Returns the value of the field element.
842 */
843$.fieldValue = function(el, successful) {
844	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
845	if (successful === undefined) {
846		successful = true;
847	}
848
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)) {
853			return null;
854	}
855
856	if (tag == 'select') {
857		var index = el.selectedIndex;
858		if (index < 0) {
859			return null;
860		}
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++) {
865			var op = ops[i];
866			if (op.selected) {
867				var v = op.value;
868				if (!v) { // extra pain for IE...
869					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
870				}
871				if (one) {
872					return v;
873				}
874				a.push(v);
875			}
876		}
877		return a;
878	}
879	return $(el).val();
880};
881
882/**
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
889 */
890$.fn.clearForm = function(includeHidden) {
891	return this.each(function() {
892		$('input,select,textarea', this).clearFields(includeHidden);
893	});
894};
895
896/**
897 * Clears the selected form elements.
898 */
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)) ) {
904			this.value = '';
905		}
906		else if (t == 'checkbox' || t == 'radio') {
907			this.checked = false;
908		}
909		else if (tag == 'select') {
910			this.selectedIndex = -1;
911		}
912	});
913};
914
915/**
916 * Resets the form data.  Causes all form elements to be reset to their original value.
917 */
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)) {
923			this.reset();
924		}
925	});
926};
927
928/**
929 * Enables or disables any matching elements.
930 */
931$.fn.enable = function(b) {
932	if (b === undefined) {
933		b = true;
934	}
935	return this.each(function() {
936		this.disabled = !b;
937	});
938};
939
940/**
941 * Checks/unchecks any matching checkboxes or radio buttons and
942 * selects/deselects and matching option elements.
943 */
944$.fn.selected = function(select) {
945	if (select === undefined) {
946		select = true;
947	}
948	return this.each(function() {
949		var t = this.type;
950		if (t == 'checkbox' || t == 'radio') {
951			this.checked = select;
952		}
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);
958			}
959			this.selected = select;
960		}
961	});
962};
963
964// expose debug var
965$.fn.ajaxSubmit.debug = false;
966
967// helper fn for console logging
968function log() {
969	if (!$.fn.ajaxSubmit.debug) 
970		return;
971	var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
972	if (window.console && window.console.log) {
973		window.console.log(msg);
974	}
975	else if (window.opera && window.opera.postError) {
976		window.opera.postError(msg);
977	}
978};
979
980})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.