Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision be18fb71

Von Moritz Bunkus vor fast 14 Jahren hinzugefügt

  • ID be18fb71d1e4a180d8a36e4c337468e9fae6efac
  • Vorgänger 2b209147
  • Nachfolger d6bb5c26

jQuery-Form-Plugin für AJAXifizierung von Forms

Unterschiede anzeigen:

js/jquery.form.js
1
/*!
2
 * jQuery Form Plugin
3
 * version: 2.52 (07-DEC-2010)
4
 * @requires jQuery v1.3.2 or later
5
 *
6
 * Examples and documentation at: http://malsup.com/jquery/form/
7
 * Dual licensed under the MIT and GPL licenses:
8
 *   http://www.opensource.org/licenses/mit-license.php
9
 *   http://www.gnu.org/licenses/gpl.html
10
 */
11
;(function($) {
12

  
13
/*
14
	Usage Note:
15
	-----------
16
	Do not use both ajaxSubmit and ajaxForm on the same form.  These
17
	functions are intended to be exclusive.  Use ajaxSubmit if you want
18
	to bind your own submit handler to the form.  For example,
19

  
20
	$(document).ready(function() {
21
		$('#myForm').bind('submit', function(e) {
22
			e.preventDefault(); // <-- important
23
			$(this).ajaxSubmit({
24
				target: '#output'
25
			});
26
		});
27
	});
28

  
29
	Use ajaxForm when you want the plugin to manage all the event binding
30
	for you.  For example,
31

  
32
	$(document).ready(function() {
33
		$('#myForm').ajaxForm({
34
			target: '#output'
35
		});
36
	});
37

  
38
	When using ajaxForm, the ajaxSubmit function will be invoked for you
39
	at the appropriate time.
40
*/
41

  
42
/**
43
 * ajaxSubmit() provides a mechanism for immediately submitting
44
 * an HTML form using AJAX.
45
 */
46
$.fn.ajaxSubmit = function(options) {
47
	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
48
	if (!this.length) {
49
		log('ajaxSubmit: skipping submit process - no element selected');
50
		return this;
51
	}
52

  
53
	if (typeof options == 'function') {
54
		options = { success: options };
55
	}
56

  
57
	var action = this.attr('action');
58
	var url = (typeof action === 'string') ? $.trim(action) : '';
59
	if (url) {
60
		// clean url (don't include hash vaue)
61
		url = (url.match(/^([^#]+)/)||[])[1];
62
	}
63
	url = url || window.location.href || '';
64

  
65
	options = $.extend(true, {
66
		url:  url,
67
		type: this.attr('method') || 'GET',
68
		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
69
	}, options);
70

  
71
	// hook for manipulating the form data before it is extracted;
72
	// convenient for use with rich editors like tinyMCE or FCKEditor
73
	var veto = {};
74
	this.trigger('form-pre-serialize', [this, options, veto]);
75
	if (veto.veto) {
76
		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
77
		return this;
78
	}
79

  
80
	// provide opportunity to alter form data before it is serialized
81
	if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
82
		log('ajaxSubmit: submit aborted via beforeSerialize callback');
83
		return this;
84
	}
85

  
86
	var n,v,a = this.formToArray(options.semantic);
87
	if (options.data) {
88
		options.extraData = options.data;
89
		for (n in options.data) {
90
			if(options.data[n] instanceof Array) {
91
				for (var k in options.data[n]) {
92
					a.push( { name: n, value: options.data[n][k] } );
93
				}
94
			}
95
			else {
96
				v = options.data[n];
97
				v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
98
				a.push( { name: n, value: v } );
99
			}
100
		}
101
	}
102

  
103
	// give pre-submit callback an opportunity to abort the submit
104
	if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
105
		log('ajaxSubmit: submit aborted via beforeSubmit callback');
106
		return this;
107
	}
108

  
109
	// fire vetoable 'validate' event
110
	this.trigger('form-submit-validate', [a, this, options, veto]);
111
	if (veto.veto) {
112
		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
113
		return this;
114
	}
115

  
116
	var q = $.param(a);
117

  
118
	if (options.type.toUpperCase() == 'GET') {
119
		options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
120
		options.data = null;  // data is null for 'get'
121
	}
122
	else {
123
		options.data = q; // data is the query string for 'post'
124
	}
125

  
126
	var $form = this, callbacks = [];
127
	if (options.resetForm) {
128
		callbacks.push(function() { $form.resetForm(); });
129
	}
130
	if (options.clearForm) {
131
		callbacks.push(function() { $form.clearForm(); });
132
	}
133

  
134
	// perform a load on the target only if dataType is not provided
135
	if (!options.dataType && options.target) {
136
		var oldSuccess = options.success || function(){};
137
		callbacks.push(function(data) {
138
			var fn = options.replaceTarget ? 'replaceWith' : 'html';
139
			$(options.target)[fn](data).each(oldSuccess, arguments);
140
		});
141
	}
142
	else if (options.success) {
143
		callbacks.push(options.success);
144
	}
145

  
146
	options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
147
		var context = options.context || options;   // jQuery 1.4+ supports scope context 
148
		for (var i=0, max=callbacks.length; i < max; i++) {
149
			callbacks[i].apply(context, [data, status, xhr || $form, $form]);
150
		}
151
	};
152

  
153
	// are there files to upload?
154
	var fileInputs = $('input:file', this).length > 0;
155
	var mp = 'multipart/form-data';
156
	var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
157

  
158
	// options.iframe allows user to force iframe mode
159
	// 06-NOV-09: now defaulting to iframe mode if file input is detected
160
   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
161
	   // hack to fix Safari hang (thanks to Tim Molendijk for this)
162
	   // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
163
	   if (options.closeKeepAlive) {
164
		   $.get(options.closeKeepAlive, fileUpload);
165
		}
166
	   else {
167
		   fileUpload();
168
		}
169
   }
170
   else {
171
	   $.ajax(options);
172
   }
173

  
174
	// fire 'notify' event
175
	this.trigger('form-submit-notify', [this, options]);
176
	return this;
177

  
178

  
179
	// private function for handling file uploads (hat tip to YAHOO!)
180
	function fileUpload() {
181
		var form = $form[0];
182

  
183
		if ($(':input[name=submit],:input[id=submit]', form).length) {
184
			// if there is an input with a name or id of 'submit' then we won't be
185
			// able to invoke the submit fn on the form (at least not x-browser)
186
			alert('Error: Form elements must not have name or id of "submit".');
187
			return;
188
		}
189
		
190
		var s = $.extend(true, {}, $.ajaxSettings, options);
191
		s.context = s.context || s;
192
		var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
193
		window[fn] = function() {
194
			var f = $io.data('form-plugin-onload');
195
			if (f) {
196
				f();
197
				window[fn] = undefined;
198
				try { delete window[fn]; } catch(e){}
199
			}
200
		}
201
		var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
202
		var io = $io[0];
203

  
204
		$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
205

  
206
		var xhr = { // mock object
207
			aborted: 0,
208
			responseText: null,
209
			responseXML: null,
210
			status: 0,
211
			statusText: 'n/a',
212
			getAllResponseHeaders: function() {},
213
			getResponseHeader: function() {},
214
			setRequestHeader: function() {},
215
			abort: function() {
216
				this.aborted = 1;
217
				$io.attr('src', s.iframeSrc); // abort op in progress
218
			}
219
		};
220

  
221
		var g = s.global;
222
		// trigger ajax global events so that activity/block indicators work like normal
223
		if (g && ! $.active++) {
224
			$.event.trigger("ajaxStart");
225
		}
226
		if (g) {
227
			$.event.trigger("ajaxSend", [xhr, s]);
228
		}
229

  
230
		if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
231
			if (s.global) { 
232
				$.active--;
233
			}
234
			return;
235
		}
236
		if (xhr.aborted) {
237
			return;
238
		}
239

  
240
		var cbInvoked = false;
241
		var timedOut = 0;
242

  
243
		// add submitting element to data if we know it
244
		var sub = form.clk;
245
		if (sub) {
246
			var n = sub.name;
247
			if (n && !sub.disabled) {
248
				s.extraData = s.extraData || {};
249
				s.extraData[n] = sub.value;
250
				if (sub.type == "image") {
251
					s.extraData[n+'.x'] = form.clk_x;
252
					s.extraData[n+'.y'] = form.clk_y;
253
				}
254
			}
255
		}
256

  
257
		// take a breath so that pending repaints get some cpu time before the upload starts
258
		function doSubmit() {
259
			// make sure form attrs are set
260
			var t = $form.attr('target'), a = $form.attr('action');
261

  
262
			// update form attrs in IE friendly way
263
			form.setAttribute('target',id);
264
			if (form.getAttribute('method') != 'POST') {
265
				form.setAttribute('method', 'POST');
266
			}
267
			if (form.getAttribute('action') != s.url) {
268
				form.setAttribute('action', s.url);
269
			}
270

  
271
			// ie borks in some cases when setting encoding
272
			if (! s.skipEncodingOverride) {
273
				$form.attr({
274
					encoding: 'multipart/form-data',
275
					enctype:  'multipart/form-data'
276
				});
277
			}
278

  
279
			// support timout
280
			if (s.timeout) {
281
				setTimeout(function() { timedOut = true; cb(); }, s.timeout);
282
			}
283

  
284
			// add "extra" data to form if provided in options
285
			var extraInputs = [];
286
			try {
287
				if (s.extraData) {
288
					for (var n in s.extraData) {
289
						extraInputs.push(
290
							$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
291
								.appendTo(form)[0]);
292
					}
293
				}
294

  
295
				// add iframe to doc and submit the form
296
				$io.appendTo('body');
297
				$io.data('form-plugin-onload', cb);
298
				form.submit();
299
			}
300
			finally {
301
				// reset attrs and remove "extra" input elements
302
				form.setAttribute('action',a);
303
				if(t) {
304
					form.setAttribute('target', t);
305
				} else {
306
					$form.removeAttr('target');
307
				}
308
				$(extraInputs).remove();
309
			}
310
		}
311

  
312
		if (s.forceSync) {
313
			doSubmit();
314
		}
315
		else {
316
			setTimeout(doSubmit, 10); // this lets dom updates render
317
		}
318
	
319
		var data, doc, domCheckCount = 50;
320

  
321
		function cb() {
322
			if (cbInvoked) {
323
				return;
324
			}
325

  
326
			$io.removeData('form-plugin-onload');
327
			
328
			var ok = true;
329
			try {
330
				if (timedOut) {
331
					throw 'timeout';
332
				}
333
				// extract the server response from the iframe
334
				doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
335
				
336
				var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
337
				log('isXml='+isXml);
338
				if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
339
					if (--domCheckCount) {
340
						// in some browsers (Opera) the iframe DOM is not always traversable when
341
						// the onload callback fires, so we loop a bit to accommodate
342
						log('requeing onLoad callback, DOM not available');
343
						setTimeout(cb, 250);
344
						return;
345
					}
346
					// let this fall through because server response could be an empty document
347
					//log('Could not access iframe DOM after mutiple tries.');
348
					//throw 'DOMException: not available';
349
				}
350

  
351
				//log('response detected');
352
				cbInvoked = true;
353
				xhr.responseText = doc.documentElement ? doc.documentElement.innerHTML : null; 
354
				xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
355
				xhr.getResponseHeader = function(header){
356
					var headers = {'content-type': s.dataType};
357
					return headers[header];
358
				};
359

  
360
				var scr = /(json|script)/.test(s.dataType);
361
				if (scr || s.textarea) {
362
					// see if user embedded response in textarea
363
					var ta = doc.getElementsByTagName('textarea')[0];
364
					if (ta) {
365
						xhr.responseText = ta.value;
366
					}
367
					else if (scr) {
368
						// account for browsers injecting pre around json response
369
						var pre = doc.getElementsByTagName('pre')[0];
370
						var b = doc.getElementsByTagName('body')[0];
371
						if (pre) {
372
							xhr.responseText = pre.textContent;
373
						}
374
						else if (b) {
375
							xhr.responseText = b.innerHTML;
376
						}
377
					}			  
378
				}
379
				else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
380
					xhr.responseXML = toXml(xhr.responseText);
381
				}
382
				data = $.httpData(xhr, s.dataType);
383
			}
384
			catch(e){
385
				log('error caught:',e);
386
				ok = false;
387
				xhr.error = e;
388
				$.handleError(s, xhr, 'error', e);
389
			}
390
			
391
			if (xhr.aborted) {
392
				log('upload aborted');
393
				ok = false;
394
			}
395

  
396
			// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
397
			if (ok) {
398
				s.success.call(s.context, data, 'success', xhr);
399
				if (g) {
400
					$.event.trigger("ajaxSuccess", [xhr, s]);
401
				}
402
			}
403
			if (g) {
404
				$.event.trigger("ajaxComplete", [xhr, s]);
405
			}
406
			if (g && ! --$.active) {
407
				$.event.trigger("ajaxStop");
408
			}
409
			if (s.complete) {
410
				s.complete.call(s.context, xhr, ok ? 'success' : 'error');
411
			}
412

  
413
			// clean up
414
			setTimeout(function() {
415
				$io.removeData('form-plugin-onload');
416
				$io.remove();
417
				xhr.responseXML = null;
418
			}, 100);
419
		}
420

  
421
		function toXml(s, doc) {
422
			if (window.ActiveXObject) {
423
				doc = new ActiveXObject('Microsoft.XMLDOM');
424
				doc.async = 'false';
425
				doc.loadXML(s);
426
			}
427
			else {
428
				doc = (new DOMParser()).parseFromString(s, 'text/xml');
429
			}
430
			return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
431
		}
432
	}
