[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/js/jquery/ -> jquery.form.js (source)

   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&amp;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&amp;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);


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu