s3_cors_fileupload 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
 - data/.gitignore +51 -0
 - data/.rspec +1 -0
 - data/Gemfile +14 -0
 - data/Gemfile.lock +39 -0
 - data/LICENSE.txt +20 -0
 - data/README.md +104 -0
 - data/Rakefile +58 -0
 - data/lib/generators/s3_cors_fileupload/install/USAGE +17 -0
 - data/lib/generators/s3_cors_fileupload/install/install_generator.rb +51 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/amazon_s3.yml +17 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/create_source_files.rb +14 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads.js +94 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads_controller.rb +90 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/source_file.rb +53 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/views/_template_download.html.erb +29 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/views/_template_upload.html.erb +31 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/views/_template_uploaded.html.erb +25 -0
 - data/lib/generators/s3_cors_fileupload/install/templates/views/index.html.erb +43 -0
 - data/lib/s3_cors_fileupload.rb +2 -0
 - data/lib/s3_cors_fileupload/rails.rb +8 -0
 - data/lib/s3_cors_fileupload/rails/config.rb +27 -0
 - data/lib/s3_cors_fileupload/rails/engine.rb +6 -0
 - data/lib/s3_cors_fileupload/rails/form_helper.rb +91 -0
 - data/lib/s3_cors_fileupload/rails/policy_helper.rb +48 -0
 - data/lib/s3_cors_fileupload/version.rb +5 -0
 - data/s3_cors_fileupload.gemspec +35 -0
 - data/spec/s3_cors_fileupload/version_spec.rb +17 -0
 - data/spec/s3_cors_fileupload_spec.rb +9 -0
 - data/spec/spec_helper.rb +16 -0
 - data/vendor/assets/images/loading.gif +0 -0
 - data/vendor/assets/images/progressbar.gif +0 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/index.js +6 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload-ui.js +732 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload.js +1106 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/jquery.iframe-transport.js +172 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/vendor/jquery.ui.widget.js +511 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/vendor/load-image.js +122 -0
 - data/vendor/assets/javascripts/s3_cors_fileupload/vendor/tmpl.js +87 -0
 - data/vendor/assets/stylesheets/jquery.fileupload-ui.css.erb +85 -0
 - metadata +205 -0
 
| 
         @@ -0,0 +1,1106 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
             * jQuery File Upload Plugin 5.19
         
     | 
| 
      
 3 
     | 
    
         
            +
             * https://github.com/blueimp/jQuery-File-Upload
         
     | 
| 
      
 4 
     | 
    
         
            +
             *
         
     | 
| 
      
 5 
     | 
    
         
            +
             * Copyright 2010, Sebastian Tschan
         
     | 
| 
      
 6 
     | 
    
         
            +
             * https://blueimp.net
         
     | 
| 
      
 7 
     | 
    
         
            +
             *
         
     | 
| 
      
 8 
     | 
    
         
            +
             * Licensed under the MIT license:
         
     | 
| 
      
 9 
     | 
    
         
            +
             * http://www.opensource.org/licenses/MIT
         
     | 
| 
      
 10 
     | 
    
         
            +
             */
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            /*jslint nomen: true, unparam: true, regexp: true */
         
     | 