433
};
434

  
435
/**
436
 * ajaxForm() provides a mechanism for fully automating form submission.
437
 *
438
 * The advantages of using this method instead of ajaxSubmit() are:
439
 *
440
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
441
 *	is used to submit the form).
442
 * 2. This method will include the submit element's name/value data (for the element that was
443
 *	used to submit the form).
444
 * 3. This method binds the submit() method to the form for you.
445
 *
446
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
447
 * passes the options argument along after properly binding events for submit elements and
448
 * the form itself.
449
 */
450
$.fn.ajaxForm = function(options) {
451
	// in jQuery 1.3+ we can fix mistakes with the ready state
452
	if (this.length === 0) {
453
		var o = { s: this.selector, c: this.context };
454
		if (!$.isReady && o.s) {
455
			log('DOM not ready, queuing ajaxForm');
456
			$(function() {
457
				$(o.s,o.c).ajaxForm(options);
458
			});
459
			return this;
460
		}
461
		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
462
		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
463
		return this;
464
	}
465
	
466
	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
467
		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
468
			e.preventDefault();
469
			$(this).ajaxSubmit(options);
470
		}
471
	}).bind('click.form-plugin', function(e) {
472
		var target = e.target;
473
		var $el = $(target);
474
		if (!($el.is(":submit,input:image"))) {
475
			// is this a child element of the submit el?  (ex: a span within a button)
476
			var t = $el.closest(':submit');
477
			if (t.length == 0) {
478
				return;
479
			}
480
			target = t[0];
481
		}
482
		var form = this;
483
		form.clk = target;
484
		if (target.type == 'image') {
485
			if (e.offsetX != undefined) {
486
				form.clk_x = e.offsetX;
487
				form.clk_y = e.offsetY;
488
			} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
489
				var offset = $el.offset();
490
				form.clk_x = e.pageX - offset.left;
491
				form.clk_y = e.pageY - offset.top;
492
			} else {
493
				form.clk_x = e.pageX - target.offsetLeft;
494
				form.clk_y = e.pageY - target.offsetTop;
495
			}
496
		}
497
		// clear form vars
498
		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
499
	});
