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