| 
      
 13 
     | 
    
         
            +
            /*global define, window, document, Blob, FormData, location */
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            (function (factory) {
         
     | 
| 
      
 16 
     | 
    
         
            +
                'use strict';
         
     | 
| 
      
 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.
         
     | 
| 
      
 38 
     | 
    
         
            +
                // In addition to the default jQuery Widget methods, the fileupload widget
         
     | 
| 
      
 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
         
     | 
| 
      
 42 
     | 
    
         
            +
                // "add" method are uploaded immediately, but it is possible to override
         
     | 
| 
      
 43 
     | 
    
         
            +
                // the "add" callback option to queue file uploads.
         
     | 
| 
      
 44 
     | 
    
         
            +
                $.widget('blueimp.fileupload', {
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    options: {
         
     | 
| 
      
 47 
     | 
    
         
            +
                        // The drop target element(s), by the default the complete document.
         
     | 
| 
      
 48 
     | 
    
         
            +
                        // Set to null to disable drag & drop support:
         
     | 
| 
      
 49 
     | 
    
         
            +
                        dropZone: $(document),
         
     | 
| 
      
 50 
     | 
    
         
            +
                        // The paste target element(s), by the default the complete document.
         
     | 
| 
      
 51 
     | 
    
         
            +
                        // Set to null to disable paste support:
         
     | 
| 
      
 52 
     | 
    
         
            +
                        pasteZone: $(document),
         
     | 
| 
      
 53 
     | 
    
         
            +
                        // The file input field(s), that are listened to for change events.
         
     | 
| 
      
 54 
     | 
    
         
            +
                        // If undefined, it is set to the file input fields inside
         
     | 
| 
      
 55 
     | 
    
         
            +
                        // of the widget element on plugin initialization.
         
     | 
| 
      
 56 
     | 
    
         
            +
                        // Set to null to disable the change listener.
         
     | 
| 
      
 57 
     | 
    
         
            +
                        fileInput: undefined,
         
     | 
| 
      
 58 
     | 
    
         
            +
                        // By default, the file input field is replaced with a clone after
         
     | 
| 
      
 59 
     | 
    
         
            +
                        // each input field change event. This is required for iframe transport
         
     | 
| 
      
 60 
     | 
    
         
            +
                        // queues and allows change events to be fired for the same file
         
     | 
| 
      
 61 
     | 
    
         
            +
                        // selection, but can be disabled by setting the following option to false:
         
     | 
| 
      
 62 
     | 
    
         
            +
                        replaceFileInput: true,
         
     | 
| 
      
 63 
     | 
    
         
            +
                        // The parameter name for the file form data (the request argument name).
         
     | 
| 
      
 64 
     | 
    
         
            +
                        // If undefined or empty, the name property of the file input field is
         
     | 
| 
      
 65 
     | 
    
         
            +
                        // used, or "files[]" if the file input name property is also empty,
         
     | 
| 
      
 66 
     | 
    
         
            +
                        // can be a string or an array of strings:
         
     | 
| 
      
 67 
     | 
    
         
            +
                        paramName: undefined,
         
     | 
| 
      
 68 
     | 
    
         
            +
                        // By default, each file of a selection is uploaded using an individual
         
     | 
| 
      
 69 
     | 
    
         
            +
                        // request for XHR type uploads. Set to false to upload file
         
     | 
| 
      
 70 
     | 
    
         
            +
                        // selections in one request each:
         
     | 
| 
      
 71 
     | 
    
         
            +
                        singleFileUploads: true,
         
     | 
| 
      
 72 
     | 
    
         
            +
                        // To limit the number of files uploaded with one XHR request,
         
     | 
| 
      
 73 
     | 
    
         
            +
                        // set the following option to an integer greater than 0:
         
     | 
| 
      
 74 
     | 
    
         
            +
                        limitMultiFileUploads: undefined,
         
     | 
| 
      
 75 
     | 
    
         
            +
                        // Set the following option to true to issue all file upload requests
         
     | 
| 
      
 76 
     | 
    
         
            +
                        // in a sequential order:
         
     | 
| 
      
 77 
     | 
    
         
            +
                        sequentialUploads: false,
         
     | 
| 
      
 78 
     | 
    
         
            +
                        // To limit the number of concurrent uploads,
         
     | 
| 
      
 79 
     | 
    
         
            +
                        // set the following option to an integer greater than 0:
         
     | 
| 
      
 80 
     | 
    
         
            +
                        limitConcurrentUploads: undefined,
         
     | 
| 
      
 81 
     | 
    
         
            +
                        // Set the following option to true to force iframe transport uploads:
         
     | 
| 
      
 82 
     | 
    
         
            +
                        forceIframeTransport: false,
         
     | 
| 
      
 83 
     | 
    
         
            +
                        // Set the following option to the location of a redirect url on the
         
     | 
| 
      
 84 
     | 
    
         
            +
                        // origin server, for cross-domain iframe transport uploads:
         
     | 
| 
      
 85 
     | 
    
         
            +
                        redirect: undefined,
         
     | 
| 
      
 86 
     | 
    
         
            +
                        // The parameter name for the redirect url, sent as part of the form
         
     | 
| 
      
 87 
     | 
    
         
            +
                        // data and set to 'redirect' if this option is empty:
         
     | 
| 
      
 88 
     | 
    
         
            +
                        redirectParamName: undefined,
         
     | 
| 
      
 89 
     | 
    
         
            +
                        // Set the following option to the location of a postMessage window,
         
     | 
| 
      
 90 
     | 
    
         
            +
                        // to enable postMessage transport uploads:
         
     | 
| 
      
 91 
     | 
    
         
            +
                        postMessage: undefined,
         
     | 
| 
      
 92 
     | 
    
         
            +
                        // By default, XHR file uploads are sent as multipart/form-data.
         
     | 
| 
      
 93 
     | 
    
         
            +
                        // The iframe transport is always using multipart/form-data.
         
     | 
| 
      
 94 
     | 
    
         
            +
                        // Set to false to enable non-multipart XHR uploads:
         
     | 
| 
      
 95 
     | 
    
         
            +
                        multipart: true,
         
     | 
| 
      
 96 
     | 
    
         
            +
                        // To upload large files in smaller chunks, set the following option
         
     | 
| 
      
 97 
     | 
    
         
            +
                        // to a preferred maximum chunk size. If set to 0, null or undefined,
         
     | 
| 
      
 98 
     | 
    
         
            +
                        // or the browser does not support the required Blob API, files will
         
     | 
| 
      
 99 
     | 
    
         
            +
                        // be uploaded as a whole.
         
     | 
| 
      
 100 
     | 
    
         
            +
                        maxChunkSize: undefined,
         
     | 
| 
      
 101 
     | 
    
         
            +
                        // When a non-multipart upload or a chunked multipart upload has been
         
     | 
| 
      
 102 
     | 
    
         
            +
                        // aborted, this option can be used to resume the upload by setting
         
     | 
| 
      
 103 
     | 
    
         
            +
                        // it to the size of the already uploaded bytes. This option is most
         
     | 
| 
      
 104 
     | 
    
         
            +
                        // useful when modifying the options object inside of the "add" or
         
     | 
| 
      
 105 
     | 
    
         
            +
                        // "send" callbacks, as the options are cloned for each file upload.
         
     | 
| 
      
 106 
     | 
    
         
            +
                        uploadedBytes: undefined,
         
     | 
| 
      
 107 
     | 
    
         
            +
                        // By default, failed (abort or error) file uploads are removed from the
         
     | 
| 
      
 108 
     | 
    
         
            +
                        // global progress calculation. Set the following option to false to
         
     | 
| 
      
 109 
     | 
    
         
            +
                        // prevent recalculating the global progress data:
         
     | 
| 
      
 110 
     | 
    
         
            +
                        recalculateProgress: true,
         
     | 
| 
      
 111 
     | 
    
         
            +
                        // Interval in milliseconds to calculate and trigger progress events:
         
     | 
| 
      
 112 
     | 
    
         
            +
                        progressInterval: 100,
         
     | 
| 
      
 113 
     | 
    
         
            +
                        // Interval in milliseconds to calculate progress bitrate:
         
     | 
| 
      
 114 
     | 
    
         
            +
                        bitrateInterval: 500,
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                        // Additional form data to be sent along with the file uploads can be set
         
     | 
| 
      
 117 
     | 
    
         
            +
                        // using this option, which accepts an array of objects with name and
         
     | 
| 
      
 118 
     | 
    
         
            +
                        // value properties, a function returning such an array, a FormData
         
     | 
| 
      
 119 
     | 
    
         
            +
                        // object (for XHR file uploads), or a simple object.
         
     | 
| 
      
 120 
     | 
    
         
            +
                        // The form of the first fileInput is given as parameter to the function:
         
     | 
| 
      
 121 
     | 
    
         
            +
                        formData: function (form) {
         
     | 
| 
      
 122 
     | 
    
         
            +
                            return form.serializeArray();
         
     | 
| 
      
 123 
     | 
    
         
            +
                        },
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                        // The add callback is invoked as soon as files are added to the fileupload
         
     | 
| 
      
 126 
     | 
    
         
            +
                        // widget (via file input selection, drag & drop, paste or add API call).
         
     | 
| 
      
 127 
     | 
    
         
            +
                        // If the singleFileUploads option is enabled, this callback will be
         
     | 
| 
      
 128 
     | 
    
         
            +
                        // called once for each file in the selection for XHR file uplaods, else
         
     | 
| 
      
 129 
     | 
    
         
            +
                        // once for each file selection.
         
     | 
| 
      
 130 
     | 
    
         
            +
                        // The upload starts when the submit method is invoked on the data parameter.
         
     | 
| 
      
 131 
     | 
    
         
            +
                        // The data object contains a files property holding the added files
         
     | 
| 
      
 132 
     | 
    
         
            +
                        // and allows to override plugin options as well as define ajax settings.
         
     | 
| 
      
 133 
     | 
    
         
            +
                        // Listeners for this callback can also be bound the following way:
         
     | 
| 
      
 134 
     | 
    
         
            +
                        // .bind('fileuploadadd', func);
         
     | 
| 
      
 135 
     | 
    
         
            +
                        // data.submit() returns a Promise object and allows to attach additional
         
     | 
| 
      
 136 
     | 
    
         
            +
                        // handlers using jQuery's Deferred callbacks:
         
     | 
| 
      
 137 
     | 
    
         
            +
                        // data.submit().done(func).fail(func).always(func);
         
     | 
| 
      
 138 
     | 
    
         
            +
                        add: function (e, data) {
         
     | 
| 
      
 139 
     | 
    
         
            +
                            data.submit();
         
     | 
| 
      
 140 
     | 
    
         
            +
                        },
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                        // Other callbacks:
         
     | 
| 
      
 143 
     | 
    
         
            +
                        // Callback for the submit event of each file upload:
         
     | 
| 
      
 144 
     | 
    
         
            +
                        // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
         
     | 
| 
      
 145 
     | 
    
         
            +
                        // Callback for the start of each file upload request:
         
     | 
| 
      
 146 
     | 
    
         
            +
                        // send: function (e, data) {}, // .bind('fileuploadsend', func);
         
     | 
| 
      
 147 
     | 
    
         
            +
                        // Callback for successful uploads:
         
     | 
| 
      
 148 
     | 
    
         
            +
                        // done: function (e, data) {}, // .bind('fileuploaddone', func);
         
     | 
| 
      
 149 
     | 
    
         
            +
                        // Callback for failed (abort or error) uploads:
         
     | 
| 
      
 150 
     | 
    
         
            +
                        // fail: function (e, data) {}, // .bind('fileuploadfail', func);
         
     | 
| 
      
 151 
     | 
    
         
            +
                        // Callback for completed (success, abort or error) requests:
         
     | 
| 
      
 152 
     | 
    
         
            +
                        // always: function (e, data) {}, // .bind('fileuploadalways', func);
         
     | 
| 
      
 153 
     | 
    
         
            +
                        // Callback for upload progress events:
         
     | 
| 
      
 154 
     | 
    
         
            +
                        // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
         
     | 
| 
      
 155 
     | 
    
         
            +
                        // Callback for global upload progress events:
         
     | 
| 
      
 156 
     | 
    
         
            +
                        // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
         
     | 
| 
      
 157 
     | 
    
         
            +
                        // Callback for uploads start, equivalent to the global ajaxStart event:
         
     | 
| 
      
 158 
     | 
    
         
            +
                        // start: function (e) {}, // .bind('fileuploadstart', func);
         
     | 
| 
      
 159 
     | 
    
         
            +
                        // Callback for uploads stop, equivalent to the global ajaxStop event:
         
     | 
| 
      
 160 
     | 
    
         
            +
                        // stop: function (e) {}, // .bind('fileuploadstop', func);
         
     | 
| 
      
 161 
     | 
    
         
            +
                        // Callback for change events of the fileInput(s):
         
     | 
| 
      
 162 
     | 
    
         
            +
                        // change: function (e, data) {}, // .bind('fileuploadchange', func);
         
     | 
| 
      
 163 
     | 
    
         
            +
                        // Callback for paste events to the pasteZone(s):
         
     | 
| 
      
 164 
     | 
    
         
            +
                        // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
         
     | 
| 
      
 165 
     | 
    
         
            +
                        // Callback for drop events of the dropZone(s):
         
     | 
| 
      
 166 
     | 
    
         
            +
                        // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
         
     | 
| 
      
 167 
     | 
    
         
            +
                        // Callback for dragover events of the dropZone(s):
         
     | 
| 
      
 168 
     | 
    
         
            +
                        // dragover: function (e) {}, // .bind('fileuploaddragover', func);
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                        // The plugin options are used as settings object for the ajax calls.
         
     | 
| 
      
 171 
     | 
    
         
            +
                        // The following are jQuery ajax settings required for the file uploads:
         
     | 
| 
      
 172 
     | 
    
         
            +
                        processData: false,
         
     | 
| 
      
 173 
     | 
    
         
            +
                        contentType: false,
         
     | 
| 
      
 174 
     | 
    
         
            +
                        cache: false
         
     | 
| 
      
 175 
     | 
    
         
            +
                    },
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                    // A list of options that require a refresh after assigning a new value:
         
     | 
| 
      
 178 
     | 
    
         
            +
                    _refreshOptionsList: [
         
     | 
| 
      
 179 
     | 
    
         
            +
                        'fileInput',
         
     | 
| 
      
 180 
     | 
    
         
            +
                        'dropZone',
         
     | 
| 
      
 181 
     | 
    
         
            +
                        'pasteZone',
         
     | 
| 
      
 182 
     | 
    
         
            +
                        'multipart',
         
     | 
| 
      
 183 
     | 
    
         
            +
                        'forceIframeTransport'
         
     | 
| 
      
 184 
     | 
    
         
            +
                    ],
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                    _BitrateTimer: function () {
         
     | 
| 
      
 187 
     | 
    
         
            +
                        this.timestamp = +(new Date());
         
     | 
| 
      
 188 
     | 
    
         
            +
                        this.loaded = 0;
         
     | 
| 
      
 189 
     | 
    
         
            +
                        this.bitrate = 0;
         
     | 
| 
      
 190 
     | 
    
         
            +
                        this.getBitrate = function (now, loaded, interval) {
         
     | 
| 
      
 191 
     | 
    
         
            +
                            var timeDiff = now - this.timestamp;
         
     | 
| 
      
 192 
     | 
    
         
            +
                            if (!this.bitrate || !interval || timeDiff > interval) {
         
     | 
| 
      
 193 
     | 
    
         
            +
                                this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
         
     | 
| 
      
 194 
     | 
    
         
            +
                                this.loaded = loaded;
         
     | 
| 
      
 195 
     | 
    
         
            +
                                this.timestamp = now;
         
     | 
| 
      
 196 
     | 
    
         
            +
                            }
         
     | 
| 
      
 197 
     | 
    
         
            +
                            return this.bitrate;
         
     | 
| 
      
 198 
     | 
    
         
            +
                        };
         
     | 
| 
      
 199 
     | 
    
         
            +
                    },
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                    _isXHRUpload: function (options) {
         
     | 
| 
      
 202 
     | 
    
         
            +
                        return !options.forceIframeTransport &&
         
     | 
| 
      
 203 
     | 
    
         
            +
                            ((!options.multipart && $.support.xhrFileUpload) ||
         
     | 
| 
      
 204 
     | 
    
         
            +
                            $.support.xhrFormDataFileUpload);
         
     | 
| 
      
 205 
     | 
    
         
            +
                    },
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                    _getFormData: function (options) {
         
     | 
| 
      
 208 
     | 
    
         
            +
                        var formData;
         
     | 
| 
      
 209 
     | 
    
         
            +
                        if (typeof options.formData === 'function') {
         
     | 
| 
      
 210 
     | 
    
         
            +
                            return options.formData(options.form);
         
     | 
| 
      
 211 
     | 
    
         
            +
                        }
         
     | 
| 
      
 212 
     | 
    
         
            +
            			if ($.isArray(options.formData)) {
         
     | 
| 
      
 213 
     | 
    
         
            +
                            return options.formData;
         
     | 
| 
      
 214 
     | 
    
         
            +
                        }
         
     | 
| 
      
 215 
     | 
    
         
            +
            			if (options.formData) {
         
     | 
| 
      
 216 
     | 
    
         
            +
                            formData = [];
         
     | 
| 
      
 217 
     | 
    
         
            +
                            $.each(options.formData, function (name, value) {
         
     | 
| 
      
 218 
     | 
    
         
            +
                                formData.push({name: name, value: value});
         
     | 
| 
      
 219 
     | 
    
         
            +
                            });
         
     | 
| 
      
 220 
     | 
    
         
            +
                            return formData;
         
     | 
| 
      
 221 
     | 
    
         
            +
                        }
         
     | 
| 
      
 222 
     | 
    
         
            +
                        return [];
         
     | 
| 
      
 223 
     | 
    
         
            +
                    },
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                    _getTotal: function (files) {
         
     | 
| 
      
 226 
     | 
    
         
            +
                        var total = 0;
         
     | 
| 
      
 227 
     | 
    
         
            +
                        $.each(files, function (index, file) {
         
     | 
| 
      
 228 
     | 
    
         
            +
                            total += file.size || 1;
         
     | 
| 
      
 229 
     | 
    
         
            +
                        });
         
     | 
| 
      
 230 
     | 
    
         
            +
                        return total;
         
     | 
| 
      
 231 
     | 
    
         
            +
                    },
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                    _onProgress: function (e, data) {
         
     | 
| 
      
 234 
     | 
    
         
            +
                        if (e.lengthComputable) {
         
     | 
| 
      
 235 
     | 
    
         
            +
                            var now = +(new Date()),
         
     | 
| 
      
 236 
     | 
    
         
            +
                                total,
         
     | 
| 
      
 237 
     | 
    
         
            +
                                loaded;
         
     | 
| 
      
 238 
     | 
    
         
            +
                            if (data._time && data.progressInterval &&
         
     | 
| 
      
 239 
     | 
    
         
            +
                                    (now - data._time < data.progressInterval) &&
         
     | 
| 
      
 240 
     | 
    
         
            +
                                    e.loaded !== e.total) {
         
     | 
| 
      
 241 
     | 
    
         
            +
                                return;
         
     | 
| 
      
 242 
     | 
    
         
            +
                            }
         
     | 
| 
      
 243 
     | 
    
         
            +
                            data._time = now;
         
     | 
| 
      
 244 
     | 
    
         
            +
                            total = data.total || this._getTotal(data.files);
         
     | 
| 
      
 245 
     | 
    
         
            +
                            loaded = parseInt(
         
     | 
| 
      
 246 
     | 
    
         
            +
                                e.loaded / e.total * (data.chunkSize || total),
         
     | 
| 
      
 247 
     | 
    
         
            +
                                10
         
     | 
| 
      
 248 
     | 
    
         
            +
                            ) + (data.uploadedBytes || 0);
         
     | 
| 
      
 249 
     | 
    
         
            +
                            this._loaded += loaded - (data.loaded || data.uploadedBytes || 0);
         
     | 
| 
      
 250 
     | 
    
         
            +
                            data.lengthComputable = true;
         
     | 
| 
      
 251 
     | 
    
         
            +
                            data.loaded = loaded;
         
     | 
| 
      
 252 
     | 
    
         
            +
                            data.total = total;
         
     | 
| 
      
 253 
     | 
    
         
            +
                            data.bitrate = data._bitrateTimer.getBitrate(
         
     | 
| 
      
 254 
     | 
    
         
            +
                                now,
         
     | 
| 
      
 255 
     | 
    
         
            +
                                loaded,
         
     | 
| 
      
 256 
     | 
    
         
            +
                                data.bitrateInterval
         
     | 
| 
      
 257 
     | 
    
         
            +
                            );
         
     | 
| 
      
 258 
     | 
    
         
            +
                            // Trigger a custom progress event with a total data property set
         
     | 
| 
      
 259 
     | 
    
         
            +
                            // to the file size(s) of the current upload and a loaded data
         
     | 
| 
      
 260 
     | 
    
         
            +
                            // property calculated accordingly:
         
     | 
| 
      
 261 
     | 
    
         
            +
                            this._trigger('progress', e, data);
         
     | 
| 
      
 262 
     | 
    
         
            +
                            // Trigger a global progress event for all current file uploads,
         
     | 
| 
      
 263 
     | 
    
         
            +
                            // including ajax calls queued for sequential file uploads:
         
     | 
| 
      
 264 
     | 
    
         
            +
                            this._trigger('progressall', e, {
         
     | 
| 
      
 265 
     | 
    
         
            +
                                lengthComputable: true,
         
     | 
| 
      
 266 
     | 
    
         
            +
                                loaded: this._loaded,
         
     | 
| 
      
 267 
     | 
    
         
            +
                                total: this._total,
         
     | 
| 
      
 268 
     | 
    
         
            +
                                bitrate: this._bitrateTimer.getBitrate(
         
     | 
| 
      
 269 
     | 
    
         
            +
                                    now,
         
     | 
| 
      
 270 
     | 
    
         
            +
                                    this._loaded,
         
     | 
| 
      
 271 
     | 
    
         
            +
                                    data.bitrateInterval
         
     | 
| 
      
 272 
     | 
    
         
            +
                                )
         
     | 
| 
      
 273 
     | 
    
         
            +
                            });
         
     | 
| 
      
 274 
     | 
    
         
            +
                        }
         
     | 
| 
      
 275 
     | 
    
         
            +
                    },
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
                    _initProgressListener: function (options) {
         
     | 
| 
      
 278 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 279 
     | 
    
         
            +
                            xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
         
     | 
| 
      
 280 
     | 
    
         
            +
                        // Accesss to the native XHR object is required to add event listeners
         
     | 
| 
      
 281 
     | 
    
         
            +
                        // for the upload progress event:
         
     | 
| 
      
 282 
     | 
    
         
            +
                        if (xhr.upload) {
         
     | 
| 
      
 283 
     | 
    
         
            +
                            $(xhr.upload).bind('progress', function (e) {
         
     | 
| 
      
 284 
     | 
    
         
            +
                                var oe = e.originalEvent;
         
     | 
| 
      
 285 
     | 
    
         
            +
                                // Make sure the progress event properties get copied over:
         
     | 
| 
      
 286 
     | 
    
         
            +
                                e.lengthComputable = oe.lengthComputable;
         
     | 
| 
      
 287 
     | 
    
         
            +
                                e.loaded = oe.loaded;
         
     | 
| 
      
 288 
     | 
    
         
            +
                                e.total = oe.total;
         
     | 
| 
      
 289 
     | 
    
         
            +
                                that._onProgress(e, options);
         
     | 
| 
      
 290 
     | 
    
         
            +
                            });
         
     | 
| 
      
 291 
     | 
    
         
            +
                            options.xhr = function () {
         
     | 
| 
      
 292 
     | 
    
         
            +
                                return xhr;
         
     | 
| 
      
 293 
     | 
    
         
            +
                            };
         
     | 
| 
      
 294 
     | 
    
         
            +
                        }
         
     | 
| 
      
 295 
     | 
    
         
            +
                    },
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                    _initXHRData: function (options) {
         
     | 
| 
      
 298 
     | 
    
         
            +
                        var formData,
         
     | 
| 
      
 299 
     | 
    
         
            +
                            file = options.files[0],
         
     | 
| 
      
 300 
     | 
    
         
            +
                            // Ignore non-multipart setting if not supported:
         
     | 
| 
      
 301 
     | 
    
         
            +
                            multipart = options.multipart || !$.support.xhrFileUpload,
         
     | 
| 
      
 302 
     | 
    
         
            +
                            paramName = options.paramName[0];
         
     | 
| 
      
 303 
     | 
    
         
            +
                        options.headers = options.headers || {};
         
     | 
| 
      
 304 
     | 
    
         
            +
                        if (options.contentRange) {
         
     | 
| 
      
 305 
     | 
    
         
            +
                            options.headers['Content-Range'] = options.contentRange;
         
     | 
| 
      
 306 
     | 
    
         
            +
                        }
         
     | 
| 
      
 307 
     | 
    
         
            +
                        if (!multipart) {
         
     | 
| 
      
 308 
     | 
    
         
            +
                            // For cross domain requests, the X-File-Name header
         
     | 
| 
      
 309 
     | 
    
         
            +
                            // must be allowed via Access-Control-Allow-Headers
         
     | 
| 
      
 310 
     | 
    
         
            +
                            // or removed using the beforeSend callback:
         
     | 
| 
      
 311 
     | 
    
         
            +
                            options.headers['X-File-Name'] = file.name;
         
     | 
| 
      
 312 
     | 
    
         
            +
                            options.contentType = file.type;
         
     | 
| 
      
 313 
     | 
    
         
            +
                            options.data = options.blob || file;
         
     | 
| 
      
 314 
     | 
    
         
            +
                        } else if ($.support.xhrFormDataFileUpload) {
         
     | 
| 
      
 315 
     | 
    
         
            +
                            if (options.postMessage) {
         
     | 
| 
      
 316 
     | 
    
         
            +
                                // window.postMessage does not allow sending FormData
         
     | 
| 
      
 317 
     | 
    
         
            +
                                // objects, so we just add the File/Blob objects to
         
     | 
| 
      
 318 
     | 
    
         
            +
                                // the formData array and let the postMessage window
         
     | 
| 
      
 319 
     | 
    
         
            +
                                // create the FormData object out of this array:
         
     | 
| 
      
 320 
     | 
    
         
            +
                                formData = this._getFormData(options);
         
     | 
| 
      
 321 
     | 
    
         
            +
                                if (options.blob) {
         
     | 
| 
      
 322 
     | 
    
         
            +
                                    formData.push({
         
     | 
| 
      
 323 
     | 
    
         
            +
                                        name: paramName,
         
     | 
| 
      
 324 
     | 
    
         
            +
                                        value: options.blob
         
     | 
| 
      
 325 
     | 
    
         
            +
                                    });
         
     | 
| 
      
 326 
     | 
    
         
            +
                                } else {
         
     | 
| 
      
 327 
     | 
    
         
            +
                                    $.each(options.files, function (index, file) {
         
     | 
| 
      
 328 
     | 
    
         
            +
                                        formData.push({
         
     | 
| 
      
 329 
     | 
    
         
            +
                                            name: options.paramName[index] || paramName,
         
     | 
| 
      
 330 
     | 
    
         
            +
                                            value: file
         
     | 
| 
      
 331 
     | 
    
         
            +
                                        });
         
     | 
| 
      
 332 
     | 
    
         
            +
                                    });
         
     | 
| 
      
 333 
     | 
    
         
            +
                                }
         
     | 
| 
      
 334 
     | 
    
         
            +
                            } else {
         
     | 
| 
      
 335 
     | 
    
         
            +
                                if (options.formData instanceof FormData) {
         
     | 
| 
      
 336 
     | 
    
         
            +
                                    formData = options.formData;
         
     | 
| 
      
 337 
     | 
    
         
            +
                                } else {
         
     | 
| 
      
 338 
     | 
    
         
            +
                                    formData = new FormData();
         
     | 
| 
      
 339 
     | 
    
         
            +
                                    $.each(this._getFormData(options), function (index, field) {
         
     | 
| 
      
 340 
     | 
    
         
            +
                                        formData.append(field.name, field.value);
         
     | 
| 
      
 341 
     | 
    
         
            +
                                    });
         
     | 
| 
      
 342 
     | 
    
         
            +
                                }
         
     | 
| 
      
 343 
     | 
    
         
            +
                                if (options.blob) {
         
     | 
| 
      
 344 
     | 
    
         
            +
                                    // For cross domain requests, the X-File-* headers
         
     | 
| 
      
 345 
     | 
    
         
            +
                                    // must be allowed via Access-Control-Allow-Headers
         
     | 
| 
      
 346 
     | 
    
         
            +
                                    // or removed using the beforeSend callback:
         
     | 
| 
      
 347 
     | 
    
         
            +
                                    options.headers['X-File-Name'] = file.name;
         
     | 
| 
      
 348 
     | 
    
         
            +
                                    options.headers['X-File-Type'] = file.type;
         
     | 
| 
      
 349 
     | 
    
         
            +
                                    formData.append(paramName, options.blob, file.name);
         
     | 
| 
      
 350 
     | 
    
         
            +
                                } else {
         
     | 
| 
      
 351 
     | 
    
         
            +
                                    $.each(options.files, function (index, file) {
         
     | 
| 
      
 352 
     | 
    
         
            +
                                        // File objects are also Blob instances.
         
     | 
| 
      
 353 
     | 
    
         
            +
                                        // This check allows the tests to run with
         
     | 
| 
      
 354 
     | 
    
         
            +
                                        // dummy objects:
         
     | 
| 
      
 355 
     | 
    
         
            +
                                        if (file instanceof Blob) {
         
     | 
| 
      
 356 
     | 
    
         
            +
                                            formData.append(
         
     | 
| 
      
 357 
     | 
    
         
            +
                                                options.paramName[index] || paramName,
         
     | 
| 
      
 358 
     | 
    
         
            +
                                                file,
         
     | 
| 
      
 359 
     | 
    
         
            +
                                                file.name
         
     | 
| 
      
 360 
     | 
    
         
            +
                                            );
         
     | 
| 
      
 361 
     | 
    
         
            +
                                        }
         
     | 
| 
      
 362 
     | 
    
         
            +
                                    });
         
     | 
| 
      
 363 
     | 
    
         
            +
                                }
         
     | 
| 
      
 364 
     | 
    
         
            +
                            }
         
     | 
| 
      
 365 
     | 
    
         
            +
                            options.data = formData;
         
     | 
| 
      
 366 
     | 
    
         
            +
                        }
         
     | 
| 
      
 367 
     | 
    
         
            +
                        // Blob reference is not needed anymore, free memory:
         
     | 
| 
      
 368 
     | 
    
         
            +
                        options.blob = null;
         
     | 
| 
      
 369 
     | 
    
         
            +
                    },
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
                    _initIframeSettings: function (options) {
         
     | 
| 
      
 372 
     | 
    
         
            +
                        // Setting the dataType to iframe enables the iframe transport:
         
     | 
| 
      
 373 
     | 
    
         
            +
                        options.dataType = 'iframe ' + (options.dataType || '');
         
     | 
| 
      
 374 
     | 
    
         
            +
                        // The iframe transport accepts a serialized array as form data:
         
     | 
| 
      
 375 
     | 
    
         
            +
                        options.formData = this._getFormData(options);
         
     | 
| 
      
 376 
     | 
    
         
            +
                        // Add redirect url to form data on cross-domain uploads:
         
     | 
| 
      
 377 
     | 
    
         
            +
                        if (options.redirect && $('<a></a>').prop('href', options.url)
         
     | 
| 
      
 378 
     | 
    
         
            +
                                .prop('host') !== location.host) {
         
     | 
| 
      
 379 
     | 
    
         
            +
                            options.formData.push({
         
     | 
| 
      
 380 
     | 
    
         
            +
                                name: options.redirectParamName || 'redirect',
         
     | 
| 
      
 381 
     | 
    
         
            +
                                value: options.redirect
         
     | 
| 
      
 382 
     | 
    
         
            +
                            });
         
     | 
| 
      
 383 
     | 
    
         
            +
                        }
         
     | 
| 
      
 384 
     | 
    
         
            +
                    },
         
     | 
| 
      
 385 
     | 
    
         
            +
             
     | 
| 
      
 386 
     | 
    
         
            +
                    _initDataSettings: function (options) {
         
     | 
| 
      
 387 
     | 
    
         
            +
                        if (this._isXHRUpload(options)) {
         
     | 
| 
      
 388 
     | 
    
         
            +
                            if (!this._chunkedUpload(options, true)) {
         
     | 
| 
      
 389 
     | 
    
         
            +
                                if (!options.data) {
         
     | 
| 
      
 390 
     | 
    
         
            +
                                    this._initXHRData(options);
         
     | 
| 
      
 391 
     | 
    
         
            +
                                }
         
     | 
| 
      
 392 
     | 
    
         
            +
                                this._initProgressListener(options);
         
     | 
| 
      
 393 
     | 
    
         
            +
                            }
         
     | 
| 
      
 394 
     | 
    
         
            +
                            if (options.postMessage) {
         
     | 
| 
      
 395 
     | 
    
         
            +
                                // Setting the dataType to postmessage enables the
         
     | 
| 
      
 396 
     | 
    
         
            +
                                // postMessage transport:
         
     | 
| 
      
 397 
     | 
    
         
            +
                                options.dataType = 'postmessage ' + (options.dataType || '');
         
     | 
| 
      
 398 
     | 
    
         
            +
                            }
         
     | 
| 
      
 399 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 400 
     | 
    
         
            +
                            this._initIframeSettings(options, 'iframe');
         
     | 
| 
      
 401 
     | 
    
         
            +
                        }
         
     | 
| 
      
 402 
     | 
    
         
            +
                    },
         
     | 
| 
      
 403 
     | 
    
         
            +
             
     | 
| 
      
 404 
     | 
    
         
            +
                    _getParamName: function (options) {
         
     | 
| 
      
 405 
     | 
    
         
            +
                        var fileInput = $(options.fileInput),
         
     | 
| 
      
 406 
     | 
    
         
            +
                            paramName = options.paramName;
         
     | 
| 
      
 407 
     | 
    
         
            +
                        if (!paramName) {
         
     | 
| 
      
 408 
     | 
    
         
            +
                            paramName = [];
         
     | 
| 
      
 409 
     | 
    
         
            +
                            fileInput.each(function () {
         
     | 
| 
      
 410 
     | 
    
         
            +
                                var input = $(this),
         
     | 
| 
      
 411 
     | 
    
         
            +
                                    name = input.prop('name') || 'files[]',
         
     | 
| 
      
 412 
     | 
    
         
            +
                                    i = (input.prop('files') || [1]).length;
         
     | 
| 
      
 413 
     | 
    
         
            +
                                while (i) {
         
     | 
| 
      
 414 
     | 
    
         
            +
                                    paramName.push(name);
         
     | 
| 
      
 415 
     | 
    
         
            +
                                    i -= 1;
         
     | 
| 
      
 416 
     | 
    
         
            +
                                }
         
     | 
| 
      
 417 
     | 
    
         
            +
                            });
         
     | 
| 
      
 418 
     | 
    
         
            +
                            if (!paramName.length) {
         
     | 
| 
      
 419 
     | 
    
         
            +
                                paramName = [fileInput.prop('name') || 'files[]'];
         
     | 
| 
      
 420 
     | 
    
         
            +
                            }
         
     | 
| 
      
 421 
     | 
    
         
            +
                        } else if (!$.isArray(paramName)) {
         
     | 
| 
      
 422 
     | 
    
         
            +
                            paramName = [paramName];
         
     | 
| 
      
 423 
     | 
    
         
            +
                        }
         
     | 
| 
      
 424 
     | 
    
         
            +
                        return paramName;
         
     | 
| 
      
 425 
     | 
    
         
            +
                    },
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
                    _initFormSettings: function (options) {
         
     | 
| 
      
 428 
     | 
    
         
            +
                        // Retrieve missing options from the input field and the
         
     | 
| 
      
 429 
     | 
    
         
            +
                        // associated form, if available:
         
     | 
| 
      
 430 
     | 
    
         
            +
                        if (!options.form || !options.form.length) {
         
     | 
| 
      
 431 
     | 
    
         
            +
                            options.form = $(options.fileInput.prop('form'));
         
     | 
| 
      
 432 
     | 
    
         
            +
                            // If the given file input doesn't have an associated form,
         
     | 
| 
      
 433 
     | 
    
         
            +
                            // use the default widget file input's form:
         
     | 
| 
      
 434 
     | 
    
         
            +
                            if (!options.form.length) {
         
     | 
| 
      
 435 
     | 
    
         
            +
                                options.form = $(this.options.fileInput.prop('form'));
         
     | 
| 
      
 436 
     | 
    
         
            +
                            }
         
     | 
| 
      
 437 
     | 
    
         
            +
                        }
         
     | 
| 
      
 438 
     | 
    
         
            +
                        options.paramName = this._getParamName(options);
         
     | 
| 
      
 439 
     | 
    
         
            +
                        if (!options.url) {
         
     | 
| 
      
 440 
     | 
    
         
            +
                            options.url = options.form.prop('action') || location.href;
         
     | 
| 
      
 441 
     | 
    
         
            +
                        }
         
     | 
| 
      
 442 
     | 
    
         
            +
                        // The HTTP request method must be "POST" or "PUT":
         
     | 
| 
      
 443 
     | 
    
         
            +
                        options.type = (options.type || options.form.prop('method') || '')
         
     | 
| 
      
 444 
     | 
    
         
            +
                            .toUpperCase();
         
     | 
| 
      
 445 
     | 
    
         
            +
                        if (options.type !== 'POST' && options.type !== 'PUT') {
         
     | 
| 
      
 446 
     | 
    
         
            +
                            options.type = 'POST';
         
     | 
| 
      
 447 
     | 
    
         
            +
                        }
         
     | 
| 
      
 448 
     | 
    
         
            +
                        if (!options.formAcceptCharset) {
         
     | 
| 
      
 449 
     | 
    
         
            +
                            options.formAcceptCharset = options.form.attr('accept-charset');
         
     | 
| 
      
 450 
     | 
    
         
            +
                        }
         
     | 
| 
      
 451 
     | 
    
         
            +
                    },
         
     | 
| 
      
 452 
     | 
    
         
            +
             
     | 
| 
      
 453 
     | 
    
         
            +
                    _getAJAXSettings: function (data) {
         
     | 
| 
      
 454 
     | 
    
         
            +
                        var options = $.extend({}, this.options, data);
         
     | 
| 
      
 455 
     | 
    
         
            +
                        this._initFormSettings(options);
         
     | 
| 
      
 456 
     | 
    
         
            +
                        this._initDataSettings(options);
         
     | 
| 
      
 457 
     | 
    
         
            +
                        return options;
         
     | 
| 
      
 458 
     | 
    
         
            +
                    },
         
     | 
| 
      
 459 
     | 
    
         
            +
             
     | 
| 
      
 460 
     | 
    
         
            +
                    // Maps jqXHR callbacks to the equivalent
         
     | 
| 
      
 461 
     | 
    
         
            +
                    // methods of the given Promise object:
         
     | 
| 
      
 462 
     | 
    
         
            +
                    _enhancePromise: function (promise) {
         
     | 
| 
      
 463 
     | 
    
         
            +
                        promise.success = promise.done;
         
     | 
| 
      
 464 
     | 
    
         
            +
                        promise.error = promise.fail;
         
     | 
| 
      
 465 
     | 
    
         
            +
                        promise.complete = promise.always;
         
     | 
| 
      
 466 
     | 
    
         
            +
                        return promise;
         
     | 
| 
      
 467 
     | 
    
         
            +
                    },
         
     | 
| 
      
 468 
     | 
    
         
            +
             
     | 
| 
      
 469 
     | 
    
         
            +
                    // Creates and returns a Promise object enhanced with
         
     | 
| 
      
 470 
     | 
    
         
            +
                    // the jqXHR methods abort, success, error and complete:
         
     | 
| 
      
 471 
     | 
    
         
            +
                    _getXHRPromise: function (resolveOrReject, context, args) {
         
     | 
| 
      
 472 
     | 
    
         
            +
                        var dfd = $.Deferred(),
         
     | 
| 
      
 473 
     | 
    
         
            +
                            promise = dfd.promise();
         
     | 
| 
      
 474 
     | 
    
         
            +
                        context = context || this.options.context || promise;
         
     | 
| 
      
 475 
     | 
    
         
            +
                        if (resolveOrReject === true) {
         
     | 
| 
      
 476 
     | 
    
         
            +
                            dfd.resolveWith(context, args);
         
     | 
| 
      
 477 
     | 
    
         
            +
                        } else if (resolveOrReject === false) {
         
     | 
| 
      
 478 
     | 
    
         
            +
                            dfd.rejectWith(context, args);
         
     | 
| 
      
 479 
     | 
    
         
            +
                        }
         
     | 
| 
      
 480 
     | 
    
         
            +
                        promise.abort = dfd.promise;
         
     | 
| 
      
 481 
     | 
    
         
            +
                        return this._enhancePromise(promise);
         
     | 
| 
      
 482 
     | 
    
         
            +
                    },
         
     | 
| 
      
 483 
     | 
    
         
            +
             
     | 
| 
      
 484 
     | 
    
         
            +
                    // Parses the Range header from the server response
         
     | 
| 
      
 485 
     | 
    
         
            +
                    // and returns the uploaded bytes:
         
     | 
| 
      
 486 
     | 
    
         
            +
                    _getUploadedBytes: function (jqXHR) {
         
     | 
| 
      
 487 
     | 
    
         
            +
                        var range = jqXHR.getResponseHeader('Range'),
         
     | 
| 
      
 488 
     | 
    
         
            +
                            parts = range && range.split('-'),
         
     | 
| 
      
 489 
     | 
    
         
            +
                            upperBytesPos = parts && parts.length > 1 &&
         
     | 
| 
      
 490 
     | 
    
         
            +
                                parseInt(parts[1], 10);
         
     | 
| 
      
 491 
     | 
    
         
            +
                        return upperBytesPos && upperBytesPos + 1;
         
     | 
| 
      
 492 
     | 
    
         
            +
                    },
         
     | 
| 
      
 493 
     | 
    
         
            +
             
     | 
| 
      
 494 
     | 
    
         
            +
                    // Uploads a file in multiple, sequential requests
         
     | 
| 
      
 495 
     | 
    
         
            +
                    // by splitting the file up in multiple blob chunks.
         
     | 
| 
      
 496 
     | 
    
         
            +
                    // If the second parameter is true, only tests if the file
         
     | 
| 
      
 497 
     | 
    
         
            +
                    // should be uploaded in chunks, but does not invoke any
         
     | 
| 
      
 498 
     | 
    
         
            +
                    // upload requests:
         
     | 
| 
      
 499 
     | 
    
         
            +
                    _chunkedUpload: function (options, testOnly) {
         
     | 
| 
      
 500 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 501 
     | 
    
         
            +
                            file = options.files[0],
         
     | 
| 
      
 502 
     | 
    
         
            +
                            fs = file.size,
         
     | 
| 
      
 503 
     | 
    
         
            +
                            ub = options.uploadedBytes = options.uploadedBytes || 0,
         
     | 
| 
      
 504 
     | 
    
         
            +
                            mcs = options.maxChunkSize || fs,
         
     | 
| 
      
 505 
     | 
    
         
            +
                            slice = file.slice || file.webkitSlice || file.mozSlice,
         
     | 
| 
      
 506 
     | 
    
         
            +
                            dfd = $.Deferred(),
         
     | 
| 
      
 507 
     | 
    
         
            +
                            promise = dfd.promise(),
         
     | 
| 
      
 508 
     | 
    
         
            +
                            jqXHR,
         
     | 
| 
      
 509 
     | 
    
         
            +
                            upload;
         
     | 
| 
      
 510 
     | 
    
         
            +
                        if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
         
     | 
| 
      
 511 
     | 
    
         
            +
                                options.data) {
         
     | 
| 
      
 512 
     | 
    
         
            +
                            return false;
         
     | 
| 
      
 513 
     | 
    
         
            +
                        }
         
     | 
| 
      
 514 
     | 
    
         
            +
                        if (testOnly) {
         
     | 
| 
      
 515 
     | 
    
         
            +
                            return true;
         
     | 
| 
      
 516 
     | 
    
         
            +
                        }
         
     | 
| 
      
 517 
     | 
    
         
            +
                        if (ub >= fs) {
         
     | 
| 
      
 518 
     | 
    
         
            +
                            file.error = 'Uploaded bytes exceed file size';
         
     | 
| 
      
 519 
     | 
    
         
            +
                            return this._getXHRPromise(
         
     | 
| 
      
 520 
     | 
    
         
            +
                                false,
         
     | 
| 
      
 521 
     | 
    
         
            +
                                options.context,
         
     | 
| 
      
 522 
     | 
    
         
            +
                                [null, 'error', file.error]
         
     | 
| 
      
 523 
     | 
    
         
            +
                            );
         
     | 
| 
      
 524 
     | 
    
         
            +
                        }
         
     | 
| 
      
 525 
     | 
    
         
            +
                        // The chunk upload method:
         
     | 
| 
      
 526 
     | 
    
         
            +
                        upload = function (i) {
         
     | 
| 
      
 527 
     | 
    
         
            +
                            // Clone the options object for each chunk upload:
         
     | 
| 
      
 528 
     | 
    
         
            +
                            var o = $.extend({}, options);
         
     | 
| 
      
 529 
     | 
    
         
            +
                            o.blob = slice.call(
         
     | 
| 
      
 530 
     | 
    
         
            +
                                file,
         
     | 
| 
      
 531 
     | 
    
         
            +
                                ub,
         
     | 
| 
      
 532 
     | 
    
         
            +
                                ub + mcs
         
     | 
| 
      
 533 
     | 
    
         
            +
                            );
         
     | 
| 
      
 534 
     | 
    
         
            +
                            // Store the current chunk size, as the blob itself
         
     | 
| 
      
 535 
     | 
    
         
            +
                            // will be dereferenced after data processing:
         
     | 
| 
      
 536 
     | 
    
         
            +
                            o.chunkSize = o.blob.size;
         
     | 
| 
      
 537 
     | 
    
         
            +
                            // Expose the chunk bytes position range:
         
     | 
| 
      
 538 
     | 
    
         
            +
                            o.contentRange = 'bytes ' + ub + '-' +
         
     | 
| 
      
 539 
     | 
    
         
            +
                                (ub + o.chunkSize - 1) + '/' + fs;
         
     | 
| 
      
 540 
     | 
    
         
            +
                            // Process the upload data (the blob and potential form data):
         
     | 
| 
      
 541 
     | 
    
         
            +
                            that._initXHRData(o);
         
     | 
| 
      
 542 
     | 
    
         
            +
                            // Add progress listeners for this chunk upload:
         
     | 
| 
      
 543 
     | 
    
         
            +
                            that._initProgressListener(o);
         
     | 
| 
      
 544 
     | 
    
         
            +
                            jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context))
         
     | 
| 
      
 545 
     | 
    
         
            +
                                .done(function (result, textStatus, jqXHR) {
         
     | 
| 
      
 546 
     | 
    
         
            +
                                    ub = that._getUploadedBytes(jqXHR) ||
         
     | 
| 
      
 547 
     | 
    
         
            +
                                        (ub + o.chunkSize);
         
     | 
| 
      
 548 
     | 
    
         
            +
                                    // Create a progress event if upload is done and
         
     | 
| 
      
 549 
     | 
    
         
            +
                                    // no progress event has been invoked for this chunk:
         
     | 
| 
      
 550 
     | 
    
         
            +
                                    if (!o.loaded) {
         
     | 
| 
      
 551 
     | 
    
         
            +
                                        that._onProgress($.Event('progress', {
         
     | 
| 
      
 552 
     | 
    
         
            +
                                            lengthComputable: true,
         
     | 
| 
      
 553 
     | 
    
         
            +
                                            loaded: ub - o.uploadedBytes,
         
     | 
| 
      
 554 
     | 
    
         
            +
                                            total: ub - o.uploadedBytes
         
     | 
| 
      
 555 
     | 
    
         
            +
                                        }), o);
         
     | 
| 
      
 556 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 557 
     | 
    
         
            +
                                    options.uploadedBytes = o.uploadedBytes = ub;
         
     | 
| 
      
 558 
     | 
    
         
            +
                                    if (ub < fs) {
         
     | 
| 
      
 559 
     | 
    
         
            +
                                        // File upload not yet complete,
         
     | 
| 
      
 560 
     | 
    
         
            +
                                        // continue with the next chunk:
         
     | 
| 
      
 561 
     | 
    
         
            +
                                        upload();
         
     | 
| 
      
 562 
     | 
    
         
            +
                                    } else {
         
     | 
| 
      
 563 
     | 
    
         
            +
                                        dfd.resolveWith(
         
     | 
| 
      
 564 
     | 
    
         
            +
                                            o.context,
         
     | 
| 
      
 565 
     | 
    
         
            +
                                            [result, textStatus, jqXHR]
         
     | 
| 
      
 566 
     | 
    
         
            +
                                        );
         
     | 
| 
      
 567 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 568 
     | 
    
         
            +
                                })
         
     | 
| 
      
 569 
     | 
    
         
            +
                                .fail(function (jqXHR, textStatus, errorThrown) {
         
     | 
| 
      
 570 
     | 
    
         
            +
                                    dfd.rejectWith(
         
     | 
| 
      
 571 
     | 
    
         
            +
                                        o.context,
         
     | 
| 
      
 572 
     | 
    
         
            +
                                        [jqXHR, textStatus, errorThrown]
         
     | 
| 
      
 573 
     | 
    
         
            +
                                    );
         
     | 
| 
      
 574 
     | 
    
         
            +
                                });
         
     | 
| 
      
 575 
     | 
    
         
            +
                        };
         
     | 
| 
      
 576 
     | 
    
         
            +
                        this._enhancePromise(promise);
         
     | 
| 
      
 577 
     | 
    
         
            +
                        promise.abort = function () {
         
     | 
| 
      
 578 
     | 
    
         
            +
                            return jqXHR.abort();
         
     | 
| 
      
 579 
     | 
    
         
            +
                        };
         
     | 
| 
      
 580 
     | 
    
         
            +
                        upload();
         
     | 
| 
      
 581 
     | 
    
         
            +
                        return promise;
         
     | 
| 
      
 582 
     | 
    
         
            +
                    },
         
     | 
| 
      
 583 
     | 
    
         
            +
             
     | 
| 
      
 584 
     | 
    
         
            +
                    _beforeSend: function (e, data) {
         
     | 
| 
      
 585 
     | 
    
         
            +
                        if (this._active === 0) {
         
     | 
| 
      
 586 
     | 
    
         
            +
                            // the start callback is triggered when an upload starts
         
     | 
| 
      
 587 
     | 
    
         
            +
                            // and no other uploads are currently running,
         
     | 
| 
      
 588 
     | 
    
         
            +
                            // equivalent to the global ajaxStart event:
         
     | 
| 
      
 589 
     | 
    
         
            +
                            this._trigger('start');
         
     | 
| 
      
 590 
     | 
    
         
            +
                            // Set timer for global bitrate progress calculation:
         
     | 
| 
      
 591 
     | 
    
         
            +
                            this._bitrateTimer = new this._BitrateTimer();
         
     | 
| 
      
 592 
     | 
    
         
            +
                        }
         
     | 
| 
      
 593 
     | 
    
         
            +
                        this._active += 1;
         
     | 
| 
      
 594 
     | 
    
         
            +
                        // Initialize the global progress values:
         
     | 
| 
      
 595 
     | 
    
         
            +
                        this._loaded += data.uploadedBytes || 0;
         
     | 
| 
      
 596 
     | 
    
         
            +
                        this._total += this._getTotal(data.files);
         
     | 
| 
      
 597 
     | 
    
         
            +
                    },
         
     | 
| 
      
 598 
     | 
    
         
            +
             
     | 
| 
      
 599 
     | 
    
         
            +
                    _onDone: function (result, textStatus, jqXHR, options) {
         
     | 
| 
      
 600 
     | 
    
         
            +
                        if (!this._isXHRUpload(options)) {
         
     | 
| 
      
 601 
     | 
    
         
            +
                            // Create a progress event for each iframe load:
         
     | 
| 
      
 602 
     | 
    
         
            +
                            this._onProgress($.Event('progress', {
         
     | 
| 
      
 603 
     | 
    
         
            +
                                lengthComputable: true,
         
     | 
| 
      
 604 
     | 
    
         
            +
                                loaded: 1,
         
     | 
| 
      
 605 
     | 
    
         
            +
                                total: 1
         
     | 
| 
      
 606 
     | 
    
         
            +
                            }), options);
         
     | 
| 
      
 607 
     | 
    
         
            +
                        }
         
     | 
| 
      
 608 
     | 
    
         
            +
                        options.result = result;
         
     | 
| 
      
 609 
     | 
    
         
            +
                        options.textStatus = textStatus;
         
     | 
| 
      
 610 
     | 
    
         
            +
                        options.jqXHR = jqXHR;
         
     | 
| 
      
 611 
     | 
    
         
            +
                        this._trigger('done', null, options);
         
     | 
| 
      
 612 
     | 
    
         
            +
                    },
         
     | 
| 
      
 613 
     | 
    
         
            +
             
     | 
| 
      
 614 
     | 
    
         
            +
                    _onFail: function (jqXHR, textStatus, errorThrown, options) {
         
     | 
| 
      
 615 
     | 
    
         
            +
                        options.jqXHR = jqXHR;
         
     | 
| 
      
 616 
     | 
    
         
            +
                        options.textStatus = textStatus;
         
     | 
| 
      
 617 
     | 
    
         
            +
                        options.errorThrown = errorThrown;
         
     | 
| 
      
 618 
     | 
    
         
            +
                        this._trigger('fail', null, options);
         
     | 
| 
      
 619 
     | 
    
         
            +
                        if (options.recalculateProgress) {
         
     | 
| 
      
 620 
     | 
    
         
            +
                            // Remove the failed (error or abort) file upload from
         
     | 
| 
      
 621 
     | 
    
         
            +
                            // the global progress calculation:
         
     | 
| 
      
 622 
     | 
    
         
            +
                            this._loaded -= options.loaded || options.uploadedBytes || 0;
         
     | 
| 
      
 623 
     | 
    
         
            +
                            this._total -= options.total || this._getTotal(options.files);
         
     | 
| 
      
 624 
     | 
    
         
            +
                        }
         
     | 
| 
      
 625 
     | 
    
         
            +
                    },
         
     | 
| 
      
 626 
     | 
    
         
            +
             
     | 
| 
      
 627 
     | 
    
         
            +
                    _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
         
     | 
| 
      
 628 
     | 
    
         
            +
                        this._active -= 1;
         
     | 
| 
      
 629 
     | 
    
         
            +
                        options.textStatus = textStatus;
         
     | 
| 
      
 630 
     | 
    
         
            +
                        if (jqXHRorError && jqXHRorError.always) {
         
     | 
| 
      
 631 
     | 
    
         
            +
                            options.jqXHR = jqXHRorError;
         
     | 
| 
      
 632 
     | 
    
         
            +
                            options.result = jqXHRorResult;
         
     | 
| 
      
 633 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 634 
     | 
    
         
            +
                            options.jqXHR = jqXHRorResult;
         
     | 
| 
      
 635 
     | 
    
         
            +
                            options.errorThrown = jqXHRorError;
         
     | 
| 
      
 636 
     | 
    
         
            +
                        }
         
     | 
| 
      
 637 
     | 
    
         
            +
                        this._trigger('always', null, options);
         
     | 
| 
      
 638 
     | 
    
         
            +
                        if (this._active === 0) {
         
     | 
| 
      
 639 
     | 
    
         
            +
                            // The stop callback is triggered when all uploads have
         
     | 
| 
      
 640 
     | 
    
         
            +
                            // been completed, equivalent to the global ajaxStop event:
         
     | 
| 
      
 641 
     | 
    
         
            +
                            this._trigger('stop');
         
     | 
| 
      
 642 
     | 
    
         
            +
                            // Reset the global progress values:
         
     | 
| 
      
 643 
     | 
    
         
            +
                            this._loaded = this._total = 0;
         
     | 
| 
      
 644 
     | 
    
         
            +
                            this._bitrateTimer = null;
         
     | 
| 
      
 645 
     | 
    
         
            +
                        }
         
     | 
| 
      
 646 
     | 
    
         
            +
                    },
         
     | 
| 
      
 647 
     | 
    
         
            +
             
     | 
| 
      
 648 
     | 
    
         
            +
                    _onSend: function (e, data) {
         
     | 
| 
      
 649 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 650 
     | 
    
         
            +
                            jqXHR,
         
     | 
| 
      
 651 
     | 
    
         
            +
                            slot,
         
     | 
| 
      
 652 
     | 
    
         
            +
                            pipe,
         
     | 
| 
      
 653 
     | 
    
         
            +
                            options = that._getAJAXSettings(data),
         
     | 
| 
      
 654 
     | 
    
         
            +
                            send = function (resolve, args) {
         
     | 
| 
      
 655 
     | 
    
         
            +
                                that._sending += 1;
         
     | 
| 
      
 656 
     | 
    
         
            +
                                // Set timer for bitrate progress calculation:
         
     | 
| 
      
 657 
     | 
    
         
            +
                                options._bitrateTimer = new that._BitrateTimer();
         
     | 
| 
      
 658 
     | 
    
         
            +
                                jqXHR = jqXHR || (
         
     | 
| 
      
 659 
     | 
    
         
            +
                                    (resolve !== false &&
         
     | 
| 
      
 660 
     | 
    
         
            +
                                    that._trigger('send', e, options) !== false &&
         
     | 
| 
      
 661 
     | 
    
         
            +
                                    (that._chunkedUpload(options) || $.ajax(options))) ||
         
     | 
| 
      
 662 
     | 
    
         
            +
                                    that._getXHRPromise(false, options.context, args)
         
     | 
| 
      
 663 
     | 
    
         
            +
                                ).done(function (result, textStatus, jqXHR) {
         
     | 
| 
      
 664 
     | 
    
         
            +
                                    that._onDone(result, textStatus, jqXHR, options);
         
     | 
| 
      
 665 
     | 
    
         
            +
                                }).fail(function (jqXHR, textStatus, errorThrown) {
         
     | 
| 
      
 666 
     | 
    
         
            +
                                    that._onFail(jqXHR, textStatus, errorThrown, options);
         
     | 
| 
      
 667 
     | 
    
         
            +
                                }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
         
     | 
| 
      
 668 
     | 
    
         
            +
                                    that._sending -= 1;
         
     | 
| 
      
 669 
     | 
    
         
            +
                                    that._onAlways(
         
     | 
| 
      
 670 
     | 
    
         
            +
                                        jqXHRorResult,
         
     | 
| 
      
 671 
     | 
    
         
            +
                                        textStatus,
         
     | 
| 
      
 672 
     | 
    
         
            +
                                        jqXHRorError,
         
     | 
| 
      
 673 
     | 
    
         
            +
                                        options
         
     | 
| 
      
 674 
     | 
    
         
            +
                                    );
         
     | 
| 
      
 675 
     | 
    
         
            +
                                    if (options.limitConcurrentUploads &&
         
     | 
| 
      
 676 
     | 
    
         
            +
                                            options.limitConcurrentUploads > that._sending) {
         
     | 
| 
      
 677 
     | 
    
         
            +
                                        // Start the next queued upload,
         
     | 
| 
      
 678 
     | 
    
         
            +
                                        // that has not been aborted:
         
     | 
| 
      
 679 
     | 
    
         
            +
                                        var nextSlot = that._slots.shift(),
         
     | 
| 
      
 680 
     | 
    
         
            +
                                            isPending;
         
     | 
| 
      
 681 
     | 
    
         
            +
                                        while (nextSlot) {
         
     | 
| 
      
 682 
     | 
    
         
            +
                                            // jQuery 1.6 doesn't provide .state(),
         
     | 
| 
      
 683 
     | 
    
         
            +
                                            // while jQuery 1.8+ removed .isRejected():
         
     | 
| 
      
 684 
     | 
    
         
            +
                                            isPending = nextSlot.state ?
         
     | 
| 
      
 685 
     | 
    
         
            +
                                                    nextSlot.state() === 'pending' :
         
     | 
| 
      
 686 
     | 
    
         
            +
                                                    !nextSlot.isRejected();
         
     | 
| 
      
 687 
     | 
    
         
            +
                                            if (isPending) {
         
     | 
| 
      
 688 
     | 
    
         
            +
                                                nextSlot.resolve();
         
     | 
| 
      
 689 
     | 
    
         
            +
                                                break;
         
     | 
| 
      
 690 
     | 
    
         
            +
                                            }
         
     | 
| 
      
 691 
     | 
    
         
            +
                                            nextSlot = that._slots.shift();
         
     | 
| 
      
 692 
     | 
    
         
            +
                                        }
         
     | 
| 
      
 693 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 694 
     | 
    
         
            +
                                });
         
     | 
| 
      
 695 
     | 
    
         
            +
                                return jqXHR;
         
     | 
| 
      
 696 
     | 
    
         
            +
                            };
         
     | 
| 
      
 697 
     | 
    
         
            +
                        this._beforeSend(e, options);
         
     | 
| 
      
 698 
     | 
    
         
            +
                        if (this.options.sequentialUploads ||
         
     | 
| 
      
 699 
     | 
    
         
            +
                                (this.options.limitConcurrentUploads &&
         
     | 
| 
      
 700 
     | 
    
         
            +
                                this.options.limitConcurrentUploads <= this._sending)) {
         
     | 
| 
      
 701 
     | 
    
         
            +
                            if (this.options.limitConcurrentUploads > 1) {
         
     | 
| 
      
 702 
     | 
    
         
            +
                                slot = $.Deferred();
         
     | 
| 
      
 703 
     | 
    
         
            +
                                this._slots.push(slot);
         
     | 
| 
      
 704 
     | 
    
         
            +
                                pipe = slot.pipe(send);
         
     | 
| 
      
 705 
     | 
    
         
            +
                            } else {
         
     | 
| 
      
 706 
     | 
    
         
            +
                                pipe = (this._sequence = this._sequence.pipe(send, send));
         
     | 
| 
      
 707 
     | 
    
         
            +
                            }
         
     | 
| 
      
 708 
     | 
    
         
            +
                            // Return the piped Promise object, enhanced with an abort method,
         
     | 
| 
      
 709 
     | 
    
         
            +
                            // which is delegated to the jqXHR object of the current upload,
         
     | 
| 
      
 710 
     | 
    
         
            +
                            // and jqXHR callbacks mapped to the equivalent Promise methods:
         
     | 
| 
      
 711 
     | 
    
         
            +
                            pipe.abort = function () {
         
     | 
| 
      
 712 
     | 
    
         
            +
                                var args = [undefined, 'abort', 'abort'];
         
     | 
| 
      
 713 
     | 
    
         
            +
                                if (!jqXHR) {
         
     | 
| 
      
 714 
     | 
    
         
            +
                                    if (slot) {
         
     | 
| 
      
 715 
     | 
    
         
            +
                                        slot.rejectWith(pipe, args);
         
     | 
| 
      
 716 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 717 
     | 
    
         
            +
                                    return send(false, args);
         
     | 
| 
      
 718 
     | 
    
         
            +
                                }
         
     | 
| 
      
 719 
     | 
    
         
            +
                                return jqXHR.abort();
         
     | 
| 
      
 720 
     | 
    
         
            +
                            };
         
     | 
| 
      
 721 
     | 
    
         
            +
                            return this._enhancePromise(pipe);
         
     | 
| 
      
 722 
     | 
    
         
            +
                        }
         
     | 
| 
      
 723 
     | 
    
         
            +
                        return send();
         
     | 
| 
      
 724 
     | 
    
         
            +
                    },
         
     | 
| 
      
 725 
     | 
    
         
            +
             
     | 
| 
      
 726 
     | 
    
         
            +
                    _onAdd: function (e, data) {
         
     | 
| 
      
 727 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 728 
     | 
    
         
            +
                            result = true,
         
     | 
| 
      
 729 
     | 
    
         
            +
                            options = $.extend({}, this.options, data),
         
     | 
| 
      
 730 
     | 
    
         
            +
                            limit = options.limitMultiFileUploads,
         
     | 
| 
      
 731 
     | 
    
         
            +
                            paramName = this._getParamName(options),
         
     | 
| 
      
 732 
     | 
    
         
            +
                            paramNameSet,
         
     | 
| 
      
 733 
     | 
    
         
            +
                            paramNameSlice,
         
     | 
| 
      
 734 
     | 
    
         
            +
                            fileSet,
         
     | 
| 
      
 735 
     | 
    
         
            +
                            i;
         
     | 
| 
      
 736 
     | 
    
         
            +
                        if (!(options.singleFileUploads || limit) ||
         
     | 
| 
      
 737 
     | 
    
         
            +
                                !this._isXHRUpload(options)) {
         
     | 
| 
      
 738 
     | 
    
         
            +
                            fileSet = [data.files];
         
     | 
| 
      
 739 
     | 
    
         
            +
                            paramNameSet = [paramName];
         
     | 
| 
      
 740 
     | 
    
         
            +
                        } else if (!options.singleFileUploads && limit) {
         
     | 
| 
      
 741 
     | 
    
         
            +
                            fileSet = [];
         
     | 
| 
      
 742 
     | 
    
         
            +
                            paramNameSet = [];
         
     | 
| 
      
 743 
     | 
    
         
            +
                            for (i = 0; i < data.files.length; i += limit) {
         
     | 
| 
      
 744 
     | 
    
         
            +
                                fileSet.push(data.files.slice(i, i + limit));
         
     | 
| 
      
 745 
     | 
    
         
            +
                                paramNameSlice = paramName.slice(i, i + limit);
         
     | 
| 
      
 746 
     | 
    
         
            +
                                if (!paramNameSlice.length) {
         
     | 
| 
      
 747 
     | 
    
         
            +
                                    paramNameSlice = paramName;
         
     | 
| 
      
 748 
     | 
    
         
            +
                                }
         
     | 
| 
      
 749 
     | 
    
         
            +
                                paramNameSet.push(paramNameSlice);
         
     | 
| 
      
 750 
     | 
    
         
            +
                            }
         
     | 
| 
      
 751 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 752 
     | 
    
         
            +
                            paramNameSet = paramName;
         
     | 
| 
      
 753 
     | 
    
         
            +
                        }
         
     | 
| 
      
 754 
     | 
    
         
            +
                        data.originalFiles = data.files;
         
     | 
| 
      
 755 
     | 
    
         
            +
                        $.each(fileSet || data.files, function (index, element) {
         
     | 
| 
      
 756 
     | 
    
         
            +
                            var newData = $.extend({}, data);
         
     | 
| 
      
 757 
     | 
    
         
            +
                            newData.files = fileSet ? element : [element];
         
     | 
| 
      
 758 
     | 
    
         
            +
                            newData.paramName = paramNameSet[index];
         
     | 
| 
      
 759 
     | 
    
         
            +
                            newData.submit = function () {
         
     | 
| 
      
 760 
     | 
    
         
            +
                                newData.jqXHR = this.jqXHR =
         
     | 
| 
      
 761 
     | 
    
         
            +
                                    (that._trigger('submit', e, this) !== false) &&
         
     | 
| 
      
 762 
     | 
    
         
            +
                                    that._onSend(e, this);
         
     | 
| 
      
 763 
     | 
    
         
            +
                                return this.jqXHR;
         
     | 
| 
      
 764 
     | 
    
         
            +
                            };
         
     | 
| 
      
 765 
     | 
    
         
            +
                            return (result = that._trigger('add', e, newData));
         
     | 
| 
      
 766 
     | 
    
         
            +
                        });
         
     | 
| 
      
 767 
     | 
    
         
            +
                        return result;
         
     | 
| 
      
 768 
     | 
    
         
            +
                    },
         
     | 
| 
      
 769 
     | 
    
         
            +
             
     | 
| 
      
 770 
     | 
    
         
            +
                    _replaceFileInput: function (input) {
         
     | 
| 
      
 771 
     | 
    
         
            +
                        var inputClone = input.clone(true);
         
     | 
| 
      
 772 
     | 
    
         
            +
                        $('<form></form>').append(inputClone)[0].reset();
         
     | 
| 
      
 773 
     | 
    
         
            +
                        // Detaching allows to insert the fileInput on another form
         
     | 
| 
      
 774 
     | 
    
         
            +
                        // without loosing the file input value:
         
     | 
| 
      
 775 
     | 
    
         
            +
                        input.after(inputClone).detach();
         
     | 
| 
      
 776 
     | 
    
         
            +
                        // Avoid memory leaks with the detached file input:
         
     | 
| 
      
 777 
     | 
    
         
            +
                        $.cleanData(input.unbind('remove'));
         
     | 
| 
      
 778 
     | 
    
         
            +
                        // Replace the original file input element in the fileInput
         
     | 
| 
      
 779 
     | 
    
         
            +
                        // elements set with the clone, which has been copied including
         
     | 
| 
      
 780 
     | 
    
         
            +
                        // event handlers:
         
     | 
| 
      
 781 
     | 
    
         
            +
                        this.options.fileInput = this.options.fileInput.map(function (i, el) {
         
     | 
| 
      
 782 
     | 
    
         
            +
                            if (el === input[0]) {
         
     | 
| 
      
 783 
     | 
    
         
            +
                                return inputClone[0];
         
     | 
| 
      
 784 
     | 
    
         
            +
                            }
         
     | 
| 
      
 785 
     | 
    
         
            +
                            return el;
         
     | 
| 
      
 786 
     | 
    
         
            +
                        });
         
     | 
| 
      
 787 
     | 
    
         
            +
                        // If the widget has been initialized on the file input itself,
         
     | 
| 
      
 788 
     | 
    
         
            +
                        // override this.element with the file input clone:
         
     | 
| 
      
 789 
     | 
    
         
            +
                        if (input[0] === this.element[0]) {
         
     | 
| 
      
 790 
     | 
    
         
            +
                            this.element = inputClone;
         
     | 
| 
      
 791 
     | 
    
         
            +
                        }
         
     | 
| 
      
 792 
     | 
    
         
            +
                    },
         
     | 
| 
      
 793 
     | 
    
         
            +
             
     | 
| 
      
 794 
     | 
    
         
            +
                    _handleFileTreeEntry: function (entry, path) {
         
     | 
| 
      
 795 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 796 
     | 
    
         
            +
                            dfd = $.Deferred(),
         
     | 
| 
      
 797 
     | 
    
         
            +
                            errorHandler = function (e) {
         
     | 
| 
      
 798 
     | 
    
         
            +
                                if (e && !e.entry) {
         
     | 
| 
      
 799 
     | 
    
         
            +
                                    e.entry = entry;
         
     | 
| 
      
 800 
     | 
    
         
            +
                                }
         
     | 
| 
      
 801 
     | 
    
         
            +
                                // Since $.when returns immediately if one
         
     | 
| 
      
 802 
     | 
    
         
            +
                                // Deferred is rejected, we use resolve instead.
         
     | 
| 
      
 803 
     | 
    
         
            +
                                // This allows valid files and invalid items
         
     | 
| 
      
 804 
     | 
    
         
            +
                                // to be returned together in one set:
         
     | 
| 
      
 805 
     | 
    
         
            +
                                dfd.resolve([e]);
         
     | 
| 
      
 806 
     | 
    
         
            +
                            },
         
     | 
| 
      
 807 
     | 
    
         
            +
                            dirReader;
         
     | 
| 
      
 808 
     | 
    
         
            +
                        path = path || '';
         
     | 
| 
      
 809 
     | 
    
         
            +
                        if (entry.isFile) {
         
     | 
| 
      
 810 
     | 
    
         
            +
                            if (entry._file) {
         
     | 
| 
      
 811 
     | 
    
         
            +
                                // Workaround for Chrome bug #149735
         
     | 
| 
      
 812 
     | 
    
         
            +
                                entry._file.relativePath = path;
         
     | 
| 
      
 813 
     | 
    
         
            +
                                dfd.resolve(entry._file);
         
     | 
| 
      
 814 
     | 
    
         
            +
                            } else {
         
     | 
| 
      
 815 
     | 
    
         
            +
                                entry.file(function (file) {
         
     | 
| 
      
 816 
     | 
    
         
            +
                                    file.relativePath = path;
         
     | 
| 
      
 817 
     | 
    
         
            +
                                    dfd.resolve(file);
         
     | 
| 
      
 818 
     | 
    
         
            +
                                }, errorHandler);
         
     | 
| 
      
 819 
     | 
    
         
            +
                            }
         
     | 
| 
      
 820 
     | 
    
         
            +
                        } else if (entry.isDirectory) {
         
     | 
| 
      
 821 
     | 
    
         
            +
                            dirReader = entry.createReader();
         
     | 
| 
      
 822 
     | 
    
         
            +
                            dirReader.readEntries(function (entries) {
         
     | 
| 
      
 823 
     | 
    
         
            +
                                that._handleFileTreeEntries(
         
     | 
| 
      
 824 
     | 
    
         
            +
                                    entries,
         
     | 
| 
      
 825 
     | 
    
         
            +
                                    path + entry.name + '/'
         
     | 
| 
      
 826 
     | 
    
         
            +
                                ).done(function (files) {
         
     | 
| 
      
 827 
     | 
    
         
            +
                                    dfd.resolve(files);
         
     | 
| 
      
 828 
     | 
    
         
            +
                                }).fail(errorHandler);
         
     | 
| 
      
 829 
     | 
    
         
            +
                            }, errorHandler);
         
     | 
| 
      
 830 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 831 
     | 
    
         
            +
                            // Return an empy list for file system items
         
     | 
| 
      
 832 
     | 
    
         
            +
                            // other than files or directories:
         
     | 
| 
      
 833 
     | 
    
         
            +
                            dfd.resolve([]);
         
     | 
| 
      
 834 
     | 
    
         
            +
                        }
         
     | 
| 
      
 835 
     | 
    
         
            +
                        return dfd.promise();
         
     | 
| 
      
 836 
     | 
    
         
            +
                    },
         
     | 
| 
      
 837 
     | 
    
         
            +
             
     | 
| 
      
 838 
     | 
    
         
            +
                    _handleFileTreeEntries: function (entries, path) {
         
     | 
| 
      
 839 
     | 
    
         
            +
                        var that = this;
         
     | 
| 
      
 840 
     | 
    
         
            +
                        return $.when.apply(
         
     | 
| 
      
 841 
     | 
    
         
            +
                            $,
         
     | 
| 
      
 842 
     | 
    
         
            +
                            $.map(entries, function (entry) {
         
     | 
| 
      
 843 
     | 
    
         
            +
                                return that._handleFileTreeEntry(entry, path);
         
     | 
| 
      
 844 
     | 
    
         
            +
                            })
         
     | 
| 
      
 845 
     | 
    
         
            +
                        ).pipe(function () {
         
     | 
| 
      
 846 
     | 
    
         
            +
                            return Array.prototype.concat.apply(
         
     | 
| 
      
 847 
     | 
    
         
            +
                                [],
         
     | 
| 
      
 848 
     | 
    
         
            +
                                arguments
         
     | 
| 
      
 849 
     | 
    
         
            +
                            );
         
     | 
| 
      
 850 
     | 
    
         
            +
                        });
         
     | 
| 
      
 851 
     | 
    
         
            +
                    },
         
     | 
| 
      
 852 
     | 
    
         
            +
             
     | 
| 
      
 853 
     | 
    
         
            +
                    _getDroppedFiles: function (dataTransfer) {
         
     | 
| 
      
 854 
     | 
    
         
            +
                        dataTransfer = dataTransfer || {};
         
     | 
| 
      
 855 
     | 
    
         
            +
                        var items = dataTransfer.items;
         
     | 
| 
      
 856 
     | 
    
         
            +
                        if (items && items.length && (items[0].webkitGetAsEntry ||
         
     | 
| 
      
 857 
     | 
    
         
            +
                                items[0].getAsEntry)) {
         
     | 
| 
      
 858 
     | 
    
         
            +
                            return this._handleFileTreeEntries(
         
     | 
| 
      
 859 
     | 
    
         
            +
                                $.map(items, function (item) {
         
     | 
| 
      
 860 
     | 
    
         
            +
                                    var entry;
         
     | 
| 
      
 861 
     | 
    
         
            +
                                    if (item.webkitGetAsEntry) {
         
     | 
| 
      
 862 
     | 
    
         
            +
                                        entry = item.webkitGetAsEntry();
         
     | 
| 
      
 863 
     | 
    
         
            +
                                        if (entry) {
         
     | 
| 
      
 864 
     | 
    
         
            +
                                            // Workaround for Chrome bug #149735:
         
     | 
| 
      
 865 
     | 
    
         
            +
                                            entry._file = item.getAsFile();
         
     | 
| 
      
 866 
     | 
    
         
            +
                                        }
         
     | 
| 
      
 867 
     | 
    
         
            +
                                        return entry;
         
     | 
| 
      
 868 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 869 
     | 
    
         
            +
                                    return item.getAsEntry();
         
     | 
| 
      
 870 
     | 
    
         
            +
                                })
         
     | 
| 
      
 871 
     | 
    
         
            +
                            );
         
     | 
| 
      
 872 
     | 
    
         
            +
                        }
         
     | 
| 
      
 873 
     | 
    
         
            +
                        return $.Deferred().resolve(
         
     | 
| 
      
 874 
     | 
    
         
            +
                            $.makeArray(dataTransfer.files)
         
     | 
| 
      
 875 
     | 
    
         
            +
                        ).promise();
         
     | 
| 
      
 876 
     | 
    
         
            +
                    },
         
     | 
| 
      
 877 
     | 
    
         
            +
             
     | 
| 
      
 878 
     | 
    
         
            +
                    _getSingleFileInputFiles: function (fileInput) {
         
     | 
| 
      
 879 
     | 
    
         
            +
                        fileInput = $(fileInput);
         
     | 
| 
      
 880 
     | 
    
         
            +
                        var entries = fileInput.prop('webkitEntries') ||
         
     | 
| 
      
 881 
     | 
    
         
            +
                                fileInput.prop('entries'),
         
     | 
| 
      
 882 
     | 
    
         
            +
                            files,
         
     | 
| 
      
 883 
     | 
    
         
            +
                            value;
         
     | 
| 
      
 884 
     | 
    
         
            +
                        if (entries && entries.length) {
         
     | 
| 
      
 885 
     | 
    
         
            +
                            return this._handleFileTreeEntries(entries);
         
     | 
| 
      
 886 
     | 
    
         
            +
                        }
         
     | 
| 
      
 887 
     | 
    
         
            +
                        files = $.makeArray(fileInput.prop('files'));
         
     | 
| 
      
 888 
     | 
    
         
            +
                        if (!files.length) {
         
     | 
| 
      
 889 
     | 
    
         
            +
                            value = fileInput.prop('value');
         
     | 
| 
      
 890 
     | 
    
         
            +
                            if (!value) {
         
     | 
| 
      
 891 
     | 
    
         
            +
                                return $.Deferred().resolve([]).promise();
         
     | 
| 
      
 892 
     | 
    
         
            +
                            }
         
     | 
| 
      
 893 
     | 
    
         
            +
                            // If the files property is not available, the browser does not
         
     | 
| 
      
 894 
     | 
    
         
            +
                            // support the File API and we add a pseudo File object with
         
     | 
| 
      
 895 
     | 
    
         
            +
                            // the input value as name with path information removed:
         
     | 
| 
      
 896 
     | 
    
         
            +
                            files = [{name: value.replace(/^.*\\/, '')}];
         
     | 
| 
      
 897 
     | 
    
         
            +
                        }
         
     | 
| 
      
 898 
     | 
    
         
            +
                        return $.Deferred().resolve(files).promise();
         
     | 
| 
      
 899 
     | 
    
         
            +
                    },
         
     | 
| 
      
 900 
     | 
    
         
            +
             
     | 
| 
      
 901 
     | 
    
         
            +
                    _getFileInputFiles: function (fileInput) {
         
     | 
| 
      
 902 
     | 
    
         
            +
                        if (!(fileInput instanceof $) || fileInput.length === 1) {
         
     | 
| 
      
 903 
     | 
    
         
            +
                            return this._getSingleFileInputFiles(fileInput);
         
     | 
| 
      
 904 
     | 
    
         
            +
                        }
         
     | 
| 
      
 905 
     | 
    
         
            +
                        return $.when.apply(
         
     | 
| 
      
 906 
     | 
    
         
            +
                            $,
         
     | 
| 
      
 907 
     | 
    
         
            +
                            $.map(fileInput, this._getSingleFileInputFiles)
         
     | 
| 
      
 908 
     | 
    
         
            +
                        ).pipe(function () {
         
     | 
| 
      
 909 
     | 
    
         
            +
                            return Array.prototype.concat.apply(
         
     | 
| 
      
 910 
     | 
    
         
            +
                                [],
         
     | 
| 
      
 911 
     | 
    
         
            +
                                arguments
         
     | 
| 
      
 912 
     | 
    
         
            +
                            );
         
     | 
| 
      
 913 
     | 
    
         
            +
                        });
         
     | 
| 
      
 914 
     | 
    
         
            +
                    },
         
     | 
| 
      
 915 
     | 
    
         
            +
             
     | 
| 
      
 916 
     | 
    
         
            +
                    _onChange: function (e) {
         
     | 
| 
      
 917 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 918 
     | 
    
         
            +
                            data = {
         
     | 
| 
      
 919 
     | 
    
         
            +
                                fileInput: $(e.target),
         
     | 
| 
      
 920 
     | 
    
         
            +
                                form: $(e.target.form)
         
     | 
| 
      
 921 
     | 
    
         
            +
                            };
         
     | 
| 
      
 922 
     | 
    
         
            +
                        this._getFileInputFiles(data.fileInput).always(function (files) {
         
     | 
| 
      
 923 
     | 
    
         
            +
                            data.files = files;
         
     | 
| 
      
 924 
     | 
    
         
            +
                            if (that.options.replaceFileInput) {
         
     | 
| 
      
 925 
     | 
    
         
            +
                                that._replaceFileInput(data.fileInput);
         
     | 
| 
      
 926 
     | 
    
         
            +
                            }
         
     | 
| 
      
 927 
     | 
    
         
            +
                            if (that._trigger('change', e, data) !== false) {
         
     | 
| 
      
 928 
     | 
    
         
            +
                                that._onAdd(e, data);
         
     | 
| 
      
 929 
     | 
    
         
            +
                            }
         
     | 
| 
      
 930 
     | 
    
         
            +
                        });
         
     | 
| 
      
 931 
     | 
    
         
            +
                    },
         
     | 
| 
      
 932 
     | 
    
         
            +
             
     | 
| 
      
 933 
     | 
    
         
            +
                    _onPaste: function (e) {
         
     | 
| 
      
 934 
     | 
    
         
            +
                        var cbd = e.originalEvent.clipboardData,
         
     | 
| 
      
 935 
     | 
    
         
            +
                            items = (cbd && cbd.items) || [],
         
     | 
| 
      
 936 
     | 
    
         
            +
                            data = {files: []};
         
     | 
| 
      
 937 
     | 
    
         
            +
                        $.each(items, function (index, item) {
         
     | 
| 
      
 938 
     | 
    
         
            +
                            var file = item.getAsFile && item.getAsFile();
         
     | 
| 
      
 939 
     | 
    
         
            +
                            if (file) {
         
     | 
| 
      
 940 
     | 
    
         
            +
                                data.files.push(file);
         
     | 
| 
      
 941 
     | 
    
         
            +
                            }
         
     | 
| 
      
 942 
     | 
    
         
            +
                        });
         
     | 
| 
      
 943 
     | 
    
         
            +
                        if (this._trigger('paste', e, data) === false ||
         
     | 
| 
      
 944 
     | 
    
         
            +
                                this._onAdd(e, data) === false) {
         
     | 
| 
      
 945 
     | 
    
         
            +
                            return false;
         
     | 
| 
      
 946 
     | 
    
         
            +
                        }
         
     | 
| 
      
 947 
     | 
    
         
            +
                    },
         
     | 
| 
      
 948 
     | 
    
         
            +
             
     | 
| 
      
 949 
     | 
    
         
            +
                    _onDrop: function (e) {
         
     | 
| 
      
 950 
     | 
    
         
            +
                        e.preventDefault();
         
     | 
| 
      
 951 
     | 
    
         
            +
                        var that = this,
         
     | 
| 
      
 952 
     | 
    
         
            +
                            dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
         
     | 
| 
      
 953 
     | 
    
         
            +
                            data = {};
         
     | 
| 
      
 954 
     | 
    
         
            +
                        this._getDroppedFiles(dataTransfer).always(function (files) {
         
     | 
| 
      
 955 
     | 
    
         
            +
                            data.files = files;
         
     | 
| 
      
 956 
     | 
    
         
            +
                            if (that._trigger('drop', e, data) !== false) {
         
     | 
| 
      
 957 
     | 
    
         
            +
                                that._onAdd(e, data);
         
     | 
| 
      
 958 
     | 
    
         
            +
                            }
         
     | 
| 
      
 959 
     | 
    
         
            +
                        });
         
     | 
| 
      
 960 
     | 
    
         
            +
                    },
         
     | 
| 
      
 961 
     | 
    
         
            +
             
     | 
| 
      
 962 
     | 
    
         
            +
                    _onDragOver: function (e) {
         
     | 
| 
      
 963 
     | 
    
         
            +
                        var dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer;
         
     | 
| 
      
 964 
     | 
    
         
            +
                        if (this._trigger('dragover', e) === false) {
         
     | 
| 
      
 965 
     | 
    
         
            +
                            return false;
         
     | 
| 
      
 966 
     | 
    
         
            +
                        }
         
     | 
| 
      
 967 
     | 
    
         
            +
                        if (dataTransfer) {
         
     | 
| 
      
 968 
     | 
    
         
            +
                            dataTransfer.dropEffect = 'copy';
         
     | 
| 
      
 969 
     | 
    
         
            +
                        }
         
     | 
| 
      
 970 
     | 
    
         
            +
                        e.preventDefault();
         
     | 
| 
      
 971 
     | 
    
         
            +
                    },
         
     | 
| 
      
 972 
     | 
    
         
            +
             
     | 
| 
      
 973 
     | 
    
         
            +
                    _initEventHandlers: function () {
         
     | 
| 
      
 974 
     | 
    
         
            +
                        if (this._isXHRUpload(this.options)) {
         
     | 
| 
      
 975 
     | 
    
         
            +
                            this._on(this.options.dropZone, {
         
     | 
| 
      
 976 
     | 
    
         
            +
                                dragover: this._onDragOver,
         
     | 
| 
      
 977 
     | 
    
         
            +
                                drop: this._onDrop
         
     | 
| 
      
 978 
     | 
    
         
            +
                            });
         
     | 
| 
      
 979 
     | 
    
         
            +
                            this._on(this.options.pasteZone, {
         
     | 
| 
      
 980 
     | 
    
         
            +
                                paste: this._onPaste
         
     | 
| 
      
 981 
     | 
    
         
            +
                            });
         
     | 
| 
      
 982 
     | 
    
         
            +
                        }
         
     | 
| 
      
 983 
     | 
    
         
            +
                        this._on(this.options.fileInput, {
         
     | 
| 
      
 984 
     | 
    
         
            +
                            change: this._onChange
         
     | 
| 
      
 985 
     | 
    
         
            +
                        });
         
     | 
| 
      
 986 
     | 
    
         
            +
                    },
         
     | 
| 
      
 987 
     | 
    
         
            +
             
     | 
| 
      
 988 
     | 
    
         
            +
                    _destroyEventHandlers: function () {
         
     | 
| 
      
 989 
     | 
    
         
            +
                        this._off(this.options.dropZone, 'dragover drop');
         
     | 
| 
      
 990 
     | 
    
         
            +
                        this._off(this.options.pasteZone, 'paste');
         
     | 
| 
      
 991 
     | 
    
         
            +
                        this._off(this.options.fileInput, 'change');
         
     | 
| 
      
 992 
     | 
    
         
            +
                    },
         
     | 
| 
      
 993 
     | 
    
         
            +
             
     | 
| 
      
 994 
     | 
    
         
            +
                    _setOption: function (key, value) {
         
     | 
| 
      
 995 
     | 
    
         
            +
                        var refresh = $.inArray(key, this._refreshOptionsList) !== -1;
         
     | 
| 
      
 996 
     | 
    
         
            +
                        if (refresh) {
         
     | 
| 
      
 997 
     | 
    
         
            +
                            this._destroyEventHandlers();
         
     | 
| 
      
 998 
     | 
    
         
            +
                        }
         
     | 
| 
      
 999 
     | 
    
         
            +
                        this._super(key, value);
         
     | 
| 
      
 1000 
     | 
    
         
            +
                        if (refresh) {
         
     | 
| 
      
 1001 
     | 
    
         
            +
                            this._initSpecialOptions();
         
     | 
| 
      
 1002 
     | 
    
         
            +
                            this._initEventHandlers();
         
     | 
| 
      
 1003 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1004 
     | 
    
         
            +
                    },
         
     | 
| 
      
 1005 
     | 
    
         
            +
             
     | 
| 
      
 1006 
     | 
    
         
            +
                    _initSpecialOptions: function () {
         
     | 
| 
      
 1007 
     | 
    
         
            +
                        var options = this.options;
         
     | 
| 
      
 1008 
     | 
    
         
            +
                        if (options.fileInput === undefined) {
         
     | 
| 
      
 1009 
     | 
    
         
            +
                            options.fileInput = this.element.is('input[type="file"]') ?
         
     | 
| 
      
 1010 
     | 
    
         
            +
                                    this.element : this.element.find('input[type="file"]');
         
     | 
| 
      
 1011 
     | 
    
         
            +
                        } else if (!(options.fileInput instanceof $)) {
         
     | 
| 
      
 1012 
     | 
    
         
            +
                            options.fileInput = $(options.fileInput);
         
     | 
| 
      
 1013 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1014 
     | 
    
         
            +
                        if (!(options.dropZone instanceof $)) {
         
     | 
| 
      
 1015 
     | 
    
         
            +
                            options.dropZone = $(options.dropZone);
         
     | 
| 
      
 1016 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1017 
     | 
    
         
            +
                        if (!(options.pasteZone instanceof $)) {
         
     | 
| 
      
 1018 
     | 
    
         
            +
                            options.pasteZone = $(options.pasteZone);
         
     | 
| 
      
 1019 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1020 
     | 
    
         
            +
                    },
         
     | 
| 
      
 1021 
     | 
    
         
            +
             
     | 
| 
      
 1022 
     | 
    
         
            +
                    _create: function () {
         
     | 
| 
      
 1023 
     | 
    
         
            +
                        var options = this.options;
         
     | 
| 
      
 1024 
     | 
    
         
            +
                        // Initialize options set via HTML5 data-attributes:
         
     | 
| 
      
 1025 
     | 
    
         
            +
                        $.extend(options, $(this.element[0].cloneNode(false)).data());
         
     | 
| 
      
 1026 
     | 
    
         
            +
                        this._initSpecialOptions();
         
     | 
| 
      
 1027 
     | 
    
         
            +
                        this._slots = [];
         
     | 
| 
      
 1028 
     | 
    
         
            +
                        this._sequence = this._getXHRPromise(true);
         
     | 
| 
      
 1029 
     | 
    
         
            +
                        this._sending = this._active = this._loaded = this._total = 0;
         
     | 
| 
      
 1030 
     | 
    
         
            +
                        this._initEventHandlers();
         
     | 
| 
      
 1031 
     | 
    
         
            +
                    },
         
     | 
| 
      
 1032 
     | 
    
         
            +
             
     | 
| 
      
 1033 
     | 
    
         
            +
                    _destroy: function () {
         
     | 
| 
      
 1034 
     | 
    
         
            +
                        this._destroyEventHandlers();
         
     | 
| 
      
 1035 
     | 
    
         
            +
                    },
         
     | 
| 
      
 1036 
     | 
    
         
            +
             
     | 
| 
      
 1037 
     | 
    
         
            +
                    // This method is exposed to the widget API and allows adding files
         
     | 
| 
      
 1038 
     | 
    
         
            +
                    // using the fileupload API. The data parameter accepts an object which
         
     | 
| 
      
 1039 
     | 
    
         
            +
                    // must have a files property and can contain additional options:
         
     | 
| 
      
 1040 
     | 
    
         
            +
                    // .fileupload('add', {files: filesList});
         
     | 
| 
      
 1041 
     | 
    
         
            +
                    add: function (data) {
         
     | 
| 
      
 1042 
     | 
    
         
            +
                        var that = this;
         
     | 
| 
      
 1043 
     | 
    
         
            +
                        if (!data || this.options.disabled) {
         
     | 
| 
      
 1044 
     | 
    
         
            +
                            return;
         
     | 
| 
      
 1045 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1046 
     | 
    
         
            +
                        if (data.fileInput && !data.files) {
         
     | 
| 
      
 1047 
     | 
    
         
            +
                            this._getFileInputFiles(data.fileInput).always(function (files) {
         
     | 
| 
      
 1048 
     | 
    
         
            +
                                data.files = files;
         
     | 
| 
      
 1049 
     | 
    
         
            +
                                that._onAdd(null, data);
         
     | 
| 
      
 1050 
     | 
    
         
            +
                            });
         
     | 
| 
      
 1051 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 1052 
     | 
    
         
            +
                            data.files = $.makeArray(data.files);
         
     | 
| 
      
 1053 
     | 
    
         
            +
                            this._onAdd(null, data);
         
     | 
| 
      
 1054 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1055 
     | 
    
         
            +
                    },
         
     | 
| 
      
 1056 
     | 
    
         
            +
             
     | 
| 
      
 1057 
     | 
    
         
            +
                    // This method is exposed to the widget API and allows sending files
         
     | 
| 
      
 1058 
     | 
    
         
            +
                    // using the fileupload API. The data parameter accepts an object which
         
     | 
| 
      
 1059 
     | 
    
         
            +
                    // must have a files or fileInput property and can contain additional options:
         
     | 
| 
      
 1060 
     | 
    
         
            +
                    // .fileupload('send', {files: filesList});
         
     | 
| 
      
 1061 
     | 
    
         
            +
                    // The method returns a Promise object for the file upload call.
         
     | 
| 
      
 1062 
     | 
    
         
            +
                    send: function (data) {
         
     | 
| 
      
 1063 
     | 
    
         
            +
                        if (data && !this.options.disabled) {
         
     | 
| 
      
 1064 
     | 
    
         
            +
                            if (data.fileInput && !data.files) {
         
     | 
| 
      
 1065 
     | 
    
         
            +
                                var that = this,
         
     | 
| 
      
 1066 
     | 
    
         
            +
                                    dfd = $.Deferred(),
         
     | 
| 
      
 1067 
     | 
    
         
            +
                                    promise = dfd.promise(),
         
     | 
| 
      
 1068 
     | 
    
         
            +
                                    jqXHR,
         
     | 
| 
      
 1069 
     | 
    
         
            +
                                    aborted;
         
     | 
| 
      
 1070 
     | 
    
         
            +
                                promise.abort = function () {
         
     | 
| 
      
 1071 
     | 
    
         
            +
                                    aborted = true;
         
     | 
| 
      
 1072 
     | 
    
         
            +
                                    if (jqXHR) {
         
     | 
| 
      
 1073 
     | 
    
         
            +
                                        return jqXHR.abort();
         
     | 
| 
      
 1074 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 1075 
     | 
    
         
            +
                                    dfd.reject(null, 'abort', 'abort');
         
     | 
| 
      
 1076 
     | 
    
         
            +
                                    return promise;
         
     | 
| 
      
 1077 
     | 
    
         
            +
                                };
         
     | 
| 
      
 1078 
     | 
    
         
            +
                                this._getFileInputFiles(data.fileInput).always(
         
     | 
| 
      
 1079 
     | 
    
         
            +
                                    function (files) {
         
     | 
| 
      
 1080 
     | 
    
         
            +
                                        if (aborted) {
         
     | 
| 
      
 1081 
     | 
    
         
            +
                                            return;
         
     | 
| 
      
 1082 
     | 
    
         
            +
                                        }
         
     | 
| 
      
 1083 
     | 
    
         
            +
                                        data.files = files;
         
     | 
| 
      
 1084 
     | 
    
         
            +
                                        jqXHR = that._onSend(null, data).then(
         
     | 
| 
      
 1085 
     | 
    
         
            +
                                            function (result, textStatus, jqXHR) {
         
     | 
| 
      
 1086 
     | 
    
         
            +
                                                dfd.resolve(result, textStatus, jqXHR);
         
     | 
| 
      
 1087 
     | 
    
         
            +
                                            },
         
     | 
| 
      
 1088 
     | 
    
         
            +
                                            function (jqXHR, textStatus, errorThrown) {
         
     | 
| 
      
 1089 
     | 
    
         
            +
                                                dfd.reject(jqXHR, textStatus, errorThrown);
         
     | 
| 
      
 1090 
     | 
    
         
            +
                                            }
         
     | 
| 
      
 1091 
     | 
    
         
            +
                                        );
         
     | 
| 
      
 1092 
     | 
    
         
            +
                                    }
         
     | 
| 
      
 1093 
     | 
    
         
            +
                                );
         
     | 
| 
      
 1094 
     | 
    
         
            +
                                return this._enhancePromise(promise);
         
     | 
| 
      
 1095 
     | 
    
         
            +
                            }
         
     | 
| 
      
 1096 
     | 
    
         
            +
                            data.files = $.makeArray(data.files);
         
     | 
| 
      
 1097 
     | 
    
         
            +
                            if (data.files.length) {
         
     | 
| 
      
 1098 
     | 
    
         
            +
                                return this._onSend(null, data);
         
     | 
| 
      
 1099 
     | 
    
         
            +
                            }
         
     | 
| 
      
 1100 
     | 
    
         
            +
                        }
         
     | 
| 
      
 1101 
     | 
    
         
            +
                        return this._getXHRPromise(false, data && data.context);
         
     | 
| 
      
 1102 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1103 
     | 
    
         
            +
             
     | 
| 
      
 1104 
     | 
    
         
            +
                });
         
     | 
| 
      
 1105 
     | 
    
         
            +
             
     | 
| 
      
 1106 
     | 
    
         
            +
            }));
         
     |