500
};
501

  
502
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
503
$.fn.ajaxFormUnbind = function() {
504
	return this.unbind('submit.form-plugin click.form-plugin');
505
};
506

  
507
/**
508
 * formToArray() gathers form element data into an array of objects that can
509
 * be passed to any of the following ajax functions: $.get, $.post, or load.
510
 * Each object in the array has both a 'name' and 'value' property.  An example of
511
 * an array for a simple login form might be:
512
 *
513
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
514
 *
515
 * It is this array that is passed to pre-submit callback functions provided to the
516
 * ajaxSubmit() and ajaxForm() methods.
517
 */
518
$.fn.formToArray = function(semantic) {
519
	var a = [];
520
	if (this.length === 0) {
521
		return a;
522
	}
523

  
524
	var form = this[0];
525
	var els = semantic ? form.getElementsByTagName('*') : form.elements;
526
	if (!els) {
527
		return a;
528
	}
529
	
530
	var i,j,n,v,el,max,jmax;
531
	for(i=0, max=els.length; i < max; i++) {
532
		el = els[i];
533
		n = el.name;
534
		if (!n) {
535
			continue;
536
		}
537

  
538
		if (semantic && form.clk && el.type == "image") {
539
			// handle image inputs on the fly when semantic == true
540
			if(!el.disabled && form.clk == el) {
541
				a.push({name: n, value: $(el).val()});
542
				a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
543
			}
544
			continue;
545
		}
546

  
547
		v = $.fieldValue(el, true);
548
		if (v && v.constructor == Array) {
549
			for(j=0, jmax=v.length; j < jmax; j++) {
550
				a.push({name: n, value: v[j]});
551
			}
552
		}
553
		else if (v !== null && typeof v != 'undefined') {
554
			a.push({name: n, value: v});
555
		}
556
	}
557

  
558
	if (!semantic && form.clk) {
559
		// input type=='image' are not found in elements array! handle it here
560
		var $input = $(form.clk), input = $input[0];
561
		n = input.name;
562
		if (n && !input.disabled && input.type == 'image') {
563
			a.push({name: n, value: $input.val()});
564
			a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
565
		}
566
	}
567
	return a;
568
};
569

  
570
/**
571
 * Serializes form data into a 'submittable' string. This method will return a string
572
 * in the format: name1=value1&amp;name2=value2
573
 */
