hobo_jquery 1.4.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,859 @@
1
+ /*!
2
+ * jQuery Form Plugin
3
+ * version: 2.77 (23-MAY-2011)
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
+ url = url || window.location.href || '';
60
+ if (url) {
61
+ // clean url (don't include hash vaue)
62
+ url = (url.match(/^([^#]+)/)||[])[1];
63
+ }
64
+
65
+ options = $.extend(true, {
66
+ url: url,
67
+ success: $.ajaxSettings.success,
68
+ type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
69
+ iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
70
+ }, options);
71
+
72
+ // hook for manipulating the form data before it is extracted;
73
+ // convenient for use with rich editors like tinyMCE or FCKEditor
74
+ var veto = {};
75
+ this.trigger('form-pre-serialize', [this, options, veto]);
76
+ if (veto.veto) {
77
+ log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
78
+ return this;
79
+ }
80
+
81
+ // provide opportunity to alter form data before it is serialized
82
+ if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
83
+ log('ajaxSubmit: submit aborted via beforeSerialize callback');
84
+ return this;
85
+ }
86
+
87
+ var n,v,a = this.formToArray(options.semantic);
88
+ if (options.data) {
89
+ options.extraData = options.data;
90
+ for (n in options.data) {
91
+ if(options.data[n] instanceof Array) {
92
+ for (var k in options.data[n]) {
93
+ a.push( { name: n, value: options.data[n][k] } );
94
+ }
95
+ }
96
+ else {
97
+ v = options.data[n];
98
+ v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
99
+ a.push( { name: n, value: v } );
100
+ }
101
+ }
102
+ }
103
+
104
+ // give pre-submit callback an opportunity to abort the submit
105
+ if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
106
+ log('ajaxSubmit: submit aborted via beforeSubmit callback');
107
+ return this;
108
+ }
109
+
110
+ // fire vetoable 'validate' event
111
+ this.trigger('form-submit-validate', [a, this, options, veto]);
112
+ if (veto.veto) {
113
+ log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
114
+ return this;
115
+ }
116
+
117
+ var q = $.param(a);
118
+
119
+ if (options.type.toUpperCase() == 'GET') {
120
+ options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
121
+ options.data = null; // data is null for 'get'
122
+ }
123
+ else {
124
+ options.data = q; // data is the query string for 'post'
125
+ }
126
+
127
+ var $form = this, callbacks = [];
128
+ if (options.resetForm) {
129
+ callbacks.push(function() { $form.resetForm(); });
130
+ }
131
+ if (options.clearForm) {
132
+ callbacks.push(function() { $form.clearForm(); });
133
+ }
134
+
135
+ // perform a load on the target only if dataType is not provided
136
+ if (!options.dataType && options.target) {
137
+ var oldSuccess = options.success || function(){};
138
+ callbacks.push(function(data) {
139
+ var fn = options.replaceTarget ? 'replaceWith' : 'html';
140
+ $(options.target)[fn](data).each(oldSuccess, arguments);
141
+ });
142
+ }
143
+ else if (options.success) {
144
+ callbacks.push(options.success);
145
+ }
146
+
147
+ options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
148
+ var context = options.context || options; // jQuery 1.4+ supports scope context
149
+ for (var i=0, max=callbacks.length; i < max; i++) {
150
+ callbacks[i].apply(context, [data, status, xhr || $form, $form]);
151
+ }
152
+ };
153
+
154
+ // are there files to upload?
155
+ var fileInputs = $('input:file', this).length > 0;
156
+ var mp = 'multipart/form-data';
157
+ var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
158
+
159
+ // options.iframe allows user to force iframe mode
160
+ // 06-NOV-09: now defaulting to iframe mode if file input is detected
161
+ if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
162
+ // hack to fix Safari hang (thanks to Tim Molendijk for this)
163
+ // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
164
+ if (options.closeKeepAlive) {
165
+ $.get(options.closeKeepAlive, fileUpload);
166
+ }
167
+ else {
168
+ fileUpload();
169
+ }
170
+ }
171
+ else {
172
+ $.ajax(options);
173
+ }
174
+
175
+ // fire 'notify' event
176
+ this.trigger('form-submit-notify', [this, options]);
177
+ return this;
178
+
179
+
180
+ // private function for handling file uploads (hat tip to YAHOO!)
181
+ function fileUpload() {
182
+ var form = $form[0], s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
183
+
184
+ if ($(':input[name=submit],:input[id=submit]', form).length) {
185
+ // if there is an input with a name or id of 'submit' then we won't be
186
+ // able to invoke the submit fn on the form (at least not x-browser)
187
+ alert('Error: Form elements must not have name or id of "submit".');
188
+ return;
189
+ }
190
+
191
+ s = $.extend(true, {}, $.ajaxSettings, options);
192
+ s.context = s.context || s;
193
+ $io, id = 'jqFormIO' + (new Date().getTime());
194
+ if (s.iframeTarget) {
195
+ $io = $(s.iframeTarget);
196
+ n = $io.attr('name');
197
+ if (n == null)
198
+ $io.attr('name', id);
199
+ else
200
+ id = n;
201
+ }
202
+ else {
203
+ $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
204
+ $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
205
+ }
206
+ io = $io[0];
207
+
208
+
209
+ xhr = { // mock object
210
+ aborted: 0,
211
+ responseText: null,
212
+ responseXML: null,
213
+ status: 0,
214
+ statusText: 'n/a',
215
+ getAllResponseHeaders: function() {},
216
+ getResponseHeader: function() {},
217
+ setRequestHeader: function() {},
218
+ abort: function(status) {
219
+ var e = (status === 'timeout' ? 'timeout' : 'aborted');
220
+ log('aborting upload... ' + e);
221
+ this.aborted = 1;
222
+ $io.attr('src', s.iframeSrc); // abort op in progress
223
+ xhr.error = e;
224
+ s.error && s.error.call(s.context, xhr, e, e);
225
+ g && $.event.trigger("ajaxError", [xhr, s, e]);
226
+ s.complete && s.complete.call(s.context, xhr, e);
227
+ }
228
+ };
229
+
230
+ g = s.global;
231
+ // trigger ajax global events so that activity/block indicators work like normal
232
+ if (g && ! $.active++) {
233
+ $.event.trigger("ajaxStart");
234
+ }
235
+ if (g) {
236
+ $.event.trigger("ajaxSend", [xhr, s]);
237
+ }
238
+
239
+ if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
240
+ if (s.global) {
241
+ $.active--;
242
+ }
243
+ return;
244
+ }
245
+ if (xhr.aborted) {
246
+ return;
247
+ }
248
+
249
+ // add submitting element to data if we know it
250
+ sub = form.clk;
251
+ if (sub) {
252
+ n = sub.name;
253
+ if (n && !sub.disabled) {
254
+ s.extraData = s.extraData || {};
255
+ s.extraData[n] = sub.value;
256
+ if (sub.type == "image") {
257
+ s.extraData[n+'.x'] = form.clk_x;
258
+ s.extraData[n+'.y'] = form.clk_y;
259
+ }
260
+ }
261
+ }
262
+
263
+ // take a breath so that pending repaints get some cpu time before the upload starts
264
+ function doSubmit() {
265
+ // make sure form attrs are set
266
+ var t = $form.attr('target'), a = $form.attr('action');
267
+
268
+ // update form attrs in IE friendly way
269
+ form.setAttribute('target',id);
270
+ if (form.getAttribute('method') != 'POST') {
271
+ form.setAttribute('method', 'POST');
272
+ }
273
+ if (form.getAttribute('action') != s.url) {
274
+ form.setAttribute('action', s.url);
275
+ }
276
+
277
+ // ie borks in some cases when setting encoding
278
+ if (! s.skipEncodingOverride) {
279
+ $form.attr({
280
+ encoding: 'multipart/form-data',
281
+ enctype: 'multipart/form-data'
282
+ });
283
+ }
284
+
285
+ // support timout
286
+ if (s.timeout) {
287
+ timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout);
288
+ }
289
+
290
+ // add "extra" data to form if provided in options
291
+ var extraInputs = [];
292
+ try {
293
+ if (s.extraData) {
294
+ for (var n in s.extraData) {
295
+ extraInputs.push(
296
+ $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
297
+ .appendTo(form)[0]);
298
+ }
299
+ }
300
+
301
+ if (!s.iframeTarget) {
302
+ // add iframe to doc and submit the form
303
+ $io.appendTo('body');
304
+ io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
305
+ }
306
+ form.submit();
307
+ }
308
+ finally {
309
+ // reset attrs and remove "extra" input elements
310
+ form.setAttribute('action',a);
311
+ if(t) {
312
+ form.setAttribute('target', t);
313
+ } else {
314
+ $form.removeAttr('target');
315
+ }
316
+ $(extraInputs).remove();
317
+ }
318
+ }
319
+
320
+ if (s.forceSync) {
321
+ doSubmit();
322
+ }
323
+ else {
324
+ setTimeout(doSubmit, 10); // this lets dom updates render
325
+ }
326
+
327
+ var data, doc, domCheckCount = 50, callbackProcessed;
328
+
329
+ function cb(e) {
330
+ if (xhr.aborted || callbackProcessed) {
331
+ return;
332
+ }
333
+ if (e === true && xhr) {
334
+ xhr.abort('timeout');
335
+ return;
336
+ }
337
+
338
+ var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
339
+ if (!doc || doc.location.href == s.iframeSrc) {
340
+ // response not received yet
341
+ if (!timedOut)
342
+ return;
343
+ }
344
+ io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
345
+
346
+ var status = 'success', errMsg;
347
+ try {
348
+ if (timedOut) {
349
+ throw 'timeout';
350
+ }
351
+
352
+ var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
353
+ log('isXml='+isXml);
354
+ if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
355
+ if (--domCheckCount) {
356
+ // in some browsers (Opera) the iframe DOM is not always traversable when
357
+ // the onload callback fires, so we loop a bit to accommodate
358
+ log('requeing onLoad callback, DOM not available');
359
+ setTimeout(cb, 250);
360
+ return;
361
+ }
362
+ // let this fall through because server response could be an empty document
363
+ //log('Could not access iframe DOM after mutiple tries.');
364
+ //throw 'DOMException: not available';
365
+ }
366
+
367
+ //log('response detected');
368
+ var docRoot = doc.body ? doc.body : doc.documentElement;
369
+ xhr.responseText = docRoot ? docRoot.innerHTML : null;
370
+ xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
371
+ if (isXml)
372
+ s.dataType = 'xml';
373
+ xhr.getResponseHeader = function(header){
374
+ var headers = {'content-type': s.dataType};
375
+ return headers[header];
376
+ };
377
+ // support for XHR 'status' & 'statusText' emulation :
378
+ if (docRoot) {
379
+ xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
380
+ xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
381
+ }
382
+
383
+ var scr = /(json|script|text)/.test(s.dataType.toLowerCase());
384
+ if (scr || s.textarea) {
385
+ // see if user embedded response in textarea
386
+ var ta = doc.getElementsByTagName('textarea')[0];
387
+ if (ta) {
388
+ xhr.responseText = ta.value;
389
+ // support for XHR 'status' & 'statusText' emulation :
390
+ xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
391
+ xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
392
+ }
393
+ else if (scr) {
394
+ // account for browsers injecting pre around json response
395
+ var pre = doc.getElementsByTagName('pre')[0];
396
+ var b = doc.getElementsByTagName('body')[0];
397
+ if (pre) {
398
+ xhr.responseText = pre.textContent ? pre.textContent : pre.innerHTML;
399
+ }
400
+ else if (b) {
401
+ xhr.responseText = b.innerHTML;
402
+ }
403
+ }
404
+ }
405
+ else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
406
+ xhr.responseXML = toXml(xhr.responseText);
407
+ }
408
+
409
+ try {
410
+ data = httpData(xhr, s.dataType, s);
411
+ }
412
+ catch (e) {
413
+ status = 'parsererror';
414
+ xhr.error = errMsg = (e || status);
415
+ }
416
+ }
417
+ catch (e) {
418
+ log('error caught',e);
419
+ status = 'error';
420
+ xhr.error = errMsg = (e || status);
421
+ }
422
+
423
+ if (xhr.aborted) {
424
+ log('upload aborted');
425
+ status = null;
426
+ }
427
+
428
+ if (xhr.status) { // we've set xhr.status
429
+ status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
430
+ }
431
+
432
+ // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
433
+ if (status === 'success') {
434
+ s.success && s.success.call(s.context, data, 'success', xhr);
435
+ g && $.event.trigger("ajaxSuccess", [xhr, s]);
436
+ }
437
+ else if (status) {
438
+ if (errMsg == undefined)
439
+ errMsg = xhr.statusText;
440
+ s.error && s.error.call(s.context, xhr, status, errMsg);
441
+ g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
442
+ }
443
+
444
+ g && $.event.trigger("ajaxComplete", [xhr, s]);
445
+
446
+ if (g && ! --$.active) {
447
+ $.event.trigger("ajaxStop");
448
+ }
449
+
450
+ s.complete && s.complete.call(s.context, xhr, status);
451
+
452
+ callbackProcessed = true;
453
+ if (s.timeout)
454
+ clearTimeout(timeoutHandle);
455
+
456
+ // clean up
457
+ setTimeout(function() {
458
+ if (!s.iframeTarget)
459
+ $io.remove();
460
+ xhr.responseXML = null;
461
+ }, 100);
462
+ }
463
+
464
+ var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
465
+ if (window.ActiveXObject) {
466
+ doc = new ActiveXObject('Microsoft.XMLDOM');
467
+ doc.async = 'false';
468
+ doc.loadXML(s);
469
+ }
470
+ else {
471
+ doc = (new DOMParser()).parseFromString(s, 'text/xml');
472
+ }
473
+ return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
474
+ };
475
+ var parseJSON = $.parseJSON || function(s) {
476
+ return window['eval']('(' + s + ')');
477
+ };
478
+
479
+ var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
480
+
481
+ var ct = xhr.getResponseHeader('content-type') || '',
482
+ xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
483
+ data = xml ? xhr.responseXML : xhr.responseText;
484
+
485
+ if (xml && data.documentElement.nodeName === 'parsererror') {
486
+ $.error && $.error('parsererror');
487
+ }
488
+ if (s && s.dataFilter) {
489
+ data = s.dataFilter(data, type);
490
+ }
491
+ if (typeof data === 'string') {
492
+ if (type === 'json' || !type && ct.indexOf('json') >= 0) {
493
+ data = parseJSON(data);
494
+ } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
495
+ $.globalEval(data);
496
+ }
497
+ }
498
+ return data;
499
+ };
500
+ }
501
+ };
502
+
503
+ /**
504
+ * ajaxForm() provides a mechanism for fully automating form submission.
505
+ *
506
+ * The advantages of using this method instead of ajaxSubmit() are:
507
+ *
508
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
509
+ * is used to submit the form).
510
+ * 2. This method will include the submit element's name/value data (for the element that was
511
+ * used to submit the form).
512
+ * 3. This method binds the submit() method to the form for you.
513
+ *
514
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
515
+ * passes the options argument along after properly binding events for submit elements and
516
+ * the form itself.
517
+ */
518
+ $.fn.ajaxForm = function(options) {
519
+ // in jQuery 1.3+ we can fix mistakes with the ready state
520
+ if (this.length === 0) {
521
+ var o = { s: this.selector, c: this.context };
522
+ if (!$.isReady && o.s) {
523
+ log('DOM not ready, queuing ajaxForm');
524
+ $(function() {
525
+ $(o.s,o.c).ajaxForm(options);
526
+ });
527
+ return this;
528
+ }
529
+ // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
530
+ log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
531
+ return this;
532
+ }
533
+
534
+ return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
535
+ if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
536
+ e.preventDefault();
537
+ $(this).ajaxSubmit(options);
538
+ }
539
+ }).bind('click.form-plugin', function(e) {
540
+ var target = e.target;
541
+ var $el = $(target);
542
+ if (!($el.is(":submit,input:image"))) {
543
+ // is this a child element of the submit el? (ex: a span within a button)
544
+ var t = $el.closest(':submit');
545
+ if (t.length == 0) {
546
+ return;
547
+ }
548
+ target = t[0];
549
+ }
550
+ var form = this;
551
+ form.clk = target;
552
+ if (target.type == 'image') {
553
+ if (e.offsetX != undefined) {
554
+ form.clk_x = e.offsetX;
555
+ form.clk_y = e.offsetY;
556
+ } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
557
+ var offset = $el.offset();
558
+ form.clk_x = e.pageX - offset.left;
559
+ form.clk_y = e.pageY - offset.top;
560
+ } else {
561
+ form.clk_x = e.pageX - target.offsetLeft;
562
+ form.clk_y = e.pageY - target.offsetTop;
563
+ }
564
+ }
565
+ // clear form vars
566
+ setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
567
+ });
568
+ };
569
+
570
+ // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
571
+ $.fn.ajaxFormUnbind = function() {
572
+ return this.unbind('submit.form-plugin click.form-plugin');
573
+ };
574
+
575
+ /**
576
+ * formToArray() gathers form element data into an array of objects that can
577
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
578
+ * Each object in the array has both a 'name' and 'value' property. An example of
579
+ * an array for a simple login form might be:
580
+ *
581
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
582
+ *
583
+ * It is this array that is passed to pre-submit callback functions provided to the
584
+ * ajaxSubmit() and ajaxForm() methods.
585
+ */
586
+ $.fn.formToArray = function(semantic) {
587
+ var a = [];
588
+ if (this.length === 0) {
589
+ return a;
590
+ }
591
+
592
+ var form = this[0];
593
+ var els = semantic ? form.getElementsByTagName('*') : form.elements;
594
+ if (!els) {
595
+ return a;
596
+ }
597
+
598
+ var i,j,n,v,el,max,jmax;
599
+ for(i=0, max=els.length; i < max; i++) {
600
+ el = els[i];
601
+ n = el.name;
602
+ if (!n) {
603
+ continue;
604
+ }
605
+
606
+ if (semantic && form.clk && el.type == "image") {
607
+ // handle image inputs on the fly when semantic == true
608
+ if(!el.disabled && form.clk == el) {
609
+ a.push({name: n, value: $(el).val()});
610
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
611
+ }
612
+ continue;
613
+ }
614
+
615
+ v = $.fieldValue(el, true);
616
+ if (v && v.constructor == Array) {
617
+ for(j=0, jmax=v.length; j < jmax; j++) {
618
+ a.push({name: n, value: v[j]});
619
+ }
620
+ }
621
+ else if (v !== null && typeof v != 'undefined') {
622
+ a.push({name: n, value: v});
623
+ }
624
+ }
625
+
626
+ if (!semantic && form.clk) {
627
+ // input type=='image' are not found in elements array! handle it here
628
+ var $input = $(form.clk), input = $input[0];
629
+ n = input.name;
630
+ if (n && !input.disabled && input.type == 'image') {
631
+ a.push({name: n, value: $input.val()});
632
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
633
+ }
634
+ }
635
+ return a;
636
+ };
637
+
638
+ /**
639
+ * Serializes form data into a 'submittable' string. This method will return a string
640
+ * in the format: name1=value1&amp;name2=value2
641
+ */
642
+ $.fn.formSerialize = function(semantic) {
643
+ //hand off to jQuery.param for proper encoding
644
+ return $.param(this.formToArray(semantic));
645
+ };
646
+
647
+ /**
648
+ * Serializes all field elements in the jQuery object into a query string.
649
+ * This method will return a string in the format: name1=value1&amp;name2=value2
650
+ */
651
+ $.fn.fieldSerialize = function(successful) {
652
+ var a = [];
653
+ this.each(function() {
654
+ var n = this.name;
655
+ if (!n) {
656
+ return;
657
+ }
658
+ var v = $.fieldValue(this, successful);
659
+ if (v && v.constructor == Array) {
660
+ for (var i=0,max=v.length; i < max; i++) {
661
+ a.push({name: n, value: v[i]});
662
+ }
663
+ }
664
+ else if (v !== null && typeof v != 'undefined') {
665
+ a.push({name: this.name, value: v});
666
+ }
667
+ });
668
+ //hand off to jQuery.param for proper encoding
669
+ return $.param(a);
670
+ };
671
+
672
+ /**
673
+ * Returns the value(s) of the element in the matched set. For example, consider the following form:
674
+ *
675
+ * <form><fieldset>
676
+ * <input name="A" type="text" />
677
+ * <input name="A" type="text" />
678
+ * <input name="B" type="checkbox" value="B1" />
679
+ * <input name="B" type="checkbox" value="B2"/>
680
+ * <input name="C" type="radio" value="C1" />
681
+ * <input name="C" type="radio" value="C2" />
682
+ * </fieldset></form>
683
+ *
684
+ * var v = $(':text').fieldValue();
685
+ * // if no values are entered into the text inputs
686
+ * v == ['','']
687
+ * // if values entered into the text inputs are 'foo' and 'bar'
688
+ * v == ['foo','bar']
689
+ *
690
+ * var v = $(':checkbox').fieldValue();
691
+ * // if neither checkbox is checked
692
+ * v === undefined
693
+ * // if both checkboxes are checked
694
+ * v == ['B1', 'B2']
695
+ *
696
+ * var v = $(':radio').fieldValue();
697
+ * // if neither radio is checked
698
+ * v === undefined
699
+ * // if first radio is checked
700
+ * v == ['C1']
701
+ *
702
+ * The successful argument controls whether or not the field element must be 'successful'
703
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
704
+ * The default value of the successful argument is true. If this value is false the value(s)
705
+ * for each element is returned.
706
+ *
707
+ * Note: This method *always* returns an array. If no valid value can be determined the
708
+ * array will be empty, otherwise it will contain one or more values.
709
+ */
710
+ $.fn.fieldValue = function(successful) {
711
+ for (var val=[], i=0, max=this.length; i < max; i++) {
712
+ var el = this[i];
713
+ var v = $.fieldValue(el, successful);
714
+ if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
715
+ continue;
716
+ }
717
+ v.constructor == Array ? $.merge(val, v) : val.push(v);
718
+ }
719
+ return val;
720
+ };
721
+
722
+ /**
723
+ * Returns the value of the field element.
724
+ */
725
+ $.fieldValue = function(el, successful) {
726
+ var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
727
+ if (successful === undefined) {
728
+ successful = true;
729
+ }
730
+
731
+ if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
732
+ (t == 'checkbox' || t == 'radio') && !el.checked ||
733
+ (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
734
+ tag == 'select' && el.selectedIndex == -1)) {
735
+ return null;
736
+ }
737
+
738
+ if (tag == 'select') {
739
+ var index = el.selectedIndex;
740
+ if (index < 0) {
741
+ return null;
742
+ }
743
+ var a = [], ops = el.options;
744
+ var one = (t == 'select-one');
745
+ var max = (one ? index+1 : ops.length);
746
+ for(var i=(one ? index : 0); i < max; i++) {
747
+ var op = ops[i];
748
+ if (op.selected) {
749
+ var v = op.value;
750
+ if (!v) { // extra pain for IE...
751
+ v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
752
+ }
753
+ if (one) {
754
+ return v;
755
+ }
756
+ a.push(v);
757
+ }
758
+ }
759
+ return a;
760
+ }
761
+ return $(el).val();
762
+ };
763
+
764
+ /**
765
+ * Clears the form data. Takes the following actions on the form's input fields:
766
+ * - input text fields will have their 'value' property set to the empty string
767
+ * - select elements will have their 'selectedIndex' property set to -1
768
+ * - checkbox and radio inputs will have their 'checked' property set to false
769
+ * - inputs of type submit, button, reset, and hidden will *not* be effected
770
+ * - button elements will *not* be effected
771
+ */
772
+ $.fn.clearForm = function() {
773
+ return this.each(function() {
774
+ $('input,select,textarea', this).clearFields();
775
+ });
776
+ };
777
+
778
+ /**
779
+ * Clears the selected form elements.
780
+ */
781
+ $.fn.clearFields = $.fn.clearInputs = function() {
782
+ return this.each(function() {
783
+ var t = this.type, tag = this.tagName.toLowerCase();
784
+ if (t == 'text' || t == 'password' || tag == 'textarea') {
785
+ this.value = '';
786
+ }
787
+ else if (t == 'checkbox' || t == 'radio') {
788
+ this.checked = false;
789
+ }
790
+ else if (tag == 'select') {
791
+ this.selectedIndex = -1;
792
+ }
793
+ });
794
+ };
795
+
796
+ /**
797
+ * Resets the form data. Causes all form elements to be reset to their original value.
798
+ */
799
+ $.fn.resetForm = function() {
800
+ return this.each(function() {
801
+ // guard against an input with the name of 'reset'
802
+ // note that IE reports the reset function as an 'object'
803
+ if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
804
+ this.reset();
805
+ }
806
+ });
807
+ };
808
+
809
+ /**
810
+ * Enables or disables any matching elements.
811
+ */
812
+ $.fn.enable = function(b) {
813
+ if (b === undefined) {
814
+ b = true;
815
+ }
816
+ return this.each(function() {
817
+ this.disabled = !b;
818
+ });
819
+ };
820
+
821
+ /**
822
+ * Checks/unchecks any matching checkboxes or radio buttons and
823
+ * selects/deselects and matching option elements.
824
+ */
825
+ $.fn.selected = function(select) {
826
+ if (select === undefined) {
827
+ select = true;
828
+ }
829
+ return this.each(function() {
830
+ var t = this.type;
831
+ if (t == 'checkbox' || t == 'radio') {
832
+ this.checked = select;
833
+ }
834
+ else if (this.tagName.toLowerCase() == 'option') {
835
+ var $sel = $(this).parent('select');
836
+ if (select && $sel[0] && $sel[0].type == 'select-one') {
837
+ // deselect all other options
838
+ $sel.find('option').selected(false);
839
+ }
840
+ this.selected = select;
841
+ }
842
+ });
843
+ };
844
+
845
+ // helper fn for console logging
846
+ // set $.fn.ajaxSubmit.debug to true to enable debug logging
847
+ function log() {
848
+ if ($.fn.ajaxSubmit.debug) {
849
+ var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
850
+ if (window.console && window.console.log) {
851
+ window.console.log(msg);
852
+ }
853
+ else if (window.opera && window.opera.postError) {
854
+ window.opera.postError(msg);
855
+ }
856
+ }
857
+ };
858
+
859
+ })(jQuery);