1 /*! 2 * jQuery Form Plugin 3 * version: 2.69 (06-APR-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 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 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]; 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 var s = $.extend(true, {}, $.ajaxSettings, options); 192 s.context = s.context || s; 193 var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id; 194 var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />'); 195 var io = $io[0]; 196 197 $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); 198 199 var xhr = { // mock object 200 aborted: 0, 201 responseText: null, 202 responseXML: null, 203 status: 0, 204 statusText: 'n/a', 205 getAllResponseHeaders: function() {}, 206 getResponseHeader: function() {}, 207 setRequestHeader: function() {}, 208 abort: function() { 209 log('aborting upload...'); 210 var e = 'aborted'; 211 this.aborted = 1; 212 $io.attr('src', s.iframeSrc); // abort op in progress 213 xhr.error = e; 214 s.error && s.error.call(s.context, xhr, 'error', e); 215 g && $.event.trigger("ajaxError", [xhr, s, e]); 216 s.complete && s.complete.call(s.context, xhr, 'error'); 217 } 218 }; 219 220 var g = s.global; 221 // trigger ajax global events so that activity/block indicators work like normal 222 if (g && ! $.active++) { 223 $.event.trigger("ajaxStart"); 224 } 225 if (g) { 226 $.event.trigger("ajaxSend", [xhr, s]); 227 } 228 229 if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) { 230 if (s.global) { 231 $.active--; 232 } 233 return; 234 } 235 if (xhr.aborted) { 236 return; 237 } 238 239 var timedOut = 0; 240 241 // add submitting element to data if we know it 242 var sub = form.clk; 243 if (sub) { 244 var n = sub.name; 245 if (n && !sub.disabled) { 246 s.extraData = s.extraData || {}; 247 s.extraData[n] = sub.value; 248 if (sub.type == "image") { 249 s.extraData[n+'.x'] = form.clk_x; 250 s.extraData[n+'.y'] = form.clk_y; 251 } 252 } 253 } 254 255 // take a breath so that pending repaints get some cpu time before the upload starts 256 function doSubmit() { 257 // make sure form attrs are set 258 var t = $form.attr('target'), a = $form.attr('action'); 259 260 // update form attrs in IE friendly way 261 form.setAttribute('target',id); 262 if (form.getAttribute('method') != 'POST') { 263 form.setAttribute('method', 'POST'); 264 } 265 if (form.getAttribute('action') != s.url) { 266 form.setAttribute('action', s.url); 267 } 268 269 // ie borks in some cases when setting encoding 270 if (! s.skipEncodingOverride) { 271 $form.attr({ 272 encoding: 'multipart/form-data', 273 enctype: 'multipart/form-data' 274 }); 275 } 276 277 // support timout 278 if (s.timeout) { 279 setTimeout(function() { timedOut = true; cb(); }, s.timeout); 280 } 281 282 // add "extra" data to form if provided in options 283 var extraInputs = []; 284 try { 285 if (s.extraData) { 286 for (var n in s.extraData) { 287 extraInputs.push( 288 $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />') 289 .appendTo(form)[0]); 290 } 291 } 292 293 // add iframe to doc and submit the form 294 $io.appendTo('body'); 295 io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); 296 form.submit(); 297 } 298 finally { 299 // reset attrs and remove "extra" input elements 300 form.setAttribute('action',a); 301 if(t) { 302 form.setAttribute('target', t); 303 } else { 304 $form.removeAttr('target'); 305 } 306 $(extraInputs).remove(); 307 } 308 } 309 310 if (s.forceSync) { 311 doSubmit(); 312 } 313 else { 314 setTimeout(doSubmit, 10); // this lets dom updates render 315 } 316 317 var data, doc, domCheckCount = 50; 318 319 function cb() { 320 if (xhr.aborted) { 321 return; 322 } 323 324 var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; 325 if (!doc || doc.location.href == s.iframeSrc) { 326 // response not received yet 327 if (!timedOut) 328 return; 329 } 330 io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); 331 332 var ok = true; 333 try { 334 if (timedOut) { 335 throw 'timeout'; 336 } 337 338 var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); 339 log('isXml='+isXml); 340 if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) { 341 if (--domCheckCount) { 342 // in some browsers (Opera) the iframe DOM is not always traversable when 343 // the onload callback fires, so we loop a bit to accommodate 344 log('requeing onLoad callback, DOM not available'); 345 setTimeout(cb, 250); 346 return; 347 } 348 // let this fall through because server response could be an empty document 349 //log('Could not access iframe DOM after mutiple tries.'); 350 //throw 'DOMException: not available'; 351 } 352 353 //log('response detected'); 354 xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null; 355 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; 356 xhr.getResponseHeader = function(header){ 357 var headers = {'content-type': s.dataType}; 358 return headers[header]; 359 }; 360 361 var scr = /(json|script)/.test(s.dataType); 362 if (scr || s.textarea) { 363 // see if user embedded response in textarea 364 var ta = doc.getElementsByTagName('textarea')[0]; 365 if (ta) { 366 xhr.responseText = ta.value; 367 } 368 else if (scr) { 369 // account for browsers injecting pre around json response 370 var pre = doc.getElementsByTagName('pre')[0]; 371 var b = doc.getElementsByTagName('body')[0]; 372 if (pre) { 373 xhr.responseText = pre.textContent; 374 } 375 else if (b) { 376 xhr.responseText = b.innerHTML; 377 } 378 } 379 } 380 else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { 381 xhr.responseXML = toXml(xhr.responseText); 382 } 383 384 data = httpData(xhr, s.dataType, s); 385 } 386 catch(e){ 387 log('error caught:',e); 388 ok = false; 389 xhr.error = e; 390 s.error && s.error.call(s.context, xhr, 'error', e); 391 g && $.event.trigger("ajaxError", [xhr, s, e]); 392 } 393 394 if (xhr.aborted) { 395 log('upload aborted'); 396 ok = false; 397 } 398 399 // ordering of these callbacks/triggers is odd, but that's how $.ajax does it 400 if (ok) { 401 s.success && s.success.call(s.context, data, 'success', xhr); 402 g && $.event.trigger("ajaxSuccess", [xhr, s]); 403 } 404 405 g && $.event.trigger("ajaxComplete", [xhr, s]); 406 407 if (g && ! --$.active) { 408 $.event.trigger("ajaxStop"); 409 } 410 411 s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error'); 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 var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+) 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.nodeName != 'parsererror') ? doc : null; 431 }; 432 var parseJSON = $.parseJSON || function(s) { 433 return window['eval']('(' + s + ')'); 434 }; 435 436 var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4 437 var ct = xhr.getResponseHeader('content-type') || '', 438 xml = type === 'xml' || !type && ct.indexOf('xml') >= 0, 439 data = xml ? xhr.responseXML : xhr.responseText; 440 441 if (xml && data.documentElement.nodeName === 'parsererror') { 442 $.error && $.error('parsererror'); 443 } 444 if (s && s.dataFilter) { 445 data = s.dataFilter(data, type); 446 } 447 if (typeof data === 'string') { 448 if (type === 'json' || !type && ct.indexOf('json') >= 0) { 449 data = parseJSON(data); 450 } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) { 451 $.globalEval(data); 452 } 453 } 454 return data; 455 }; 456 } 457 }; 458 459 /** 460 * ajaxForm() provides a mechanism for fully automating form submission. 461 * 462 * The advantages of using this method instead of ajaxSubmit() are: 463 * 464 * 1: This method will include coordinates for <input type="image" /> elements (if the element 465 * is used to submit the form). 466 * 2. This method will include the submit element's name/value data (for the element that was 467 * used to submit the form). 468 * 3. This method binds the submit() method to the form for you. 469 * 470 * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely 471 * passes the options argument along after properly binding events for submit elements and 472 * the form itself. 473 */ 474 $.fn.ajaxForm = function(options) { 475 // in jQuery 1.3+ we can fix mistakes with the ready state 476 if (this.length === 0) { 477 var o = { s: this.selector, c: this.context }; 478 if (!$.isReady && o.s) { 479 log('DOM not ready, queuing ajaxForm'); 480 $(function() { 481 $(o.s,o.c).ajaxForm(options); 482 }); 483 return this; 484 } 485 // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready() 486 log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); 487 return this; 488 } 489 490 return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) { 491 if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed 492 e.preventDefault(); 493 $(this).ajaxSubmit(options); 494 } 495 }).bind('click.form-plugin', function(e) { 496 var target = e.target; 497 var $el = $(target); 498 if (!($el.is(":submit,input:image"))) { 499 // is this a child element of the submit el? (ex: a span within a button) 500 var t = $el.closest(':submit'); 501 if (t.length == 0) { 502 return; 503 } 504 target = t[0]; 505 } 506 var form = this; 507 form.clk = target; 508 if (target.type == 'image') { 509 if (e.offsetX != undefined) { 510 form.clk_x = e.offsetX; 511 form.clk_y = e.offsetY; 512 } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin 513 var offset = $el.offset(); 514 form.clk_x = e.pageX - offset.left; 515 form.clk_y = e.pageY - offset.top; 516 } else { 517 form.clk_x = e.pageX - target.offsetLeft; 518 form.clk_y = e.pageY - target.offsetTop; 519 } 520 } 521 // clear form vars 522 setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); 523 }); 524 }; 525 526 // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm 527 $.fn.ajaxFormUnbind = function() { 528 return this.unbind('submit.form-plugin click.form-plugin'); 529 }; 530 531 /** 532 * formToArray() gathers form element data into an array of objects that can 533 * be passed to any of the following ajax functions: $.get, $.post, or load. 534 * Each object in the array has both a 'name' and 'value' property. An example of 535 * an array for a simple login form might be: 536 * 537 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] 538 * 539 * It is this array that is passed to pre-submit callback functions provided to the 540 * ajaxSubmit() and ajaxForm() methods. 541 */ 542 $.fn.formToArray = function(semantic) { 543 var a = []; 544 if (this.length === 0) { 545 return a; 546 } 547 548 var form = this[0]; 549 var els = semantic ? form.getElementsByTagName('*') : form.elements; 550 if (!els) { 551 return a; 552 } 553 554 var i,j,n,v,el,max,jmax; 555 for(i=0, max=els.length; i < max; i++) { 556 el = els[i]; 557 n = el.name; 558 if (!n) { 559 continue; 560 } 561 562 if (semantic && form.clk && el.type == "image") { 563 // handle image inputs on the fly when semantic == true 564 if(!el.disabled && form.clk == el) { 565 a.push({name: n, value: $(el).val()}); 566 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 567 } 568 continue; 569 } 570 571 v = $.fieldValue(el, true); 572 if (v && v.constructor == Array) { 573 for(j=0, jmax=v.length; j < jmax; j++) { 574 a.push({name: n, value: v[j]}); 575 } 576 } 577 else if (v !== null && typeof v != 'undefined') { 578 a.push({name: n, value: v}); 579 } 580 } 581 582 if (!semantic && form.clk) { 583 // input type=='image' are not found in elements array! handle it here 584 var $input = $(form.clk), input = $input[0]; 585 n = input.name; 586 if (n && !input.disabled && input.type == 'image') { 587 a.push({name: n, value: $input.val()}); 588 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 589 } 590 } 591 return a; 592 }; 593 594 /** 595 * Serializes form data into a 'submittable' string. This method will return a string 596 * in the format: name1=value1&name2=value2 597 */ 598 $.fn.formSerialize = function(semantic) { 599 //hand off to jQuery.param for proper encoding 600 return $.param(this.formToArray(semantic)); 601 }; 602 603 /** 604 * Serializes all field elements in the jQuery object into a query string. 605 * This method will return a string in the format: name1=value1&name2=value2 606 */ 607 $.fn.fieldSerialize = function(successful) { 608 var a = []; 609 this.each(function() { 610 var n = this.name; 611 if (!n) { 612 return; 613 } 614 var v = $.fieldValue(this, successful); 615 if (v && v.constructor == Array) { 616 for (var i=0,max=v.length; i < max; i++) { 617 a.push({name: n, value: v[i]}); 618 } 619 } 620 else if (v !== null && typeof v != 'undefined') { 621 a.push({name: this.name, value: v}); 622 } 623 }); 624 //hand off to jQuery.param for proper encoding 625 return $.param(a); 626 }; 627 628 /** 629 * Returns the value(s) of the element in the matched set. For example, consider the following form: 630 * 631 * <form><fieldset> 632 * <input name="A" type="text" /> 633 * <input name="A" type="text" /> 634 * <input name="B" type="checkbox" value="B1" /> 635 * <input name="B" type="checkbox" value="B2"/> 636 * <input name="C" type="radio" value="C1" /> 637 * <input name="C" type="radio" value="C2" /> 638 * </fieldset></form> 639 * 640 * var v = $(':text').fieldValue(); 641 * // if no values are entered into the text inputs 642 * v == ['',''] 643 * // if values entered into the text inputs are 'foo' and 'bar' 644 * v == ['foo','bar'] 645 * 646 * var v = $(':checkbox').fieldValue(); 647 * // if neither checkbox is checked 648 * v === undefined 649 * // if both checkboxes are checked 650 * v == ['B1', 'B2'] 651 * 652 * var v = $(':radio').fieldValue(); 653 * // if neither radio is checked 654 * v === undefined 655 * // if first radio is checked 656 * v == ['C1'] 657 * 658 * The successful argument controls whether or not the field element must be 'successful' 659 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). 660 * The default value of the successful argument is true. If this value is false the value(s) 661 * for each element is returned. 662 * 663 * Note: This method *always* returns an array. If no valid value can be determined the 664 * array will be empty, otherwise it will contain one or more values. 665 */ 666 $.fn.fieldValue = function(successful) { 667 for (var val=[], i=0, max=this.length; i < max; i++) { 668 var el = this[i]; 669 var v = $.fieldValue(el, successful); 670 if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) { 671 continue; 672 } 673 v.constructor == Array ? $.merge(val, v) : val.push(v); 674 } 675 return val; 676 }; 677 678 /** 679 * Returns the value of the field element. 680 */ 681 $.fieldValue = function(el, successful) { 682 var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); 683 if (successful === undefined) { 684 successful = true; 685 } 686 687 if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || 688 (t == 'checkbox' || t == 'radio') && !el.checked || 689 (t == 'submit' || t == 'image') && el.form && el.form.clk != el || 690 tag == 'select' && el.selectedIndex == -1)) { 691 return null; 692 } 693 694 if (tag == 'select') { 695 var index = el.selectedIndex; 696 if (index < 0) { 697 return null; 698 } 699 var a = [], ops = el.options; 700 var one = (t == 'select-one'); 701 var max = (one ? index+1 : ops.length); 702 for(var i=(one ? index : 0); i < max; i++) { 703 var op = ops[i]; 704 if (op.selected) { 705 var v = op.value; 706 if (!v) { // extra pain for IE... 707 v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; 708 } 709 if (one) { 710 return v; 711 } 712 a.push(v); 713 } 714 } 715 return a; 716 } 717 return $(el).val(); 718 }; 719 720 /** 721 * Clears the form data. Takes the following actions on the form's input fields: 722 * - input text fields will have their 'value' property set to the empty string 723 * - select elements will have their 'selectedIndex' property set to -1 724 * - checkbox and radio inputs will have their 'checked' property set to false 725 * - inputs of type submit, button, reset, and hidden will *not* be effected 726 * - button elements will *not* be effected 727 */ 728 $.fn.clearForm = function() { 729 return this.each(function() { 730 $('input,select,textarea', this).clearFields(); 731 }); 732 }; 733 734 /** 735 * Clears the selected form elements. 736 */ 737 $.fn.clearFields = $.fn.clearInputs = function() { 738 return this.each(function() { 739 var t = this.type, tag = this.tagName.toLowerCase(); 740 if (t == 'text' || t == 'password' || tag == 'textarea') { 741 this.value = ''; 742 } 743 else if (t == 'checkbox' || t == 'radio') { 744 this.checked = false; 745 } 746 else if (tag == 'select') { 747 this.selectedIndex = -1; 748 } 749 }); 750 }; 751 752 /** 753 * Resets the form data. Causes all form elements to be reset to their original value. 754 */ 755 $.fn.resetForm = function() { 756 return this.each(function() { 757 // guard against an input with the name of 'reset' 758 // note that IE reports the reset function as an 'object' 759 if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) { 760 this.reset(); 761 } 762 }); 763 }; 764 765 /** 766 * Enables or disables any matching elements. 767 */ 768 $.fn.enable = function(b) { 769 if (b === undefined) { 770 b = true; 771 } 772 return this.each(function() { 773 this.disabled = !b; 774 }); 775 }; 776 777 /** 778 * Checks/unchecks any matching checkboxes or radio buttons and 779 * selects/deselects and matching option elements. 780 */ 781 $.fn.selected = function(select) { 782 if (select === undefined) { 783 select = true; 784 } 785 return this.each(function() { 786 var t = this.type; 787 if (t == 'checkbox' || t == 'radio') { 788 this.checked = select; 789 } 790 else if (this.tagName.toLowerCase() == 'option') { 791 var $sel = $(this).parent('select'); 792 if (select && $sel[0] && $sel[0].type == 'select-one') { 793 // deselect all other options 794 $sel.find('option').selected(false); 795 } 796 this.selected = select; 797 } 798 }); 799 }; 800 801 // helper fn for console logging 802 // set $.fn.ajaxSubmit.debug to true to enable debug logging 803 function log() { 804 if ($.fn.ajaxSubmit.debug) { 805 var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); 806 if (window.console && window.console.log) { 807 window.console.log(msg); 808 } 809 else if (window.opera && window.opera.postError) { 810 window.opera.postError(msg); 811 } 812 } 813 }; 814 815 })(jQuery); 816