574
$.fn.formSerialize = function(semantic) {
575
	//hand off to jQuery.param for proper encoding
576
	return $.param(this.formToArray(semantic));
577
};
578

  
579
/**
580
 * Serializes all field elements in the jQuery object into a query string.
581
 * This method will return a string in the format: name1=value1&amp;name2=value2
582
 */
583
$.fn.fieldSerialize = function(successful) {
584
	var a = [];
585
	this.each(function() {
586
		var n = this.name;
587
		if (!n) {
588
			return;
589
		}
590
		var v = $.fieldValue(this, successful);
591
		if (v && v.constructor == Array) {
592
			for (var i=0,max=v.length; i < max; i++) {
593
				a.push({name: n, value: v[i]});
594
			}
595
		}
596
		else if (v !== null && typeof v != 'undefined') {
597
			a.push({name: this.name, value: v});
598
		}
599
	});
600
	//hand off to jQuery.param for proper encoding
601
	return $.param(a);
602
};
603

  
604
/**
605
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
606
 *
607
 *  <form><fieldset>
608
 *	  <input name="A" type="text" />
609
 *	  <input name="A" type="text" />
610
 *	  <input name="B" type="checkbox" value="B1" />
611
 *	  <input name="B" type="checkbox" value="B2"/>
612
 *	  <input name="C" type="radio" value="C1" />
613
 *	  <input name="C" type="radio" value="C2" />
614
 *  </fieldset></form>
615
 *
616
 *  var v = $(':text').fieldValue();
617
 *  // if no values are entered into the text inputs
618
 *  v == ['','']
619
 *  // if values entered into the text inputs are 'foo' and 'bar'
620
 *  v == ['foo','bar']
621
 *
622
 *  var v = $(':checkbox').fieldValue();
623
 *  // if neither checkbox is checked
624
 *  v === undefined
625
 *  // if both checkboxes are checked
626
 *  v == ['B1', 'B2']
627
 *
628
 *  var v = $(':radio').fieldValue();
629
 *  // if neither radio is checked
630
 *  v === undefined
631
 *  // if first radio is checked
632
 *  v == ['C1']
633
 *
634
 * The successful argument controls whether or not the field element must be 'successful'
635
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
636
 * The default value of the successful argument is true.  If this value is false the value(s)
637
 * for each element is returned.
638
 *
639
 * Note: This method *always* returns an array.  If no valid value can be determined the
640
 *	   array will be empty, otherwise it will contain one or more values.
641
 */
