├── .gitignore ├── README.md ├── SampleImages └── Screenshot.png ├── app.py ├── static ├── css │ └── style.css └── js │ ├── app.js │ ├── dropzone.js │ └── jquery.js ├── templates └── index.html └── upload └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | upload/*.png 2 | upload/*.jpg 3 | upload/*.gif 4 | log.txt 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## flask-fileupload-dropzonejs 2 | Flask File Upload with dropzone.js. 3 | 4 | ![Preview Image](./SampleImages/Screenshot.png "Preview Image") 5 | -------------------------------------------------------------------------------- /SampleImages/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moremorefor/flask-fileupload-dropzonejs/ee70558ca775f87237f959e7a7922b0298b6a15a/SampleImages/Screenshot.png -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import ( 2 | Flask, 3 | request, 4 | render_template, 5 | send_from_directory, 6 | url_for, 7 | jsonify 8 | ) 9 | from werkzeug import secure_filename 10 | import os 11 | 12 | basedir = os.path.abspath(os.path.dirname(__file__)) 13 | 14 | app = Flask(__name__) 15 | 16 | from logging import Formatter, FileHandler 17 | handler = FileHandler(os.path.join(basedir, 'log.txt'), encoding='utf8') 18 | handler.setFormatter( 19 | Formatter("[%(asctime)s] %(levelname)-8s %(message)s", "%Y-%m-%d %H:%M:%S") 20 | ) 21 | app.logger.addHandler(handler) 22 | 23 | 24 | app.config['ALLOWED_EXTENSIONS'] = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) 25 | 26 | 27 | def allowed_file(filename): 28 | return '.' in filename and \ 29 | filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS'] 30 | 31 | 32 | @app.context_processor 33 | def override_url_for(): 34 | return dict(url_for=dated_url_for) 35 | 36 | 37 | def dated_url_for(endpoint, **values): 38 | if endpoint == 'js_static': 39 | filename = values.get('filename', None) 40 | if filename: 41 | file_path = os.path.join(app.root_path, 42 | 'static/js', filename) 43 | values['q'] = int(os.stat(file_path).st_mtime) 44 | if endpoint == 'css_static': 45 | filename = values.get('filename', None) 46 | if filename: 47 | file_path = os.path.join(app.root_path, 48 | 'static/css', filename) 49 | values['q'] = int(os.stat(file_path).st_mtime) 50 | return url_for(endpoint, **values) 51 | 52 | 53 | @app.route('/css/') 54 | def css_static(filename): 55 | return send_from_directory(app.root_path + '/static/css/', filename) 56 | 57 | 58 | @app.route('/js/') 59 | def js_static(filename): 60 | return send_from_directory(app.root_path + '/static/js/', filename) 61 | 62 | 63 | @app.route('/') 64 | def index(): 65 | return render_template('index.html') 66 | 67 | 68 | @app.route('/uploadajax', methods=['POST']) 69 | def upldfile(): 70 | if request.method == 'POST': 71 | files = request.files.getlist('file[]') 72 | for f in files: 73 | if f and allowed_file(f.filename): 74 | filename = secure_filename(f.filename) 75 | updir = os.path.join(basedir, 'upload/') 76 | f.save(os.path.join(updir, filename)) 77 | file_size = os.path.getsize(os.path.join(updir, filename)) 78 | else: 79 | app.logger.info('ext name error') 80 | return jsonify(error='ext name error') 81 | return jsonify(name=filename, size=file_size) 82 | 83 | 84 | if __name__ == '__main__': 85 | app.run(debug=True) 86 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-weight: bold; 3 | color: rgba(0, 82, 156, 1); 4 | background: rgba(0, 82, 156, 0.1); 5 | } 6 | 7 | #droparea{ 8 | width: 400px; 9 | min-height: 400px; 10 | margin: 30px auto 0; 11 | padding: 0 20px; 12 | border: 4px solid rgba(0, 82, 156, 0.8); 13 | } 14 | 15 | #previewsContainer { 16 | width: 300px; 17 | min-height: 280px; 18 | padding: 10px 20px; 19 | background: #FFF; 20 | margin: 0 auto 20px; 21 | } 22 | 23 | #selectImage { 24 | color: #FFF; 25 | width: 200px; 26 | text-align: center; 27 | padding: 10px 0; 28 | background: rgba(0, 82, 156, 0.5); 29 | float: left; 30 | cursor: pointer; 31 | } 32 | 33 | #fileSubmit { 34 | color: #FFF; 35 | width: 200px; 36 | margin: 0 0 0 30px; 37 | text-align: center; 38 | padding: 10px 0; 39 | background: rgba(0, 82, 156, 0.5); 40 | float: left; 41 | cursor: pointer; 42 | } 43 | -------------------------------------------------------------------------------- /static/js/app.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var myDropzone = new Dropzone("div#droparea", { 4 | url: "/uploadajax", 5 | method: "POST", // can be changed to "put" if necessary 6 | maxFilesize: 2, // in MB 7 | paramName: "file", // The name that will be used to transfer the file 8 | uploadMultiple: true, // This option will also trigger additional events (like processingmultiple). 9 | headers: { 10 | "My-Awesome-Header": "header value" 11 | }, 12 | addRemoveLinks: true, // add an Remove file element to the file preview that will remove the file, and it will change to Cancel upload 13 | previewsContainer: "#previewsContainer", 14 | clickable: "#selectImage", 15 | createImageThumbnails: true, 16 | maxThumbnailFilesize: 2, // in MB 17 | thumbnailWidth: 300, 18 | thumbnailHeight: 300, 19 | maxFiles: 3, 20 | acceptedFiles: "image/png, image/jpeg, image/gif", //This is a comma separated list of mime types or file extensions.Eg.: image/*,application/pdf,.psd. 21 | autoProcessQueue: false, // When set to false you have to call myDropzone.processQueue() yourself in order to upload the dropped files. 22 | forceFallback: false, 23 | 24 | init: function() { 25 | console.log("init"); 26 | }, 27 | resize: function(file) { 28 | console.log("resize"); 29 | /* 30 | * Crop rectangle range 31 | * Those values are going to be used by ctx.drawImage(). 32 | */ 33 | return {"srcX":0, "srcY":0, "srcWidth":300, "srcHeight":300} 34 | }, 35 | accept: function(file, done) { 36 | console.log("accept"); 37 | done(); 38 | }, 39 | fallback: function() { 40 | console.log("fallback"); 41 | } 42 | }); 43 | 44 | /* 45 | * Custom preview template here. 46 | * ex) myDropzone.options.previewTemplate = ''; 47 | */ 48 | myDropzone.options.previewTemplate = '\ 49 |
\ 50 |
\ 51 |
\ 52 |
\ 53 | \ 54 |
\ 55 |
\ 56 |
\ 57 |
'; 58 | 59 | 60 | /* 61 | * Available Events 62 | */ 63 | 64 | /* receive the "event" as first parameter */ 65 | myDropzone.on("drop", function(event){ 66 | console.log(event.type); 67 | console.log(event) 68 | }); 69 | myDropzone.on("dragstart", function(event){ console.log(event.type); }); 70 | myDropzone.on("dragend", function(event){ console.log(event.type); }); 71 | myDropzone.on("dragenter", function(event){ console.log(event.type); }); 72 | myDropzone.on("dragover", function(event){ console.log(event.type); }); 73 | myDropzone.on("dragremove", function(event){ console.log(event.type); }); 74 | 75 | /* receive the "file" as first parameter */ 76 | myDropzone.on("addedfile", function(file) { 77 | console.log("addedfile"); 78 | console.log(file); 79 | $('#fileSubmit').click(function(){ 80 | myDropzone.processQueue(); //processes the queue 81 | }); 82 | }); 83 | myDropzone.on("removedfile", function(file) { console.log("removedfile"); }); 84 | myDropzone.on("selectedfiles", function(file) { console.log("selectedfiles"); }); 85 | myDropzone.on("thumbnail", function(file) { console.log("thumbnail"); }); 86 | myDropzone.on("error", function(file) { console.log("error"); }); 87 | myDropzone.on("processing ", function(file) { console.log("processing "); }); 88 | myDropzone.on("uploadprogress", function(file) { console.log("uploadprogress"); }); 89 | myDropzone.on("sending", function(file) { console.log("sending"); }); 90 | myDropzone.on("success", function(file) { console.log("success"); }); 91 | myDropzone.on("complete", function(file) { console.log("complete"); }); 92 | myDropzone.on("canceled", function(file) { console.log("canceled"); }); 93 | myDropzone.on("maxfilesreached", function(file) { console.log("maxfilesreached"); }); 94 | myDropzone.on("maxfilesexceeded", function(file) { console.log("maxfilesexceeded"); }); 95 | 96 | /* receive a "list of files" as first parameter 97 | * only called if the uploadMultiple option is true: 98 | */ 99 | myDropzone.on("processingmultiple", function(files) { console.log("processingmultiple") }); 100 | myDropzone.on("sendingmultiple", function(files) { console.log("sendingmultiple") }); 101 | myDropzone.on("successmultiple", function(files) { console.log("successmultiple") }); 102 | myDropzone.on("completemultiple", function(files) { console.log("completemultiple") }); 103 | myDropzone.on("canceledmultiple", function(files) { console.log("canceledmultiple") }); 104 | 105 | /* Special events */ 106 | myDropzone.on("totaluploadprogress", function() { console.log("totaluploadprogress") }); 107 | myDropzone.on("reset", function() { console.log("reset") }); 108 | 109 | }); 110 | -------------------------------------------------------------------------------- /static/js/dropzone.js: -------------------------------------------------------------------------------- 1 | ;(function(){ 2 | 3 | /** 4 | * Require the given path. 5 | * 6 | * @param {String} path 7 | * @return {Object} exports 8 | * @api public 9 | */ 10 | 11 | function require(path, parent, orig) { 12 | var resolved = require.resolve(path); 13 | 14 | // lookup failed 15 | if (null == resolved) { 16 | orig = orig || path; 17 | parent = parent || 'root'; 18 | var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); 19 | err.path = orig; 20 | err.parent = parent; 21 | err.require = true; 22 | throw err; 23 | } 24 | 25 | var module = require.modules[resolved]; 26 | 27 | // perform real require() 28 | // by invoking the module's 29 | // registered function 30 | if (!module._resolving && !module.exports) { 31 | var mod = {}; 32 | mod.exports = {}; 33 | mod.client = mod.component = true; 34 | module._resolving = true; 35 | module.call(this, mod.exports, require.relative(resolved), mod); 36 | delete module._resolving; 37 | module.exports = mod.exports; 38 | } 39 | 40 | return module.exports; 41 | } 42 | 43 | /** 44 | * Registered modules. 45 | */ 46 | 47 | require.modules = {}; 48 | 49 | /** 50 | * Registered aliases. 51 | */ 52 | 53 | require.aliases = {}; 54 | 55 | /** 56 | * Resolve `path`. 57 | * 58 | * Lookup: 59 | * 60 | * - PATH/index.js 61 | * - PATH.js 62 | * - PATH 63 | * 64 | * @param {String} path 65 | * @return {String} path or null 66 | * @api private 67 | */ 68 | 69 | require.resolve = function(path) { 70 | if (path.charAt(0) === '/') path = path.slice(1); 71 | 72 | var paths = [ 73 | path, 74 | path + '.js', 75 | path + '.json', 76 | path + '/index.js', 77 | path + '/index.json' 78 | ]; 79 | 80 | for (var i = 0; i < paths.length; i++) { 81 | var path = paths[i]; 82 | if (require.modules.hasOwnProperty(path)) return path; 83 | if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; 84 | } 85 | }; 86 | 87 | /** 88 | * Normalize `path` relative to the current path. 89 | * 90 | * @param {String} curr 91 | * @param {String} path 92 | * @return {String} 93 | * @api private 94 | */ 95 | 96 | require.normalize = function(curr, path) { 97 | var segs = []; 98 | 99 | if ('.' != path.charAt(0)) return path; 100 | 101 | curr = curr.split('/'); 102 | path = path.split('/'); 103 | 104 | for (var i = 0; i < path.length; ++i) { 105 | if ('..' == path[i]) { 106 | curr.pop(); 107 | } else if ('.' != path[i] && '' != path[i]) { 108 | segs.push(path[i]); 109 | } 110 | } 111 | 112 | return curr.concat(segs).join('/'); 113 | }; 114 | 115 | /** 116 | * Register module at `path` with callback `definition`. 117 | * 118 | * @param {String} path 119 | * @param {Function} definition 120 | * @api private 121 | */ 122 | 123 | require.register = function(path, definition) { 124 | require.modules[path] = definition; 125 | }; 126 | 127 | /** 128 | * Alias a module definition. 129 | * 130 | * @param {String} from 131 | * @param {String} to 132 | * @api private 133 | */ 134 | 135 | require.alias = function(from, to) { 136 | if (!require.modules.hasOwnProperty(from)) { 137 | throw new Error('Failed to alias "' + from + '", it does not exist'); 138 | } 139 | require.aliases[to] = from; 140 | }; 141 | 142 | /** 143 | * Return a require function relative to the `parent` path. 144 | * 145 | * @param {String} parent 146 | * @return {Function} 147 | * @api private 148 | */ 149 | 150 | require.relative = function(parent) { 151 | var p = require.normalize(parent, '..'); 152 | 153 | /** 154 | * lastIndexOf helper. 155 | */ 156 | 157 | function lastIndexOf(arr, obj) { 158 | var i = arr.length; 159 | while (i--) { 160 | if (arr[i] === obj) return i; 161 | } 162 | return -1; 163 | } 164 | 165 | /** 166 | * The relative require() itself. 167 | */ 168 | 169 | function localRequire(path) { 170 | var resolved = localRequire.resolve(path); 171 | return require(resolved, parent, path); 172 | } 173 | 174 | /** 175 | * Resolve relative to the parent. 176 | */ 177 | 178 | localRequire.resolve = function(path) { 179 | var c = path.charAt(0); 180 | if ('/' == c) return path.slice(1); 181 | if ('.' == c) return require.normalize(p, path); 182 | 183 | // resolve deps by returning 184 | // the dep in the nearest "deps" 185 | // directory 186 | var segs = parent.split('/'); 187 | var i = lastIndexOf(segs, 'deps') + 1; 188 | if (!i) i = 0; 189 | path = segs.slice(0, i + 1).join('/') + '/deps/' + path; 190 | return path; 191 | }; 192 | 193 | /** 194 | * Check if module is defined at `path`. 195 | */ 196 | 197 | localRequire.exists = function(path) { 198 | return require.modules.hasOwnProperty(localRequire.resolve(path)); 199 | }; 200 | 201 | return localRequire; 202 | }; 203 | require.register("component-emitter/index.js", function(exports, require, module){ 204 | 205 | /** 206 | * Expose `Emitter`. 207 | */ 208 | 209 | module.exports = Emitter; 210 | 211 | /** 212 | * Initialize a new `Emitter`. 213 | * 214 | * @api public 215 | */ 216 | 217 | function Emitter(obj) { 218 | if (obj) return mixin(obj); 219 | }; 220 | 221 | /** 222 | * Mixin the emitter properties. 223 | * 224 | * @param {Object} obj 225 | * @return {Object} 226 | * @api private 227 | */ 228 | 229 | function mixin(obj) { 230 | for (var key in Emitter.prototype) { 231 | obj[key] = Emitter.prototype[key]; 232 | } 233 | return obj; 234 | } 235 | 236 | /** 237 | * Listen on the given `event` with `fn`. 238 | * 239 | * @param {String} event 240 | * @param {Function} fn 241 | * @return {Emitter} 242 | * @api public 243 | */ 244 | 245 | Emitter.prototype.on = function(event, fn){ 246 | this._callbacks = this._callbacks || {}; 247 | (this._callbacks[event] = this._callbacks[event] || []) 248 | .push(fn); 249 | return this; 250 | }; 251 | 252 | /** 253 | * Adds an `event` listener that will be invoked a single 254 | * time then automatically removed. 255 | * 256 | * @param {String} event 257 | * @param {Function} fn 258 | * @return {Emitter} 259 | * @api public 260 | */ 261 | 262 | Emitter.prototype.once = function(event, fn){ 263 | var self = this; 264 | this._callbacks = this._callbacks || {}; 265 | 266 | function on() { 267 | self.off(event, on); 268 | fn.apply(this, arguments); 269 | } 270 | 271 | fn._off = on; 272 | this.on(event, on); 273 | return this; 274 | }; 275 | 276 | /** 277 | * Remove the given callback for `event` or all 278 | * registered callbacks. 279 | * 280 | * @param {String} event 281 | * @param {Function} fn 282 | * @return {Emitter} 283 | * @api public 284 | */ 285 | 286 | Emitter.prototype.off = 287 | Emitter.prototype.removeListener = 288 | Emitter.prototype.removeAllListeners = function(event, fn){ 289 | this._callbacks = this._callbacks || {}; 290 | var callbacks = this._callbacks[event]; 291 | if (!callbacks) return this; 292 | 293 | // remove all handlers 294 | if (1 == arguments.length) { 295 | delete this._callbacks[event]; 296 | return this; 297 | } 298 | 299 | // remove specific handler 300 | var i = callbacks.indexOf(fn._off || fn); 301 | if (~i) callbacks.splice(i, 1); 302 | return this; 303 | }; 304 | 305 | /** 306 | * Emit `event` with the given args. 307 | * 308 | * @param {String} event 309 | * @param {Mixed} ... 310 | * @return {Emitter} 311 | */ 312 | 313 | Emitter.prototype.emit = function(event){ 314 | this._callbacks = this._callbacks || {}; 315 | var args = [].slice.call(arguments, 1) 316 | , callbacks = this._callbacks[event]; 317 | 318 | if (callbacks) { 319 | callbacks = callbacks.slice(0); 320 | for (var i = 0, len = callbacks.length; i < len; ++i) { 321 | callbacks[i].apply(this, args); 322 | } 323 | } 324 | 325 | return this; 326 | }; 327 | 328 | /** 329 | * Return array of callbacks for `event`. 330 | * 331 | * @param {String} event 332 | * @return {Array} 333 | * @api public 334 | */ 335 | 336 | Emitter.prototype.listeners = function(event){ 337 | this._callbacks = this._callbacks || {}; 338 | return this._callbacks[event] || []; 339 | }; 340 | 341 | /** 342 | * Check if this emitter has `event` handlers. 343 | * 344 | * @param {String} event 345 | * @return {Boolean} 346 | * @api public 347 | */ 348 | 349 | Emitter.prototype.hasListeners = function(event){ 350 | return !! this.listeners(event).length; 351 | }; 352 | 353 | }); 354 | require.register("dropzone/index.js", function(exports, require, module){ 355 | 356 | 357 | /** 358 | * Exposing dropzone 359 | */ 360 | module.exports = require("./lib/dropzone.js"); 361 | 362 | }); 363 | require.register("dropzone/lib/dropzone.js", function(exports, require, module){ 364 | /* 365 | # 366 | # More info at [www.dropzonejs.com](http://www.dropzonejs.com) 367 | # 368 | # Copyright (c) 2012, Matias Meno 369 | # 370 | # Permission is hereby granted, free of charge, to any person obtaining a copy 371 | # of this software and associated documentation files (the "Software"), to deal 372 | # in the Software without restriction, including without limitation the rights 373 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 374 | # copies of the Software, and to permit persons to whom the Software is 375 | # furnished to do so, subject to the following conditions: 376 | # 377 | # The above copyright notice and this permission notice shall be included in 378 | # all copies or substantial portions of the Software. 379 | # 380 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 381 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 382 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 383 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 384 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 385 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 386 | # THE SOFTWARE. 387 | # 388 | */ 389 | 390 | 391 | (function() { 392 | var Dropzone, Em, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without, 393 | __hasProp = {}.hasOwnProperty, 394 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 395 | __slice = [].slice; 396 | 397 | Em = typeof Emitter !== "undefined" && Emitter !== null ? Emitter : require("emitter"); 398 | 399 | noop = function() {}; 400 | 401 | Dropzone = (function(_super) { 402 | var extend; 403 | 404 | __extends(Dropzone, _super); 405 | 406 | /* 407 | This is a list of all available events you can register on a dropzone object. 408 | 409 | You can register an event handler like this: 410 | 411 | dropzone.on("dragEnter", function() { }); 412 | */ 413 | 414 | 415 | Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached"]; 416 | 417 | Dropzone.prototype.defaultOptions = { 418 | url: null, 419 | method: "post", 420 | withCredentials: false, 421 | parallelUploads: 2, 422 | uploadMultiple: false, 423 | maxFilesize: 256, 424 | paramName: "file", 425 | createImageThumbnails: true, 426 | maxThumbnailFilesize: 10, 427 | thumbnailWidth: 100, 428 | thumbnailHeight: 100, 429 | maxFiles: null, 430 | params: {}, 431 | clickable: true, 432 | ignoreHiddenFiles: true, 433 | acceptedFiles: null, 434 | acceptedMimeTypes: null, 435 | autoProcessQueue: true, 436 | addRemoveLinks: false, 437 | previewsContainer: null, 438 | dictDefaultMessage: "Drop files here to upload", 439 | dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", 440 | dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.", 441 | dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.", 442 | dictInvalidFileType: "You can't upload files of this type.", 443 | dictResponseError: "Server responded with {{statusCode}} code.", 444 | dictCancelUpload: "Cancel upload", 445 | dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", 446 | dictRemoveFile: "Remove file", 447 | dictRemoveFileConfirmation: null, 448 | dictMaxFilesExceeded: "You can not upload any more files.", 449 | accept: function(file, done) { 450 | return done(); 451 | }, 452 | init: function() { 453 | return noop; 454 | }, 455 | forceFallback: false, 456 | fallback: function() { 457 | var child, messageElement, span, _i, _len, _ref; 458 | this.element.className = "" + this.element.className + " dz-browser-not-supported"; 459 | _ref = this.element.getElementsByTagName("div"); 460 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 461 | child = _ref[_i]; 462 | if (/(^| )dz-message($| )/.test(child.className)) { 463 | messageElement = child; 464 | child.className = "dz-message"; 465 | continue; 466 | } 467 | } 468 | if (!messageElement) { 469 | messageElement = Dropzone.createElement("
"); 470 | this.element.appendChild(messageElement); 471 | } 472 | span = messageElement.getElementsByTagName("span")[0]; 473 | if (span) { 474 | span.textContent = this.options.dictFallbackMessage; 475 | } 476 | return this.element.appendChild(this.getFallbackForm()); 477 | }, 478 | resize: function(file) { 479 | var info, srcRatio, trgRatio; 480 | info = { 481 | srcX: 0, 482 | srcY: 0, 483 | srcWidth: file.width, 484 | srcHeight: file.height 485 | }; 486 | srcRatio = file.width / file.height; 487 | trgRatio = this.options.thumbnailWidth / this.options.thumbnailHeight; 488 | if (file.height < this.options.thumbnailHeight || file.width < this.options.thumbnailWidth) { 489 | info.trgHeight = info.srcHeight; 490 | info.trgWidth = info.srcWidth; 491 | } else { 492 | if (srcRatio > trgRatio) { 493 | info.srcHeight = file.height; 494 | info.srcWidth = info.srcHeight * trgRatio; 495 | } else { 496 | info.srcWidth = file.width; 497 | info.srcHeight = info.srcWidth / trgRatio; 498 | } 499 | } 500 | info.srcX = (file.width - info.srcWidth) / 2; 501 | info.srcY = (file.height - info.srcHeight) / 2; 502 | return info; 503 | }, 504 | /* 505 | Those functions register themselves to the events on init and handle all 506 | the user interface specific stuff. Overwriting them won't break the upload 507 | but can break the way it's displayed. 508 | You can overwrite them if you don't like the default behavior. If you just 509 | want to add an additional event handler, register it on the dropzone object 510 | and don't overwrite those options. 511 | */ 512 | 513 | drop: function(e) { 514 | return this.element.classList.remove("dz-drag-hover"); 515 | }, 516 | dragstart: noop, 517 | dragend: function(e) { 518 | return this.element.classList.remove("dz-drag-hover"); 519 | }, 520 | dragenter: function(e) { 521 | return this.element.classList.add("dz-drag-hover"); 522 | }, 523 | dragover: function(e) { 524 | return this.element.classList.add("dz-drag-hover"); 525 | }, 526 | dragleave: function(e) { 527 | return this.element.classList.remove("dz-drag-hover"); 528 | }, 529 | paste: noop, 530 | reset: function() { 531 | return this.element.classList.remove("dz-started"); 532 | }, 533 | addedfile: function(file) { 534 | var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results, 535 | _this = this; 536 | if (this.element === this.previewsContainer) { 537 | this.element.classList.add("dz-started"); 538 | } 539 | file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim()); 540 | file.previewTemplate = file.previewElement; 541 | this.previewsContainer.appendChild(file.previewElement); 542 | _ref = file.previewElement.querySelectorAll("[data-dz-name]"); 543 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 544 | node = _ref[_i]; 545 | node.textContent = file.name; 546 | } 547 | _ref1 = file.previewElement.querySelectorAll("[data-dz-size]"); 548 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 549 | node = _ref1[_j]; 550 | node.innerHTML = this.filesize(file.size); 551 | } 552 | if (this.options.addRemoveLinks) { 553 | file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + ""); 554 | file.previewElement.appendChild(file._removeLink); 555 | } 556 | removeFileEvent = function(e) { 557 | e.preventDefault(); 558 | e.stopPropagation(); 559 | if (file.status === Dropzone.UPLOADING) { 560 | return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() { 561 | return _this.removeFile(file); 562 | }); 563 | } else { 564 | if (_this.options.dictRemoveFileConfirmation) { 565 | return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() { 566 | return _this.removeFile(file); 567 | }); 568 | } else { 569 | return _this.removeFile(file); 570 | } 571 | } 572 | }; 573 | _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]"); 574 | _results = []; 575 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 576 | removeLink = _ref2[_k]; 577 | _results.push(removeLink.addEventListener("click", removeFileEvent)); 578 | } 579 | return _results; 580 | }, 581 | removedfile: function(file) { 582 | var _ref; 583 | if ((_ref = file.previewElement) != null) { 584 | _ref.parentNode.removeChild(file.previewElement); 585 | } 586 | return this._updateMaxFilesReachedClass(); 587 | }, 588 | thumbnail: function(file, dataUrl) { 589 | var thumbnailElement, _i, _len, _ref, _results; 590 | file.previewElement.classList.remove("dz-file-preview"); 591 | file.previewElement.classList.add("dz-image-preview"); 592 | _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]"); 593 | _results = []; 594 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 595 | thumbnailElement = _ref[_i]; 596 | thumbnailElement.alt = file.name; 597 | _results.push(thumbnailElement.src = dataUrl); 598 | } 599 | return _results; 600 | }, 601 | error: function(file, message) { 602 | var node, _i, _len, _ref, _results; 603 | file.previewElement.classList.add("dz-error"); 604 | if (typeof message !== "String" && message.error) { 605 | message = message.error; 606 | } 607 | _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); 608 | _results = []; 609 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 610 | node = _ref[_i]; 611 | _results.push(node.textContent = message); 612 | } 613 | return _results; 614 | }, 615 | errormultiple: noop, 616 | processing: function(file) { 617 | file.previewElement.classList.add("dz-processing"); 618 | if (file._removeLink) { 619 | return file._removeLink.textContent = this.options.dictCancelUpload; 620 | } 621 | }, 622 | processingmultiple: noop, 623 | uploadprogress: function(file, progress, bytesSent) { 624 | var node, _i, _len, _ref, _results; 625 | _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"); 626 | _results = []; 627 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 628 | node = _ref[_i]; 629 | _results.push(node.style.width = "" + progress + "%"); 630 | } 631 | return _results; 632 | }, 633 | totaluploadprogress: noop, 634 | sending: noop, 635 | sendingmultiple: noop, 636 | success: function(file) { 637 | return file.previewElement.classList.add("dz-success"); 638 | }, 639 | successmultiple: noop, 640 | canceled: function(file) { 641 | return this.emit("error", file, "Upload canceled."); 642 | }, 643 | canceledmultiple: noop, 644 | complete: function(file) { 645 | if (file._removeLink) { 646 | return file._removeLink.textContent = this.options.dictRemoveFile; 647 | } 648 | }, 649 | completemultiple: noop, 650 | maxfilesexceeded: noop, 651 | maxfilesreached: noop, 652 | previewTemplate: "
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
" 653 | }; 654 | 655 | extend = function() { 656 | var key, object, objects, target, val, _i, _len; 657 | target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 658 | for (_i = 0, _len = objects.length; _i < _len; _i++) { 659 | object = objects[_i]; 660 | for (key in object) { 661 | val = object[key]; 662 | target[key] = val; 663 | } 664 | } 665 | return target; 666 | }; 667 | 668 | function Dropzone(element, options) { 669 | var elementOptions, fallback, _ref; 670 | this.element = element; 671 | this.version = Dropzone.version; 672 | this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, ""); 673 | this.clickableElements = []; 674 | this.listeners = []; 675 | this.files = []; 676 | if (typeof this.element === "string") { 677 | this.element = document.querySelector(this.element); 678 | } 679 | if (!(this.element && (this.element.nodeType != null))) { 680 | throw new Error("Invalid dropzone element."); 681 | } 682 | if (this.element.dropzone) { 683 | throw new Error("Dropzone already attached."); 684 | } 685 | Dropzone.instances.push(this); 686 | this.element.dropzone = this; 687 | elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {}; 688 | this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {}); 689 | if (this.options.forceFallback || !Dropzone.isBrowserSupported()) { 690 | return this.options.fallback.call(this); 691 | } 692 | if (this.options.url == null) { 693 | this.options.url = this.element.getAttribute("action"); 694 | } 695 | if (!this.options.url) { 696 | throw new Error("No URL provided."); 697 | } 698 | if (this.options.acceptedFiles && this.options.acceptedMimeTypes) { 699 | throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); 700 | } 701 | if (this.options.acceptedMimeTypes) { 702 | this.options.acceptedFiles = this.options.acceptedMimeTypes; 703 | delete this.options.acceptedMimeTypes; 704 | } 705 | this.options.method = this.options.method.toUpperCase(); 706 | if ((fallback = this.getExistingFallback()) && fallback.parentNode) { 707 | fallback.parentNode.removeChild(fallback); 708 | } 709 | if (this.options.previewsContainer) { 710 | this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer"); 711 | } else { 712 | this.previewsContainer = this.element; 713 | } 714 | if (this.options.clickable) { 715 | if (this.options.clickable === true) { 716 | this.clickableElements = [this.element]; 717 | } else { 718 | this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable"); 719 | } 720 | } 721 | this.init(); 722 | } 723 | 724 | Dropzone.prototype.getAcceptedFiles = function() { 725 | var file, _i, _len, _ref, _results; 726 | _ref = this.files; 727 | _results = []; 728 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 729 | file = _ref[_i]; 730 | if (file.accepted) { 731 | _results.push(file); 732 | } 733 | } 734 | return _results; 735 | }; 736 | 737 | Dropzone.prototype.getRejectedFiles = function() { 738 | var file, _i, _len, _ref, _results; 739 | _ref = this.files; 740 | _results = []; 741 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 742 | file = _ref[_i]; 743 | if (!file.accepted) { 744 | _results.push(file); 745 | } 746 | } 747 | return _results; 748 | }; 749 | 750 | Dropzone.prototype.getQueuedFiles = function() { 751 | var file, _i, _len, _ref, _results; 752 | _ref = this.files; 753 | _results = []; 754 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 755 | file = _ref[_i]; 756 | if (file.status === Dropzone.QUEUED) { 757 | _results.push(file); 758 | } 759 | } 760 | return _results; 761 | }; 762 | 763 | Dropzone.prototype.getUploadingFiles = function() { 764 | var file, _i, _len, _ref, _results; 765 | _ref = this.files; 766 | _results = []; 767 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 768 | file = _ref[_i]; 769 | if (file.status === Dropzone.UPLOADING) { 770 | _results.push(file); 771 | } 772 | } 773 | return _results; 774 | }; 775 | 776 | Dropzone.prototype.init = function() { 777 | var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1, 778 | _this = this; 779 | if (this.element.tagName === "form") { 780 | this.element.setAttribute("enctype", "multipart/form-data"); 781 | } 782 | if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { 783 | this.element.appendChild(Dropzone.createElement("
" + this.options.dictDefaultMessage + "
")); 784 | } 785 | if (this.clickableElements.length) { 786 | setupHiddenFileInput = function() { 787 | if (_this.hiddenFileInput) { 788 | document.body.removeChild(_this.hiddenFileInput); 789 | } 790 | _this.hiddenFileInput = document.createElement("input"); 791 | _this.hiddenFileInput.setAttribute("type", "file"); 792 | if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) { 793 | _this.hiddenFileInput.setAttribute("multiple", "multiple"); 794 | } 795 | if (_this.options.acceptedFiles != null) { 796 | _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles); 797 | } 798 | _this.hiddenFileInput.style.visibility = "hidden"; 799 | _this.hiddenFileInput.style.position = "absolute"; 800 | _this.hiddenFileInput.style.top = "0"; 801 | _this.hiddenFileInput.style.left = "0"; 802 | _this.hiddenFileInput.style.height = "0"; 803 | _this.hiddenFileInput.style.width = "0"; 804 | document.body.appendChild(_this.hiddenFileInput); 805 | return _this.hiddenFileInput.addEventListener("change", function() { 806 | var file, files, _i, _len; 807 | files = _this.hiddenFileInput.files; 808 | if (files.length) { 809 | for (_i = 0, _len = files.length; _i < _len; _i++) { 810 | file = files[_i]; 811 | _this.addFile(file); 812 | } 813 | } 814 | return setupHiddenFileInput(); 815 | }); 816 | }; 817 | setupHiddenFileInput(); 818 | } 819 | this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL; 820 | _ref1 = this.events; 821 | for (_i = 0, _len = _ref1.length; _i < _len; _i++) { 822 | eventName = _ref1[_i]; 823 | this.on(eventName, this.options[eventName]); 824 | } 825 | this.on("uploadprogress", function() { 826 | return _this.updateTotalUploadProgress(); 827 | }); 828 | this.on("removedfile", function() { 829 | return _this.updateTotalUploadProgress(); 830 | }); 831 | this.on("canceled", function(file) { 832 | return _this.emit("complete", file); 833 | }); 834 | this.on("complete", function(file) { 835 | if (_this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) { 836 | return setTimeout((function() { 837 | return _this.emit("queuecomplete"); 838 | }), 0); 839 | } 840 | }); 841 | noPropagation = function(e) { 842 | e.stopPropagation(); 843 | if (e.preventDefault) { 844 | return e.preventDefault(); 845 | } else { 846 | return e.returnValue = false; 847 | } 848 | }; 849 | this.listeners = [ 850 | { 851 | element: this.element, 852 | events: { 853 | "dragstart": function(e) { 854 | return _this.emit("dragstart", e); 855 | }, 856 | "dragenter": function(e) { 857 | noPropagation(e); 858 | return _this.emit("dragenter", e); 859 | }, 860 | "dragover": function(e) { 861 | var efct; 862 | try { 863 | efct = e.dataTransfer.effectAllowed; 864 | } catch (_error) {} 865 | e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; 866 | noPropagation(e); 867 | return _this.emit("dragover", e); 868 | }, 869 | "dragleave": function(e) { 870 | return _this.emit("dragleave", e); 871 | }, 872 | "drop": function(e) { 873 | noPropagation(e); 874 | return _this.drop(e); 875 | }, 876 | "dragend": function(e) { 877 | return _this.emit("dragend", e); 878 | } 879 | } 880 | } 881 | ]; 882 | this.clickableElements.forEach(function(clickableElement) { 883 | return _this.listeners.push({ 884 | element: clickableElement, 885 | events: { 886 | "click": function(evt) { 887 | if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) { 888 | return _this.hiddenFileInput.click(); 889 | } 890 | } 891 | } 892 | }); 893 | }); 894 | this.enable(); 895 | return this.options.init.call(this); 896 | }; 897 | 898 | Dropzone.prototype.destroy = function() { 899 | var _ref; 900 | this.disable(); 901 | this.removeAllFiles(true); 902 | if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) { 903 | this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); 904 | this.hiddenFileInput = null; 905 | } 906 | delete this.element.dropzone; 907 | return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); 908 | }; 909 | 910 | Dropzone.prototype.updateTotalUploadProgress = function() { 911 | var acceptedFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref; 912 | totalBytesSent = 0; 913 | totalBytes = 0; 914 | acceptedFiles = this.getAcceptedFiles(); 915 | if (acceptedFiles.length) { 916 | _ref = this.getAcceptedFiles(); 917 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 918 | file = _ref[_i]; 919 | totalBytesSent += file.upload.bytesSent; 920 | totalBytes += file.upload.total; 921 | } 922 | totalUploadProgress = 100 * totalBytesSent / totalBytes; 923 | } else { 924 | totalUploadProgress = 100; 925 | } 926 | return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); 927 | }; 928 | 929 | Dropzone.prototype.getFallbackForm = function() { 930 | var existingFallback, fields, fieldsString, form; 931 | if (existingFallback = this.getExistingFallback()) { 932 | return existingFallback; 933 | } 934 | fieldsString = "
"; 935 | if (this.options.dictFallbackText) { 936 | fieldsString += "

" + this.options.dictFallbackText + "

"; 937 | } 938 | fieldsString += "
"; 939 | fields = Dropzone.createElement(fieldsString); 940 | if (this.element.tagName !== "FORM") { 941 | form = Dropzone.createElement("
"); 942 | form.appendChild(fields); 943 | } else { 944 | this.element.setAttribute("enctype", "multipart/form-data"); 945 | this.element.setAttribute("method", this.options.method); 946 | } 947 | return form != null ? form : fields; 948 | }; 949 | 950 | Dropzone.prototype.getExistingFallback = function() { 951 | var fallback, getFallback, tagName, _i, _len, _ref; 952 | getFallback = function(elements) { 953 | var el, _i, _len; 954 | for (_i = 0, _len = elements.length; _i < _len; _i++) { 955 | el = elements[_i]; 956 | if (/(^| )fallback($| )/.test(el.className)) { 957 | return el; 958 | } 959 | } 960 | }; 961 | _ref = ["div", "form"]; 962 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 963 | tagName = _ref[_i]; 964 | if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { 965 | return fallback; 966 | } 967 | } 968 | }; 969 | 970 | Dropzone.prototype.setupEventListeners = function() { 971 | var elementListeners, event, listener, _i, _len, _ref, _results; 972 | _ref = this.listeners; 973 | _results = []; 974 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 975 | elementListeners = _ref[_i]; 976 | _results.push((function() { 977 | var _ref1, _results1; 978 | _ref1 = elementListeners.events; 979 | _results1 = []; 980 | for (event in _ref1) { 981 | listener = _ref1[event]; 982 | _results1.push(elementListeners.element.addEventListener(event, listener, false)); 983 | } 984 | return _results1; 985 | })()); 986 | } 987 | return _results; 988 | }; 989 | 990 | Dropzone.prototype.removeEventListeners = function() { 991 | var elementListeners, event, listener, _i, _len, _ref, _results; 992 | _ref = this.listeners; 993 | _results = []; 994 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 995 | elementListeners = _ref[_i]; 996 | _results.push((function() { 997 | var _ref1, _results1; 998 | _ref1 = elementListeners.events; 999 | _results1 = []; 1000 | for (event in _ref1) { 1001 | listener = _ref1[event]; 1002 | _results1.push(elementListeners.element.removeEventListener(event, listener, false)); 1003 | } 1004 | return _results1; 1005 | })()); 1006 | } 1007 | return _results; 1008 | }; 1009 | 1010 | Dropzone.prototype.disable = function() { 1011 | var file, _i, _len, _ref, _results; 1012 | this.clickableElements.forEach(function(element) { 1013 | return element.classList.remove("dz-clickable"); 1014 | }); 1015 | this.removeEventListeners(); 1016 | _ref = this.files; 1017 | _results = []; 1018 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1019 | file = _ref[_i]; 1020 | _results.push(this.cancelUpload(file)); 1021 | } 1022 | return _results; 1023 | }; 1024 | 1025 | Dropzone.prototype.enable = function() { 1026 | this.clickableElements.forEach(function(element) { 1027 | return element.classList.add("dz-clickable"); 1028 | }); 1029 | return this.setupEventListeners(); 1030 | }; 1031 | 1032 | Dropzone.prototype.filesize = function(size) { 1033 | var string; 1034 | if (size >= 1024 * 1024 * 1024 * 1024 / 10) { 1035 | size = size / (1024 * 1024 * 1024 * 1024 / 10); 1036 | string = "TiB"; 1037 | } else if (size >= 1024 * 1024 * 1024 / 10) { 1038 | size = size / (1024 * 1024 * 1024 / 10); 1039 | string = "GiB"; 1040 | } else if (size >= 1024 * 1024 / 10) { 1041 | size = size / (1024 * 1024 / 10); 1042 | string = "MiB"; 1043 | } else if (size >= 1024 / 10) { 1044 | size = size / (1024 / 10); 1045 | string = "KiB"; 1046 | } else { 1047 | size = size * 10; 1048 | string = "b"; 1049 | } 1050 | return "" + (Math.round(size) / 10) + " " + string; 1051 | }; 1052 | 1053 | Dropzone.prototype._updateMaxFilesReachedClass = function() { 1054 | if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { 1055 | if (this.getAcceptedFiles().length === this.options.maxFiles) { 1056 | this.emit('maxfilesreached', this.files); 1057 | } 1058 | return this.element.classList.add("dz-max-files-reached"); 1059 | } else { 1060 | return this.element.classList.remove("dz-max-files-reached"); 1061 | } 1062 | }; 1063 | 1064 | Dropzone.prototype.drop = function(e) { 1065 | var files, items; 1066 | if (!e.dataTransfer) { 1067 | return; 1068 | } 1069 | this.emit("drop", e); 1070 | files = e.dataTransfer.files; 1071 | if (files.length) { 1072 | items = e.dataTransfer.items; 1073 | if (items && items.length && (items[0].webkitGetAsEntry != null)) { 1074 | this._addFilesFromItems(items); 1075 | } else { 1076 | this.handleFiles(files); 1077 | } 1078 | } 1079 | }; 1080 | 1081 | Dropzone.prototype.paste = function(e) { 1082 | var items, _ref; 1083 | if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) { 1084 | return; 1085 | } 1086 | this.emit("paste", e); 1087 | items = e.clipboardData.items; 1088 | if (items.length) { 1089 | return this._addFilesFromItems(items); 1090 | } 1091 | }; 1092 | 1093 | Dropzone.prototype.handleFiles = function(files) { 1094 | var file, _i, _len, _results; 1095 | _results = []; 1096 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1097 | file = files[_i]; 1098 | _results.push(this.addFile(file)); 1099 | } 1100 | return _results; 1101 | }; 1102 | 1103 | Dropzone.prototype._addFilesFromItems = function(items) { 1104 | var entry, item, _i, _len, _results; 1105 | _results = []; 1106 | for (_i = 0, _len = items.length; _i < _len; _i++) { 1107 | item = items[_i]; 1108 | if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) { 1109 | if (entry.isFile) { 1110 | _results.push(this.addFile(item.getAsFile())); 1111 | } else if (entry.isDirectory) { 1112 | _results.push(this._addFilesFromDirectory(entry, entry.name)); 1113 | } else { 1114 | _results.push(void 0); 1115 | } 1116 | } else if (item.getAsFile != null) { 1117 | if ((item.kind == null) || item.kind === "file") { 1118 | _results.push(this.addFile(item.getAsFile())); 1119 | } else { 1120 | _results.push(void 0); 1121 | } 1122 | } else { 1123 | _results.push(void 0); 1124 | } 1125 | } 1126 | return _results; 1127 | }; 1128 | 1129 | Dropzone.prototype._addFilesFromDirectory = function(directory, path) { 1130 | var dirReader, entriesReader, 1131 | _this = this; 1132 | dirReader = directory.createReader(); 1133 | entriesReader = function(entries) { 1134 | var entry, _i, _len; 1135 | for (_i = 0, _len = entries.length; _i < _len; _i++) { 1136 | entry = entries[_i]; 1137 | if (entry.isFile) { 1138 | entry.file(function(file) { 1139 | if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { 1140 | return; 1141 | } 1142 | file.fullPath = "" + path + "/" + file.name; 1143 | return _this.addFile(file); 1144 | }); 1145 | } else if (entry.isDirectory) { 1146 | _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name); 1147 | } 1148 | } 1149 | }; 1150 | return dirReader.readEntries(entriesReader, function(error) { 1151 | return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0; 1152 | }); 1153 | }; 1154 | 1155 | Dropzone.prototype.accept = function(file, done) { 1156 | if (file.size > this.options.maxFilesize * 1024 * 1024) { 1157 | return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); 1158 | } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { 1159 | return done(this.options.dictInvalidFileType); 1160 | } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { 1161 | done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles)); 1162 | return this.emit("maxfilesexceeded", file); 1163 | } else { 1164 | return this.options.accept.call(this, file, done); 1165 | } 1166 | }; 1167 | 1168 | Dropzone.prototype.addFile = function(file) { 1169 | var _this = this; 1170 | file.upload = { 1171 | progress: 0, 1172 | total: file.size, 1173 | bytesSent: 0 1174 | }; 1175 | this.files.push(file); 1176 | file.status = Dropzone.ADDED; 1177 | this.emit("addedfile", file); 1178 | this._enqueueThumbnail(file); 1179 | return this.accept(file, function(error) { 1180 | if (error) { 1181 | file.accepted = false; 1182 | _this._errorProcessing([file], error); 1183 | } else { 1184 | _this.enqueueFile(file); 1185 | } 1186 | return _this._updateMaxFilesReachedClass(); 1187 | }); 1188 | }; 1189 | 1190 | Dropzone.prototype.enqueueFiles = function(files) { 1191 | var file, _i, _len; 1192 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1193 | file = files[_i]; 1194 | this.enqueueFile(file); 1195 | } 1196 | return null; 1197 | }; 1198 | 1199 | Dropzone.prototype.enqueueFile = function(file) { 1200 | var _this = this; 1201 | file.accepted = true; 1202 | if (file.status === Dropzone.ADDED) { 1203 | file.status = Dropzone.QUEUED; 1204 | if (this.options.autoProcessQueue) { 1205 | return setTimeout((function() { 1206 | return _this.processQueue(); 1207 | }), 0); 1208 | } 1209 | } else { 1210 | throw new Error("This file can't be queued because it has already been processed or was rejected."); 1211 | } 1212 | }; 1213 | 1214 | Dropzone.prototype._thumbnailQueue = []; 1215 | 1216 | Dropzone.prototype._processingThumbnail = false; 1217 | 1218 | Dropzone.prototype._enqueueThumbnail = function(file) { 1219 | var _this = this; 1220 | if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { 1221 | this._thumbnailQueue.push(file); 1222 | return setTimeout((function() { 1223 | return _this._processThumbnailQueue(); 1224 | }), 0); 1225 | } 1226 | }; 1227 | 1228 | Dropzone.prototype._processThumbnailQueue = function() { 1229 | var _this = this; 1230 | if (this._processingThumbnail || this._thumbnailQueue.length === 0) { 1231 | return; 1232 | } 1233 | this._processingThumbnail = true; 1234 | return this.createThumbnail(this._thumbnailQueue.shift(), function() { 1235 | _this._processingThumbnail = false; 1236 | return _this._processThumbnailQueue(); 1237 | }); 1238 | }; 1239 | 1240 | Dropzone.prototype.removeFile = function(file) { 1241 | if (file.status === Dropzone.UPLOADING) { 1242 | this.cancelUpload(file); 1243 | } 1244 | this.files = without(this.files, file); 1245 | this.emit("removedfile", file); 1246 | if (this.files.length === 0) { 1247 | return this.emit("reset"); 1248 | } 1249 | }; 1250 | 1251 | Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) { 1252 | var file, _i, _len, _ref; 1253 | if (cancelIfNecessary == null) { 1254 | cancelIfNecessary = false; 1255 | } 1256 | _ref = this.files.slice(); 1257 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1258 | file = _ref[_i]; 1259 | if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { 1260 | this.removeFile(file); 1261 | } 1262 | } 1263 | return null; 1264 | }; 1265 | 1266 | Dropzone.prototype.createThumbnail = function(file, callback) { 1267 | var fileReader, 1268 | _this = this; 1269 | fileReader = new FileReader; 1270 | fileReader.onload = function() { 1271 | var img; 1272 | img = document.createElement("img"); 1273 | img.onload = function() { 1274 | var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3; 1275 | file.width = img.width; 1276 | file.height = img.height; 1277 | resizeInfo = _this.options.resize.call(_this, file); 1278 | if (resizeInfo.trgWidth == null) { 1279 | resizeInfo.trgWidth = _this.options.thumbnailWidth; 1280 | } 1281 | if (resizeInfo.trgHeight == null) { 1282 | resizeInfo.trgHeight = _this.options.thumbnailHeight; 1283 | } 1284 | canvas = document.createElement("canvas"); 1285 | ctx = canvas.getContext("2d"); 1286 | canvas.width = resizeInfo.trgWidth; 1287 | canvas.height = resizeInfo.trgHeight; 1288 | drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight); 1289 | thumbnail = canvas.toDataURL("image/png"); 1290 | _this.emit("thumbnail", file, thumbnail); 1291 | if (callback != null) { 1292 | return callback(); 1293 | } 1294 | }; 1295 | return img.src = fileReader.result; 1296 | }; 1297 | return fileReader.readAsDataURL(file); 1298 | }; 1299 | 1300 | Dropzone.prototype.processQueue = function() { 1301 | var i, parallelUploads, processingLength, queuedFiles; 1302 | parallelUploads = this.options.parallelUploads; 1303 | processingLength = this.getUploadingFiles().length; 1304 | i = processingLength; 1305 | if (processingLength >= parallelUploads) { 1306 | return; 1307 | } 1308 | queuedFiles = this.getQueuedFiles(); 1309 | if (!(queuedFiles.length > 0)) { 1310 | return; 1311 | } 1312 | if (this.options.uploadMultiple) { 1313 | return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); 1314 | } else { 1315 | while (i < parallelUploads) { 1316 | if (!queuedFiles.length) { 1317 | return; 1318 | } 1319 | this.processFile(queuedFiles.shift()); 1320 | i++; 1321 | } 1322 | } 1323 | }; 1324 | 1325 | Dropzone.prototype.processFile = function(file) { 1326 | return this.processFiles([file]); 1327 | }; 1328 | 1329 | Dropzone.prototype.processFiles = function(files) { 1330 | var file, _i, _len; 1331 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1332 | file = files[_i]; 1333 | file.processing = true; 1334 | file.status = Dropzone.UPLOADING; 1335 | this.emit("processing", file); 1336 | } 1337 | if (this.options.uploadMultiple) { 1338 | this.emit("processingmultiple", files); 1339 | } 1340 | return this.uploadFiles(files); 1341 | }; 1342 | 1343 | Dropzone.prototype._getFilesWithXhr = function(xhr) { 1344 | var file, files; 1345 | return files = (function() { 1346 | var _i, _len, _ref, _results; 1347 | _ref = this.files; 1348 | _results = []; 1349 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1350 | file = _ref[_i]; 1351 | if (file.xhr === xhr) { 1352 | _results.push(file); 1353 | } 1354 | } 1355 | return _results; 1356 | }).call(this); 1357 | }; 1358 | 1359 | Dropzone.prototype.cancelUpload = function(file) { 1360 | var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref; 1361 | if (file.status === Dropzone.UPLOADING) { 1362 | groupedFiles = this._getFilesWithXhr(file.xhr); 1363 | for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) { 1364 | groupedFile = groupedFiles[_i]; 1365 | groupedFile.status = Dropzone.CANCELED; 1366 | } 1367 | file.xhr.abort(); 1368 | for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) { 1369 | groupedFile = groupedFiles[_j]; 1370 | this.emit("canceled", groupedFile); 1371 | } 1372 | if (this.options.uploadMultiple) { 1373 | this.emit("canceledmultiple", groupedFiles); 1374 | } 1375 | } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) { 1376 | file.status = Dropzone.CANCELED; 1377 | this.emit("canceled", file); 1378 | if (this.options.uploadMultiple) { 1379 | this.emit("canceledmultiple", [file]); 1380 | } 1381 | } 1382 | if (this.options.autoProcessQueue) { 1383 | return this.processQueue(); 1384 | } 1385 | }; 1386 | 1387 | Dropzone.prototype.uploadFile = function(file) { 1388 | return this.uploadFiles([file]); 1389 | }; 1390 | 1391 | Dropzone.prototype.uploadFiles = function(files) { 1392 | var file, formData, handleError, headerName, headerValue, headers, input, inputName, inputType, key, option, progressObj, response, updateProgress, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, 1393 | _this = this; 1394 | xhr = new XMLHttpRequest(); 1395 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1396 | file = files[_i]; 1397 | file.xhr = xhr; 1398 | } 1399 | xhr.open(this.options.method, this.options.url, true); 1400 | xhr.withCredentials = !!this.options.withCredentials; 1401 | response = null; 1402 | handleError = function() { 1403 | var _j, _len1, _results; 1404 | _results = []; 1405 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1406 | file = files[_j]; 1407 | _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr)); 1408 | } 1409 | return _results; 1410 | }; 1411 | updateProgress = function(e) { 1412 | var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results; 1413 | if (e != null) { 1414 | progress = 100 * e.loaded / e.total; 1415 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1416 | file = files[_j]; 1417 | file.upload = { 1418 | progress: progress, 1419 | total: e.total, 1420 | bytesSent: e.loaded 1421 | }; 1422 | } 1423 | } else { 1424 | allFilesFinished = true; 1425 | progress = 100; 1426 | for (_k = 0, _len2 = files.length; _k < _len2; _k++) { 1427 | file = files[_k]; 1428 | if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) { 1429 | allFilesFinished = false; 1430 | } 1431 | file.upload.progress = progress; 1432 | file.upload.bytesSent = file.upload.total; 1433 | } 1434 | if (allFilesFinished) { 1435 | return; 1436 | } 1437 | } 1438 | _results = []; 1439 | for (_l = 0, _len3 = files.length; _l < _len3; _l++) { 1440 | file = files[_l]; 1441 | _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent)); 1442 | } 1443 | return _results; 1444 | }; 1445 | xhr.onload = function(e) { 1446 | var _ref; 1447 | if (files[0].status === Dropzone.CANCELED) { 1448 | return; 1449 | } 1450 | if (xhr.readyState !== 4) { 1451 | return; 1452 | } 1453 | response = xhr.responseText; 1454 | if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { 1455 | try { 1456 | response = JSON.parse(response); 1457 | } catch (_error) { 1458 | e = _error; 1459 | response = "Invalid JSON response from server."; 1460 | } 1461 | } 1462 | updateProgress(); 1463 | if (!((200 <= (_ref = xhr.status) && _ref < 300))) { 1464 | return handleError(); 1465 | } else { 1466 | return _this._finished(files, response, e); 1467 | } 1468 | }; 1469 | xhr.onerror = function() { 1470 | if (files[0].status === Dropzone.CANCELED) { 1471 | return; 1472 | } 1473 | return handleError(); 1474 | }; 1475 | progressObj = (_ref = xhr.upload) != null ? _ref : xhr; 1476 | progressObj.onprogress = updateProgress; 1477 | headers = { 1478 | "Accept": "application/json", 1479 | "Cache-Control": "no-cache", 1480 | "X-Requested-With": "XMLHttpRequest" 1481 | }; 1482 | if (this.options.headers) { 1483 | extend(headers, this.options.headers); 1484 | } 1485 | for (headerName in headers) { 1486 | headerValue = headers[headerName]; 1487 | xhr.setRequestHeader(headerName, headerValue); 1488 | } 1489 | formData = new FormData(); 1490 | if (this.options.params) { 1491 | _ref1 = this.options.params; 1492 | for (key in _ref1) { 1493 | value = _ref1[key]; 1494 | formData.append(key, value); 1495 | } 1496 | } 1497 | for (_j = 0, _len1 = files.length; _j < _len1; _j++) { 1498 | file = files[_j]; 1499 | this.emit("sending", file, xhr, formData); 1500 | } 1501 | if (this.options.uploadMultiple) { 1502 | this.emit("sendingmultiple", files, xhr, formData); 1503 | } 1504 | if (this.element.tagName === "FORM") { 1505 | _ref2 = this.element.querySelectorAll("input, textarea, select, button"); 1506 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 1507 | input = _ref2[_k]; 1508 | inputName = input.getAttribute("name"); 1509 | inputType = input.getAttribute("type"); 1510 | if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { 1511 | _ref3 = input.options; 1512 | for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { 1513 | option = _ref3[_l]; 1514 | if (option.selected) { 1515 | formData.append(inputName, option.value); 1516 | } 1517 | } 1518 | } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) { 1519 | formData.append(inputName, input.value); 1520 | } 1521 | } 1522 | } 1523 | for (_m = 0, _len4 = files.length; _m < _len4; _m++) { 1524 | file = files[_m]; 1525 | formData.append("" + this.options.paramName + (this.options.uploadMultiple ? "[]" : ""), file, file.name); 1526 | } 1527 | return xhr.send(formData); 1528 | }; 1529 | 1530 | Dropzone.prototype._finished = function(files, responseText, e) { 1531 | var file, _i, _len; 1532 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1533 | file = files[_i]; 1534 | file.status = Dropzone.SUCCESS; 1535 | this.emit("success", file, responseText, e); 1536 | this.emit("complete", file); 1537 | } 1538 | if (this.options.uploadMultiple) { 1539 | this.emit("successmultiple", files, responseText, e); 1540 | this.emit("completemultiple", files); 1541 | } 1542 | if (this.options.autoProcessQueue) { 1543 | return this.processQueue(); 1544 | } 1545 | }; 1546 | 1547 | Dropzone.prototype._errorProcessing = function(files, message, xhr) { 1548 | var file, _i, _len; 1549 | for (_i = 0, _len = files.length; _i < _len; _i++) { 1550 | file = files[_i]; 1551 | file.status = Dropzone.ERROR; 1552 | this.emit("error", file, message, xhr); 1553 | this.emit("complete", file); 1554 | } 1555 | if (this.options.uploadMultiple) { 1556 | this.emit("errormultiple", files, message, xhr); 1557 | this.emit("completemultiple", files); 1558 | } 1559 | if (this.options.autoProcessQueue) { 1560 | return this.processQueue(); 1561 | } 1562 | }; 1563 | 1564 | return Dropzone; 1565 | 1566 | })(Em); 1567 | 1568 | Dropzone.version = "4.0.0-dev"; 1569 | 1570 | Dropzone.options = {}; 1571 | 1572 | Dropzone.optionsForElement = function(element) { 1573 | if (element.getAttribute("id")) { 1574 | return Dropzone.options[camelize(element.getAttribute("id"))]; 1575 | } else { 1576 | return void 0; 1577 | } 1578 | }; 1579 | 1580 | Dropzone.instances = []; 1581 | 1582 | Dropzone.forElement = function(element) { 1583 | if (typeof element === "string") { 1584 | element = document.querySelector(element); 1585 | } 1586 | if ((element != null ? element.dropzone : void 0) == null) { 1587 | throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."); 1588 | } 1589 | return element.dropzone; 1590 | }; 1591 | 1592 | Dropzone.autoDiscover = true; 1593 | 1594 | Dropzone.discover = function() { 1595 | var checkElements, dropzone, dropzones, _i, _len, _results; 1596 | if (document.querySelectorAll) { 1597 | dropzones = document.querySelectorAll(".dropzone"); 1598 | } else { 1599 | dropzones = []; 1600 | checkElements = function(elements) { 1601 | var el, _i, _len, _results; 1602 | _results = []; 1603 | for (_i = 0, _len = elements.length; _i < _len; _i++) { 1604 | el = elements[_i]; 1605 | if (/(^| )dropzone($| )/.test(el.className)) { 1606 | _results.push(dropzones.push(el)); 1607 | } else { 1608 | _results.push(void 0); 1609 | } 1610 | } 1611 | return _results; 1612 | }; 1613 | checkElements(document.getElementsByTagName("div")); 1614 | checkElements(document.getElementsByTagName("form")); 1615 | } 1616 | _results = []; 1617 | for (_i = 0, _len = dropzones.length; _i < _len; _i++) { 1618 | dropzone = dropzones[_i]; 1619 | if (Dropzone.optionsForElement(dropzone) !== false) { 1620 | _results.push(new Dropzone(dropzone)); 1621 | } else { 1622 | _results.push(void 0); 1623 | } 1624 | } 1625 | return _results; 1626 | }; 1627 | 1628 | Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; 1629 | 1630 | Dropzone.isBrowserSupported = function() { 1631 | var capableBrowser, regex, _i, _len, _ref; 1632 | capableBrowser = true; 1633 | if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { 1634 | if (!("classList" in document.createElement("a"))) { 1635 | capableBrowser = false; 1636 | } else { 1637 | _ref = Dropzone.blacklistedBrowsers; 1638 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1639 | regex = _ref[_i]; 1640 | if (regex.test(navigator.userAgent)) { 1641 | capableBrowser = false; 1642 | continue; 1643 | } 1644 | } 1645 | } 1646 | } else { 1647 | capableBrowser = false; 1648 | } 1649 | return capableBrowser; 1650 | }; 1651 | 1652 | without = function(list, rejectedItem) { 1653 | var item, _i, _len, _results; 1654 | _results = []; 1655 | for (_i = 0, _len = list.length; _i < _len; _i++) { 1656 | item = list[_i]; 1657 | if (item !== rejectedItem) { 1658 | _results.push(item); 1659 | } 1660 | } 1661 | return _results; 1662 | }; 1663 | 1664 | camelize = function(str) { 1665 | return str.replace(/[\-_](\w)/g, function(match) { 1666 | return match[1].toUpperCase(); 1667 | }); 1668 | }; 1669 | 1670 | Dropzone.createElement = function(string) { 1671 | var div; 1672 | div = document.createElement("div"); 1673 | div.innerHTML = string; 1674 | return div.childNodes[0]; 1675 | }; 1676 | 1677 | Dropzone.elementInside = function(element, container) { 1678 | if (element === container) { 1679 | return true; 1680 | } 1681 | while (element = element.parentNode) { 1682 | if (element === container) { 1683 | return true; 1684 | } 1685 | } 1686 | return false; 1687 | }; 1688 | 1689 | Dropzone.getElement = function(el, name) { 1690 | var element; 1691 | if (typeof el === "string") { 1692 | element = document.querySelector(el); 1693 | } else if (el.nodeType != null) { 1694 | element = el; 1695 | } 1696 | if (element == null) { 1697 | throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); 1698 | } 1699 | return element; 1700 | }; 1701 | 1702 | Dropzone.getElements = function(els, name) { 1703 | var e, el, elements, _i, _j, _len, _len1, _ref; 1704 | if (els instanceof Array) { 1705 | elements = []; 1706 | try { 1707 | for (_i = 0, _len = els.length; _i < _len; _i++) { 1708 | el = els[_i]; 1709 | elements.push(this.getElement(el, name)); 1710 | } 1711 | } catch (_error) { 1712 | e = _error; 1713 | elements = null; 1714 | } 1715 | } else if (typeof els === "string") { 1716 | elements = []; 1717 | _ref = document.querySelectorAll(els); 1718 | for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { 1719 | el = _ref[_j]; 1720 | elements.push(el); 1721 | } 1722 | } else if (els.nodeType != null) { 1723 | elements = [els]; 1724 | } 1725 | if (!((elements != null) && elements.length)) { 1726 | throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); 1727 | } 1728 | return elements; 1729 | }; 1730 | 1731 | Dropzone.confirm = function(question, accepted, rejected) { 1732 | if (window.confirm(question)) { 1733 | return accepted(); 1734 | } else if (rejected != null) { 1735 | return rejected(); 1736 | } 1737 | }; 1738 | 1739 | Dropzone.isValidFile = function(file, acceptedFiles) { 1740 | var baseMimeType, mimeType, validType, _i, _len; 1741 | if (!acceptedFiles) { 1742 | return true; 1743 | } 1744 | acceptedFiles = acceptedFiles.split(","); 1745 | mimeType = file.type; 1746 | baseMimeType = mimeType.replace(/\/.*$/, ""); 1747 | for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) { 1748 | validType = acceptedFiles[_i]; 1749 | validType = validType.trim(); 1750 | if (validType.charAt(0) === ".") { 1751 | if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) { 1752 | return true; 1753 | } 1754 | } else if (/\/\*$/.test(validType)) { 1755 | if (baseMimeType === validType.replace(/\/.*$/, "")) { 1756 | return true; 1757 | } 1758 | } else { 1759 | if (mimeType === validType) { 1760 | return true; 1761 | } 1762 | } 1763 | } 1764 | return false; 1765 | }; 1766 | 1767 | if (typeof jQuery !== "undefined" && jQuery !== null) { 1768 | jQuery.fn.dropzone = function(options) { 1769 | return this.each(function() { 1770 | return new Dropzone(this, options); 1771 | }); 1772 | }; 1773 | } 1774 | 1775 | if (typeof module !== "undefined" && module !== null) { 1776 | module.exports = Dropzone; 1777 | } else { 1778 | window.Dropzone = Dropzone; 1779 | } 1780 | 1781 | Dropzone.ADDED = "added"; 1782 | 1783 | Dropzone.QUEUED = "queued"; 1784 | 1785 | Dropzone.ACCEPTED = Dropzone.QUEUED; 1786 | 1787 | Dropzone.UPLOADING = "uploading"; 1788 | 1789 | Dropzone.PROCESSING = Dropzone.UPLOADING; 1790 | 1791 | Dropzone.CANCELED = "canceled"; 1792 | 1793 | Dropzone.ERROR = "error"; 1794 | 1795 | Dropzone.SUCCESS = "success"; 1796 | 1797 | /* 1798 | 1799 | Bugfix for iOS 6 and 7 1800 | Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios 1801 | based on the work of https://github.com/stomita/ios-imagefile-megapixel 1802 | */ 1803 | 1804 | 1805 | detectVerticalSquash = function(img) { 1806 | var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy; 1807 | iw = img.naturalWidth; 1808 | ih = img.naturalHeight; 1809 | canvas = document.createElement("canvas"); 1810 | canvas.width = 1; 1811 | canvas.height = ih; 1812 | ctx = canvas.getContext("2d"); 1813 | ctx.drawImage(img, 0, 0); 1814 | data = ctx.getImageData(0, 0, 1, ih).data; 1815 | sy = 0; 1816 | ey = ih; 1817 | py = ih; 1818 | while (py > sy) { 1819 | alpha = data[(py - 1) * 4 + 3]; 1820 | if (alpha === 0) { 1821 | ey = py; 1822 | } else { 1823 | sy = py; 1824 | } 1825 | py = (ey + sy) >> 1; 1826 | } 1827 | ratio = py / ih; 1828 | if (ratio === 0) { 1829 | return 1; 1830 | } else { 1831 | return ratio; 1832 | } 1833 | }; 1834 | 1835 | drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { 1836 | var vertSquashRatio; 1837 | vertSquashRatio = detectVerticalSquash(img); 1838 | return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); 1839 | }; 1840 | 1841 | /* 1842 | # contentloaded.js 1843 | # 1844 | # Author: Diego Perini (diego.perini at gmail.com) 1845 | # Summary: cross-browser wrapper for DOMContentLoaded 1846 | # Updated: 20101020 1847 | # License: MIT 1848 | # Version: 1.2 1849 | # 1850 | # URL: 1851 | # http://javascript.nwbox.com/ContentLoaded/ 1852 | # http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE 1853 | */ 1854 | 1855 | 1856 | contentLoaded = function(win, fn) { 1857 | var add, doc, done, init, poll, pre, rem, root, top; 1858 | done = false; 1859 | top = true; 1860 | doc = win.document; 1861 | root = doc.documentElement; 1862 | add = (doc.addEventListener ? "addEventListener" : "attachEvent"); 1863 | rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); 1864 | pre = (doc.addEventListener ? "" : "on"); 1865 | init = function(e) { 1866 | if (e.type === "readystatechange" && doc.readyState !== "complete") { 1867 | return; 1868 | } 1869 | (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); 1870 | if (!done && (done = true)) { 1871 | return fn.call(win, e.type || e); 1872 | } 1873 | }; 1874 | poll = function() { 1875 | var e; 1876 | try { 1877 | root.doScroll("left"); 1878 | } catch (_error) { 1879 | e = _error; 1880 | setTimeout(poll, 50); 1881 | return; 1882 | } 1883 | return init("poll"); 1884 | }; 1885 | if (doc.readyState !== "complete") { 1886 | if (doc.createEventObject && root.doScroll) { 1887 | try { 1888 | top = !win.frameElement; 1889 | } catch (_error) {} 1890 | if (top) { 1891 | poll(); 1892 | } 1893 | } 1894 | doc[add](pre + "DOMContentLoaded", init, false); 1895 | doc[add](pre + "readystatechange", init, false); 1896 | return win[add](pre + "load", init, false); 1897 | } 1898 | }; 1899 | 1900 | Dropzone._autoDiscoverFunction = function() { 1901 | if (Dropzone.autoDiscover) { 1902 | return Dropzone.discover(); 1903 | } 1904 | }; 1905 | 1906 | contentLoaded(window, Dropzone._autoDiscoverFunction); 1907 | 1908 | }).call(this); 1909 | 1910 | }); 1911 | require.alias("component-emitter/index.js", "dropzone/deps/emitter/index.js"); 1912 | require.alias("component-emitter/index.js", "emitter/index.js"); 1913 | if (typeof exports == "object") { 1914 | module.exports = require("dropzone"); 1915 | } else if (typeof define == "function" && define.amd) { 1916 | define(function(){ return require("dropzone"); }); 1917 | } else { 1918 | this["Dropzone"] = require("dropzone"); 1919 | }})(); -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Select Image
10 |
Submit
11 | 12 |
13 |

droparea

14 |
15 |

previewsContainer

16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /upload/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moremorefor/flask-fileupload-dropzonejs/ee70558ca775f87237f959e7a7922b0298b6a15a/upload/.gitkeep --------------------------------------------------------------------------------