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