642
$.fn.fieldValue = function(successful) {
643
	for (var val=[], i=0, max=this.length; i < max; i++) {
644
		var el = this[i];
645
		var v = $.fieldValue(el, successful);
646
		if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
647
			continue;
648
		}
649
		v.constructor == Array ? $.merge(val, v) : val.push(v);
650
	}
651
	return val;
652
};
653

  
654
/**
655
 * Returns the value of the field element.
656
 */
657
$.fieldValue = function(el, successful) {
658
	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
659
	if (successful === undefined) {
660
		successful = true;
661
	}
662

  
663
	if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
664
		(t == 'checkbox' || t == 'radio') && !el.checked ||
665
		(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
666
		tag == 'select' && el.selectedIndex == -1)) {
667
			return null;
668
	}
669

  
670
	if (tag == 'select') {
671
		var index = el.selectedIndex;
672
		if (index < 0) {
673
			return null;
674
		}
675
		var a = [], ops = el.options;
676
		var one = (t == 'select-one');
677
		var max = (one ? index+1 : ops.length);
678
		for(var i=(one ? index : 0); i < max; i++) {
679
			var op = ops[i];
680
			if (op.selected) {
681
				var v = op.value;
682
				if (!v) { // extra pain for IE...
683
					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
684
				}
685
				if (one) {
686
					return v;
687
				}
688
				a.push(v);
689
			}
690
		}
691
		return a;
692
	}
