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