PageSourceSearch

https://www.fhf.fr/core/misc/jquery.form.js?v=4.3.0

js fhf.fr collected 2026-09-24 09:26:17 UTC 41,927 bytes, 1,539 lines download raw bytes

1/*!
2 * jQuery Form Plugin
3 * version: 4.3.0
4 * Requires jQuery v1.7.2 or later
5 * Project repository: https://github.com/jquery-form/form
6
7 * Copyright 2017 Kevin Morris
8 * Copyright 2006 M. Alsup
9
10 * Dual licensed under the LGPL-2.1+ or MIT licenses
11 * https://github.com/jquery-form/form#license
12
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 * Lesser General Public License for more details.
21 */
22/* global ActiveXObject */
23
24(function (factory) {
25	if (typeof define === 'function' && define.amd) {
26		// AMD. Register as an anonymous module.
27		define(['jquery'], factory);
28	} else if (typeof module === 'object' && module.exports) {
29		// Node/CommonJS
30		module.exports = function( root, jQuery ) {
31			if (typeof jQuery === 'undefined') {
32				// require('jQuery') returns a factory that requires window to build a jQuery instance, we normalize how we use modules
33				// that require this pattern but the window provided is a noop if it's defined (how jquery works)
34				if (typeof window !== 'undefined') {
35					jQuery = require('jquery');
36				}
37				else {
38					jQuery = require('jquery')(root);
39				}
40			}
41			factory(jQuery);
42			return jQuery;
43		};
44	} else {
45		// Browser globals
46		factory(jQuery);
47	}
48
49}(function ($) {
50/* eslint-enable */
51	'use strict';
52
53	/*
54		Usage Note:
55		-----------
56		Do not use both ajaxSubmit and ajaxForm on the same form. These
57		functions are mutually exclusive. Use ajaxSubmit if you want
58		to bind your own submit handler to the form. For example,
59
60		$(document).ready(function() {
61			$('#myForm').on('submit', function(e) {
62				e.preventDefault(); // <-- important
63				$(this).ajaxSubmit({
64					target: '#output'
65				});
66			});
67		});
68
69		Use ajaxForm when you want the plugin to manage all the event binding
70		for you. For example,
71
72		$(document).ready(function() {
73			$('#myForm').ajaxForm({
74				target: '#output'
75			});
76		});
77
78		You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
79		form does not have to exist when you invoke ajaxForm:
80
81		$('#myForm').ajaxForm({
82			delegation: true,
83			target: '#output'
84		});
85
86		When using ajaxForm, the ajaxSubmit function will be invoked for you
87		at the appropriate time.
88	*/
89
90	var rCRLF = /\r?\n/g;
91
92	/**
93	 * Feature detection
94	 */
95	var feature = {};
96
97	feature.fileapi = $('<input type="file">').get(0).files !== undefined;
98	feature.formdata = (typeof window.FormData !== 'undefined');
99
100	var hasProp = !!$.fn.prop;
101
102	// attr2 uses prop when it can but checks the return type for
103	// an expected string. This accounts for the case where a form
104	// contains inputs with names like "action" or "method"; in those
105	// cases "prop" returns the element
106	$.fn.attr2 = function() {
107		if (!hasProp) {
108			return this.attr.apply(this, arguments);
109		}
110
111		var val = this.prop.apply(this, arguments);
112
113		if ((val && val.jquery) || typeof val === 'string') {
114			return val;
115		}
116
117		return this.attr.apply(this, arguments);
118	};
119
120	/**
121	 * ajaxSubmit() provides a mechanism for immediately submitting
122	 * an HTML form using AJAX.
123	 *
124	 * @param	{object|string}	options		jquery.form.js parameters or custom url for submission
125	 * @param	{object}		data		extraData
126	 * @param	{string}		dataType	ajax dataType
127	 * @param	{function}		onSuccess	ajax success callback function
128	 */
129	$.fn.ajaxSubmit = function(options, data, dataType, onSuccess) {
130		// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
131		if (!this.length) {
132			log('ajaxSubmit: skipping submit process - no element selected');
133
134			return this;
135		}
136
137		/* eslint consistent-this: ["error", "$form"] */
138		var method, action, url, isMsie, iframeSrc, $form = this;
139
140		if (typeof options === 'function') {
141			options = {success: options};
142
143		} else if (typeof options === 'string' || (options === false && arguments.length > 0)) {
144			options = {
145				'url'      : options,
146				'data'     : data,
147				'dataType' : dataType
148			};
149
150			if (typeof onSuccess === 'function') {
151				options.success = onSuccess;
152			}
153
154		} else if (typeof options === 'undefined') {
155			options = {};
156		}
157
158		method = options.method || options.type || this.attr2('method');
159		action = options.url || this.attr2('action');
160
161		url = (typeof action === 'string') ? action.trim() : '';
162		url = url || window.location.href || '';
163		if (url) {
164			// clean url (don't include hash vaue)
165			url = (url.match(/^([^#]+)/) || [])[1];
166		}
167		// IE requires javascript:false in https, but this breaks chrome >
16783 and goes against spec.
168		// Instead of using javascript:false always, let's only apply it for IE.
169		isMsie = /(MSIE|Trident)/.test(navigator.userAgent || '');
170		iframeSrc = (isMsie && /^https/i.test(window.location.href || '')) ? 'javascript:false' : 'about:blank'; // eslint-disable-line no-script-url
171
172		options = $.extend(true, {
173			url       : url,
174			success   : $.ajaxSettings.success,
175			type      : method || $.ajaxSettings.type,
176			iframeSrc : iframeSrc
177		}, options);
178
179		// hook for manipulating the form data before it is extracted;
180		// convenient for use with rich editors like tinyMCE or FCKEditor
181		var veto = {};
182
183		this.trigger('form-pre-serialize', [this, options, veto]);
184
185		if (veto.veto) {
186			log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
187
188			return this;
189		}
190
191		// provide opportunity to alter form data before it is serialized
192		if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
193			log('ajaxSubmit: submit aborted via beforeSerialize callback');
194
195			return this;
196		}
197
198		var traditional = options.traditional;
199
200		if (typeof traditional === 'undefined') {
201			traditional = $.ajaxSettings.traditional;
202		}
203
204		var elements = [];
205		var qx, a = this.formToArray(options.semantic, elements, options.filtering);
206
207		if (options.data) {
208			var optionsData = typeof(options.data) === "function" ? options.data(a) : options.data;
209
210			options.extraData = optionsData;
211			qx = $.param(optionsData, traditional);
212		}
213
214		// give pre-submit callback an opportunity to abort the submit
215		if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
216			log('ajaxSubmit: submit aborted via beforeSubmit callback');
217
218			return this;
219		}
220
221		// fire vetoable 'validate' event
222		this.trigger('form-submit-validate', [a, this, options, veto]);
223		if (veto.veto) {
224			log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
225
226			return this;
227		}
228
229		var q = $.param(a, traditional);
230
231		if (qx) {
232			q = (q ? (q + '&' + qx) : qx);
233		}
234
235		if (options.type.toUpperCase() === 'GET') {
236			options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
237			options.data = null;	// data is null for 'get'
238		} else {
239			options.data = q;		// data is the query string for 'post'
240		}
241
242		var callbacks = [];
243
244		if (options.resetForm) {
245			callbacks.push(function() {
246				$form.resetForm();
247			});
248		}
249
250		if (options.clearForm) {
251			callbacks.push(function() {
252				$form.clearForm(options.includeHidden);
253			});
254		}
255
256		// perform a load on the target only if dataType is not provided
257		if (!options.dataType && options.target) {
258			var oldSuccess = options.success || function(){};
259
260			callbacks.push(function(data, textStatus, jqXHR) {
261				var successArguments = arguments,
262					fn = options.replaceTarget ? 'replaceWith' : 'html';
263
264				$(options.target)[fn](data).each(function(){
265					oldSuccess.apply(this, successArguments);
266				});
267			});
268
269		} else if (options.success) {
270			if (Array.isArray(options.success)) {
271				callbacks = callbacks.concat(options.success);
272			} else {
273				callbacks.push(options.success);
274			}
275		}
276
277		options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
278			var context = options.context || this;		// jQuery 1.4+ supports scope context
279
280			for (var i = 0, max = callbacks.length; i < max; i++) {
281				callbacks[i].apply(context, [data, status, xhr || $form, $form]);
282			}
283		};
284
285		if (options.error) {
286			var oldError = options.error;
287
288			options.error = function(xhr, status, error) {
289				var context = options.context || this;
290
291				oldError.apply(context, [xhr, status, error, $form]);
292			};
293		}
294
295		if (options.complete) {
296			var oldComplete = options.complete;
297
298			options.complete = function(xhr, status) {
299				var context = options.context || this;
300
301				oldComplete.apply(context, [xhr, status, $form]);
302			};
303		}
304
305		// are there files to upload?
306
307		// [value] (issue #113), also see comment:
308		// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
309		var fileInputs = $('input[type=file]:enabled', this).filter(function() {
310			return $(this).val() !== '';
311		});
312		var hasFileInputs = fileInputs.length > 0;
313		var mp = 'multipart/form-data';
314		var multipart = ($form.attr('enctype') === mp || $form.attr('encoding') === mp);
315		var fileAPI = feature.fileapi && feature.formdata;
316
317		log('fileAPI :' + fileAPI);
318
319		var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
320		var jqxhr;
321
322		// options.iframe allows user to force iframe mode
323		// 06-NOV-09: now defaulting to iframe mode if file input is detected
324		if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
325			// hack to fix Safari hang (thanks to Tim Molendijk for this)
326			// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
327			if (options.closeKeepAlive) {
328				$.get(options.closeKeepAlive, function() {
329					jqxhr = fileUploadIframe(a);
330				});
331
332			} else {
333				jqxhr = fileUploadIframe(a);
334			}
335
336		} else if ((hasFileInputs || multipart) && fileAPI) {
337			jqxhr = fileUploadXhr(a);
338
339		} else {
340			jqxhr = $.ajax(options);
341		}
342
343		$form.removeData('jqxhr').data('jqxhr', jqxhr);
344
345		// clear element array
346		for (var k = 0; k < elements.length; k++) {
347			elements[k] = null;
348		}
349
350		// fire 'notify' event
351		this.trigger('form-submit-notify', [this, options]);
352
353		return this;
354
355		// utility fn for deep serialization
356		function deepSerialize(extraData) {
357			var serialized = $.param(extraData, options.traditional).split('&');
358			var len = serialized.length;
359			var result = [];
360			var i, part;
361
362			for (i = 0; i < len; i++) {
363				// #252; undo param space replacement
364				serialized[i] = serialized[i].replace(/\+/g, ' ');
365				part = serialized[i].split('=');
366				// #278; use array instead of object storage, favoring array serializations
367				result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
368			}
369
370			return result;
371		}
372
373		// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
374		function fileUploadXhr(a) {
375			var formdata = new FormData();
376
377			for (var i = 0; i < a.length; i++) {
378				formdata.append(a[i].name, a[i].value);
379			}
380
381			if (options.extraData) {
382				var serializedData = deepSerialize(options.extraData);
383
384				for (i = 0; i < serializedData.length; i++) {
385					if (serializedData[i]) {
386						formdata.append(serializedData[i][0], serializedData[i][1]);
387					}
388				}
389			}
390
391			options.data = null;
392
393			var s = $.extend(true, {}, $.ajaxSettings, options, {
394				contentType : false,
395				processData : false,
396				cache       : false,
397				type        : method || 'POST'
398			});
399
400			if (options.uploadProgress) {
401				// workaround because jqXHR does not expose upload property
402				s.xhr = function() {
403					var xhr = $.ajaxSettings.xhr();
404
405					if (xhr.upload) {
406						xhr.upload.addEventListener('progress', function(event) {
407							var percent = 0;
408							var position = event.loaded || event.position;			/* event.position is deprecated */
409							var total = event.total;
410
411							if (event.lengthComputable) {
412								percent = Math.ceil(position / total * 100);
413							}
414
415							options.uploadProgress(event, position, total, percent);
416						}, false);
417					}
418
419					return xhr;
420				};
421			}
422
423			s.data = null;
424
425			var beforeSend = s.beforeSend;
426
427			s.beforeSend = function(xhr, o) {
428				// Send FormData() provided by user
429				if (options.formData) {
430					o.data = options.formData;
431				} else {
432					o.data = formdata;
433				}
434
435				if (beforeSend) {
436					beforeSend.call(this, xhr, o);
437				}
438			};
439
440			return $.ajax(s);
441		}
442
443		// private function for handling file uploads (hat tip to YAHOO!)
444		function fileUploadIframe(a) {
445			var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
446			var deferred = $.Deferred();
447
448			// #341
449			deferred.abort = function(status) {
450				xhr.abort(status);
451			};
452
453			if (a) {
454				// ensure that every serialized input is still enabled
455				for (i = 0; i < elements.length; i++) {
456					el = $(elements[i]);
457					if (hasProp) {
458						el.prop('disabled', false);
459					} else {
460						el.removeAttr('disabled');
461					}
462				}
463			}
464
465			s = $.extend(true, {}, $.ajaxSettings, options);
466			s.context = s.context || s;
467			id = 'jqFormIO' + new Date().getTime();
468			var ownerDocument = form.ownerDocument;
469			var $body = $form.closest('body');
470
471			if (s.iframeTarget) {
472				$io = $(s.iframeTarget, ownerDocument);
473				n = $io.attr2('name');
474				if (!n) {
475					$io.attr2('name', id);
476				} else {
477					id = n;
478				}
479
480			} else {
481				$io = $('<iframe name="' + id + '" src="' + s.iframeSrc + '" />', ownerDocument);
482				$io.css({position: 'absolute', top: '-1000px', left: '-1000px'});
483			}
484			io = $io[0];
485
486
487			xhr = { // mock object
488				aborted               : 0,
489				responseText          : null,
490				responseXML           : null,
491				status                : 0,
492				statusText            : 'n/a',
493				getAllResponseHeaders : function() {},
494				getResponseHeader     : function() {},
495				setRequestHeader      : function() {},
496				abort                 : function(status) {
497					var e = (status === 'timeout' ? 'timeout' : 'aborted');
498
499					log('aborting upload... ' + e);
500					this.aborted = 1;
501
502					try { // #214, #257
503						if (io.contentWindow.document.execCommand) {
504							io.contentWindow.document.execCommand('Stop');
505						}
506					} catch (ignore) {}
507
508					$io.attr('src', s.iframeSrc); // abort op in progress
509					xhr.error = e;
510					if (s.error) {
511						s.error.call(s.context, xhr, e, status);
512					}
513
514					if (g) {
515						$.event.trigger('ajaxError', [xhr, s, e]);
516					}
517
518					if (s.complete) {
519						s.complete.call(s.context, xhr, e);
520					}
521				}
522			};
523
524			g = s.global;
525			// trigger ajax global events so that activity/block indicators work like normal
526			if (g && $.active++ === 0) {
527				$.event.trigger('ajaxStart');
528			}
529			if (g) {
530				$.event.trigger('ajaxSend', [xhr, s]);
531			}
532
533			if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
534				if (s.global) {
535					$.active--;
536				}
537				deferred.reject();
538
539				return deferred;
540			}
541
542			if (xhr.aborted) {
543				deferred.reject();
544
545				return deferred;
546			}
547
548			// add submitting element to data if we know it
549			sub = form.clk;
550			if (sub) {
551				n = sub.name;
552				if (n && !sub.disabled) {
553					s.extraData = s.extraData || {};
554					s.extraData[n] = sub.value;
555					if (sub.type === 'image') {
556						s.extraData[n + '.x'] = form.clk_x;
557						s.extraData[n + '.y'] = form.clk_y;
558					}
559				}
560			}
561
562			var CLIENT_TIMEOUT_ABORT = 1;
563			var SERVER_ABORT = 2;
564
565			function getDoc(frame) {
566				/* it looks like contentWindow or contentDocument do not
567				 * carry the protocol property in ie8, when running under ssl
568				 * frame.document is the only valid response document, since
569				 * the protocol is know but not on the other two objects. strange?
570				 * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
571				 */
572
573				var doc = null;
574
575				// IE8 cascading access check
576				try {
577					if (frame.contentWindow) {
578						doc = frame.contentWindow.document;
579					}
580				} catch (err) {
581					// IE8 access denied under ssl & missing protocol
582					log('cannot get iframe.contentWindow document: ' + err);
583				}
584
585				if (doc) { // successful getting content
586					return doc;
587				}
588
589				try { // simply checking may throw in ie8 under ssl or mismatched protocol
590					doc = frame.contentDocument ? frame.contentDocument : frame.document;
591				} catch (err) {
592					// last attempt
593					log('cannot get iframe.contentDocument: ' + err);
594					doc = frame.document;
595				}
596
597				return doc;
598			}
599
600			// Rails CSRF hack (thanks to Yvan Barthelemy)
601			var csrf_token = $('meta[name=csrf-token]').attr('content');
602			var csrf_param = $('meta[name=csrf-param]').attr('content');
603
604			if (csrf_param && csrf_token) {
605				s.extraData = s.extraData || {};
606				s.extraData[csrf_param] = csrf_token;
607			}
608
609			// take a breath so that pending repaints get some cpu time before the upload starts
610			function doSubmit() {
611				// make sure form attrs are set
612				var t = $form.attr2('target'),
613					a = $form.attr2('action'),
614					mp = 'multipart/form-data',
615					et = $form.attr('enctype') || $form.attr('encoding') || mp;
616
617				// update form attrs in IE friendly way
618				form.setAttribute('target', id);
619				if (!method || /post/i.test(method)) {
620					form.setAttribute('method', 'POST');
621				}
622				if (a !== s.url) {
623					form.setAttribute('action', s.url);
624				}
625
626				// ie borks in some cases when setting encoding
627				if (!s.skipEncodingOverride && (!method || /post/i.test(method))) {
628					$form.attr({
629						encoding : 'multipart/form-data',
630						enctype  : 'multipart/form-data'
631					});
632				}
633
634				// support timout
635				if (s.timeout) {
636					timeoutHandle = setTimeout(function() {
637						timedOut = true; cb(CLIENT_TIMEOUT_ABORT);
638					}, s.timeout);
639				}
640
641				// look for server aborts
642				function checkState() {
643					try {
644						var state = getDoc(io).readyState;
645
646						log('state = ' + state);
647						if (state && state.toLowerCase() === 'uninitialized') {
648							setTimeout(checkState, 50);
649						}
650
651					} catch (e) {
652						log('Server abort: ', e, ' (', e.name, ')');
653						cb(SERVER_ABORT);				// eslint-disable-line callback-return
654						if (timeoutHandle) {
655							clearTimeout(timeoutHandle);
656						}
657						timeoutHandle = undefined;
658					}
659				}
660
661				// add "extra" data to form if provided in options
662				var extraInputs = [];
663
664				try {
665					if (s.extraData) {
666						for (var n in s.extraData) {
667							if (s.extraData.hasOwnProperty(n)) {
668								// if using the $.param format that allows for multiple values with the same name
669								if ($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
670									extraInputs.push(
671										$('<input type="hidden" name="' + s.extraData[n].name + '">', ownerDocument).val(s.extraData[n].value)
672											.appendTo(form)[0]);
673								} else {
674									extraInputs.push(
675										$('<input type="hidden" name="' + n + '">', ownerDocument).val(s.extraData[n])
676											.appendTo(form)[0]);
677								}
678							}
679						}
680					}
681
682					if (!s.iframeTarget) {
683						// add iframe to doc and submit the form
684						$io.appendTo($body);
685					}
686
687					if (io.attachEvent) {
688						io.attachEvent('onload', cb);
689					} else {
690						io.addEventListener('load', cb, false);
691					}
692
693					setTimeout(checkState, 15);
694
695					try {
696						form.submit();
697
698					} catch (err) {
699						// just in case form has element with name/id of 'submit'
700						var submitFn = document.createElement('form').submit;
701
702						submitFn.apply(form);
703					}
704
705				} finally {
706					// reset attrs and remove "extra" input elements
707					form.setAttribute('action', a);
708					form.setAttribute('enctype', et); // #380
709					if (t) {
710						form.setAttribute('target', t);
711					} else {
712						$form.removeAttr('target');
713					}
714					$(extraInputs).remove();
715				}
716			}
717
718			if (s.forceSync) {
719				doSubmit();
720			} else {
721				setTimeout(doSubmit, 10); // this lets dom updates render
722			}
723
724			var data, doc, domCheckCount = 50, callbackProcessed;
725
726			function cb(e) {
727				if (xhr.aborted || callbackProcessed) {
728					return;
729				}
730
731				doc = getDoc(io);
732				if (!doc) {
733					log('cannot access response document');
734					e = SERVER_ABORT;
735				}
736				if (e === CLIENT_TIMEOUT_ABORT && xhr) {
737					xhr.abort('timeout');
738					deferred.reject(xhr, 'timeout');
739
740					return;
741
742				}
743				if (e === SERVER_ABORT && xhr) {
744					xhr.abort('server abort');
745					deferred.reject(xhr, 'error', 'server abort');
746
747					return;
748				}
749
750				if (!doc || doc.location.href === s.iframeSrc) {
751					// response not received yet
752					if (!timedOut) {
753						return;
754					}
755				}
756
757				if (io.detachEvent) {
758					io.detachEvent('onload', cb);
759				} else {
760					io.removeEventListener('load', cb, false);
761				}
762
763				var status = 'success', errMsg;
764
765				try {
766					if (timedOut) {
767						throw 'timeout';
768					}
769
770					var isXml = s.dataType === 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
771
772					log('isXml=' + isXml);
773
774					if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
775						if (--domCheckCount) {
776							// in some browsers (Opera) the iframe DOM is not always traversable when
777							// the onload callback fires, so we loop a bit to accommodate
778							log('requeing onLoad callback, DOM not available');
779							setTimeout(cb, 250);
780
781							return;
782						}
783						// let this fall through because server response could be an empty document
784						// log('Could not access iframe DOM after mutiple tries.');
785						// throw 'DOMException: not available';
786					}
787
788					// log('response detected');
789					var docRoot = doc.body ? doc.body : doc.documentElement;
790
791					xhr.responseText = docRoot ? docRoot.innerHTML : null;
792					xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
793					if (isXml) {
794						s.dataType = 'xml';
795					}
796					xhr.getResponseHeader = function(header){
797						var headers = {'content-type': s.dataType};
798
799						return headers[header.toLowerCase()];
800					};
801					// support for XHR 'status' & 'statusText' emulation :
802					if (docRoot) {
803						xhr.status = Number(docRoot.getAttribute('status')) || xhr.status;
804						xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
805					}
806
807					var dt = (s.dataType || '').toLowerCase();
808					var scr = /(json|script|text)/.test(dt);
809
810					if (scr || s.textarea) {
811						// see if user embedded response in textarea
812						var ta = doc.getElementsByTagName('textarea')[0];
813
814						if (ta) {
815							xhr.responseText = ta.value;
816							// support for XHR 'status' & 'statusText' emulation :
817							xhr.status = Number(ta.getAttribute('status')) || xhr.status;
818							xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
819
820						} else if (scr) {
821							// account for browsers injecting pre around json response
822							var pre = doc.getElementsByTagName('pre')[0];
823							var b = doc.getElementsByTagName('body')[0];
824
825							if (pre) {
826								xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
827							} else if (b) {
828								xhr.responseText = b.textContent ? b.textContent : b.innerText;
829							}
830						}
831
832					} else if (dt === 'xml' && !xhr.responseXML && xhr.responseText) {
833						xhr.responseXML = toXml(xhr.responseText);			// eslint-disable-line no-use-before-define
834					}
835
836					try {
837						data = httpData(xhr, dt, s);						// eslint-disable-line no-use-before-define
838
839					} catch (err) {
840						status = 'parsererror';
841						xhr.error = errMsg = (err || status);
842					}
843
844				} catch (err) {
845					log('error caught: ', err);
846					status = 'error';
847					xhr.error = errMsg = (err || status);
848				}
849
850				if (xhr.aborted) {
851					log('upload aborted');
852					status = null;
853				}
854
855				if (xhr.status) { // we've set xhr.status
856					status = ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) ? 'success' : 'error';
857				}
858
859				// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
860				if (status === 'success') {
861					if (s.success) {
862						s.success.call(s.context, data, 'success', xhr);
863					}
864
865					deferred.resolve(xhr.responseText, 'success', xhr);
866
867					if (g) {
868						$.event.trigger('ajaxSuccess', [xhr, s]);
869					}
870
871				} else if (status) {
872					if (typeof errMsg === 'undefined') {
873						errMsg = xhr.statusText;
874					}
875					if (s.error) {
876						s.error.call(s.context, xhr, status, errMsg);
877					}
878					deferred.reject(xhr, 'error', errMsg);
879					if (g) {
880						$.event.trigger('ajaxError', [xhr, s, errMsg]);
881					}
882				}
883
884				if (g) {
885					$.event.trigger('ajaxComplete', [xhr, s]);
886				}
887
888				if (g && !--$.active) {
889					$.event.trigger('ajaxStop');
890				}
891
892				if (s.complete) {
893					s.complete.call(s.context, xhr, status);
894				}
895
896				callbackProcessed = true;
897				if (s.timeout) {
898					clearTimeout(timeoutHandle);
899				}
900
901				// clean up
902				setTimeout(function() {
903					if (!s.iframeTarget) {
904						$io.remove();
905					} else { // adding else to clean up existing iframe response.
906						$io.attr('src', s.iframeSrc);
907					}
908					xhr.responseXML = null;
909				}, 100);
910			}
911
912			var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
913				if (window.ActiveXObject) {
914					doc = new ActiveXObject('Microsoft.XMLDOM');
915					doc.async = 'false';
916					doc.loadXML(s);
917
918				} else {
919					doc = (new DOMParser()).parseFromString(s, 'text/xml');
920				}
921
922				return (doc && doc.documentElement && doc.documentElement.nodeName !== 'parsererror') ? doc : null;
923			};
924			var parseJSON = $.parseJSON || function(s) {
925				/* jslint evil:true */
926				return window['eval']('(' + s + ')');			// eslint-disable-line dot-notation
927			};
928
929			var httpData = function(xhr, type, s) { // mostly lifted from jq1.4.4
930
931				var ct = xhr.getResponseHeader('content-type') || '',
932					xml = ((type === 'xml' || !type) && ct.indexOf('xml') >= 0),
933					data = xml ? xhr.responseXML : xhr.responseText;
934
935				if (xml && data.documentElement.nodeName === 'parsererror') {
936					if ($.error) {
937						$.error('parsererror');
938					}
939				}
940				if (s && s.dataFilter) {
941					data = s.dataFilter(data, type);
942				}
943				if (typeof data === 'string') {
944					if ((type === 'json' || !type) && ct.indexOf('json') >= 0) {
945						data = parseJSON(data);
946					} else if ((type === 'script' || !type) && ct.indexOf('javascript') >= 0) {
947						$.globalEval(data);
948					}
949				}
950
951				return data;
952			};
953
954			return deferred;
955		}
956	};
957
958	/**
959	 * ajaxForm() provides a mechanism for fully automating form submission.
960	 *
961	 * The advantages of using this method instead of ajaxSubmit() are:
962	 *
963	 * 1: This method will include coordinates for <input type="image"> elements (if the element
964	 *	is used to submit the form).
965	 * 2. This method will include the submit element's name/value data (for the element that was
966	 *	used to submit the form).
967	 * 3. This method binds the submit() method to the form for you.
968	 *
969	 * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
970	 * passes the options argument along after properly binding events for submit elements and
971	 * the form itself.
972	 */
973	$.fn.ajaxForm = function(options, data, dataType, onSuccess) {
974		if (typeof options === 'string' || (options === false && arguments.length > 0)) {
975			options = {
976				'url'      : options,
977				'data'     : data,
978				'dataType' : dataType
979			};
980
981			if (typeof onSuccess === 'function') {
982				options.success = onSuccess;
983			}
984		}
985
986		options = options || {};
987		options.delegation = options.delegation && typeof $.fn.on === 'function';
988
989		// in jQuery 1.3+ we can fix mistakes with the ready state
990		if (!options.delegation && this.length === 0) {
991			var o = {s: this.selector, c: this.context};
992
993			if (!$.isReady && o.s) {
994				log('DOM not ready, queuing ajaxForm');
995				$(function() {
996					$(o.s, o.c).ajaxForm(options);
997				});
998
999				return this;
1000			}
1001
1002			// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
1003			log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
1004
1005			return this;
1006		}
1007
1008		if (options.delegation) {
1009			$(document)
1010				.off('submit.form-plugin', this.selector, doAjaxSubmit)
1011				.off('click.form-plugin', this.selector, captureSubmittingElement)
1012				.on('submit.form-plugin', this.selector, options, doAjaxSubmit)
1013				.on('click.form-plugin', this.selector, options, captureSubmittingElement);
1014
1015			return this;
1016		}
1017
1018		if (options.beforeFormUnbind) {
1019			options.beforeFormUnbind(this, options);
1020		}
1021
1022		return this.ajaxFormUnbind()
1023			.on('submit.form-plugin', options, doAjaxSubmit)
1024			.on('click.form-plugin', options, captureSubmittingElement);
1025	};
1026
1027	// private event handlers
1028	function doAjaxSubmit(e) {
1029		/* jshint validthis:true */
1030		var options = e.data;
1031
1032		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
1033			e.preventDefault();
1034			$(e.target).closest('form').ajaxSubmit(options); // #365
1035		}
1036	}
1037
1038	function captureSubmittingElement(e) {
1039		/* jshint validthis:true */
1040		var target = e.target;
1041		var $el = $(target);
1042
1043		if (!$el.is('[type=submit],[type=image]')) {
1044			// is this a child element of the submit el?  (ex: a span within a button)
1045			var t = $el.closest('[type=submit]');
1046
1047			if (t.length === 0) {
1048				return;
1049			}
1050			target = t[0];
1051		}
1052
1053		var form = target.form;
1054
1055		form.clk = target;
1056
1057		if (target.type === 'image') {
1058			if (typeof e.offsetX !== 'undefined') {
1059				form.clk_x = e.offsetX;
1060				form.clk_y = e.offsetY;
1061
1062			} else if (typeof $.fn.offset === 'function') {
1063				var offset = $el.offset();
1064
1065				form.clk_x = e.pageX - offset.left;
1066				form.clk_y = e.pageY - offset.top;
1067
1068			} else {
1069				form.clk_x = e.pageX - target.offsetLeft;
1070				form.clk_y = e.pageY - target.offsetTop;
1071			}
1072		}
1073		// clear form vars
1074		setTimeout(function() {
1075			form.clk = form.clk_x = form.clk_y = null;
1076		}, 100);
1077	}
1078
1079
1080	// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
1081	$.fn.ajaxFormUnbind = function() {
1082		return this.off('submit.form-plugin click.form-plugin');
1083	};
1084
1085	/**
1086	 * formToArray() gathers form element data into an array of objects that can
1087	 * be passed to any of the following ajax functions: $.get, $.post, or load.
1088	 * Each object in the array has both a 'name' and 'value' property. An example of
1089	 * an array for a simple login form might be:
1090	 *
1091	 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
1092	 *
1093	 * It is this array that is passed to pre-submit callback functions provided to the
1094	 * ajaxSubmit() and ajaxForm() methods.
1095	 */
1096	$.fn.formToArray = function(semantic, elements, filtering) {
1097		var a = [];
1098
1099		if (this.length === 0) {
1100			return a;
1101		}
1102
1103		var form = this[0];
1104		var formId = this.attr('id');
1105		var els = (semantic || typeof form.elements === 'undefined') ? form.getElementsByTagName('*') : form.elements;
1106		var els2;
1107
1108		if (els) {
1109			els = $.makeArray(els); // convert to standard array
1110		}
1111
1112		// #386; account for inputs outside the form which use the 'form' attribute
1113		// FinesseRus: in non-IE browsers outside fields are already included in form.elements.
1114		if (formId && (semantic || /(Edge|Trident)\//.test(navigator.userAgent))) {
1115			els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet
1116			if (els2.length) {
1117				els = (els || []).concat(els2);
1118			}
1119		}
1120
1121		if (!els || !els.length) {
1122			return a;
1123		}
1124
1125		if (typeof(filtering) === "function") {
1126			els = $.map(els, filtering);
1127		}
1128
1129		var i, j, n, v, el, max, jmax;
1130
1131		for (i = 0, max = els.length; i < max; i++) {
1132			el = els[i];
1133			n = el.name;
1134			if (!n || el.disabled) {
1135				continue;
1136			}
1137
1138			if (semantic && form.clk && el.type === 'image') {
1139				// handle image inputs on the fly when semantic == true
1140				if (form.clk === el) {
1141					a.push({name: n, value: $(el).val(), type: el.type});
1142					a.push({name: n + '.x', value: form.clk_x}
1142, {name: n + '.y', value: form.clk_y});
1143				}
1144				continue;
1145			}
1146
1147			v = $.fieldValue(el, true);
1148			if (v && v.constructor === Array) {
1149				if (elements) {
1150					elements.push(el);
1151				}
1152				for (j = 0, jmax = v.length; j < jmax; j++) {
1153					a.push({name: n, value: v[j]});
1154				}
1155
1156			} else if (feature.fileapi && el.type === 'file') {
1157				if (elements) {
1158					elements.push(el);
1159				}
1160
1161				var files = el.files;
1162
1163				if (files.length) {
1164					for (j = 0; j < files.length; j++) {
1165						a.push({name: n, value: files[j], type: el.type});
1166					}
1167				} else {
1168					// #180
1169					a.push({name: n, value: '', type: el.type});
1170				}
1171
1172			} else if (v !== null && typeof v !== 'undefined') {
1173				if (elements) {
1174					elements.push(el);
1175				}
1176				a.push({name: n, value: v, type: el.type, required: el.required});
1177			}
1178		}
1179
1180		if (!semantic && form.clk) {
1181			// input type=='image' are not found in elements array! handle it here
1182			var $input = $(form.clk), input = $input[0];
1183
1184			n = input.name;
1185
1186			if (n && !input.disabled && input.type === 'image') {
1187				a.push({name: n, value: $input.val()});
1188				a.push({name: n + '.x', value: form.clk_x}, {name: n + '.y', value: form.clk_y});
1189			}
1190		}
1191
1192		return a;
1193	};
1194
1195	/**
1196	 * Serializes form data into a 'submittable' string. This method will return a string
1197	 * in the format: name1=value1&amp;name2=value2
1198	 */
1199	$.fn.formSerialize = function(semantic) {
1200		// hand off to jQuery.param for proper encoding
1201		return $.param(this.formToArray(semantic));
1202	};
1203
1204	/**
1205	 * Serializes all field elements in the jQuery object into a query string.
1206	 * This method will return a string in the format: name1=value1&amp;name2=value2
1207	 */
1208	$.fn.fieldSerialize = function(successful) {
1209		var a = [];
1210
1211		this.each(function() {
1212			var n = this.name;
1213
1214			if (!n) {
1215				return;
1216			}
1217
1218			var v = $.fieldValue(this, successful);
1219
1220			if (v && v.constructor === Array) {
1221				for (var i = 0, max = v.length; i < max; i++) {
1222					a.push({name: n, value: v[i]});
1223				}
1224
1225			} else if (v !== null && typeof v !== 'undefined') {
1226				a.push({name: this.name, value: v});
1227			}
1228		});
1229
1230		// hand off to jQuery.param for proper encoding
1231		return $.param(a);
1232	};
1233
1234	/**
1235	 * Returns the value(s) of the element in the matched set. For example, consider the following form:
1236	 *
1237	 *	<form><fieldset>
1238	 *		<input name="A" type="text">
1239	 *		<input name="A" type="text">
1240	 *		<input name="B" type="checkbox" value="B1">
1241	 *		<input name="B" type="checkbox" value="B2">
1242	 *		<input name="C" type="radio" value="C1">
1243	 *		<input name="C" type="radio" value="C2">
1244	 *	</fieldset></form>
1245	 *
1246	 *	var v = $('input[type=text]').fieldValue();
1247	 *	// if no values are entered into the text inputs
1248	 *	v === ['','']
1249	 *	// if values entered into the text inputs are 'foo' and 'bar'
1250	 *	v === ['foo','bar']
1251	 *
1252	 *	var v = $('input[type=checkbox]').fieldValue();
1253	 *	// if neither checkbox is checked
1254	 *	v === undefined
1255	 *	// if both checkboxes are checked
1256	 *	v === ['B1', 'B2']
1257	 *
1258	 *	var v = $('input[type=radio]').fieldValue();
1259	 *	// if neither radio is checked
1260	 *	v === undefined
1261	 *	// if first radio is checked
1262	 *	v === ['C1']
1263	 *
1264	 * The successful argument controls whether or not the field element must be 'successful'
1265	 * (per https://www.w3.org/TR/html4/interact/forms.html#successful-controls).
1266	 * The default value of the successful argument is true. If this value is false the value(s)
1267	 * for each element is returned.
1268	 *
1269	 * Note: This method *always* returns an array. If no valid value can be determined the
1270	 *	array will be empty, otherwise it will contain one or more values.
1271	 */
1272	$.fn.fieldValue = function(successful) {
1273		for (var val = [], i = 0, max = this.length; i < max; i++) {
1274			var el = this[i];
1275			var v = $.fieldValue(el, successful);
1276
1277			if (v === null || typeof v === 'undefined' || (v.constructor === Array && !v.length)) {
1278				continue;
1279			}
1280
1281			if (Array.isArray(v)) {
1282				val = val.concat(v);
1283			} else {
1284				val.push(v);
1285			}
1286		}
1287
1288		return val;
1289	};
1290
1291	/**
1292	 * Returns the value of the field element.
1293	 */
1294	$.fieldValue = function(el, successful) {
1295		var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
1296
1297		if (typeof successful === 'undefined') {
1298			successful = true;
1299		}
1300
1301		/* eslint-disable no-mixed-operators */
1302		if (successful && (!n || el.disabled || t === 'reset' || t === 'button' ||
1303			(t === 'checkbox' || t === 'radio') && !el.checked ||
1304			(t === 'submit' || t === 'image') && el.form && el.form.clk !== el ||
1305			tag === 'select' && el.selectedIndex === -1)) {
1306		/* eslint-enable no-mixed-operators */
1307			return null;
1308		}
1309
1310		if (tag === 'select') {
1311			var index = el.selectedIndex;
1312
1313			if (index < 0) {
1314				return null;
1315			}
1316
1317			var a = [], ops = el.options;
1318			var one = (t === 'select-one');
1319			var max = (one ? index + 1 : ops.length);
1320
1321			for (var i = (one ? index : 0); i < max; i++) {
1322				var op = ops[i];
1323
1324				if (op.selected && !op.disabled) {
1325					var v = op.value;
1326
1327					if (!v) { // extra pain for IE...
1328						v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value;
1329					}
1330
1331					if (one) {
1332						return v;
1333					}
1334
1335					a.push(v);
1336				}
1337			}
1338
1339			return a;
1340		}
1341
1342		return $(el).val().replace(rCRLF, '\r\n');
1343	};
1344
1345	/**
1346	 * Clears the form data. Takes the following actions on the form's input fields:
1347	 *  - input text fields will have their 'value' property set to the empty string
1348	 *  - select elements will have their 'selectedIndex' property set to -1
1349	 *  - checkbox and radio inputs will have their 'checked' property set to false
1350	 *  - inputs of type submit, button, reset, and hidden will *not* be effected
1351	 *  - button elements will *not* be effected
1352	 */
1353	$.fn.clearForm = function(includeHidden) {
1354		return this.each(function() {
1355			$('input,select,textarea', this).clearFields(includeHidden);
1356		});
1357	};
1358
1359	/**
1360	 * Clears the selected form elements.
1361	 */
1362	$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
1363		var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
1364
1365		return this.each(function() {
1366			var t = this.type, tag = this.tagName.toLowerCase();
1367
1368			if (re.test(t) || tag === 'textarea') {
1369				this.value = '';
1370
1371			} else if (t === 'checkbox' || t === 'radio') {
1372				this.checked = false;
1373
1374			} else if (tag === 'select') {
1375				this.selectedIndex = -1;
1376
1377			} else if (t === 'file') {
1378				if (/MSIE/.test(navigator.userAgent)) {
1379					$(this).replaceWith($(this).clone(true));
1380				} else {
1381					$(this).val('');
1382				}
1383
1384			} else if (includeHidden) {
1385				// includeHidden can be the value true, or it can be a selector string
1386				// indicating a special test; for example:
1387				// $('#myForm').clearForm('.special:hidden')
1388				// the above would clean hidden inputs that have the class of 'special'
1389				if ((includeHidden === true && /hidden/.test(t)) ||
1390					(typeof includeHidden === 'string' && $(this).is(includeHidden))) {
1391					this.value = '';
1392				}
1393			}
1394		});
1395	};
1396
1397
1398	/**
1399	 * Resets the form data or individual elements. Takes the following actions
1400	 * on the selected tags:
1401	 * - all fields within form elements will be reset to their original value
1402	 * - input / textarea / select fields will be reset to their original value
1403	 * - option / optgroup fields (for multi-selects) will defaulted individually
1404	 * - non-multiple options will find the right select to default
1405	 * - label elements will be searched against its 'for' attribute
1406	 * - all others will be searched for appropriate children to default
1407	 */
1408	$.fn.resetForm = function() {
1409		return this.each(function() {
1410			var el = $(this);
1411			var tag = this.tagName.toLowerCase();
1412
1413			switch (tag) {
1414			case 'input':
1415				this.checked = this.defaultChecked;
1416				// fall through
1417
1418			case 'textarea':
1419				this.value = this.defaultValue;
1420
1421				return true;
1422
1423			case 'option':
1424			case 'optgroup':
1425				var select = el.parents('select');
1426
1427				if (select.length && select[0].multiple) {
1428					if (tag === 'option') {
1429						this.selected = this.defaultSelected;
1430					} else {
1431						el.find('option').resetForm();
1432					}
1433				} else {
1434					select.resetForm();
1435				}
1436
1437				return true;
1438
1439			case 'select':
1440				el.find('option').each(function(i) {				// eslint-disable-line consistent-return
1441					this.selected = this.defaultSelected;
1442					if (this.defaultSelected && !el[0].multiple) {
1443						el[0].selectedIndex = i;
1444
1445						return false;
1446					}
1447				});
1448
1449				return true;
1450
1451			case 'label':
1452				var forEl = $(el.attr('for'));
1453				var list = el.find('input,select,textarea');
1454
1455				if (forEl[0]) {
1456					list.unshift(forEl[0]);
1457				}
1458
1459				list.resetForm();
1460
1461				return true;
1462
1463			case 'form':
1464				// guard against an input with the name of 'reset'
1465				// note that IE reports the reset function as an 'object'
1466				if (typeof this.reset === 'function' || (typeof this.reset === 'object' && !this.reset.nodeType)) {
1467					this.reset();
1468				}
1469
1470				return true;
1471
1472			default:
1473				el.find('form,input,label,select,textarea').resetForm();
1474
1475				return true;
1476			}
1477		});
1478	};
1479
1480	/**
1481	 * Enables or disables any matching elements.
1482	 */
1483	$.fn.enable = function(b) {
1484		if (typeof b === 'undefined') {
1485			b = true;
1486		}
1487
1488		return this.each(function() {
1489			this.disabled = !b;
1490		});
1491	};
1492
1493	/**
1494	 * Checks/unchecks any matching checkboxes or radio buttons and
1495	 * selects/deselects and matching option elements.
1496	 */
1497	$.fn.selected = function(select) {
1498		if (typeof select === 'undefined') {
1499			select = true;
1500		}
1501
1502		return this.each(function() {
1503			var t = this.type;
1504
1505			if (t === 'checkbox' || t === 'radio') {
1506				this.checked = select;
1507
1508			} else if (this.tagName.toLowerCase() === 'option') {
1509				var $sel = $(this).parent('select');
1510
1511				if (select && $sel[0] && $sel[0].type === 'select-one') {
1512					// deselect all other options
1513					$sel.find('option').selected(false);
1514				}
1515
1516				this.selected = select;
1517			}
1518		});
1519	};
1520
1521	// expose debug var
1522	$.fn.ajaxSubmit.debug = false;
1523
1524	// helper fn for console logging
1525	function log() {
1526		if (!$.fn.ajaxSubmit.debug) {
1527			return;
1528		}
1529
1530		var msg = '[jquery.form] ' + Array.prototype.join.call(arguments, '');
1531
1532		if (window.console && window.console.log) {
1533			window.console.log(msg);
1534
1535		} else if (window.opera && window.opera.postError) {
1536			window.opera.postError(msg);
1537		}
1538	}
1539}));

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.