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