|
1 /* |
|
2 * jQuery Form Plugin |
|
3 * version: 2.28 (10-MAY-2009) |
|
4 * @requires jQuery v1.2.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() { |
|
22 $(this).ajaxSubmit({ |
|
23 target: '#output' |
|
24 }); |
|
25 return false; // <-- important! |
|
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 var url = $.trim(this.attr('action')); |
|
57 if (url) { |
|
58 // clean url (don't include hash vaue) |
|
59 url = (url.match(/^([^#]+)/)||[])[1]; |
|
60 } |
|
61 url = url || window.location.href || '' |
|
62 |
|
63 options = $.extend({ |
|
64 url: url, |
|
65 type: this.attr('method') || 'GET' |
|
66 }, options || {}); |
|
67 |
|
68 // hook for manipulating the form data before it is extracted; |
|
69 // convenient for use with rich editors like tinyMCE or FCKEditor |
|
70 var veto = {}; |
|
71 this.trigger('form-pre-serialize', [this, options, veto]); |
|
72 if (veto.veto) { |
|
73 log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); |
|
74 return this; |
|
75 } |
|
76 |
|
77 // provide opportunity to alter form data before it is serialized |
|
78 if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { |
|
79 log('ajaxSubmit: submit aborted via beforeSerialize callback'); |
|
80 return this; |
|
81 } |
|
82 |
|
83 var a = this.formToArray(options.semantic); |
|
84 if (options.data) { |
|
85 options.extraData = options.data; |
|
86 for (var n in options.data) { |
|
87 if(options.data[n] instanceof Array) { |
|
88 for (var k in options.data[n]) |
|
89 a.push( { name: n, value: options.data[n][k] } ); |
|
90 } |
|
91 else |
|
92 a.push( { name: n, value: options.data[n] } ); |
|
93 } |
|
94 } |
|
95 |
|
96 // give pre-submit callback an opportunity to abort the submit |
|
97 if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { |
|
98 log('ajaxSubmit: submit aborted via beforeSubmit callback'); |
|
99 return this; |
|
100 } |
|
101 |
|
102 // fire vetoable 'validate' event |
|
103 this.trigger('form-submit-validate', [a, this, options, veto]); |
|
104 if (veto.veto) { |
|
105 log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); |
|
106 return this; |
|
107 } |
|
108 |
|
109 var q = $.param(a); |
|
110 |
|
111 if (options.type.toUpperCase() == 'GET') { |
|
112 options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; |
|
113 options.data = null; // data is null for 'get' |
|
114 } |
|
115 else |
|
116 options.data = q; // data is the query string for 'post' |
|
117 |
|
118 var $form = this, callbacks = []; |
|
119 if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); |
|
120 if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); |
|
121 |
|
122 // perform a load on the target only if dataType is not provided |
|
123 if (!options.dataType && options.target) { |
|
124 var oldSuccess = options.success || function(){}; |
|
125 callbacks.push(function(data) { |
|
126 $(options.target).html(data).each(oldSuccess, arguments); |
|
127 }); |
|
128 } |
|
129 else if (options.success) |
|
130 callbacks.push(options.success); |
|
131 |
|
132 options.success = function(data, status) { |
|
133 for (var i=0, max=callbacks.length; i < max; i++) |
|
134 callbacks[i].apply(options, [data, status, $form]); |
|
135 }; |
|
136 |
|
137 // are there files to upload? |
|
138 var files = $('input:file', this).fieldValue(); |
|
139 var found = false; |
|
140 for (var j=0; j < files.length; j++) |
|
141 if (files[j]) |
|
142 found = true; |
|
143 |
|
144 var multipart = false; |
|
145 // var mp = 'multipart/form-data'; |
|
146 // multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); |
|
147 |
|
148 // options.iframe allows user to force iframe mode |
|
149 if (options.iframe || found || multipart) { |
|
150 // hack to fix Safari hang (thanks to Tim Molendijk for this) |
|
151 // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d |
|
152 if (options.closeKeepAlive) |
|
153 $.get(options.closeKeepAlive, fileUpload); |
|
154 else |
|
155 fileUpload(); |
|
156 } |
|
157 else |
|
158 $.ajax(options); |
|
159 |
|
160 // fire 'notify' event |
|
161 this.trigger('form-submit-notify', [this, options]); |
|
162 return this; |
|
163 |
|
164 |
|
165 // private function for handling file uploads (hat tip to YAHOO!) |
|
166 function fileUpload() { |
|
167 var form = $form[0]; |
|
168 |
|
169 if ($(':input[name=submit]', form).length) { |
|
170 alert('Error: Form elements must not be named "submit".'); |
|
171 return; |
|
172 } |
|
173 |
|
174 var opts = $.extend({}, $.ajaxSettings, options); |
|
175 var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts); |
|
176 |
|
177 var id = 'jqFormIO' + (new Date().getTime()); |
|
178 var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />'); |
|
179 var io = $io[0]; |
|
180 |
|
181 $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); |
|
182 |
|
183 var xhr = { // mock object |
|
184 aborted: 0, |
|
185 responseText: null, |
|
186 responseXML: null, |
|
187 status: 0, |
|
188 statusText: 'n/a', |
|
189 getAllResponseHeaders: function() {}, |
|
190 getResponseHeader: function() {}, |
|
191 setRequestHeader: function() {}, |
|
192 abort: function() { |
|
193 this.aborted = 1; |
|
194 $io.attr('src','about:blank'); // abort op in progress |
|
195 } |
|
196 }; |
|
197 |
|
198 var g = opts.global; |
|
199 // trigger ajax global events so that activity/block indicators work like normal |
|
200 if (g && ! $.active++) $.event.trigger("ajaxStart"); |
|
201 if (g) $.event.trigger("ajaxSend", [xhr, opts]); |
|
202 |
|
203 if (s.beforeSend && s.beforeSend(xhr, s) === false) { |
|
204 s.global && $.active--; |
|
205 return; |
|
206 } |
|
207 if (xhr.aborted) |
|
208 return; |
|
209 |
|
210 var cbInvoked = 0; |
|
211 var timedOut = 0; |
|
212 |
|
213 // add submitting element to data if we know it |
|
214 var sub = form.clk; |
|
215 if (sub) { |
|
216 var n = sub.name; |
|
217 if (n && !sub.disabled) { |
|
218 options.extraData = options.extraData || {}; |
|
219 options.extraData[n] = sub.value; |
|
220 if (sub.type == "image") { |
|
221 options.extraData[name+'.x'] = form.clk_x; |
|
222 options.extraData[name+'.y'] = form.clk_y; |
|
223 } |
|
224 } |
|
225 } |
|
226 |
|
227 // take a breath so that pending repaints get some cpu time before the upload starts |
|
228 setTimeout(function() { |
|
229 // make sure form attrs are set |
|
230 var t = $form.attr('target'), a = $form.attr('action'); |
|
231 |
|
232 // update form attrs in IE friendly way |
|
233 form.setAttribute('target',id); |
|
234 if (form.getAttribute('method') != 'POST') |
|
235 form.setAttribute('method', 'POST'); |
|
236 if (form.getAttribute('action') != opts.url) |
|
237 form.setAttribute('action', opts.url); |
|
238 |
|
239 // ie borks in some cases when setting encoding |
|
240 if (! options.skipEncodingOverride) { |
|
241 $form.attr({ |
|
242 encoding: 'multipart/form-data', |
|
243 enctype: 'multipart/form-data' |
|
244 }); |
|
245 } |
|
246 |
|
247 // support timout |
|
248 if (opts.timeout) |
|
249 setTimeout(function() { timedOut = true; cb(); }, opts.timeout); |
|
250 |
|
251 // add "extra" data to form if provided in options |
|
252 var extraInputs = []; |
|
253 try { |
|
254 if (options.extraData) |
|
255 for (var n in options.extraData) |
|
256 extraInputs.push( |
|
257 $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />') |
|
258 .appendTo(form)[0]); |
|
259 |
|
260 // add iframe to doc and submit the form |
|
261 $io.appendTo('body'); |
|
262 io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); |
|
263 form.submit(); |
|
264 } |
|
265 finally { |
|
266 // reset attrs and remove "extra" input elements |
|
267 form.setAttribute('action',a); |
|
268 t ? form.setAttribute('target', t) : $form.removeAttr('target'); |
|
269 $(extraInputs).remove(); |
|
270 } |
|
271 }, 10); |
|
272 |
|
273 var nullCheckFlag = 0; |
|
274 |
|
275 function cb() { |
|
276 if (cbInvoked++) return; |
|
277 |
|
278 io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); |
|
279 |
|
280 var ok = true; |
|
281 try { |
|
282 if (timedOut) throw 'timeout'; |
|
283 // extract the server response from the iframe |
|
284 var data, doc; |
|
285 |
|
286 doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; |
|
287 |
|
288 if ((doc.body == null || doc.body.innerHTML == '') && !nullCheckFlag) { |
|
289 // in some browsers (cough, Opera 9.2.x) the iframe DOM is not always traversable when |
|
290 // the onload callback fires, so we give them a 2nd chance |
|
291 nullCheckFlag = 1; |
|
292 cbInvoked--; |
|
293 setTimeout(cb, 100); |
|
294 return; |
|
295 } |
|
296 |
|
297 xhr.responseText = doc.body ? doc.body.innerHTML : null; |
|
298 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; |
|
299 xhr.getResponseHeader = function(header){ |
|
300 var headers = {'content-type': opts.dataType}; |
|
301 return headers[header]; |
|
302 }; |
|
303 |
|
304 if (opts.dataType == 'json' || opts.dataType == 'script') { |
|
305 var ta = doc.getElementsByTagName('textarea')[0]; |
|
306 xhr.responseText = ta ? ta.value : xhr.responseText; |
|
307 } |
|
308 else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { |
|
309 xhr.responseXML = toXml(xhr.responseText); |
|
310 } |
|
311 data = $.httpData(xhr, opts.dataType); |
|
312 } |
|
313 catch(e){ |
|
314 ok = false; |
|
315 $.handleError(opts, xhr, 'error', e); |
|
316 } |
|
317 |
|
318 // ordering of these callbacks/triggers is odd, but that's how $.ajax does it |
|
319 if (ok) { |
|
320 opts.success(data, 'success'); |
|
321 if (g) $.event.trigger("ajaxSuccess", [xhr, opts]); |
|
322 } |
|
323 if (g) $.event.trigger("ajaxComplete", [xhr, opts]); |
|
324 if (g && ! --$.active) $.event.trigger("ajaxStop"); |
|
325 if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error'); |
|
326 |
|
327 // clean up |
|
328 setTimeout(function() { |
|
329 $io.remove(); |
|
330 xhr.responseXML = null; |
|
331 }, 100); |
|
332 }; |
|
333 |
|
334 function toXml(s, doc) { |
|
335 if (window.ActiveXObject) { |
|
336 doc = new ActiveXObject('Microsoft.XMLDOM'); |
|
337 doc.async = 'false'; |
|
338 doc.loadXML(s); |
|
339 } |
|
340 else |
|
341 doc = (new DOMParser()).parseFromString(s, 'text/xml'); |
|
342 return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null; |
|
343 }; |
|
344 }; |
|
345 }; |
|
346 |
|
347 /** |
|
348 * ajaxForm() provides a mechanism for fully automating form submission. |
|
349 * |
|
350 * The advantages of using this method instead of ajaxSubmit() are: |
|
351 * |
|
352 * 1: This method will include coordinates for <input type="image" /> elements (if the element |
|
353 * is used to submit the form). |
|
354 * 2. This method will include the submit element's name/value data (for the element that was |
|
355 * used to submit the form). |
|
356 * 3. This method binds the submit() method to the form for you. |
|
357 * |
|
358 * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely |
|
359 * passes the options argument along after properly binding events for submit elements and |
|
360 * the form itself. |
|
361 */ |
|
362 $.fn.ajaxForm = function(options) { |
|
363 return this.ajaxFormUnbind().bind('submit.form-plugin',function() { |
|
364 $(this).ajaxSubmit(options); |
|
365 return false; |
|
366 }).each(function() { |
|
367 // store options in hash |
|
368 $(":submit,input:image", this).bind('click.form-plugin',function(e) { |
|
369 var form = this.form; |
|
370 form.clk = this; |
|
371 if (this.type == 'image') { |
|
372 if (e.offsetX != undefined) { |
|
373 form.clk_x = e.offsetX; |
|
374 form.clk_y = e.offsetY; |
|
375 } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin |
|
376 var offset = $(this).offset(); |
|
377 form.clk_x = e.pageX - offset.left; |
|
378 form.clk_y = e.pageY - offset.top; |
|
379 } else { |
|
380 form.clk_x = e.pageX - this.offsetLeft; |
|
381 form.clk_y = e.pageY - this.offsetTop; |
|
382 } |
|
383 } |
|
384 // clear form vars |
|
385 setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10); |
|
386 }); |
|
387 }); |
|
388 }; |
|
389 |
|
390 // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm |
|
391 $.fn.ajaxFormUnbind = function() { |
|
392 this.unbind('submit.form-plugin'); |
|
393 return this.each(function() { |
|
394 $(":submit,input:image", this).unbind('click.form-plugin'); |
|
395 }); |
|
396 |
|
397 }; |
|
398 |
|
399 /** |
|
400 * formToArray() gathers form element data into an array of objects that can |
|
401 * be passed to any of the following ajax functions: $.get, $.post, or load. |
|
402 * Each object in the array has both a 'name' and 'value' property. An example of |
|
403 * an array for a simple login form might be: |
|
404 * |
|
405 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] |
|
406 * |
|
407 * It is this array that is passed to pre-submit callback functions provided to the |
|
408 * ajaxSubmit() and ajaxForm() methods. |
|
409 */ |
|
410 $.fn.formToArray = function(semantic) { |
|
411 var a = []; |
|
412 if (this.length == 0) return a; |
|
413 |
|
414 var form = this[0]; |
|
415 var els = semantic ? form.getElementsByTagName('*') : form.elements; |
|
416 if (!els) return a; |
|
417 for(var i=0, max=els.length; i < max; i++) { |
|
418 var el = els[i]; |
|
419 var n = el.name; |
|
420 if (!n) continue; |
|
421 |
|
422 if (semantic && form.clk && el.type == "image") { |
|
423 // handle image inputs on the fly when semantic == true |
|
424 if(!el.disabled && form.clk == el) { |
|
425 a.push({name: n, value: $(el).val()}); |
|
426 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); |
|
427 } |
|
428 continue; |
|
429 } |
|
430 |
|
431 var v = $.fieldValue(el, true); |
|
432 if (v && v.constructor == Array) { |
|
433 for(var j=0, jmax=v.length; j < jmax; j++) |
|
434 a.push({name: n, value: v[j]}); |
|
435 } |
|
436 else if (v !== null && typeof v != 'undefined') |
|
437 a.push({name: n, value: v}); |
|
438 } |
|
439 |
|
440 if (!semantic && form.clk) { |
|
441 // input type=='image' are not found in elements array! handle it here |
|
442 var $input = $(form.clk), input = $input[0], n = input.name; |
|
443 if (n && !input.disabled && input.type == 'image') { |
|
444 a.push({name: n, value: $input.val()}); |
|
445 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); |
|
446 } |
|
447 } |
|
448 return a; |
|
449 }; |
|
450 |
|
451 /** |
|
452 * Serializes form data into a 'submittable' string. This method will return a string |
|
453 * in the format: name1=value1&name2=value2 |
|
454 */ |
|
455 $.fn.formSerialize = function(semantic) { |
|
456 //hand off to jQuery.param for proper encoding |
|
457 return $.param(this.formToArray(semantic)); |
|
458 }; |
|
459 |
|
460 /** |
|
461 * Serializes all field elements in the jQuery object into a query string. |
|
462 * This method will return a string in the format: name1=value1&name2=value2 |
|
463 */ |
|
464 $.fn.fieldSerialize = function(successful) { |
|
465 var a = []; |
|
466 this.each(function() { |
|
467 var n = this.name; |
|
468 if (!n) return; |
|
469 var v = $.fieldValue(this, successful); |
|
470 if (v && v.constructor == Array) { |
|
471 for (var i=0,max=v.length; i < max; i++) |
|
472 a.push({name: n, value: v[i]}); |
|
473 } |
|
474 else if (v !== null && typeof v != 'undefined') |
|
475 a.push({name: this.name, value: v}); |
|
476 }); |
|
477 //hand off to jQuery.param for proper encoding |
|
478 return $.param(a); |
|
479 }; |
|
480 |
|
481 /** |
|
482 * Returns the value(s) of the element in the matched set. For example, consider the following form: |
|
483 * |
|
484 * <form><fieldset> |
|
485 * <input name="A" type="text" /> |
|
486 * <input name="A" type="text" /> |
|
487 * <input name="B" type="checkbox" value="B1" /> |
|
488 * <input name="B" type="checkbox" value="B2"/> |
|
489 * <input name="C" type="radio" value="C1" /> |
|
490 * <input name="C" type="radio" value="C2" /> |
|
491 * </fieldset></form> |
|
492 * |
|
493 * var v = $(':text').fieldValue(); |
|
494 * // if no values are entered into the text inputs |
|
495 * v == ['',''] |
|
496 * // if values entered into the text inputs are 'foo' and 'bar' |
|
497 * v == ['foo','bar'] |
|
498 * |
|
499 * var v = $(':checkbox').fieldValue(); |
|
500 * // if neither checkbox is checked |
|
501 * v === undefined |
|
502 * // if both checkboxes are checked |
|
503 * v == ['B1', 'B2'] |
|
504 * |
|
505 * var v = $(':radio').fieldValue(); |
|
506 * // if neither radio is checked |
|
507 * v === undefined |
|
508 * // if first radio is checked |
|
509 * v == ['C1'] |
|
510 * |
|
511 * The successful argument controls whether or not the field element must be 'successful' |
|
512 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). |
|
513 * The default value of the successful argument is true. If this value is false the value(s) |
|
514 * for each element is returned. |
|
515 * |
|
516 * Note: This method *always* returns an array. If no valid value can be determined the |
|
517 * array will be empty, otherwise it will contain one or more values. |
|
518 */ |
|
519 $.fn.fieldValue = function(successful) { |
|
520 for (var val=[], i=0, max=this.length; i < max; i++) { |
|
521 var el = this[i]; |
|
522 var v = $.fieldValue(el, successful); |
|
523 if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) |
|
524 continue; |
|
525 v.constructor == Array ? $.merge(val, v) : val.push(v); |
|
526 } |
|
527 return val; |
|
528 }; |
|
529 |
|
530 /** |
|
531 * Returns the value of the field element. |
|
532 */ |
|
533 $.fieldValue = function(el, successful) { |
|
534 var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); |
|
535 if (typeof successful == 'undefined') successful = true; |
|
536 |
|
537 if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || |
|
538 (t == 'checkbox' || t == 'radio') && !el.checked || |
|
539 (t == 'submit' || t == 'image') && el.form && el.form.clk != el || |
|
540 tag == 'select' && el.selectedIndex == -1)) |
|
541 return null; |
|
542 |
|
543 if (tag == 'select') { |
|
544 var index = el.selectedIndex; |
|
545 if (index < 0) return null; |
|
546 var a = [], ops = el.options; |
|
547 var one = (t == 'select-one'); |
|
548 var max = (one ? index+1 : ops.length); |
|
549 for(var i=(one ? index : 0); i < max; i++) { |
|
550 var op = ops[i]; |
|
551 if (op.selected) { |
|
552 var v = op.value; |
|
553 if (!v) // extra pain for IE... |
|
554 v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; |
|
555 if (one) return v; |
|
556 a.push(v); |
|
557 } |
|
558 } |
|
559 return a; |
|
560 } |
|
561 return el.value; |
|
562 }; |
|
563 |
|
564 /** |
|
565 * Clears the form data. Takes the following actions on the form's input fields: |
|
566 * - input text fields will have their 'value' property set to the empty string |
|
567 * - select elements will have their 'selectedIndex' property set to -1 |
|
568 * - checkbox and radio inputs will have their 'checked' property set to false |
|
569 * - inputs of type submit, button, reset, and hidden will *not* be effected |
|
570 * - button elements will *not* be effected |
|
571 */ |
|
572 $.fn.clearForm = function() { |
|
573 return this.each(function() { |
|
574 $('input,select,textarea', this).clearFields(); |
|
575 }); |
|
576 }; |
|
577 |
|
578 /** |
|
579 * Clears the selected form elements. |
|
580 */ |
|
581 $.fn.clearFields = $.fn.clearInputs = function() { |
|
582 return this.each(function() { |
|
583 var t = this.type, tag = this.tagName.toLowerCase(); |
|
584 if (t == 'text' || t == 'password' || tag == 'textarea') |
|
585 this.value = ''; |
|
586 else if (t == 'checkbox' || t == 'radio') |
|
587 this.checked = false; |
|
588 else if (tag == 'select') |
|
589 this.selectedIndex = -1; |
|
590 }); |
|
591 }; |
|
592 |
|
593 /** |
|
594 * Resets the form data. Causes all form elements to be reset to their original value. |
|
595 */ |
|
596 $.fn.resetForm = function() { |
|
597 return this.each(function() { |
|
598 // guard against an input with the name of 'reset' |
|
599 // note that IE reports the reset function as an 'object' |
|
600 if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) |
|
601 this.reset(); |
|
602 }); |
|
603 }; |
|
604 |
|
605 /** |
|
606 * Enables or disables any matching elements. |
|
607 */ |
|
608 $.fn.enable = function(b) { |
|
609 if (b == undefined) b = true; |
|
610 return this.each(function() { |
|
611 this.disabled = !b; |
|
612 }); |
|
613 }; |
|
614 |
|
615 /** |
|
616 * Checks/unchecks any matching checkboxes or radio buttons and |
|
617 * selects/deselects and matching option elements. |
|
618 */ |
|
619 $.fn.selected = function(select) { |
|
620 if (select == undefined) select = true; |
|
621 return this.each(function() { |
|
622 var t = this.type; |
|
623 if (t == 'checkbox' || t == 'radio') |
|
624 this.checked = select; |
|
625 else if (this.tagName.toLowerCase() == 'option') { |
|
626 var $sel = $(this).parent('select'); |
|
627 if (select && $sel[0] && $sel[0].type == 'select-one') { |
|
628 // deselect all other options |
|
629 $sel.find('option').selected(false); |
|
630 } |
|
631 this.selected = select; |
|
632 } |
|
633 }); |
|
634 }; |
|
635 |
|
636 // helper fn for console logging |
|
637 // set $.fn.ajaxSubmit.debug to true to enable debug logging |
|
638 function log() { |
|
639 if ($.fn.ajaxSubmit.debug && window.console && window.console.log) |
|
640 window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,'')); |
|
641 }; |
|
642 |
|
643 })(jQuery); |