PageSourceSearch

https://ksbbs.com/static/danceui/js/jquery.form.js

js ksbbs.com collected 2026-10-02 15:21:09 UTC 41,543 bytes, 1,532 lines download raw bytes

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

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.