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