Ignore:
Timestamp:
05/04/12 18:00:28 (12 years ago)
Author:
gustavo
Message:

Ticket #2676 - Falha ao anexar arquivo no expresso mail

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/prototype/plugins/fileupload/jquery.fileupload.js

    r5341 r6107  
    11/* 
    2  * jQuery File Upload Plugin 5.2 
     2 * jQuery File Upload Plugin 5.10.1 
    33 * https://github.com/blueimp/jQuery-File-Upload 
    44 * 
     
    77 * 
    88 * Licensed under the MIT license: 
    9  * http://creativecommons.org/licenses/MIT/ 
     9 * http://www.opensource.org/licenses/MIT 
    1010 */ 
    1111 
    1212/*jslint nomen: true, unparam: true, regexp: true */ 
    13 /*global document, XMLHttpRequestUpload, Blob, File, FormData, location, jQuery */ 
    14  
    15 (function ($) { 
     13/*global define, window, document, Blob, FormData, location */ 
     14 
     15(function (factory) { 
    1616    'use strict'; 
    17  
    18     // The fileupload widget listens for change events on file input fields 
    19     // defined via fileInput setting and drop events of the given dropZone. 
     17    if (typeof define === 'function' && define.amd) { 
     18        // Register as an anonymous AMD module: 
     19        define([ 
     20            'jquery', 
     21            'jquery.ui.widget' 
     22        ], factory); 
     23    } else { 
     24        // Browser globals: 
     25        factory(window.jQuery); 
     26    } 
     27}(function ($) { 
     28    'use strict'; 
     29 
     30    // The FileReader API is not actually used, but works as feature detection, 
     31    // as e.g. Safari supports XHR file uploads via the FormData API, 
     32    // but not non-multipart XHR file uploads: 
     33    $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); 
     34    $.support.xhrFormDataFileUpload = !!window.FormData; 
     35 
     36    // The fileupload widget listens for change events on file input fields defined 
     37    // via fileInput setting and paste or drop events of the given dropZone. 
    2038    // In addition to the default jQuery Widget methods, the fileupload widget 
    21     // exposes the "add" and "send" methods, to add or directly send files 
    22     // using the fileupload API. 
    23     // By default, files added via file input selection, drag & drop or 
     39    // exposes the "add" and "send" methods, to add or directly send files using 
     40    // the fileupload API. 
     41    // By default, files added via file input selection, paste, drag & drop or 
    2442    // "add" method are uploaded immediately, but it is possible to override 
    2543    // the "add" callback option to queue file uploads. 
    2644    $.widget('blueimp.fileupload', { 
    27          
     45 
    2846        options: { 
    2947            // The namespace used for event handler binding on the dropZone and 
     
    4664            // The parameter name for the file form data (the request argument name). 
    4765            // If undefined or empty, the name property of the file input field is 
    48             // used, or "files[]" if the file input name property is also empty: 
     66            // used, or "files[]" if the file input name property is also empty, 
     67            // can be a string or an array of strings: 
    4968            paramName: undefined, 
    5069            // By default, each file of a selection is uploaded using an individual 
     
    6382            // Set the following option to true to force iframe transport uploads: 
    6483            forceIframeTransport: false, 
     84            // Set the following option to the location of a redirect url on the 
     85            // origin server, for cross-domain iframe transport uploads: 
     86            redirect: undefined, 
     87            // The parameter name for the redirect url, sent as part of the form 
     88            // data and set to 'redirect' if this option is empty: 
     89            redirectParamName: undefined, 
     90            // Set the following option to the location of a postMessage window, 
     91            // to enable postMessage transport uploads: 
     92            postMessage: undefined, 
    6593            // By default, XHR file uploads are sent as multipart/form-data. 
    6694            // The iframe transport is always using multipart/form-data. 
     
    82110            // prevent recalculating the global progress data: 
    83111            recalculateProgress: true, 
    84              
     112 
    85113            // Additional form data to be sent along with the file uploads can be set 
    86114            // using this option, which accepts an array of objects with name and 
     
    91119                return form.serializeArray(); 
    92120            }, 
    93              
     121 
    94122            // The add callback is invoked as soon as files are added to the fileupload 
    95             // widget (via file input selection, drag & drop or add API call). 
     123            // widget (via file input selection, drag & drop, paste or add API call). 
    96124            // If the singleFileUploads option is enabled, this callback will be 
    97125            // called once for each file in the selection for XHR file uplaods, else 
     
    108136                data.submit(); 
    109137            }, 
    110              
     138 
    111139            // Other callbacks: 
     140            // Callback for the submit event of each file upload: 
     141            // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); 
    112142            // Callback for the start of each file upload request: 
    113143            // send: function (e, data) {}, // .bind('fileuploadsend', func); 
     
    128158            // Callback for change events of the fileInput collection: 
    129159            // change: function (e, data) {}, // .bind('fileuploadchange', func); 
     160            // Callback for paste events to the dropZone collection: 
     161            // paste: function (e, data) {}, // .bind('fileuploadpaste', func); 
    130162            // Callback for drop events of the dropZone collection: 
    131163            // drop: function (e, data) {}, // .bind('fileuploaddrop', func); 
    132164            // Callback for dragover events of the dropZone collection: 
    133165            // dragover: function (e) {}, // .bind('fileuploaddragover', func); 
    134              
     166 
    135167            // The plugin options are used as settings object for the ajax calls. 
    136168            // The following are jQuery ajax settings required for the file uploads: 
     
    139171            cache: false 
    140172        }, 
    141          
     173 
    142174        // A list of options that require a refresh after assigning a new value: 
    143         _refreshOptionsList: ['namespace', 'dropZone', 'fileInput'], 
     175        _refreshOptionsList: [ 
     176            'namespace', 
     177            'dropZone', 
     178            'fileInput', 
     179            'multipart', 
     180            'forceIframeTransport' 
     181        ], 
    144182 
    145183        _isXHRUpload: function (options) { 
    146             var undef = 'undefined'; 
    147184            return !options.forceIframeTransport && 
    148                 typeof XMLHttpRequestUpload !== undef && typeof File !== undef && 
    149                 (!options.multipart || typeof FormData !== undef); 
     185                ((!options.multipart && $.support.xhrFileUpload) || 
     186                $.support.xhrFormDataFileUpload); 
    150187        }, 
    151188 
     
    204241            // Accesss to the native XHR object is required to add event listeners 
    205242            // for the upload progress event: 
    206             if (xhr.upload && xhr.upload.addEventListener) { 
    207                 xhr.upload.addEventListener('progress', function (e) { 
     243            if (xhr.upload) { 
     244                $(xhr.upload).bind('progress', function (e) { 
     245                    var oe = e.originalEvent; 
     246                    // Make sure the progress event properties get copied over: 
     247                    e.lengthComputable = oe.lengthComputable; 
     248                    e.loaded = oe.loaded; 
     249                    e.total = oe.total; 
    208250                    that._onProgress(e, options); 
    209                 }, false); 
     251                }); 
    210252                options.xhr = function () { 
    211253                    return xhr; 
     
    216258        _initXHRData: function (options) { 
    217259            var formData, 
    218                 file = options.files[0]; 
    219             if (!options.multipart || options.blob) { 
     260                file = options.files[0], 
     261                // Ignore non-multipart setting if not supported: 
     262                multipart = options.multipart || !$.support.xhrFileUpload, 
     263                paramName = options.paramName[0]; 
     264            if (!multipart || options.blob) { 
    220265                // For non-multipart uploads and chunked uploads, 
    221266                // file meta data is not part of the request body, 
     
    233278                    options.contentType = file.type; 
    234279                    options.data = file; 
    235                 } else if (!options.multipart) { 
     280                } else if (!multipart) { 
    236281                    // Chunked non-multipart upload: 
    237282                    options.contentType = 'application/octet-stream'; 
     
    239284                } 
    240285            } 
    241             if (options.multipart && typeof FormData !== 'undefined') { 
    242                 if (options.formData instanceof FormData) { 
    243                     formData = options.formData; 
     286            if (multipart && $.support.xhrFormDataFileUpload) { 
     287                if (options.postMessage) { 
     288                    // window.postMessage does not allow sending FormData 
     289                    // objects, so we just add the File/Blob objects to 
     290                    // the formData array and let the postMessage window 
     291                    // create the FormData object out of this array: 
     292                    formData = this._getFormData(options); 
     293                    if (options.blob) { 
     294                        formData.push({ 
     295                            name: paramName, 
     296                            value: options.blob 
     297                        }); 
     298                    } else { 
     299                        $.each(options.files, function (index, file) { 
     300                            formData.push({ 
     301                                name: options.paramName[index] || paramName, 
     302                                value: file 
     303                            }); 
     304                        }); 
     305                    } 
    244306                } else { 
    245                     formData = new FormData(); 
    246                     $.each(this._getFormData(options), function (index, field) { 
    247                         formData.append(field.name, field.value); 
    248                     }); 
    249                 } 
    250                 if (options.blob) { 
    251                     formData.append(options.paramName, options.blob); 
    252                 } else { 
    253                     $.each(options.files, function (index, file) { 
    254                         // File objects are also Blob instances. 
    255                         // This check allows the tests to run with 
    256                         // dummy objects: 
    257                         if (file instanceof Blob) { 
    258                             formData.append(options.paramName, file); 
    259                         } 
    260                     }); 
     307                    if (options.formData instanceof FormData) { 
     308                        formData = options.formData; 
     309                    } else { 
     310                        formData = new FormData(); 
     311                        $.each(this._getFormData(options), function (index, field) { 
     312                            formData.append(field.name, field.value); 
     313                        }); 
     314                    } 
     315                    if (options.blob) { 
     316                        formData.append(paramName, options.blob, file.name); 
     317                    } else { 
     318                        $.each(options.files, function (index, file) { 
     319                            // File objects are also Blob instances. 
     320                            // This check allows the tests to run with 
     321                            // dummy objects: 
     322                            if (file instanceof Blob) { 
     323                                formData.append( 
     324                                    options.paramName[index] || paramName, 
     325                                    file, 
     326                                    file.name 
     327                                ); 
     328                            } 
     329                        }); 
     330                    } 
    261331                } 
    262332                options.data = formData; 
     
    265335            options.blob = null; 
    266336        }, 
    267          
     337 
    268338        _initIframeSettings: function (options) { 
    269339            // Setting the dataType to iframe enables the iframe transport: 
     
    271341            // The iframe transport accepts a serialized array as form data: 
    272342            options.formData = this._getFormData(options); 
    273         }, 
    274          
     343            // Add redirect url to form data on cross-domain uploads: 
     344            if (options.redirect && $('<a></a>').prop('href', options.url) 
     345                    .prop('host') !== location.host) { 
     346                options.formData.push({ 
     347                    name: options.redirectParamName || 'redirect', 
     348                    value: options.redirect 
     349                }); 
     350            } 
     351        }, 
     352 
    275353        _initDataSettings: function (options) { 
    276354            if (this._isXHRUpload(options)) { 
     
    281359                    this._initProgressListener(options); 
    282360                } 
     361                if (options.postMessage) { 
     362                    // Setting the dataType to postmessage enables the 
     363                    // postMessage transport: 
     364                    options.dataType = 'postmessage ' + (options.dataType || ''); 
     365                } 
    283366            } else { 
    284                 this._initIframeSettings(options); 
    285             } 
    286         }, 
    287          
     367                this._initIframeSettings(options, 'iframe'); 
     368            } 
     369        }, 
     370 
     371        _getParamName: function (options) { 
     372            var fileInput = $(options.fileInput), 
     373                paramName = options.paramName; 
     374            if (!paramName) { 
     375                paramName = []; 
     376                fileInput.each(function () { 
     377                    var input = $(this), 
     378                        name = input.prop('name') || 'files[]', 
     379                        i = (input.prop('files') || [1]).length; 
     380                    while (i) { 
     381                        paramName.push(name); 
     382                        i -= 1; 
     383                    } 
     384                }); 
     385                if (!paramName.length) { 
     386                    paramName = [fileInput.prop('name') || 'files[]']; 
     387                } 
     388            } else if (!$.isArray(paramName)) { 
     389                paramName = [paramName]; 
     390            } 
     391            return paramName; 
     392        }, 
     393 
    288394        _initFormSettings: function (options) { 
    289395            // Retrieve missing options from the input field and the 
     
    292398                options.form = $(options.fileInput.prop('form')); 
    293399            } 
    294             if (!options.paramName) { 
    295                 options.paramName = options.fileInput.prop('name') || 
    296                     'files[]'; 
    297             } 
     400            options.paramName = this._getParamName(options); 
    298401            if (!options.url) { 
    299402                options.url = options.form.prop('action') || location.href; 
     
    306409            } 
    307410        }, 
    308          
     411 
    309412        _getAJAXSettings: function (data) { 
    310413            var options = $.extend({}, this.options, data); 
     
    365468            if (ub >= fs) { 
    366469                file.error = 'uploadedBytes'; 
    367                 return this._getXHRPromise(false); 
     470                return this._getXHRPromise( 
     471                    false, 
     472                    options.context, 
     473                    [null, 'error', file.error] 
     474                ); 
    368475            } 
    369476            // n is the number of blobs to upload, 
     
    373480            upload = function (i) { 
    374481                if (!i) { 
    375                     return that._getXHRPromise(true); 
     482                    return that._getXHRPromise(true, options.context); 
    376483                } 
    377484                // Upload the blobs in sequential order: 
     
    402509                                }), o); 
    403510                            } 
    404                             options.uploadedBytes = o.uploadedBytes 
    405                                 += o.chunkSize; 
     511                            options.uploadedBytes = o.uploadedBytes += 
     512                                o.chunkSize; 
    406513                        }); 
    407514                    return jqXHR; 
     
    459566        }, 
    460567 
    461         _onAlways: function (result, textStatus, jqXHR, errorThrown, options) { 
     568        _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { 
    462569            this._active -= 1; 
    463             options.result = result; 
    464570            options.textStatus = textStatus; 
    465             options.jqXHR = jqXHR; 
    466             options.errorThrown = errorThrown; 
     571            if (jqXHRorError && jqXHRorError.always) { 
     572                options.jqXHR = jqXHRorError; 
     573                options.result = jqXHRorResult; 
     574            } else { 
     575                options.jqXHR = jqXHRorResult; 
     576                options.errorThrown = jqXHRorError; 
     577            } 
    467578            this._trigger('always', null, options); 
    468579            if (this._active === 0) { 
     
    492603                    }).fail(function (jqXHR, textStatus, errorThrown) { 
    493604                        that._onFail(jqXHR, textStatus, errorThrown, options); 
    494                     }).always(function (a1, a2, a3) { 
     605                    }).always(function (jqXHRorResult, textStatus, jqXHRorError) { 
    495606                        that._sending -= 1; 
    496                         if (a3 && a3.done) { 
    497                             that._onAlways(a1, a2, a3, undefined, options); 
    498                         } else { 
    499                             that._onAlways(undefined, a2, a1, a3, options); 
    500                         } 
     607                        that._onAlways( 
     608                            jqXHRorResult, 
     609                            textStatus, 
     610                            jqXHRorError, 
     611                            options 
     612                        ); 
    501613                        if (options.limitConcurrentUploads && 
    502614                                options.limitConcurrentUploads > that._sending) { 
     
    543655            return send(); 
    544656        }, 
    545          
     657 
    546658        _onAdd: function (e, data) { 
    547659            var that = this, 
    548660                result = true, 
    549661                options = $.extend({}, this.options, data), 
    550                 fileSet = data.files, 
    551662                limit = options.limitMultiFileUploads, 
     663                paramName = this._getParamName(options), 
     664                paramNameSet, 
     665                paramNameSlice, 
     666                fileSet, 
    552667                i; 
    553668            if (!(options.singleFileUploads || limit) || 
    554669                    !this._isXHRUpload(options)) { 
    555                 fileSet = [fileSet]; 
     670                fileSet = [data.files]; 
     671                paramNameSet = [paramName]; 
    556672            } else if (!options.singleFileUploads && limit) { 
    557673                fileSet = []; 
     674                paramNameSet = []; 
    558675                for (i = 0; i < data.files.length; i += limit) { 
    559676                    fileSet.push(data.files.slice(i, i + limit)); 
    560                 } 
    561             } 
    562             $.each(fileSet, function (index, file) { 
    563                 var files = $.isArray(file) ? file : [file], 
    564                     newData = $.extend({}, data, {files: files}); 
     677                    paramNameSlice = paramName.slice(i, i + limit); 
     678                    if (!paramNameSlice.length) { 
     679                        paramNameSlice = paramName; 
     680                    } 
     681                    paramNameSet.push(paramNameSlice); 
     682                } 
     683            } else { 
     684                paramNameSet = paramName; 
     685            } 
     686            data.originalFiles = data.files; 
     687            $.each(fileSet || data.files, function (index, element) { 
     688                var newData = $.extend({}, data); 
     689                newData.files = fileSet ? element : [element]; 
     690                newData.paramName = paramNameSet[index]; 
    565691                newData.submit = function () { 
    566                     return that._onSend(e, newData); 
     692                    newData.jqXHR = this.jqXHR = 
     693                        (that._trigger('submit', e, this) !== false) && 
     694                        that._onSend(e, this); 
     695                    return this.jqXHR; 
    567696                }; 
    568697                return (result = that._trigger('add', e, newData)); 
     
    570699            return result; 
    571700        }, 
    572          
     701 
    573702        // File Normalization for Gecko 1.9.1 (Firefox 3.5) support: 
    574703        _normalizeFile: function (index, file) { 
     
    585714            // without loosing the file input value: 
    586715            input.after(inputClone).detach(); 
     716            // Avoid memory leaks with the detached file input: 
     717            $.cleanData(input.unbind('remove')); 
    587718            // Replace the original file input element in the fileInput 
    588719            // collection with the clone, which has been copied including 
     
    594725                return el; 
    595726            }); 
    596         }, 
    597          
     727            // If the widget has been initialized on the file input itself, 
     728            // override this.element with the file input clone: 
     729            if (input[0] === this.element[0]) { 
     730                this.element = inputClone; 
     731            } 
     732        }, 
     733 
    598734        _onChange: function (e) { 
    599735            var that = e.data.fileupload, 
     
    609745                data.files = [{name: e.target.value.replace(/^.*\\/, '')}]; 
    610746            } 
    611             // Store the form reference as jQuery data for other event handlers, 
    612             // as the form property is not available after replacing the file input:  
    613             if (data.form.length) { 
    614                 data.fileInput.data('blueimp.fileupload.form', data.form); 
    615             } else { 
    616                 data.form = data.fileInput.data('blueimp.fileupload.form'); 
    617             } 
    618747            if (that.options.replaceFileInput) { 
    619748                that._replaceFileInput(data.fileInput); 
     
    624753            } 
    625754        }, 
    626          
     755 
     756        _onPaste: function (e) { 
     757            var that = e.data.fileupload, 
     758                cbd = e.originalEvent.clipboardData, 
     759                items = (cbd && cbd.items) || [], 
     760                data = {files: []}; 
     761            $.each(items, function (index, item) { 
     762                var file = item.getAsFile && item.getAsFile(); 
     763                if (file) { 
     764                    data.files.push(file); 
     765                } 
     766            }); 
     767            if (that._trigger('paste', e, data) === false || 
     768                    that._onAdd(e, data) === false) { 
     769                return false; 
     770            } 
     771        }, 
     772 
    627773        _onDrop: function (e) { 
    628774            var that = e.data.fileupload, 
     
    640786            e.preventDefault(); 
    641787        }, 
    642          
     788 
    643789        _onDragOver: function (e) { 
    644790            var that = e.data.fileupload, 
     
    652798            e.preventDefault(); 
    653799        }, 
    654          
     800 
    655801        _initEventHandlers: function () { 
    656             var ns = this.options.namespace || this.name; 
    657             this.options.dropZone 
    658                 .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) 
    659                 .bind('drop.' + ns, {fileupload: this}, this._onDrop); 
     802            var ns = this.options.namespace; 
     803            if (this._isXHRUpload(this.options)) { 
     804                this.options.dropZone 
     805                    .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) 
     806                    .bind('drop.' + ns, {fileupload: this}, this._onDrop) 
     807                    .bind('paste.' + ns, {fileupload: this}, this._onPaste); 
     808            } 
    660809            this.options.fileInput 
    661810                .bind('change.' + ns, {fileupload: this}, this._onChange); 
     
    663812 
    664813        _destroyEventHandlers: function () { 
    665             var ns = this.options.namespace || this.name; 
     814            var ns = this.options.namespace; 
    666815            this.options.dropZone 
    667816                .unbind('dragover.' + ns, this._onDragOver) 
    668                 .unbind('drop.' + ns, this._onDrop); 
     817                .unbind('drop.' + ns, this._onDrop) 
     818                .unbind('paste.' + ns, this._onPaste); 
    669819            this.options.fileInput 
    670820                .unbind('change.' + ns, this._onChange); 
    671821        }, 
    672          
    673         _beforeSetOption: function (key, value) { 
    674             this._destroyEventHandlers(); 
    675         }, 
    676          
    677         _afterSetOption: function (key, value) { 
    678             var options = this.options; 
    679             if (!options.fileInput) { 
    680                 options.fileInput = $(); 
    681             } 
    682             if (!options.dropZone) { 
    683                 options.dropZone = $(); 
    684             } 
    685             this._initEventHandlers(); 
    686         }, 
    687          
     822 
    688823        _setOption: function (key, value) { 
    689824            var refresh = $.inArray(key, this._refreshOptionsList) !== -1; 
    690825            if (refresh) { 
    691                 this._beforeSetOption(key, value); 
     826                this._destroyEventHandlers(); 
    692827            } 
    693828            $.Widget.prototype._setOption.call(this, key, value); 
    694829            if (refresh) { 
    695                 this._afterSetOption(key, value); 
    696             } 
    697         }, 
    698  
    699         _create: function () { 
     830                this._initSpecialOptions(); 
     831                this._initEventHandlers(); 
     832            } 
     833        }, 
     834 
     835        _initSpecialOptions: function () { 
    700836            var options = this.options; 
    701837            if (options.fileInput === undefined) { 
    702838                options.fileInput = this.element.is('input:file') ? 
    703                     this.element : this.element.find('input:file'); 
    704             } else if (!options.fileInput) { 
    705                 options.fileInput = $(); 
    706             } 
    707             if (!options.dropZone) { 
    708                 options.dropZone = $(); 
    709             } 
     839                        this.element : this.element.find('input:file'); 
     840            } else if (!(options.fileInput instanceof $)) { 
     841                options.fileInput = $(options.fileInput); 
     842            } 
     843            if (!(options.dropZone instanceof $)) { 
     844                options.dropZone = $(options.dropZone); 
     845            } 
     846        }, 
     847 
     848        _create: function () { 
     849            var options = this.options; 
     850            // Initialize options set via HTML5 data-attributes: 
     851            $.extend(options, $(this.element[0].cloneNode(false)).data()); 
     852            options.namespace = options.namespace || this.widgetName; 
     853            this._initSpecialOptions(); 
    710854            this._slots = []; 
    711855            this._sequence = this._getXHRPromise(true); 
     
    713857            this._initEventHandlers(); 
    714858        }, 
    715          
     859 
    716860        destroy: function () { 
    717861            this._destroyEventHandlers(); 
     
    723867            this._initEventHandlers(); 
    724868        }, 
    725          
     869 
    726870        disable: function () { 
    727871            this._destroyEventHandlers(); 
     
    740884            this._onAdd(null, data); 
    741885        }, 
    742          
     886 
    743887        // This method is exposed to the widget API and allows sending files 
    744888        // using the fileupload API. The data parameter accepts an object which 
     
    755899            return this._getXHRPromise(false, data && data.context); 
    756900        } 
    757          
     901 
    758902    }); 
    759      
    760 }(jQuery)); 
     903 
     904})); 
Note: See TracChangeset for help on using the changeset viewer.