693
	return $(el).val();
694
};
695

  
696
/**
697
 * Clears the form data.  Takes the following actions on the form's input fields:
698
 *  - input text fields will have their 'value' property set to the empty string
699
 *  - select elements will have their 'selectedIndex' property set to -1
700
 *  - checkbox and radio inputs will have their 'checked' property set to false
701
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
702
 *  - button elements will *not* be effected
703
 */
704
$.fn.clearForm = function() {
705
	return this.each(function() {
706
		$('input,select,textarea', this).clearFields();
707
	});
708
};
709

  
710
/**
711
 * Clears the selected form elements.
712
 */
713
$.fn.clearFields = $.fn.clearInputs = function() {
714
	return this.each(function() {
715
		var t = this.type, tag = this.tagName.toLowerCase();
716
		if (t == 'text' || t == 'password' || tag == 'textarea') {
717
			this.value = '';
718
		}
719
		else if (t == 'checkbox' || t == 'radio') {
720
			this.checked = false;
721
		}
722
		else if (tag == 'select') {
723
			this.selectedIndex = -1;
724
		}
725
	});
726
};
727

  
728
/**
729
 * Resets the form data.  Causes all form elements to be reset to their original value.
730
 */
731
$.fn.resetForm = function() {
732
	return this.each(function() {
733
		// guard against an input with the name of 'reset'
734
		// note that IE reports the reset function as an 'object'
735
		if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
736
			this.reset();
737
		}
738
	});
739
};
740

  
741
/**
742
 * Enables or disables any matching elements.
743
 */
744
$.fn.enable = function(b) {
745
	if (b === undefined) {
746
		b = true;
747
	}
748
	return this.each(function() {
749
		this.disabled = !b;
750
	});
751
};
752

  
753
/**
754
 * Checks/unchecks any matching checkboxes or radio buttons and
755
 * selects/deselects and matching option elements.
756
 */
757
$.fn.selected = function(select) {
758
	if (select === undefined) {
759
		select = true;
760
	}
761
	return this.each(function() {
762
		var t = this.type;
763
		if (t == 'checkbox' || t == 'radio') {
764
			this.checked = select;
765
		}
766
		else if (this.tagName.toLowerCase() == 'option') {
767
			var $sel = $(this).parent('select');
768
			if (select && $sel[0] && $sel[0].type == 'select-one') {
769
				// deselect all other options
770
				$sel.find('option').selected(false);
771
			}
772
			this.selected = select;
773
		}
774
	});
775
};
776

  
777
// helper fn for console logging
778
// set $.fn.ajaxSubmit.debug to true to enable debug logging
779
function log() {
780
	if ($.fn.ajaxSubmit.debug) {
781
		var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
782
		if (window.console && window.console.log) {
783
			window.console.log(msg);
784
		}
785
		else if (window.opera && window.opera.postError) {
786
			window.opera.postError(msg);
787
		}
788
	}
789
};
790

  
791
})(jQuery);

Auch abrufbar als: Unified diff