1/*! 2 * jQuery Form Plugin 3 * version: 3.51.0-2014.06.20 4 * Requires jQuery v1.5 or later 5 * Copyright (c) 2014 M. Alsup 6 * Examples and documentation at: http://malsup.com/jquery/form/ 7 * Project repository: https://github.com/malsup/form 8 * Dual licensed under the MIT and GPL licenses. 9 * https://github.com/malsup/form#copyright-and-license 10 */ 11/*global ActiveXObject */ 12 13(function (factory) { 14 "use strict"; 15 factory(window.$ || window.Zepto); 16} 17 18(function($) { 19"use strict"; 20 21/* 22 Usage Note: 23 ----------- 24 Do not use both ajaxSubmit and ajaxForm on the same form. These 25 functions are mutually exclusive. Use ajaxSubmit if you want 26 to bind your own submit handler to the form. For example, 27 28 $(document).ready(function() { 29 $('#myForm').on('submit', function(e) { 30 e.preventDefault(); // <-- important 31 $(this).ajaxSubmit({ 32 target: '#output' 33 }); 34 }); 35 }); 36 37 Use ajaxForm when you want the plugin to manage all the event binding 38 for you. For example, 39 40 $(document).ready(function() { 41 $('#myForm').ajaxForm({ 42 target: '#output' 43 }); 44 }); 45 46 You can also use ajaxForm with delegation (requires jQuery v1.7+), so the 47 form does not have to exist when you invoke ajaxForm: 48 49 $('#myForm').ajaxForm({ 50 delegation: true, 51 target: '#output' 52 }); 53 54 When using ajaxForm, the ajaxSubmit function will be invoked for you 55 at the appropriate time. 56*/ 57 58/** 59 * Feature detection 60 */ 61var feature = {}; 62feature.fileapi = $("<input type='file'/>").get(0).files !== undefined; 63feature.formdata = window.FormData !== undefined; 64 65var hasProp = !!$.fn.prop; 66 67// attr2 uses prop when it can but checks the return type for 68// an expected string. this accounts for the case where a form 69// contains inputs with names like "action" or "method"; in those 70// cases "prop" returns the element 71$.fn.attr2 = function() { 72 if ( ! hasProp ) { 73 return this.attr.apply(this, arguments); 74 } 75 var val = this.prop.apply(this, arguments); 76 if ( ( val && val.jquery ) || typeof val === 'string' ) { 77 return val; 78 } 79 return this.attr.apply(this, arguments); 80}; 81 82/** 83 * ajaxSubmit() provides a mechanism for immediately submitting 84 * an HTML form using AJAX. 85 */ 86$.fn.ajaxSubmit = function(options) { 87 /*jshint scripturl:true */ 88 89 // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) 90 if (!this.length) { 91 log('ajaxSubmit: skipping submit process - no element selected'); 92 return this; 93 } 94 95 var method, action, url, $form = this; 96 97 if (typeof options == 'function') { 98 options = { success: options }; 99 } 100 else if ( options === undefined ) { 101 options = {}; 102 } 103 104 method = options.type || this.attr2('method'); 105 action = options.url || this.attr2('action'); 106 107 url = (typeof action === 'string') ? $.trim(action) : ''; 108 url = url || window.location.href || ''; 109 if (url) { 110 // clean url (don't include hash vaue) 111 url = (url.match(/^([^#]+)/)||[])[1]; 112 } 113 114 options = $.extend(true, { 115 url: url, 116 success: $.ajaxSettings.success, 117 type: method || $.ajaxSettings.type, 118 iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' 119 }, options); 120 121 // hook for manipulating the form data before it is extracted; 122 // convenient for use with rich editors like tinyMCE or FCKEditor 123 var veto = {}; 124 this.trigger('form-pre-serialize', [this, options, veto]); 125 if (veto.veto) { 126 log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); 127 return this; 128 } 129 130 // provide opportunity to alter form data before it is serialized 131 if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { 132 log('ajaxSubmit: submit aborted via beforeSerialize callback'); 133 return this; 134 } 135 136 var traditional = options.traditional; 137 if ( traditional === undefined ) { 138 traditional = $.ajaxSettings.traditional; 139 } 140 141 var elements = []; 142 var qx, a = this.formToArray(options.semantic, elements); 143 if (options.data) { 144 options.extraData = options.data; 145 qx = $.param(options.data, traditional); 146 } 147 148 // give pre-submit callback an opportunity to abort the submit 149 if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { 150 log('ajaxSubmit: submit aborted via beforeSubmit callback'); 151 return this; 152 } 153 154 // fire vetoable 'validate' event 155 this.trigger('form-submit-validate', [a, this, options, veto]); 156 if (veto.veto) { 157 log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); 158 return this; 159 } 160 161 var q = $.param(a, traditional); 162 if (qx) { 163 q = ( q ? (q + '&' + qx) : qx ); 164 } 165 if (options.type.toUpperCase() == 'GET') { 166 options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; 167 options.data = null; // data is null for 'get' 168 } 169 else { 170 options.data = q; // data is the query string for 'post' 171 } 172 173 var callbacks = []; 174 if (options.resetForm) { 175 callbacks.push(function() { $form.resetForm(); }); 176 } 177 if (options.clearForm) { 178 callbacks.push(function() { $form.clearForm(options.includeHidden); }); 179 } 180 181 // perform a load on the target only if dataType is not provided 182 if (!options.dataType && options.target) { 183 var oldSuccess = options.success || function(){}; 184 callbacks.push(function(data) { 185 var fn = options.replaceTarget ? 'replaceWith' : 'html'; 186 187 // Validate `data` through `HTML encoding` when passed 188 // `data` is passed to `html()`, as suggested in 189 // https://github.com/jquery-form/form/issues/464 190 191 data = options.replaceTarget 192 ? data 193 : $.parseHTML($('<div>').text(data).html()); 194 195 $(options.target)[fn](data).each(oldSuccess, arguments); 196 }); 197 } 198 else if (options.success) { 199 callbacks.push(options.success); 200 } 201 202 options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg 203 var context = options.context || this ; // jQuery 1.4+ supports scope context 204 for (var i=0, max=callbacks.length; i < max; i++) { 205 callbacks[i].apply(context, [data, status, xhr || $form, $form]); 206 } 207 }; 208 209 if (options.error) { 210 var oldError = options.error; 211 options.error = function(xhr, status, error) { 212 var context = options.context || this; 213 oldError.apply(context, [xhr, status, error, $form]); 214 }; 215 } 216 217 if (options.complete) { 218 var oldComplete = options.complete; 219 options.complete = function(xhr, status) { 220 var context = options.context || this; 221 oldComplete.apply(context, [xhr, status, $form]); 222 }; 223 } 224 225 // are there files to upload? 226 227 // [value] (issue #113), also see comment: 228 // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219 229 var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; }); 230 231 var hasFileInputs = fileInputs.length > 0; 232 var mp = 'multipart/form-data'; 233 var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); 234 235 var fileAPI = feature.fileapi && feature.formdata; 236 log("fileAPI :" + fileAPI); 237 var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; 238 239 var jqxhr; 240 241 // options.iframe allows user to force iframe mode 242 // 06-NOV-09: now defaulting to iframe mode if file input is detected 243 if (options.iframe !== false && (options.iframe || shouldUseFrame)) { 244 // hack to fix Safari hang (thanks to Tim Molendijk for this) 245 // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d 246 if (options.closeKeepAlive) { 247 $.get(options.closeKeepAlive, function() { 248 jqxhr = fileUploadIframe(a); 249 }); 250 } 251 else { 252 jqxhr = fileUploadIframe(a); 253 } 254 } 255 else if ((hasFileInputs || multipart) && fileAPI) { 256 jqxhr = fileUploadXhr(a); 257 } 258 else { 259 jqxhr = $.ajax(options); 260 } 261 262 $form.removeData('jqxhr').data('jqxhr', jqxhr); 263 264 // clear element array 265 for (var k=0; k < elements.length; k++) { 266 elements[k] = null; 267 } 268 269 // fire 'notify' event 270 this.trigger('form-submit-notify', [this, options]); 271 return this; 272 273 // utility fn for deep serialization 274 function deepSerialize(extraData){ 275 var serialized = $.param(extraData, options.traditional).split('&'); 276 var len = serialized.length; 277 var result = []; 278 var i, part; 279 for (i=0; i < len; i++) { 280 // #252; undo param space replacement 281 serialized[i] = serialized[i].replace(/\+/g,' '); 282 part = serialized[i].split('='); 283 // #278; use array instead of object storage, favoring array serializations 284 result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]); 285 } 286 return result; 287 } 288 289 // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) 290 function fileUploadXhr(a) { 291 var formdata = new FormData(); 292 293 for (var i=0; i < a.length; i++) { 294 formdata.append(a[i].name, a[i].value); 295 } 296 297 if (options.extraData) { 298 var serializedData = deepSerialize(options.extraData); 299 for (i=0; i < serializedData.length; i++) { 300 if (serializedData[i]) { 301 formdata.append(serializedData[i][0], serializedData[i][1]); 302 } 303 } 304 } 305 306 options.data = null; 307 308 var s = $.extend(true, {}, $.ajaxSettings, options, { 309 contentType: false, 310 processData: false, 311 cache: false, 312 type: method || 'POST' 313 }); 314 315 if (options.uploadProgress) { 316 // workaround because jqXHR does not expose upload property 317 s.xhr = function() { 318 var xhr = $.ajaxSettings.xhr(); 319 if (xhr.upload) { 320 xhr.upload.addEventListener('progress', function(event) { 321 var percent = 0; 322 var position = event.loaded || event.position; /*event.position is deprecated*/ 323 var total = event.total; 324 if (event.lengthComputable) {
325 percent = Math.ceil(position / total * 100); 326 } 327 options.uploadProgress(event, position, total, percent); 328 }, false); 329 } 330 return xhr; 331 }; 332 } 333 334 s.data = null; 335 var beforeSend = s.beforeSend; 336 s.beforeSend = function(xhr, o) { 337 //Send FormData() provided by user 338 if (options.formData) { 339 o.data = options.formData; 340 } 341 else { 342 o.data = formdata; 343 } 344 if(beforeSend) { 345 beforeSend.call(this, xhr, o); 346 } 347 }; 348 return $.ajax(s); 349 } 350 351 // private function for handling file uploads (hat tip to YAHOO!) 352 function fileUploadIframe(a) { 353 var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; 354 var deferred = $.Deferred(); 355 356 // #341 357 deferred.abort = function(status) { 358 xhr.abort(status); 359 }; 360 361 if (a) { 362 // ensure that every serialized input is still enabled 363 for (i=0; i < elements.length; i++) { 364 el = $(elements[i]); 365 if ( hasProp ) { 366 el.prop('disabled', false); 367 } 368 else { 369 el.removeAttr('disabled'); 370 } 371 } 372 } 373 374 s = $.extend(true, {}, $.ajaxSettings, options); 375 s.context = s.context || s; 376 id = 'jqFormIO' + (new Date().getTime()); 377 if (s.iframeTarget) { 378 $io = $(s.iframeTarget); 379 n = $io.attr2('name'); 380 if (!n) { 381 $io.attr2('name', id); 382 } 383 else { 384 id = n; 385 } 386 } 387 else { 388 $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />'); 389 $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); 390 } 391 io = $io[0]; 392 393 394 xhr = { // mock object 395 aborted: 0, 396 responseText: null, 397 responseXML: null, 398 status: 0, 399 statusText: 'n/a', 400 getAllResponseHeaders: function() {}, 401 getResponseHeader: function() {}, 402 setRequestHeader: function() {}, 403 abort: function(status) { 404 var e = (status === 'timeout' ? 'timeout' : 'aborted'); 405 log('aborting upload... ' + e); 406 this.aborted = 1; 407 408 try { // #214, #257 409 if (io.contentWindow.document.execCommand) { 410 io.contentWindow.document.execCommand('Stop'); 411 } 412 } 413 catch(ignore) {} 414 415 $io.attr('src', s.iframeSrc); // abort op in progress 416 xhr.error = e; 417 if (s.error) { 418 s.error.call(s.context, xhr, e, status); 419 } 420 if (g) { 421 $.event.trigger("ajaxError", [xhr, s, e]); 422 } 423 if (s.complete) { 424 s.complete.call(s.context, xhr, e); 425 } 426 } 427 }; 428 429 g = s.global; 430 // trigger ajax global events so that activity/block indicators work like normal 431 if (g && 0 === $.active++) { 432 $.event.trigger("ajaxStart"); 433 } 434 if (g) { 435 $.event.trigger("ajaxSend", [xhr, s]); 436 } 437 438 if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) { 439 if (s.global) { 440 $.active--; 441 } 442 deferred.reject(); 443 return deferred; 444 } 445 if (xhr.aborted) { 446 deferred.reject(); 447 return deferred; 448 } 449 450 // add submitting element to data if we know it 451 sub = form.clk; 452 if (sub) { 453 n = sub.name; 454 if (n && !sub.disabled) { 455 s.extraData = s.extraData || {}; 456 s.extraData[n] = sub.value; 457 if (sub.type == "image") { 458 s.extraData[n+'.x'] = form.clk_x; 459 s.extraData[n+'.y'] = form.clk_y; 460 } 461 } 462 } 463 464 var CLIENT_TIMEOUT_ABORT = 1; 465 var SERVER_ABORT = 2; 466 467 function getDoc(frame) { 468 /* it looks like contentWindow or contentDocument do not 469 * carry the protocol property in ie8, when running under ssl 470 * frame.document is the only valid response document, since 471 * the protocol is know but not on the other two objects. strange? 472 * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy 473 */ 474 475 var doc = null; 476 477 // IE8 cascading access check 478 try { 479 if (frame.contentWindow) { 480 doc = frame.contentWindow.document; 481 } 482 } catch(err) { 483 // IE8 access denied under ssl & missing protocol 484 log('cannot get iframe.contentWindow document: ' + err); 485 } 486 487 if (doc) { // successful getting content 488 return doc; 489 } 490 491 try { // simply checking may throw in ie8 under ssl or mismatched protocol 492 doc = frame.contentDocument ? frame.contentDocument : frame.document; 493 } catch(err) { 494 // last attempt 495 log('cannot get iframe.contentDocument: ' + err); 496 doc = frame.document; 497 } 498 return doc; 499 } 500 501 // Rails CSRF hack (thanks to Yvan Barthelemy) 502 var csrf_token = $('meta[name=csrf-token]').attr('content'); 503 var csrf_param = $('meta[name=csrf-param]').attr('content'); 504 if (csrf_param && csrf_token) { 505 s.extraData = s.extraData || {}; 506 s.extraData[csrf_param] = csrf_token; 507 } 508 509 // take a breath so that pending repaints get some cpu time before the upload starts 510 function doSubmit() { 511 // make sure form attrs are set 512 var t = $form.attr2('target'), 513 a = $form.attr2('action'),
514 mp = 'multipart/form-data', 515 et = $form.attr('enctype') || $form.attr('encoding') || mp; 516 517 // update form attrs in IE friendly way 518 form.setAttribute('target',id); 519 if (!method || /post/i.test(method) ) { 520 form.setAttribute('method', 'POST'); 521 } 522 if (a != s.url) { 523 form.setAttribute('action', s.url); 524 } 525 526 // ie borks in some cases when setting encoding 527 if (! s.skipEncodingOverride && (!method || /post/i.test(method))) { 528 $form.attr({ 529 encoding: 'multipart/form-data', 530 enctype: 'multipart/form-data' 531 }); 532 } 533 534 // support timout 535 if (s.timeout) { 536 timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout); 537 } 538 539 // look for server aborts 540 function checkState() { 541 try { 542 var state = getDoc(io).readyState; 543 log('state = ' + state); 544 if (state && state.toLowerCase() == 'uninitialized') { 545 setTimeout(checkState,50); 546 } 547 } 548 catch(e) { 549 log('Server abort: ' , e, ' (', e.name, ')'); 550 cb(SERVER_ABORT); 551 if (timeoutHandle) { 552 clearTimeout(timeoutHandle); 553 } 554 timeoutHandle = undefined; 555 } 556 } 557 558 // add "extra" data to form if provided in options 559 var extraInputs = []; 560 try { 561 if (s.extraData) { 562 for (var n in s.extraData) { 563 if (s.extraData.hasOwnProperty(n)) { 564 // if using the $.param format that allows for multiple values with the same name 565 if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) { 566 extraInputs.push( 567 $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value) 568 .appendTo(form)[0]); 569 } else { 570 extraInputs.push( 571 $('<input type="hidden" name="'+n+'">').val(s.extraData[n]) 572 .appendTo(form)[0]); 573 } 574 } 575 } 576 } 577 578 if (!s.iframeTarget) { 579 // add iframe to doc and submit the form 580 $io.appendTo('body'); 581 } 582 if (io.attachEvent) { 583 io.attachEvent('onload', cb); 584 } 585 else { 586 io.addEventListener('load', cb, false); 587 } 588 setTimeout(checkState,15); 589 590 try { 591 form.submit(); 592 } catch(err) { 593 // just in case form has element with name/id of 'submit' 594 var submitFn = document.createElement('form').submit; 595 submitFn.apply(form); 596 } 597 } 598 finally { 599 // reset attrs and remove "extra" input elements 600 form.setAttribute('action',a); 601 form.setAttribute('enctype', et); // #380 602 if(t) { 603 form.setAttribute('target', t); 604 } else { 605 $form.removeAttr('target'); 606 } 607 $(extraInputs).remove(); 608 } 609 } 610 611 if (s.forceSync) { 612 doSubmit(); 613 } 614 else { 615 setTimeout(doSubmit, 10); // this lets dom updates render 616 } 617 618 var data, doc, domCheckCount = 50, callbackProcessed; 619 620 function cb(e) { 621 if (xhr.aborted || callbackProcessed) { 622 return; 623 } 624 625 doc = getDoc(io); 626 if(!doc) { 627 log('cannot access response document'); 628 e = SERVER_ABORT; 629 } 630 if (e === CLIENT_TIMEOUT_ABORT && xhr) { 631 xhr.abort('timeout'); 632 deferred.reject(xhr, 'timeout'); 633 return; 634 } 635 else if (e == SERVER_ABORT && xhr) { 636 xhr.abort('server abort'); 637 deferred.reject(xhr, 'error', 'server abort'); 638 return; 639 } 640 641 if (!doc || doc.location.href == s.iframeSrc) { 642 // response not received yet 643 if (!timedOut) { 644 return; 645 } 646 } 647 if (io.detachEvent) { 648 io.detachEvent('onload', cb); 649 } 650 else { 651 io.removeEventListener('load', cb, false); 652 } 653 654 var status = 'success', errMsg; 655 try { 656 if (timedOut) { 657 throw 'timeout'; 658 } 659 660 var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); 661 log('isXml='+isXml); 662 if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) { 663 if (--domCheckCount) { 664 // in some browsers (Opera) the iframe DOM is not always traversable when 665 // the onload callback fires, so we loop a bit to accommodate 666 log('requeing onLoad callback, DOM not available'); 667 setTimeout(cb, 250); 668 return; 669 } 670 // let this fall through because server response could be an empty document 671 //log('Could not access iframe DOM after mutiple tries.'); 672 //throw 'DOMException: not available'; 673 } 674 675 //log('response detected'); 676 var docRoot = doc.body ? doc.body : doc.documentElement; 677 xhr.responseText = docRoot ? docRoot.innerHTML : null; 678 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; 679 if (isXml) { 680 s.dataType = 'xml'; 681 } 682 xhr.getResponseHeader = function(header){ 683 var headers = {'content-type': s.dataType}; 684 return headers[header.toLowerCase()]; 685 }; 686 // support for XHR 'status' & 'statusText' emulation : 687 if (docRoot) { 688 xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status; 689 xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText; 690 } 691 692 var dt = (s.dataType || '').toLowerCase(); 693 var scr = /(json|script|text)/.test(dt); 694 if (scr || s.textarea) { 695 // see if user embedded response in textarea 696 var ta = doc.getElementsByTagName('textarea')[0]; 697 if (ta) { 698 xhr.responseText = ta.value; 699 // support for XHR 'status' & 'statusText' emulation : 700 xhr.status = Number( ta.getAttribute('status') ) || xhr.status; 701 xhr.statusText = ta.getAttribute('statusText') || xhr.statusText; 702 } 703 else if (scr) { 704 // account for browsers injecting pre around json response 705 var pre = doc.getElementsByTagName('pre')[0]; 706 var b = doc.getElementsByTagName('body')[0]; 707 if (pre) { 708 xhr.responseText = pre.textContent ? pre.textContent : pre.innerText; 709 } 710 else if (b) { 711 xhr.responseText = b.textContent ? b.textContent : b.innerText; 712 } 713 } 714 } 715 else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) { 716 xhr.responseXML = toXml(xhr.responseText); 717 } 718 719 try { 720 data = httpData(xhr, dt, s); 721 } 722 catch (err) { 723 status = 'parsererror'; 724 xhr.error = errMsg = (err || status); 725 } 726 } 727 catch (err) { 728 log('error caught: ',err); 729 status = 'error'; 730 xhr.error = errMsg = (err || status); 731 } 732 733 if (xhr.aborted) { 734 log('upload aborted'); 735 status = null; 736 } 737 738 if (xhr.status) { // we've set xhr.status 739 status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error'; 740 } 741 742 // ordering of these callbacks/triggers is odd, but that's how $.ajax does it 743 if (status === 'success') { 744 if (s.success) { 745 s.success.call(s.context, data, 'success', xhr); 746 } 747 deferred.resolve(xhr.responseText, 'success', xhr); 748 if (g) { 749 $.event.trigger("ajaxSuccess", [xhr, s]); 750 } 751 } 752 else if (status) { 753 if (errMsg === undefined) { 754 errMsg = xhr.statusText; 755 } 756 if (s.error) { 757 s.error.call(s.context, xhr, status, errMsg); 758 } 759 deferred.reject(xhr, 'error', errMsg); 760 if (g) { 761 $.event.trigger("ajaxError", [xhr, s, errMsg]); 762 } 763 } 764 765 if (g) {
766 $.event.trigger("ajaxComplete", [xhr, s]); 767 } 768 769 if (g && ! --$.active) { 770 $.event.trigger("ajaxStop"); 771 } 772 773 if (s.complete) { 774 s.complete.call(s.context, xhr, status); 775 } 776 777 callbackProcessed = true; 778 if (s.timeout) { 779 clearTimeout(timeoutHandle); 780 } 781 782 // clean up 783 setTimeout(function() { 784 if (!s.iframeTarget) { 785 $io.remove(); 786 } 787 else { //adding else to clean up existing iframe response. 788 $io.attr('src', s.iframeSrc); 789 } 790 xhr.responseXML = null; 791 }, 100); 792 } 793 794 var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+) 795 if (window.ActiveXObject) { 796 doc = new ActiveXObject('Microsoft.XMLDOM'); 797 doc.async = 'false'; 798 doc.loadXML(s); 799 } 800 else { 801 doc = (new DOMParser()).parseFromString(s, 'text/xml'); 802 } 803 return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null; 804 }; 805 var parseJSON = $.parseJSON || function(s) { 806 // Throw an error instead of making a new function using 807 // unsanitized inputs to avoid XSS attacks. 808 809 window.console.error('jquery.parseJSON is undefined'); 810 811 return null; 812 }; 813 814 var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4 815 816 var ct = xhr.getResponseHeader('content-type') || '', 817 xml = type === 'xml' || !type && ct.indexOf('xml') >= 0, 818 data = xml ? xhr.responseXML : xhr.responseText; 819 820 if (xml && data.documentElement.nodeName === 'parsererror') { 821 if ($.error) { 822 $.error('parsererror'); 823 } 824 } 825 if (s && s.dataFilter) { 826 data = s.dataFilter(data, type); 827 } 828 if (typeof data === 'string') { 829 if (type === 'json' || !type && ct.indexOf('json') >= 0) { 830 data = parseJSON(data); 831 } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) { 832 $.globalEval(data); 833 } 834 } 835 return data; 836 }; 837 838 return deferred; 839 } 840}; 841 842/** 843 * ajaxForm() provides a mechanism for fully automating form submission. 844 * 845 * The advantages of using this method instead of ajaxSubmit() are: 846 * 847 * 1: This method will include coordinates for <input type="image" /> elements (if the element 848 * is used to submit the form). 849 * 2. This method will include the submit element's name/value data (for the element that was 850 * used to submit the form). 851 * 3. This method binds the submit() method to the form for you. 852 * 853 * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely 854 * passes the options argument along after properly binding events for submit elements and 855 * the form itself. 856 */ 857$.fn.ajaxForm = function(options) { 858 options = options || {}; 859 options.delegation = options.delegation && $.isFunction($.fn.on); 860 861 // in jQuery 1.3+ we can fix mistakes with the ready state 862 if (!options.delegation && this.length === 0) { 863 var o = { s: this.selector, c: this.context }; 864 if (!$.isReady && o.s) { 865 log('DOM not ready, queuing ajaxForm'); 866 $(function() { 867 $(o.s,o.c).ajaxForm(options); 868 }); 869 return this; 870 } 871 // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready() 872 log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); 873 return this; 874 } 875 876 if ( options.delegation ) { 877 $(document) 878 .off('submit.form-plugin', this.selector, doAjaxSubmit) 879 .off('click.form-plugin', this.selector, captureSubmittingElement) 880 .on('submit.form-plugin', this.selector, options, doAjaxSubmit) 881 .on('click.form-plugin', this.selector, options, captureSubmittingElement); 882 return this; 883 } 884 885 return this.ajaxFormUnbind() 886 .bind('submit.form-plugin', options, doAjaxSubmit) 887 .bind('click.form-plugin', options, captureSubmittingElement); 888}; 889 890// private event handlers 891function doAjaxSubmit(e) { 892 /*jshint validthis:true */ 893 var options = e.data; 894 if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed 895 e.preventDefault(); 896 $(e.target).ajaxSubmit(options); // #365 897 } 898} 899 900function captureSubmittingElement(e) { 901 /*jshint validthis:true */ 902 var target = e.target; 903 var $el = $(target); 904 if (!($el.is("[type=submit],[type=image]"))) { 905 // is this a child element of the submit el? (ex: a span within a button) 906 var t = $el.closest('[type=submit]'); 907 if (t.length === 0) { 908 return; 909 } 910 target = t[0]; 911 } 912 var form = this; 913 form.clk = target; 914 if (target.type == 'image') { 915 if (e.offsetX !== undefined) { 916 form.clk_x = e.offsetX; 917 form.clk_y = e.offsetY; 918 } else if (typeof $.fn.offset == 'function') { 919 var offset = $el.offset(); 920 form.clk_x = e.pageX - offset.left; 921 form.clk_y = e.pageY - offset.top; 922 } else { 923 form.clk_x = e.pageX - target.offsetLeft; 924 form.clk_y = e.pageY - target.offsetTop; 925 } 926 } 927 // clear form vars 928 setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); 929} 930 931 932// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm 933$.fn.ajaxFormUnbind = function() { 934 return this.unbind('submit.form-plugin click.form-plugin'); 935}; 936 937/** 938 * formToArray() gathers form element data into an array of objects that can 939 * be passed to any of the following ajax functions: $.get, $.post, or load. 940 * Each object in the array has both a 'name' and 'value' property. An example of 941 * an array for a simple login form might be: 942 * 943 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] 944 * 945 * It is this array that is passed to pre-submit callback functions provided to the 946 * ajaxSubmit() and ajaxForm() methods. 947 */ 948$.fn.formToArray = function(semantic, elements) { 949 var a = []; 950 if (this.length === 0) { 951 return a; 952 } 953 954 var form = this[0]; 955 var formId = this.attr('id'); 956 var els = semantic ? form.getElementsByTagName('*') : form.elements; 957 var els2; 958 959 if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390 960 els = $(els).get(); // convert to standard array 961 } 962 963 // #386; account for inputs outside the form which use the 'form' attribute 964 if ( formId ) { 965 els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet 966 if ( els2.length ) { 967 els = (els || []).concat(els2); 968 } 969 } 970 971 if (!els || !els.length) { 972 return a; 973 } 974 975 var i,j,n,v,el,max,jmax; 976 for(i=0, max=els.length; i < max; i++) { 977 el = els[i]; 978 n = el.name; 979 if (!n || el.disabled) { 980 continue; 981 } 982 983 if (semantic && form.clk && el.type == "image") { 984 // handle image inputs on the fly when semantic == true 985 if(form.clk == el) { 986 a.push({name: n, value: $(el).val(), type: el.type }); 987 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 988 } 989 continue; 990 } 991 992 v = $.fieldValue(el, true); 993 if (v && v.constructor == Array) { 994 if (elements) { 995 elements.push(el); 996 } 997 for(j=0, jmax=v.length; j < jmax; j++) { 998 a.push({name: n, value: v[j]}); 999 } 1000 } 1001 else if (feature.fileapi && el.type == 'file') { 1002 if (elements) { 1003 elements.push(el); 1004 } 1005 var files = el.files; 1006 if (files.length) { 1007 for (j=0; j < files.length; j++) { 1008 a.push({name: n, value: files[j], type: el.type}); 1009 } 1010 } 1011 else { 1012 // #180 1013 a.push({ name: n, value: '', type: el.type }); 1014 } 1015 } 1016 else if (v !== null && typeof v != 'undefined') { 1017 if (elements) { 1018 elements.push(el); 1019 } 1020 a.push({name: n, value: v, type: el.type, required: el.required}); 1021 } 1022 } 1023 1024 if (!semantic && form.clk) { 1025 // input type=='image' are not found in elements array! handle it here 1026 var $input = $(form.clk), input = $input[0]; 1027 n = input.name; 1028 if (n && !input.disabled && input.type == 'image') { 1029 a.push({name: n, value: $input.val()}); 1030 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 1031 } 1032 } 1033 return a; 1034}; 1035 1036/** 1037 * Serializes form data into a 'submittable' string. This method will return a string 1038 * in the format: name1=value1&name2=value2 1039 */
1040$.fn.formSerialize = function(semantic) { 1041 //hand off to jQuery.param for proper encoding 1042 return $.param(this.formToArray(semantic)); 1043}; 1044 1045/** 1046 * Serializes all field elements in the jQuery object into a query string. 1047 * This method will return a string in the format: name1=value1&name2=value2 1048 */ 1049$.fn.fieldSerialize = function(successful) { 1050 var a = []; 1051 this.each(function() { 1052 var n = this.name; 1053 if (!n) { 1054 return; 1055 } 1056 var v = $.fieldValue(this, successful); 1057 if (v && v.constructor == Array) { 1058 for (var i=0,max=v.length; i < max; i++) { 1059 a.push({name: n, value: v[i]}); 1060 } 1061 } 1062 else if (v !== null && typeof v != 'undefined') { 1063 a.push({name: this.name, value: v}); 1064 } 1065 }); 1066 //hand off to jQuery.param for proper encoding 1067 return $.param(a); 1068}; 1069 1070/** 1071 * Returns the value(s) of the element in the matched set. For example, consider the following form: 1072 * 1073 * <form><fieldset> 1074 * <input name="A" type="text" /> 1075 * <input name="A" type="text" /> 1076 * <input name="B" type="checkbox" value="B1" /> 1077 * <input name="B" type="checkbox" value="B2"/> 1078 * <input name="C" type="radio" value="C1" /> 1079 * <input name="C" type="radio" value="C2" /> 1080 * </fieldset></form> 1081 * 1082 * var v = $('input[type=text]').fieldValue(); 1083 * // if no values are entered into the text inputs 1084 * v == ['',''] 1085 * // if values entered into the text inputs are 'foo' and 'bar' 1086 * v == ['foo','bar'] 1087 * 1088 * var v = $('input[type=checkbox]').fieldValue(); 1089 * // if neither checkbox is checked 1090 * v === undefined 1091 * // if both checkboxes are checked 1092 * v == ['B1', 'B2'] 1093 * 1094 * var v = $('input[type=radio]').fieldValue(); 1095 * // if neither radio is checked 1096 * v === undefined 1097 * // if first radio is checked 1098 * v == ['C1'] 1099 * 1100 * The successful argument controls whether or not the field element must be 'successful' 1101 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). 1102 * The default value of the successful argument is true. If this value is false the value(s) 1103 * for each element is returned. 1104 * 1105 * Note: This method *always* returns an array. If no valid value can be determined the 1106 * array will be empty, otherwise it will contain one or more values. 1107 */ 1108$.fn.fieldValue = function(successful) { 1109 for (var val=[], i=0, max=this.length; i < max; i++) { 1110 var el = this[i]; 1111 var v = $.fieldValue(el, successful); 1112 if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) { 1113 continue; 1114 } 1115 if (v.constructor == Array) { 1116 $.merge(val, v); 1117 } 1118 else { 1119 val.push(v); 1120 } 1121 } 1122 return val; 1123}; 1124 1125/** 1126 * Returns the value of the field element. 1127 */ 1128$.fieldValue = function(el, successful) { 1129 var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); 1130 if (successful === undefined) { 1131 successful = true; 1132 } 1133 1134 if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || 1135 (t == 'checkbox' || t == 'radio') && !el.checked || 1136 (t == 'submit' || t == 'image') && el.form && el.form.clk != el || 1137 tag == 'select' && el.selectedIndex == -1)) { 1138 return null; 1139 } 1140 1141 if (tag == 'select') { 1142 var index = el.selectedIndex; 1143 if (index < 0) { 1144 return null; 1145 } 1146 var a = [], ops = el.options; 1147 var one = (t == 'select-one'); 1148 var max = (one ? index+1 : ops.length); 1149 for(var i=(one ? index : 0); i < max; i++) { 1150 var op = ops[i]; 1151 if (op.selected) { 1152 var v = op.value; 1153 if (!v) { // extra pain for IE... 1154 v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value; 1155 } 1156 if (one) { 1157 return v; 1158 } 1159 a.push(v); 1160 } 1161 } 1162 return a; 1163 } 1164 return $(el).val(); 1165}; 1166 1167/** 1168 * Clears the form data. Takes the following actions on the form's input fields: 1169 * - input text fields will have their 'value' property set to the empty string 1170 * - select elements will have their 'selectedIndex' property set to -1 1171 * - checkbox and radio inputs will have their 'checked' property set to false 1172 * - inputs of type submit, button, reset, and hidden will *not* be effected 1173 * - button elements will *not* be effected 1174 */ 1175$.fn.clearForm = function(includeHidden) { 1176 return this.each(function() { 1177 $('input,select,textarea', this).clearFields(includeHidden); 1178 }); 1179}; 1180 1181/** 1182 * Clears the selected form elements. 1183 */ 1184$.fn.clearFields = $.fn.clearInputs = function(includeHidden) { 1185 var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list 1186 return this.each(function() { 1187 var t = this.type, tag = this.tagName.toLowerCase(); 1188 if (re.test(t) || tag == 'textarea') { 1189 this.value = ''; 1190 } 1191 else if (t == 'checkbox' || t == 'radio') { 1192 this.checked = false;
1193 } 1194 else if (tag == 'select') { 1195 this.selectedIndex = -1; 1196 } 1197 else if (t == "file") { 1198 if (/MSIE/.test(navigator.userAgent)) { 1199 $(this).replaceWith($(this).clone(true)); 1200 } else { 1201 $(this).val(''); 1202 } 1203 } 1204 else if (includeHidden) { 1205 // includeHidden can be the value true, or it can be a selector string 1206 // indicating a special test; for example: 1207 // $('#myForm').clearForm('.special:hidden') 1208 // the above would clean hidden inputs that have the class of 'special' 1209 if ( (includeHidden === true && /hidden/.test(t)) || 1210 (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) { 1211 this.value = ''; 1212 } 1213 } 1214 }); 1215}; 1216 1217/** 1218 * Resets the form data. Causes all form elements to be reset to their original value. 1219 */ 1220$.fn.resetForm = function() { 1221 return this.each(function() { 1222 // guard against an input with the name of 'reset' 1223 // note that IE reports the reset function as an 'object' 1224 if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) { 1225 this.reset(); 1226 } 1227 }); 1228}; 1229 1230/** 1231 * Enables or disables any matching elements. 1232 */ 1233$.fn.enable = function(b) { 1234 if (b === undefined) { 1235 b = true; 1236 } 1237 return this.each(function() { 1238 this.disabled = !b; 1239 }); 1240}; 1241 1242/** 1243 * Checks/unchecks any matching checkboxes or radio buttons and 1244 * selects/deselects and matching option elements. 1245 */ 1246$.fn.selected = function(select) { 1247 if (select === undefined) { 1248 select = true; 1249 } 1250 return this.each(function() { 1251 var t = this.type; 1252 if (t == 'checkbox' || t == 'radio') { 1253 this.checked = select; 1254 } 1255 else if (this.tagName.toLowerCase() == 'option') { 1256 var $sel = $(this).parent('select'); 1257 if (select && $sel[0] && $sel[0].type == 'select-one') { 1258 // deselect all other options 1259 $sel.find('option').selected(false); 1260 } 1261 this.selected = select; 1262 } 1263 }); 1264}; 1265 1266// expose debug var 1267$.fn.ajaxSubmit.debug = false; 1268 1269// helper fn for console logging 1270function log() { 1271 if (!$.fn.ajaxSubmit.debug) { 1272 return; 1273 } 1274 var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); 1275 if (window.console && window.console.log) { 1276 window.console.log(msg); 1277 } 1278 else if (window.opera && window.opera.postError) { 1279 window.opera.postError(msg); 1280 } 1281} 1282 1283}));
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.