[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/jquery/ -> jquery.form.js (source)

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


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1