PageSourceSearch

https://www.kimtec.or.kr/inc/js/jquery.form.js

js kimtec.or.kr collected 2026-10-08 23:12:35 UTC 41,025 bytes, 1,520 lines download raw bytes

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

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.