.Net Mvc MyAjaxForm.js異步提交上傳圖片

MyAjaxForm.js源碼腳本javascript

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

前臺部分代碼css

 1 //引入JS類庫
 2 <script src="~/Scripts/MyAjaxForm.js"></script>
 3 
 4 //部分代碼
 5     <div id="addDialogDiv">
 6         @using (Ajax.BeginForm("Add", "ActionInfo", new AjaxOptions() { OnSuccess = "afterAdd" }))
 7         {
 8             <table>
 9                 <tr id="trIconUrl">
10                     <td>菜單的圖標地址:</td>
11                     <td>
12                         <input type="hidden" id="MenuIcon" name="MenuIcon" />
13                         <input type="file" id="fileMenuIcon" name="fileMenuIcon" />
14                         <input type="button" value="上傳" id="btnUploadFile" />
15                         <div id="uploadImg">
16 
17                         </div>
18                     </td>
19 
20                 </tr>
21             </table>
22         }
23     </div>

js腳本部分html

 1     <script type="text/javascript">
 2         $(function () {
 3             //綁定上傳圖片的點擊事件
 4             bindUploadBtnClick();
 5         })
 6 
 7         //綁定一個上傳圖片的按鈕點擊事件
 8         function bindUploadBtnClick() {
 9             $("#btnUploadFile").click(function () {
10                 $("#addDialogDiv form").ajaxSubmit({
11                     url: "/ActionInfo/UploadImage",
12                     type: "Post",
13                     success: function (data) {
14                         //把返回的URL地址,放到頁面的隱藏域
15                         $("#MenuIcon").val(data);
16                         $("#uploadImg").html("<img src='"+data+"' style='width:40px,height:40px;'/>");
17                     }
18                 })
19             })
20         }
21 
22 
23     </script>

後臺邏輯java

1         public ActionResult UploadImage()
2         {            
3             var file = Request.Files["fileMenuIcon"];
4             //根目錄下,建立相應文件夾,存放圖片
5             string path = "/UploadFiles/UploadImgs/"+Guid.NewGuid().ToString()+"-"+ file.FileName;
6             file.SaveAs(Request.MapPath(path)); //Request.MapPath將相對路徑轉絕對路徑
7             return Content(path);
8         }

實現node

相關文章
相關標籤/搜索