PageSourceSearch

https://corpwatchers.eu/prive/javascript/jquery.form.js?1788356854

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

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.