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