PageSourceSearch

https://www.ludocards.com/dropzone.js

js ludocards.com collected 2026-10-10 01:16:20 UTC 121,533 bytes, 3,532 lines download raw bytes

1"use strict";
2
3var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4
5function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6
7function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
8
9function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10
11/*
12 *
13 * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
14 *
15 * Copyright (c) 2012, Matias Meno
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining a copy
18 * of this software and associated documentation files (the "Software"), to deal
19 * in the Software without restriction, including without limitation the rights
20 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 * copies of the Software, and to permit persons to whom the Software is
22 * furnished to do so, subject to the following conditions:
23 *
24 * The above copyright notice and this permission notice shall be included in
25 * all copies or substantial portions of the Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33 * THE SOFTWARE.
34 *
35 */
36
37// The Emitter class provides the ability to call `.on()` on Dropzone to listen
38// to events.
39// It is strongly based on component's emitter class, and I removed the
40// functionality because of the dependency hell with different frameworks.
41var Emitter = function () {
42  function Emitter() {
43    _classCallCheck(this, Emitter);
44  }
45
46  _createClass(Emitter, [{
47    key: "on",
48
49    // Add an event listener for given event
50    value: function on(event, fn) {
51      this._callbacks = this._callbacks || {};
52      // Create namespace for this event
53      if (!this._callbacks[event]) {
54        this._callbacks[event] = [];
55      }
56      this._callbacks[event].push(fn);
57      return this;
58    }
59  }, {
60    key: "emit",
61    value: function emit(event) {
62      this._callbacks = this._callbacks || {};
63      var callbacks = this._callbacks[event];
64
65      if (callbacks) {
66        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
67          args[_key - 1] = arguments[_key];
68        }
69
70        for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
71          var _ref;
72
73          if (_isArray) {
74            if (_i >= _iterator.length) break;
75            _ref = _iterator[_i++];
76          } else {
77            _i = _iterator.next();
78            if (_i.done) break;
79            _ref = _i.value;
80          }
81
82          var callback = _ref;
83
84          callback.apply(this, args);
85        }
86      }
87
88      return this;
89    }
90
91    // Remove event listener for given event. If fn is not provided, all event
92    // listeners for that event will be removed. If neither is provided, all
93    // event listeners will be removed.
94
95  }, {
96    key: "off",
97    value: function off(event, fn) {
98      if (!this._callbacks || arguments.length === 0) {
99        this._callbacks = {};
100        return this;
101      }
102
103      // specific event
104      var callbacks = this._callbacks[event];
105      if (!callbacks) {
106        return this;
107      }
108
109      // remove all handlers
110      if (arguments.length === 1) {
111        delete this._callbacks[event];
112        return this;
113      }
114
115      // remove specific handler
116      for (var i = 0; i < callbacks.length; i++) {
117        var callback = callbacks[i];
118        if (callback === fn) {
119          callbacks.splice(i, 1);
120          break;
121        }
122      }
123
124      return this;
125    }
126  }]);
127
128  return Emitter;
129}();
130
131var Dropzone = function (_Emitter) {
132  _inherits(Dropzone, _Emitter);
133
134  _createClass(Dropzone, null, [{
135    key: "initClass",
136    value: function initClass() {
137
138      // Exposing the emitter class, mainly for tests
139      this.prototype.Emitter = Emitter;
140
141      /*
142       This is a list of all available events you can register on a dropzone object.
143        You can register an event handler like this:
144        dropzone.on("dragEnter", function() { });
145        */
146      this.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
147
148      this.prototype.defaultOptions = {
149        /**
150         * Has to be specified on elements other than form (or when the form
151         * doesn't have an `action` attribute). You can also
152         * provide a function that will be called with `files` and
153         * must return the url (since `v3.12.0`)
154         */
155        url: null,
156
157        /**
158         * Can be changed to `"put"` if necessary. You can also provide a function
159         * that will be called with `files` and must return the method (since `v3.12.0`).
160         */
161        method: "post",
162
163        /**
164         * Will be set on the XHRequest.
165         */
166        withCredentials: false,
167
168        /**
169         * The timeout for the XHR requests in milliseconds (since `v4.4.0`).
170         */
171        timeout: 30000,
172
173        /**
174         * How many file uploads to process in parallel (See the
175         * Enqueuing file uploads* documentation section for more info)
176         */
177        parallelUploads: 2,
178
179        /**
180         * Whether to send multiple files in one request. If
181         * this it set to true, then the fallback file input element will
182         * have the `multiple` attribute as well. This option will
183         * also trigger additional events (like `processingmultiple`). See the events
184         * documentation section for more information.
185         */
186        uploadMultiple: false,
187
188        /**
189         * Whether you want files to be uploaded in chunks to your server. This can't be
190         * used in combination with `uploadMultiple`.
191         *
192         * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.
193         */
194        chunking: false,
195
196        /**
197         * If `chunking` is enabled, this defines whether **every** file should be chunked,
198         * even if the file size is below chunkSize. This means, that the additional chunk
199         * form data will be submitted and the `chunksUploaded` callback will be invoked.
200         */
201        forceChunking: false,
202
203        /**
204         * If `chunking` is `true`, then this defines the chunk size in bytes.
205         */
206        chunkSize: 2000000,
207
208        /**
209         * If `true`, the individual chunks of a file are being uploaded simultaneously.
210         */
211        parallelChunkUploads: false,
212
213        /**
214         * Whether a chunk should be retried if it fails.
215         */
216        retryChunks: false,
217
218        /**
219         * If `retryChunks` is true, how many times should it be retried.
220         */
221        retryChunksLimit: 3,
222
223        /**
224         * If not `null` defines how many files this Dropzone handles. If it exceeds,
225         * the event `maxfilesexceeded` will be called. The dropzone element gets the
226         * class `dz-max-files-reached` accordingly so you can provide visual feedback.
227         */
228        maxFilesize: 256,
229
230        /**
231         * The name of the file param that gets transferred.
232         * **NOTE**: If you have the option  `uploadMultiple` set to `true`, then
233         * Dropzone will append `[]` to the name.
234         */
235        paramName: "file",
236
237        /**
238         * Whether thumbnails for images should be generated
239         */
240        createImageThumbnails: true,
241
242        /**
243         * In MB. When the filename exceeds this limit, the thumbnail will not be generated.
244         */
245        maxThumbnailFilesize: 10,
246
247        /**
248         * If `null`, the ratio of the image will be used to calculate it.
249         */
250        thumbnailWidth: 120,
251
252        /**
253         * The same as `thumbnailWidth`. If both are null, images will not be resized.
254         */
255        thumbnailHeight: 120,
256
257        /**
258         * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.
259         * Can be either `contain` or `crop`.
260         */
261        thumbnailMethod: 'crop',
262
263        /**
264         * If set, images will be resized to these dimensions before being **uploaded**.
265         * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect
266         * ratio of the file will be preserved.
267         *
268         * The `options.transformFile` function uses these options, so if the `transformFile` function
269         * is overridden, these options don't do anything.
270         */
271        resizeWidth: null,
272
273        /**
274         * See `resizeWidth`.
275         */
276        resizeHeight: null,
277
278        /**
279         * The mime type of the resized image (before it gets uploaded to the server).
280         * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.
281         * See `resizeWidth` for more information.
282         */
283        resizeMimeType: null,
284
285        /**
286         * The quality of the resized images. See `resizeWidth`.
287         */
288        resizeQuality: 0.8,
289
290        /**
291         * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.
292         * Can be either `contain` or `crop`.
293         */
294        resizeMethod: 'contain',
295
296        /**
297         * The base that is used to calculate the filesize. You can change this to
298         * 1024 if you would rather display kibibytes, mebibytes, etc...
299         * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.
300         * You can change this to `1024` if you don't care about validity.
301         */
302        filesizeBase: 1000,
303
304        /**
305         * Can be used to limit the maximum number of files that will be handled by this Dropzone
306         */
307        maxFiles: null,
308
309        /**
310         * An optional object to send additional headers to the server. Eg:
311         * `{ "My-Awesome-Header": "header value" }`
312         */
313        headers: null,
314
315        /**
316         * If `true`, the dropzone element itself will be clickable, if `false`
317         * nothing will be clickable.
318         *
319         * You can also pass an HTML element, a CSS selector (for multiple elements)
320         * or an array of those. In that case, all of those elements will trigger an
321         * upload when clicked.
322         */
323        clickable: true,
324
325        /**
326         * Whether hidden files in directories should be ignored.
327         */
328        ignoreHiddenFiles: true,
329
330        /**
331         * The default implementation of `accept` checks the file's mime type or
332         * extension against this list. This is a comma separated list of mime
333         * types or file extensions.
334         *
335         * Eg.: `image/*,application/pdf,.psd`
336         *
337         * If the Dropzone is `clickable` this option will also be used as
338         * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)
339         * parameter on the hidden file input as well.
340         */
341        acceptedFiles: null,
342
343        /**
344         * **Deprecated!**
345         * Use acceptedFiles instead.
346         */
347        acceptedMimeTypes: null,
348
349        /**
350         * If false, files will be added to the queue but the queue will not be
351         * processed automatically.
352         * This can be useful if you need some additional user input before sending
353         * files (or if you want want all files sent at once).
354         * If you're ready to send the file simply call `myDropzone.processQueue()`.
355         *
356         * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation
357         * section for more information.
358         */
359        autoProcessQueue: true,
360
361        /**
362         * If false, files added to the dropzone will not be queued by default.
363         * You'll have to call `enqueueFile(file)` manually.
364         */
365        autoQueue: true,
366
367        /**
368         * If `true`, this will add a link to every file preview to remove or cancel (if
369         * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`
370         * and `dictRemoveFile` options are used for the wording.
371         */
372        addRemoveLinks: false,
373
374        /**
375         * Defines where to display the file previews – if `null` the
376         * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS
377         * selector. The element should have the `dropzone-previews` class so
378         * the previews are displayed properly.
379         */
380        previewsContainer: null,
381
382        /**
383         * This is the element the hidden input field (which is used when clicking on the
384         * dropzone to trigger file selection) will be appended to. This might
385         * be important in case you use frameworks to switch the content of your page.
386         *
387         * Can be a selector string, or an element directly.
388         */
389        hiddenInputContainer: "body",
390
391        /**
392         * If null, no capture type will be specified
393         * If camera, mobile devices will skip the file selection and choose camera
394         * If microphone, mobile devices will skip the file selection and choose the microphone
395         * If camcorder, mobile devices will skip the file selection and choose the camera in video mode
396         * On apple devices multiple must be set to false.  AcceptedFiles may need to
397         * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").
398         */
399        capture: null,
400
401        /**
402         * **Deprecated**. Use `renameFile` instead.
403         */
404        renameFilename: null,
405
406        /**
407         * A function that is invoked before the file is uploaded to the server and renames the file.
408         * This function gets the `File` as argument and can use the `file.name`. The actual name of the
409         * file that gets used during the upload can be accessed through `file.upload.filename`.
410         */
411        renameFile: null,
412
413        /**
414         * If `true` the fallback will be forced. This is very useful to test your server
415         * implementations first and make sure that everything works as
416         * expected without dropzone if you experience problems, and to test
417         * how your fallbacks will look.
418         */
419        forceFallback: false,
420
421        /**
422         * The text used before any files are dropped.
423         */
424        dictDefaultMessage: "Drop files here to upload",
425
426        /**
427         * The text that replaces the default message text it the browser is not supported.
428         */
429        dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
430
431        /**
432         * The text that will be added before the fallback form.
433         * If you provide a  fallback element yourself, or if this option is `null` this will
434         * be ignored.
435         */
436        dictFallbackText: "Please use the fallback form below to upload your files like in the olde
436n days.",
437
438        /**
439         * If the filesize is too big.
440         * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.
441         */
442        dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
443
444        /**
445         * If the file doesn't match the file type.
446         */
447        dictInvalidFileType: "You can't upload files of this type.",
448
449        /**
450         * If the server response was invalid.
451         * `{{statusCode}}` will be replaced with the servers status code.
452         */
453        dictResponseError: "Server responded with {{statusCode}} code.",
454
455        /**
456         * If `addRemoveLinks` is true, the text to be used for the cancel upload link.
457         */
458        dictCancelUpload: "Cancel upload",
459
460        /**
461         * The text that is displayed if an upload was manually canceled
462         */
463        dictUploadCanceled: "Upload canceled.",
464
465        /**
466         * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.
467         */
468        dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
469
470        /**
471         * If `addRemoveLinks` is true, the text to be used to remove a file.
472         */
473        dictRemoveFile: "Remove file",
474
475        /**
476         * If this is not null, then the user will be prompted before removing a file.
477         */
478        dictRemoveFileConfirmation: null,
479
480        /**
481         * Displayed if `maxFiles` is st and exceeded.
482         * The string `{{maxFiles}}` will be replaced by the configuration value.
483         */
484        dictMaxFilesExceeded: "You can not upload any more files.",
485
486        /**
487         * Allows you to translate the different units. Starting with `tb` for terabytes and going down to
488         * `b` for bytes.
489         */
490        dictFileSizeUnits: { tb: "TB", gb: "GB", mb: "MB", kb: "KB", b: "b" },
491        /**
492         * Called when dropzone initialized
493         * You can add event listeners here
494         */
495        init: function init() {},
496
497
498        /**
499         * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`
500         * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case
501         * of a function, this needs to return a map.
502         *
503         * The default implementation does nothing for normal uploads, but adds relevant information for
504         * chunked uploads.
505         *
506         * This is the same as adding hidden input fields in the form element.
507         */
508        params: function params(files, xhr, chunk) {
509          if (chunk) {
510            return {
511              dzuuid: chunk.file.upload.uuid,
512              dzchunkindex: chunk.index,
513              dztotalfilesize: chunk.file.size,
514              dzchunksize: this.options.chunkSize,
515              dztotalchunkcount: chunk.file.upload.totalChunkCount,
516              dzchunkbyteoffset: chunk.index * this.options.chunkSize
517            };
518          }
519        },
520
521
522        /**
523         * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)
524         * and a `done` function as parameters.
525         *
526         * If the done function is invoked without arguments, the file is "accepted" and will
527         * be processed. If you pass an error message, the file is rejected, and the error
528         * message will be displayed.
529         * This function will not be called if the file is too big or doesn't match the mime types.
530         */
531        accept: function accept(file, done) {
532          return done();
533        },
534
535
536        /**
537         * The callback that will be invoked when all chunks have been uploaded for a file.
538         * It gets the file for which the chunks have been uploaded as the first parameter,
539         * and the `done` function as second. `done()` needs to be invoked when everything
540         * needed to finish the upload process is done.
541         */
542        chunksUploaded: function chunksUploaded(file, done) {
543          done();
544        },
545
546        /**
547         * Gets called when the browser is not supported.
548         * The default implementation shows the fallback input field and adds
549         * a text.
550         */
551        fallback: function fallback() {
552          // This code should pass in IE7... :(
553          var messageElement = void 0;
554          this.element.className = this.element.className + " dz-browser-not-supported";
555
556          for (var _iterator2 = this.element.getElementsByTagName("div"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
557            var _ref2;
558
559            if (_isArray2) {
560              if (_i2 >= _iterator2.length) break;
561              _ref2 = _iterator2[_i2++];
562            } else {
563              _i2 = _iterator2.next();
564              if (_i2.done) break;
565              _ref2 = _i2.value;
566            }
567
568            var child = _ref2;
569
570            if (/(^| )dz-message($| )/.test(child.className)) {
571              messageElement = child;
572              child.className = "dz-message"; // Removes the 'dz-default' class
573              break;
574            }
575          }
576          if (!messageElement) {
577            messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
578            this.element.appendChild(messageElement);
579          }
580
581          var span = messageElement.getElementsByTagName("span")[0];
582          if (span) {
583            if (span.textContent != null) {
584              span.textContent = this.options.dictFallbackMessage;
585            }
585 else if (span.innerText != null) {
586              span.innerText = this.options.dictFallbackMessage;
587            }
588          }
589
590          return this.element.appendChild(this.getFallbackForm());
591        },
592
593
594        /**
595         * Gets called to calculate the thumbnail dimensions.
596         *
597         * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:
598         *
599         *  - `srcWidth` & `srcHeight` (required)
600         *  - `trgWidth` & `trgHeight` (required)
601         *  - `srcX` & `srcY` (optional, default `0`)
602         *  - `trgX` & `trgY` (optional, default `0`)
603         *
604         * Those values are going to be used by `ctx.drawImage()`.
605         */
606        resize: function resize(file, width, height, resizeMethod) {
607          var info = {
608            srcX: 0,
609            srcY: 0,
610            srcWidth: file.width,
611            srcHeight: file.height
612          };
613
614          var srcRatio = file.width / file.height;
615
616          // Automatically calculate dimensions if not specified
617          if (width == null && height == null) {
618            width = info.srcWidth;
619            height = info.srcHeight;
620          } else if (width == null) {
621            width = height * srcRatio;
622          } else if (height == null) {
623            height = width / srcRatio;
624          }
625
626          // Make sure images aren't upscaled
627          width = Math.min(width, info.srcWidth);
628          height = Math.min(height, info.srcHeight);
629
630          var trgRatio = width / height;
631
632          if (info.srcWidth > width || info.srcHeight > height) {
633            // Image is bigger and needs rescaling
634            if (resizeMethod === 'crop') {
635              if (srcRatio > trgRatio) {
636                info.srcHeight = file.height;
637                info.srcWidth = info.srcHeight * trgRatio;
638              } else {
639                info.srcWidth = file.width;
640                info.srcHeight = info.srcWidth / trgRatio;
641              }
642            } else if (resizeMethod === 'contain') {
643              // Method 'contain'
644              if (srcRatio > trgRatio) {
645                height = width / srcRatio;
646              } else {
647                width = height * srcRatio;
648              }
649            } else {
650              throw new Error("Unknown resizeMethod '" + resizeMethod + "'");
651            }
652          }
653
654          info.srcX = (file.width - info.srcWidth) / 2;
655          info.srcY = (file.height - info.srcHeight) / 2;
656
657          info.trgWidth = width;
658          info.trgHeight = height;
659
660          return info;
661        },
662
663
664        /**
665         * Can be used to transform the file (for example, resize an image if necessary).
666         *
667         * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes
668         * images according to those dimensions.
669         *
670         * Gets the `file` as the first parameter, and a `done()` function as the second, that needs
671         * to be invoked with the file when the transformation is done.
672         */
673        transformFile: function transformFile(file, done) {
674          if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
675            return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
676          } else {
677            return done(file);
678          }
679        },
680
681
682        /**
683         * A string that contains the template used for each dropped
684         * file. Change it to fulfill your needs but make sure to properly
685         * provide all elements.
686         *
687         * If you want to use an actual HTML element instead of providing a String
688         * as a config option, you could create a div with the id `tpl`,
689         * put the template inside it and provide the element like this:
690         *
691         *     document
692         *       .querySelector('#tpl')
693         *       .innerHTML
694         *
695         */
696        previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n  <div class=\"dz-details\">\n    <div class=\"dz-size\"><span data-dz-size></span></div>\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\n  </div>\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n  <div class=\"dz-success-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Check</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n      </g>\n    </svg>\n  </div>\n  <div class=\"dz-error-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Error</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n        </g>\n      </g>\n    </svg>\n  </div>\n</div>",
697
698        // END OPTIONS
699        // (Required by the dropzone documentation parser)
700
701
702        /*
703         Those functions register themselves to the events on init and handle all
704         the user interface specific stuff. Overwriting them won't break the upload
705         but can break the way it's displayed.
706         You can overwrite them if you don't like the default behavior. If you just
707         want to add an additional event handler, register it on the dropzone object
708         and don't overwrite those options.
709         */
710
711        // Those are self explanatory and simply concern the DragnDrop.
712        drop: function drop(e) {
713          return this.element.classList.remove("dz-drag-hover");
714        },
715        dragstart: function dragstart(e) {},
716        dragend: function dragend(e) {
717          return this.element.classList.remove("dz-drag-hover");
718        },
719        dragenter: function dragenter(e) {
720          return this.element.classList.add("dz-drag-hover");
721        },
722        dragover: function dragover(e) {
723          return this.element.classList.add("dz-drag-hover");
724        },
725        dragleave: function dragleave(e) {
726          return this.element.classList.remove("dz-drag-hover");
727        },
728        paste: function paste(e) {},
729
730
731        // Called whenever there are no files left in the dropzone anymore, and the
732        // dropzone should be displayed as if in the initial state.
733        reset: function reset() {
734          return this.element.classList.remove("dz-started");
735        },
736
737
738        // Called when a file is added to the queue
739        // Receives `file`
740        addedfile: function addedfile(file) {
741          var _this2 = this;
742
743          if (this.element === this.previewsContainer) {
744            this.element.classList.add("dz-started");
745          }
746
747          if (this.previewsContainer) {
748            file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
749            file.previewTemplate = file.previewElement; // Backwards compatibility
750
751            this.previewsContainer.appendChild(file.previewElement);
752            for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
753              var _ref3;
754
755              if (_isArray3) {
756                if (_i3 >= _iterator3.length) break;
757                _ref3 = _iterator3[_i3++];
758              } else {
759                _i3 = _iterator3.next();
760                if (_i3.done) break;
761                _ref3 = _i3.value;
762              }
763
764              var node = _ref3;
765
766              node.textContent = file.name;
767            }
768            for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
769              if (_isArray4) {
770                if (_i4 >= _iterator4.length) break;
771                node = _iterator4[_i4++];
772              } else {
773                _i4 = _iterator4.next();
774                if (_i4.done) break;
775                node = _i4.value;
776              }
777
778              node.innerHTML = this.filesize(file.size);
779            }
780
781            if (this.options.addRemoveLinks) {
782              file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
783              file.previewElement.appendChild(file._removeLink);
784            }
785
786            var removeFileEvent = function removeFileEvent(e) {
787              e.preventDefault();
788              e.stopPropagation();
789              if (file.status === Dropzone.UPLOADING) {
790                return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {
791                  return _this2.removeFile(file);
792                });
793              } else {
794                if (_this2.options.dictRemoveFileConfirmation) {
795                  return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {
796                    return _this2.removeFile(file);
797                  });
798                } else {
799                  return _this2.removeFile(file);
800                }
801              }
802            };
803
804            for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
805              var _ref4;
806
807              if (_isArray5) {
808                if (_i5 >= _iterator5.length) break;
809                _ref4 = _iterator5[_i5++];
810              } else {
811                _i5 = _iterator5.next();
812                if (_i5.done) break;
813                _ref4 = _i5.value;
814              }
815
816              var removeLink = _ref4;
817
818              removeLink.addEventListener("click", removeFileEvent);
819            }
820          }
821        },
822
823
824        // Called whenever a file is removed.
825        removedfile: function removedfile(file) {
826          if (file.previewElement != null && file.previewElement.parentNode != null) {
827            file.previewElement.parentNode.removeChild(file.previewElement);
828          }
829          return this._updateMaxFilesReachedClass();
830        },
831
832
833        // Called when a thumbnail has been generated
834        // Receives `file` and `dataUrl`
835        thumbnail: function thumbnail(file, dataUrl) {
836          if (file.previewElement) {
837            file.previewElement.classList.remove("dz-file-preview");
838            for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
839              var _ref5;
840
841              if (_isArray6) {
842                if (_i6 >= _iterator6.length) break;
843                _ref5 = _iterator6[_i6++];
844              } else {
845                _i6 = _iterator6.next();
846                if (_i6.done) break;
847                _ref5 = _i6.value;
848              }
849
850              var thumbnailElement = _ref5;
851
852              thumbnailElement.alt = file.name;
853              thumbnailElement.src = dataUrl;
854            }
855
856            return setTimeout(function () {
857              return file.previewElement.classList.add("dz-image-preview");
858            }, 1);
859          }
860        },
861
862
863        // Called whenever an error occurs
864        // Receives `file` and `message`
865        error: function error(file, message) {
866          if (file.previewElement) {
867            file.previewElement.classList.add("dz-error");
868            if (typeof message !== "String" && message.error) {
869              message = message.error;
870            }
871            for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
872              var _ref6;
873
874              if (_isArray7) {
875                if (_i7 >= _iterator7.length) break;
876                _ref6 = _iterator7[_i7++];
877              } else {
878                _i7 = _iterator7.next();
879                if (_i7.done) break;
880                _ref6 = _i7.value;
881              }
882
883              var node = _ref6;
884
885              node.textContent = message;
886            }
887          }
888        },
889        errormultiple: function errormultiple() {},
890
891
892        // Called when a file gets processed. Since there is a cue, not all added
893        // files are processed immediately.
894        // Receives `file`
895        processing: function processing(file) {
896          if (file.previewElement) {
897            file.previewElement.classList.add("dz-processing");
898            if (file._removeLink) {
899              return file._removeLink.innerHTML = this.options.dictCancelUpload;
900            }
901          }
902        },
903        processingmultiple: function processingmultiple() {},
904
905
906        // Called whenever the upload progress gets updated.
907        // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.
908        // To get the total number of bytes of the file, use `file.size`
909        uploadprogress: function uploadprogress(file, progress, bytesSent) {
910          if (file.previewElement) {
911            for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
912              var _ref7;
913
914              if (_isArray8) {
915                if (_i8 >= _iterator8.length) break;
916                _ref7 = _iterator8[_i8++];
917              } else {
918                _i8 = _iterator8.next();
919                if (_i8.done) break;
920                _ref7 = _i8.value;
921              }
922
923              var node = _ref7;
924
925              node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + "%";
926            }
927          }
928        },
929
930
931        // Called whenever the total upload progress gets updated.
932        // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent
933        totaluploadprogress: function totaluploadprogress() {},
934
935
936        // Called just before the file is sent. Get
936s the `xhr` object as second
937        // parameter, so you can modify it (for example to add a CSRF token) and a
938        // `formData` object to add additional information.
939        sending: function sending() {},
940        sendingmultiple: function sendingmultiple() {},
941
942
943        // When the complete upload is finished and successful
944        // Receives `file`
945        success: function success(file) {
946          if (file.previewElement) {
947            return file.previewElement.classList.add("dz-success");
948          }
949        },
950        successmultiple: function successmultiple() {},
951
952
953        // When the upload is canceled.
954        canceled: function canceled(file) {
955          return this.emit("error", file, this.options.dictUploadCanceled);
956        },
957        canceledmultiple: function canceledmultiple() {},
958
959
960        // When the upload is finished, either with success or an error.
961        // Receives `file`
962        complete: function complete(file) {
963          if (file._removeLink) {
964            file._removeLink.innerHTML = this.options.dictRemoveFile;
965          }
966          if (file.previewElement) {
967            return file.previewElement.classList.add("dz-complete");
968          }
969        },
970        completemultiple: function completemultiple() {},
971        maxfilesexceeded: function maxfilesexceeded() {},
972        maxfilesreached: function maxfilesreached() {},
973        queuecomplete: function queuecomplete() {},
974        addedfiles: function addedfiles() {}
975      };
976
977      this.prototype._thumbnailQueue = [];
978      this.prototype._processingThumbnail = false;
979    }
980
981    // global utility
982
983  }, {
984    key: "extend",
985    value: function extend(target) {
986      for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
987        objects[_key2 - 1] = arguments[_key2];
988      }
989
990      for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
991        var _ref8;
992
993        if (_isArray9) {
994          if (_i9 >= _iterator9.length) break;
995          _ref8 = _iterator9[_i9++];
996        } else {
997          _i9 = _iterator9.next();
998          if (_i9.done) break;
999          _ref8 = _i9.value;
1000        }
1001
1002        var object = _ref8;
1003
1004        for (var key in object) {
1005          var val = object[key];
1006          target[key] = val;
1007        }
1008      }
1009      return target;
1010    }
1011  }]);
1012
1013  function Dropzone(el, options) {
1014    _classCallCheck(this, Dropzone);
1015
1016    var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));
1017
1018    var fallback = void 0,
1019        left = void 0;
1020    _this.element = el;
1021    // For backwards compatibility since the version was in the prototype previously
1022    _this.version = Dropzone.version;
1023
1024    _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, "");
1025
1026    _this.clickableElements = [];
1027    _this.listeners = [];
1028    _this.files = []; // All files
1029
1030    if (typeof _this.element === "string") {
1031      _this.element = document.querySelector(_this.element);
1032    }
1033
1034    // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.
1035    if (!_this.element || _this.element.nodeType == null) {
1036      throw new Error("Invalid dropzone element.");
1037    }
1038
1039    if (_this.element.dropzone) {
1040     // throw new Error("Dropzone already attached.");
1041    }
1042
1043    // Now add this dropzone to the instances.
1044    Dropzone.instances.push(_this);
1045
1046    // Put the dropzone inside the element itself.
1047    _this.element.dropzone = _this;
1048
1049    var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};
1050
1051    _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});
1052
1053    // If the browser failed, just call the fallback and leave
1054    if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {
1055      var _ret;
1056
1057      return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);
1058    }
1059
1060    // @options.url = @element.getAttribute "action" unless @options.url?
1061    if (_this.options.url == null) {
1062      _this.options.url = _this.element.getAttribute("action");
1063    }
1064
1065    /*
1066    if (!_this.options.url) {
1067      throw new Error("No URL provided.");
1068    }
1069    */
1070
1071    if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {
1072      throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
1073    }
1074
1075    if (_this.options.uploadMultiple && _this.options.chunking) {
1076      throw new Error('You cannot set both: uploadMultiple and chunking.');
1077    }
1078
1079    // Backwards compatibility
1080    if (_this.options.acceptedMimeTypes) {
1081      _this.options.acceptedFiles = _this.options.acceptedMimeTypes;
1082      delete _this.options.acceptedMimeTypes;
1083    }
1084
1085    // Backwards compatibility
1086    if (_this.options.renameFilename != null) {
1087      _this.options.renameFile = function (file) {
1088        return _this.options.renameFilename.call(_this, file.name, file);
1089      };
1090    }
1091
1092    _this.options.method = _this.options.method.toUpperCase();
1093
1094    if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {
1095      // Remove the fallback
1096      fallback.parentNode.removeChild(fallback);
1097    }
1098
1099    // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false
1100    if (_this.options.previewsContainer !== false) {
1101      if (_this.options.previewsContainer) {
1102        _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer");
1103      } else {
1104        _this.previewsContainer = _this.element;
1105      }
1106    }
1107
1108    if (_this.options.clickable) {
1109      if (_this.options.clickable === true) {
1110        _this.clickableElements = [_this.element];
1111      } else {
1112        _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable");
1113      }
1114    }
1115
1116    _this.init();
1117    return _this;
1118  }
1119
1120  // Returns all files that have been accepted
1121
1122
1123  _createClass(Dropzone, [{
1124    key: "getAcceptedFiles",
1125    value: function getAcceptedFiles() {
1126      return this.files.filter(function (file) {
1127        return file.accepted;
1128      }).map(function (file) {
1129        return file;
1130      });
1131    }
1132
1133    // Returns all files that have been rejected
1134    // Not sure when that's going to be useful, but added for completeness.
1135
1136  }, {
1137    key: "getRejectedFiles",
1138    value: function getRejectedFiles() {
1139      return this.files.filter(function (file) {
1140        return !file.accepted;
1141      }).map(function (file) {
1142        return file;
1143      });
1144    }
1145  }, {
1146    key: "getFilesWithStatus",
1147    value: function getFilesWithStatus(status) {
1148      return this.files.filter(function (file) {
1149        return file.status === status;
1150      }).map(function (file) {
1151        return file;
1152      });
1153    }
1154
1155    // Returns all files that are in the queue
1156
1157  }, {
1158    key: "getQueuedFiles",
1159    value: function getQueuedFiles() {
1160      return this.getFilesWithStatus(Dropzone.QUEUED);
1161    }
1162  }, {
1163    key: "getUploadingFiles",
1164    value: function getUploadingFiles() {
1165      return this.getFilesWithStatus(Dropzone.UPLOADING);
1166    }
1167  }, {
1168    key: "getAddedFiles",
1169    value: function getAddedFiles() {
1170      return this.getFilesWithStatus(Dropzone.ADDED);
1171    }
1172
1173    // Files that are either queued or uploading
1174
1175  }, {
1176    key: "getActiveFiles",
1177    value: function getActiveFiles() {
1178      return this.files.filter(function (file) {
1179        return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;
1180      }).map(function (file) {
1181        return file;
1182      });
1183    }
1184
1185    // The function that gets called when Dropzone is initialized. You
1186    // can (and should) setup event listeners inside this function.
1187
1188  }, {
1189    key: "init",
1190    value: function init() {
1191      var _this3 = this;
1192
1193      // In case it isn't set already
1194      if (this.element.tagName === "form") {
1195        this.element.setAttribute("enctype", "multipart/form-data");
1196      }
1197
1198      if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
1199        this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
1200      }
1201
1202      if (this.clickableElements.length) {
1203        var setupHiddenFileInput = function setupHiddenFileInput() {
1204          if (_this3.hiddenFileInput) {
1205            _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
1206          }
1207          _this3.hiddenFileInput = document.createElement("input");
1208          _this3.hiddenFileInput.setAttribute("type", "file");
1209          if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
1210            _this3.hiddenFileInput.setAttribute("multiple", "multiple");
1211          }
1212          _this3.hiddenFileInput.className = "dz-hidden-input";
1213
1214          if (_this3.options.acceptedFiles !== null) {
1215            _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles);
1216          }
1217          if (_this3.options.capture !== null) {
1218            _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture);
1219          }
1220
1221          // Not setting `display="none"` because some browsers don't accept clicks
1222          // on elements that aren't displayed.
1223          _this3.hiddenFileInput.style.visibility = "hidden";
1224          _this3.hiddenFileInput.style.position = "absolute";
1225          _this3.hiddenFileInput.style.top = "0";
1226          _this3.hiddenFileInput.style.left = "0";
1227          _this3.hiddenFileInput.style.height = "0";
1228          _this3.hiddenFileInput.style.width = "0";
1229          Dropzone.getElement(_this3.options.hiddenInputContainer, 'hiddenInputContainer').appendChild(_this3.hiddenFileInput);
1230          return _this3.hiddenFileInput.addEventListener("change", function () {
1231            var files = _this3.hiddenFileInput.files;
1232
1233            if (files.length) {
1234              for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
1235                var _ref9;
1236
1237                if (_isArray10) {
1238                  if (_i10 >= _iterator10.length) break;
1239                  _ref9 = _iterator10[_i10++];
1240                } else {
1241                  _i10 = _iterator10.next();
1242                  if (_i10.done) break;
1243                  _ref9 = _i10.value;
1244                }
1245
1246                var file = _ref9;
1247
1248                _this3.addFile(file);
1249              }
1250            }
1251            _this3.emit("addedfiles", files);
1252            return setupHiddenFileInput();
1253          });
1254        };
1255        setupHiddenFileInput();
1256      }
1257
1258      this.URL = window.URL !== null ? window.URL : window.webkitURL;
1259
1260      // Setup all event listeners on the Dropzone object itself.
1261      // They're not in @setupEventListeners() because they shouldn't be removed
1262      // again when the dropzone gets disabled.
1263      for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
1264        var _ref10;
1265
1266        if (_isArray11) {
1267          if (_i11 >= _iterator11.length) break;
1268          _ref10 = _iterator11[_i11++];
1269        } else {
1270          _i11 = _iterator11.next();
1271          if (_i11.done) break;
1272          _ref10 = _i11.value;
1273        }
1274
1275        var eventName = _ref10;
1276
1277        this.on(eventName, this.options[eventName]);
1278      }
1279
1280      this.on("uploadprogress", function () {
1281        return _this3.updateTotalUploadProgress();
1282      });
1283
1284      this.on("removedfile", function () {
1285        return _this3.updateTotalUploadProgress();
1286      });
1287
1288      this.on("canceled", function (file) {
1289        return _this3.emit("complete", file);
1290      });
1291
1292      // Emit a `queuecomplete` event if all files finished uploading.
1293      this.on("complete", function (file) {
1294        if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {
1295          // This needs to be deferred so that `queuecomplete` really triggers after `complete`
1296          return setTimeout(function () {
1297            return _this3.emit("queuecomplete");
1298          }, 0);
1299        }
1300      });
1301
1302      var noPropagation = function noPropagation(e) {
1303        e.stopPropagation();
1304        if (e.preventDefault) {
1305          return e.preventDefault();
1306        } else {
1307          return e.returnValue = false;
1308        }
1309      };
1310
1311      // Create the listeners
1312      this.listeners = [{
1313        element: this.element,
1314        events: {
1315          "dragstart": function dragstart(e) {
1316            return _this3.emit("dragstart", e);
1317          },
1318          "dragenter": function dragenter(e) {
1319            noPropagation(e);
1320            return _this3.emit("dragenter", e);
1321          },
1322          "dragover": function dragover(e) {
1323            // Makes it possible to drag files from chrome's download bar
1324            // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar
1325            // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)
1326            var efct = void 0;
1327            try {
1328              efct = e.dataTransfer.effectAllowed;
1329            } catch (error) {}
1330            e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
1331
1332            noPropagation(e);
1333            return _this3.emit("dragover", e);
1334          },
1335          "dragleave": function dragleave(e) {
1336            return _this3.emit("dragleave", e);
1337          },
1338          "drop": function drop(e) {
1339            noPropagation(e);
1340            return _this3.drop(e);
1341          },
1342          "dragend": function dragend(e) {
1343            return _this3.emit("dragend", e);
1344          }
1345
1346          // This is disabled right now, because the browsers don't implement it properly.
1347          // "paste": (e) =>
1348          //   noPropagation e
1349          //   @paste e
1350        } }];
1351
1352      this.clickableElements.forEach(function (clickableElement) {
1353        return _this3.listeners.push({
1354          element: clickableElement,
1355          events: {
1356            "click": function click(evt) {
1357              // Only the actual dropzone or the message element should trigger file selection
1358              if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) {
1359                _this3.hiddenFileInput.click(); // Forward the click
1360              }
1361              return true;
1362            }
1363          }
1364        });
1365      });
1366
1367      this.enable();
1368
1369      return this.options.init.call(this);
1370    }
1371
1372    // Not fully tested yet
1373
1374  }, {
1375    key: "destroy",
1376    value: function destroy() {
1377      this.disable();
1378      this.removeAllFiles(true);
1379      if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {
1380        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
1381        this.hiddenFileInput = null;
1382      }
1383      delete this.element.dropzone;
1384      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
1385    }
1386  }, {
1387    key: "updateTotalUploadProgress",
1388    value: function updateTotalUploadProgress() {
1389      var totalUploadProgress = void 0;
1390      var totalBytesSent = 0;
1391      var totalBytes = 0;
1392
1393      var activeFiles = this.getActiveFiles();
1394
1395      if (activeFiles.length) {
1396        for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
1397          var _ref11;
1398
1399          if (_isArray12) {
1400            if (_i12 >= _iterator12.length) break;
1401            _ref11 = _iterator12[_i12++];
1402          } else {
1403            _i12 = _iterator12.next();
1404            if (_i12.done) break;
1405            _ref11 = _i12.value;
1406          }
1407
1408          var file = _ref11;
1409
1410          totalBytesSent += file.upload.bytesSent;
1411          totalBytes += file.upload.total;
1412        }
1413        totalUploadProgress = 100 * totalBytesSent / totalBytes;
1414      } else {
1415        totalUploadProgress = 100;
1416      }
1417
1418      return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
1419    }
1420
1421    // @options.paramName can be a function taking one parameter rather than a string.
1422    // A parameter name for a file is obtained simply by calling this with an index number.
1423
1424  }, {
1425    key: "_getParamName",
1426    value: function _getParamName(n) {
1427      if (typeof this.options.paramName === "function") {
1428        return this.options.paramName(n);
1429      } else {
1430        return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
1431      }
1432    }
1433
1434    // If @options.renameFile is a function,
1435    // the function will be used to rename the file.name before appending it to the formData
1436
1437  }, {
1438    key: "_renameFile",
1439    value: function _renameFile(file) {
1440      if (typeof this.options.renameFile !== "function") {
1441        return file.name;
1442      }
1443      return this.options.renameFile(file);
1444    }
1445
1446    // Returns a form that can be used as fallback if the browser does not support DragnDrop
1447    //
1448    // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
1449    // This code has to pass in IE7 :(
1450
1451  }, {
1452    key: "getFallbackForm",
1453    value: function getFallbackForm() {
1454      var existingFallback = void 0,
1455          form = void 0;
1456      if (existingFallback = this.getExistingFallback()) {
1457        return existingFallback;
1458      }
1459
1460      var fieldsString = "<div class=\"dz-fallback\">";
1461      if (this.options.dictFallbackText) {
1462        fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
1463      }
1464      fieldsString += "<input type=\"file\" name=\"" + this._getParamName(0) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : undefined) + " /><input type=\"submit\" value=\"Upload!\"></div>";
1465
1466      var fields = Dropzone.createElement(fieldsString);
1467      if (this.element.tagName !== "FORM") {
1468        form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>");
1469        form.appendChild(fields);
1470      } else {
1471        // Make sure that the enctype and method attributes are set properly
1472        this.element.setAttribute("enctype", "multipart/form-data");
1473        this.element.setAttribute("method", this.options.method);
1474      }
1475      return form != null ? form : fields;
1476    }
1477
1478    // Returns the fallback elements if they exist already
1479    //
1480    // This code has to pass in IE7 :(
1481
1482  }, {
1483    key: "getExistingFallback",
1484    value: function getExistingFallback() {
1485      var getFallback = function getFallback(elements) {
1486        for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {
1487          var _ref12;
1488
1489          if (_isArray13) {
1490            if (_i13 >= _iterator13.length) break;
1491            _ref12 = _iterator13[_i13++];
1492          } else {
1493            _i13 = _iterator13.next();
1494            if (_i13.done) break;
1495            _ref12 = _i13.value;
1496          }
1497
1498          var el = _ref12;
1499
1500          if (/(^| )fallback($| )/.test(el.className)) {
1501            return el;
1502          }
1503        }
1504      };
1505
1506      var _arr = ["div", "form"];
1507      for (var _i14 = 0; _i14 < _arr.length; _i14++) {
1508        var tagName = _arr[_i14];
1509        var fallback;
1510        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
1511          return fallback;
1512        }
1513      }
1514    }
1515
1516    // Activates all listeners stored in @listeners
1517
1518  }, {
1519    key: "setupEventListeners",
1520    value: function setupEventListeners() {
1521      return this.listeners.map(function (elementListeners) {
1522        return function () {
1523          var result = [];
1524          for (var event in elementListeners.events) {
1525            var listener = elementListeners.events[event];
1526            result.push(elementListeners.element.addEventListener(event, listener, false));
1527          }
1528          return result;
1529        }();
1530      });
1531    }
1532
1533    // Deactivates all listeners stored in @listeners
1534
1535  }, {
1536    key: "removeEventListeners",
1537    value: function removeEventListeners() {
1538      return this.listeners.map(function (elementListeners) {
1539        return function () {
1540          var result = [];
1541          for (var event in elementListeners.events) {
1542            var listener = elementListeners.events[event];
1543            result.push(elementListeners.element.removeEventListener(event, listener, false));
1544          }
1545          return result;
1546        }();
1547      });
1548    }
1549
1550    // Removes all event listeners and cancels all files in the queue or being processed.
1551
1552  }, {
1553    key: "disable",
1554    value: function disable() {
1555      var _this4 = this;
1556
1557      this.clickableElements.forEach(function (element) {
1558        return element.classList.remove("dz-clickable");
1559      });
1560      this.removeEventListeners();
1561      this.disabled = true;
1562
1563      return this.files.map(function (file) {
1564        return _this4.cancelUpload(file);
1565      });
1566    }
1567  }, {
1568    key: "enable",
1569    value: function enable() {
1570      delete this.disabled;
1571      this.clickableElements.forEach(function (element) {
1572        return element.classList.add("dz-clickable");
1573      });
1574      return this.setupEventListeners();
1575    }
1576
1577    // Returns a nicely formatted filesize
1578
1579  }, {
1580    key: "filesize",
1581    value: function filesize(size) {
1582      var selectedSize = 0;
1583      var selectedUnit = "b";
1584
1585      if (size > 0) {
1586        var units = ['tb', 'gb', 'mb', 'kb', 'b'];
1587
1588        for (var i = 0; i < units.length; i++) {
1589          var unit = units[i];
1590          var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
1591
1592          if (size >= cutoff) {
1593            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
1594            selectedUnit = unit;
1595            break;
1596          }
1597        }
1598
1599        selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits
1600      }
1601
1602      return "<strong>" + selectedSize + "</strong> " + this.options.dictFileSizeUnits[selectedUnit];
1603    }
1604
1605    // Adds or removes the `dz-max-files-reached` class from the form.
1606
1607  }, {
1608    key: "_updateMaxFilesReachedClass",
1609    value: function _updateMaxFilesReachedClass() {
1610      if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
1611        if (this.getAcceptedFiles().length === this.options.maxFiles) {
1612          this.emit('maxfilesreached', this.files);
1613        }
1614        return this.element.classList.add("dz-max-files-reached");
1615      } else {
1616        return this.element.classList.remove("dz-max-files-reached");
1617      }
1618    }
1619  }, {
1620    key: "drop",
1621    value: function drop(e) {
1622      if (!e.dataTransfer) {
1623        return;
1624      }
1625      this.emit("drop", e);
1626
1627      // Convert the FileList to an Array
1628      // This is necessary for IE11
1629      var files = [];
1630      for (var i = 0; i < e.dataTransfer.files.length; i++) {
1631        files[i] = e.dataTransfer.files[i];
1632      }
1633
1634      this.emit("addedfiles", files);
1635
1636      // Even if it's a folder, files.length will contain the folders.
1637      if (files.length) {
1638        var items = e.dataTransfer.items;
1639
1640        if (items && items.length && items[0].webkitGetAsEntry != null) {
1641          // The browser supports dropping of folders, so handle items instead of files
1642          this._addFilesFromItems(items);
1643        } else {
1644          this.handleFiles(files);
1645        }
1646      }
1647    }
1648  }, {
1649    key: "paste",
1650    value: function paste(e) {
1651      if (__guard__(e != null ? e.clipboardData : undefined, function (x) {
1652        return x.items;
1653      }) == null) {
1654        return;
1655      }
1656
1657      this.emit("paste", e);
1658      var items = e.clipboardData.items;
1659
1660
1661      if (items.length) {
1662        return this._addFilesFromItems(items);
1663      }
1664    }
1665  }, {
1666    key: "handleFiles",
1667    value: function handleFiles(files) {
1668      for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {
1669        var _ref13;
1670
1671        if (_isArray14) {
1672          if (_i15 >= _iterator14.length) break;
1673          _ref13 = _iterator14[_i15++];
1674        } else {
1675          _i15 = _iterator14.next();
1676          if (_i15.done) break;
1677          _ref13 = _i15.value;
1678        }
1679
1680        var file = _ref13;
1681
1682        this.addFile(file);
1683      }
1684    }
1685
1686    // When a folder is dropped (or files are pasted), items must be handled
1687    // instead of files.
1688
1689  }, {
1690    key: "_addFilesFromItems",
1691    value: function _addFilesFromItems(items) {
1692      var _this5 = this;
1693
1694      return function () {
1695        var result = [];
1696        for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {
1697          var _ref14;
1698
1699          if (_isArray15) {
1700            if (_i16 >= _iterator15.length) break;
1701            _ref14 = _iterator15[_i16++];
1702          } else {
1703            _i16 = _iterator15.next();
1704            if (_i16.done) break;
1705            _ref14 = _i16.value;
1706          }
1707
1708          var item = _ref14;
1709
1710          var entry;
1711          if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {
1712            if (entry.isFile) {
1713              result.push(_this5.addFile(item.getAsFile()));
1714            } else if (entry.isDirectory) {
1715              // Append all files from that directory to files
1716              result.push(_this5._addFilesFromDirectory(entry, entry.name));
1717            } else {
1718              result.push(undefined);
1719            }
1720          } else if (item.getAsFile != null) {
1721            if (item.kind == null || item.kind === "file") {
1722              result.push(_this5.addFile(item.getAsFile()));
1723            } else {
1724              result.push(undefined);
1725            }
1726          } else {
1727            result.push(undefined);
1728          }
1729        }
1730        return result;
1731      }();
1732    }
1733
1734    // Goes through the directory, and adds each file it finds recursively
1735
1736  }, {
1737    key: "_addFilesFromDirectory",
1738    value: function _addFilesFromDirectory(directory, path) {
1739      var _this6 = this;
1740
1741      var dirReader = directory.createReader();
1742
1743      var errorHandler = function errorHandler(error) {
1744        return __guardMethod__(console, 'log', function (o) {
1745          return o.log(error);
1746        });
1747      };
1748
1749      var readEntries = function readEntries() {
1750        return dirReader.readEntries(function (entries) {
1751          if (entries.length > 0) {
1752            for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {
1753              var _ref15;
1754
1755              if (_isArray16) {
1756                if (_i17 >= _iterator16.length) break;
1757                _ref15 = _iterator16[_i17++];
1758              } else {
1759                _i17 = _iterator16.next();
1760                if (_i17.done) break;
1761                _ref15 = _i17.value;
1762              }
1763
1764              var entry = _ref15;
1765
1766              if (entry.isFile) {
1767                entry.file(function (file) {
1768                  if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
1769                    return;
1770                  }
1771                  file.fullPath = path + "/" + file.name;
1772                  return _this6.addFile(file);
1773                });
1774              } else if (entry.isDirectory) {
1775                _this6._addFilesFromDirectory(entry, path + "/" + entry.name);
1776              }
1777            }
1778
1779            // Recursively call readEntries() again, since browser only handle
1780            // the first 100 entries.
1781            // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries
1782            readEntries();
1783          }
1784          return null;
1785        }, errorHandler);
1786      };
1787
1788      return readEntries();
1789    }
1790
1791    // If `done()` is called without argument the file is accepted
1792    // If you call it with an error message, the file is rejected
1793    // (This allows for asynchronous validation)
1794    //
1795    // This function checks the filesize, and if the file.type passes the
1796    // `acceptedFiles` check.
1797
1798  }, {
1799    key: "accept",
1800    value: function accept(file, done) {
1801      if (this.options.maxFilesize && file.size > this.options.maxFilesize * 1024 * 1024) {
1802        return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
1803      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
1804        return done(this.options.dictInvalidFileType);
1805      } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
1806        done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
1807        return this.emit("maxfilesexceeded", file);
1808      } else {
1809        return this.options.accept.call(this, file, done);
1810      }
1811    }
1812  }, {
1813    key: "addFile",
1814    value: function addFile(file) {
1815      var _this7 = this;
1816
1817      file.upload = {
1818        uuid: Dropzone.uuidv4(),
1819        progress: 0,
1820        // Setting the total upload size to file.size for the beginning
1821        // It's actual different than the size to be transmitted.
1822        total: file.size,
1823        bytesSent: 0,
1824        filename: this._renameFile(file),
1825        chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),
1826        totalChunkCount: Math.ceil(file.size / this.options.chunkSize)
1827      };
1828      this.files.push(file);
1829
1830      file.status = Dropzone.ADDED;
1831
1832      this.emit("addedfile", file);
1833
1834      this._enqueueThumbnail(file);
1835
1836      return this.accept(file, function (error) {
1837        if (error) {
1838          file.accepted = false;
1839          _this7._errorProcessing([file], error); // Will set the file.status
1840        } else {
1841          file.accepted = true;
1842          if (_this7.options.autoQueue) {
1843            _this7.enqueueFile(file);
1844          } // Will set .accepted = true
1845        }
1846        return _this7._updateMaxFilesReachedClass();
1847      });
1848    }
1849
1850    // Wrapper for enqueueFile
1851
1852  }, {
1853    key: "enqueueFiles",
1854    value: function enqueueFiles(files) {
1855      for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {
1856        var _ref16;
1857
1858        if (_isArray17) {
1859          if (_i18 >= _iterator17.length) break;
1860          _ref16 = _iterator17[_i18++];
1861        } else {
1862          _i18 = _iterator17.next();
1863          if (_i18.done) break;
1864          _ref16 = _i18.value;
1865        }
1866
1867        var file = _ref16;
1868
1869        this.enqueueFile(file);
1870      }
1871      return null;
1872    }
1873  }, {
1874    key: "enqueueFile",
1875    value: function enqueueFile(file) {
1876      var _this8 = this;
1877
1878      if (file.status === Dropzone.ADDED && file.accepted === true) {
1879        file.status = Dropzone.QUEUED;
1880        if (this.options.autoProcessQueue) {
1881          return setTimeout(function () {
1882            return _this8.processQueue();
1883          }, 0); // Deferring the call
1884        }
1885      } else {
1886        throw new Error("This file can't be queued because it has already been processed or was rejected.");
1887      }
1888    }
1889  }, {
1890    key: "_enqueueThumbnail",
1891    value: function _enqueueThumbnail(file) {
1892      var _this9 = this;
1893
1894      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
1895        this._thumbnailQueue.push(file);
1896        return setTimeout(function () {
1897          return _this9._processThumbnailQueue();
1898        }, 0); // Deferring the call
1899      }
1900    }
1901  }, {
1902    key: "_processThumbnailQueue",
1903    value: function _processThumbnailQueue() {
1904      var _this10 = this;
1905
1906      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
1907        return;
1908      }
1909
1910      this._processingThumbnail = true;
1911      var file = this._thumbnailQueue.shift();
1912      return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {
1913        _this10.emit("thumbnail", file, dataUrl);
1914        _this10._processingThumbnail = false;
1915        return _this10._processThumbnailQueue();
1916      });
1917    }
1918
1919    // Can be called by the user to remove a file
1920
1921  }, {
1922    key: "removeFile",
1923    value: function removeFile(file) {
1924      if (file.status === Dropzone.UPLOADING) {
1925        this.cancelUpload(file);
1926      }
1927      this.files = without(this.files, file);
1928
1929      this.emit("removedfile", file);
1930      if (this.files.length === 0) {
1931        return this.emit("reset");
1932      }
1933    }
1934
1935    // Removes all files that aren't currently processed from the list
1936
1937  }, {
1938    key: "removeAllFiles",
1939    value: function removeAllFiles(cancelIfNecessary) {
1940      // Create a copy of files since removeFile() changes the @files array.
1941      if (cancelIfNecessary == null) {
1942        cancelIfNecessary = false;
1943      }
1944      for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {
1945        var _ref17;
1946
1947        if (_isArray18) {
1948          if (_i19 >= _iterator18.length) break;
1949          _ref17 = _iterator18[_i19++];
1950        } else {
1951          _i19 = _iterator18.next();
1952          if (_i19.done) break;
1953          _ref17 = _i19.value;
1954        }
1955
1956        var file = _ref17;
1957
1958        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
1959          this.removeFile(file);
1960        }
1961      }
1962      return null;
1963    }
1964
1965    // Resizes an image before it gets sent to the server. This function is the default behavior of
1966    // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with
1967    // the resized blob.
1968
1969  }, {
1970    key: "resizeImage",
1971    value: function resizeImage(file, width, height, resizeMethod, callback) {
1972      var _this11 = this;
1973
1974      return this.createThumbnail(file, width, height, resizeMethod, true, function (dataUrl, canvas) {
1975        if (canvas == null) {
1976          // The image has not been resized
1977          return callback(file);
1978        } else {
1979          var resizeMimeType = _this11.options.resizeMimeType;
1980
1981          if (resizeMimeType == null) {
1982            resizeMimeType = file.type;
1983          }
1984          var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);
1985          if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {
1986            // Now add the original EXIF information
1987            resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
1988          }
1989          return callback(Dropzone.dataURItoBlob(resizedDataURL));
1990        }
1991      });
1992    }
1993  }, {
1994    key: "createThumbnail",
1995    value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {
1996      var _this12 = this;
1997
1998      var fileReader = new FileReader();
1999
2000      fileReader.onload = function () {
2001
2002        file.dataURL = fileReader.result;
2003
2004        // Don't bother creating a thumbnail for SVG images since they're vector
2005        if (file.type === "image/svg+xml") {
2006          if (callback != null) {
2007            callback(fileReader.result);
2008          }
2009          return;
2010        }
2011
2012        return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
2013      };
2014
2015      return fileReader.readAsDataURL(file);
2016    }
2017  }, {
2018    key: "createThumbnailFromUrl",
2019    value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
2020      var _this13 = this;
2021
2022      // Not using `new Image` here because of a bug in latest Chrome versions.
2023      // See https://github.com/enyo/dropzone/pull/226
2024      var img = document.createElement("img");
2025
2026      if (crossOrigin) {
2027        img.crossOrigin = crossOrigin;
2028      }
2029
2030      img.onload = function () {
2031        var loadExif = function loadExif(callback) {
2032          return callback(1);
2033        };
2034        if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {
2035          loadExif = function loadExif(callback) {
2036            return EXIF.getData(img, function () {
2037              return callback(EXIF.getTag(this, 'Orientation'));
2038            });
2039          };
2040        }
2041
2042        return loadExif(function (orientation) {
2043          file.width = img.width;
2044          file.height = img.height;
2045
2046          var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);
2047
2048          var canvas = document.createElement("canvas");
2049          var ctx = canvas.getContext("2d");
2050
2051          canvas.width = resizeInfo.trgWidth;
2052          canvas.height = resizeInfo.trgHeight;
2053
2054          if (orientation > 4) {
2055            canvas.width = resizeInfo.trgHeight;
2056            canvas.height = resizeInfo.trgWidth;
2057          }
2058
2059          switch (orientation) {
2060            case 2:
2061              // horizontal flip
2062              ctx.translate(canvas.width, 0);
2063              ctx.scale(-1, 1);
2064              break;
2065            case 3:
2066              // 180° rotate left
2067              ctx.translate(canvas.width, canvas.height);
2068              ctx.rotate(Math.PI);
2069              break;
2070            case 4:
2071              // vertical flip
2072              ctx.translate(0, canvas.height);
2073              ctx.scale(1, -1);
2074              break;
2075            case 5:
2076              // vertical flip + 90 rotate right
2077              ctx.rotate(0.5 * Math.PI);
2078              ctx.scale(1, -1);
2079              break;
2080            case 6:
2081              // 90° rotate right
2082              ctx.rotate(0.5 * Math.PI);
2083              ctx.translate(0, -canvas.width);
2084              break;
2085            case 7:
2086              // horizontal flip + 90 rotate right
2087              ctx.rotate(0.5 * Math.PI);
2088              ctx.translate(canvas.height, -canvas.width);
2089              ctx.scale(-1, 1);
2090              break;
2091            case 8:
2092              // 90° rotate left
2093              ctx.rotate(-0.5 * Math.PI);
2094              ctx.translate(-canvas.height, 0);
2095              break;
2096          }
2097
2098          // This is a bugfix for iOS' scaling bug.
2099          drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
2100
2101          var thumbnail = canvas.toDataURL("image/png");
2102
2103          if (callback != null) {
2104            return callback(thumbnail, canvas);
2105          }
2106        });
2107      };
2108
2109      if (callback != null) {
2110        img.onerror = callback;
2111      }
2112
2113      return img.src = file.dataURL;
2114    }
2115
2116    // Goes through the queue and processes files if there aren't too many already.
2117
2118  }, {
2119    key: "processQueue",
2120    value: function processQueue() {
2121      var parallelUploads = this.options.parallelUploads;
2122
2123      var processingLength = this.getUploadingFiles().length;
2124      var i = processingLength;
2125
2126      // There are already at least as many files uploading than should be
2127      if (processingLength >= parallelUploads) {
2128        return;
2129      }
2130
2131      var queuedFiles = this.getQueuedFiles();
2132
2133      if (!(queuedFiles.length > 0)) {
2134        return;
2135      }
2136
2137      if (this.options.uploadMultiple) {
2138        // The files should be uploaded in one request
2139        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
2140      } else {
2141        while (i < parallelUploads) {
2142          if (!queuedFiles.length) {
2143            return;
2144          } // Nothing left to process
2145          this.processFile(queuedFiles.shift());
2146          i++;
2147        }
2148      }
2149    }
2150
2151    // Wrapper for `processFiles`
2152
2153  }, {
2154    key: "processFile",
2155    value: function processFile(file) {
2156      return this.processFiles([file]);
2157    }
2158
2159    // Loads the file, then calls finishedLoading()
2160
2161  }, {
2162    key: "processFiles",
2163    value: function processFiles(files) {
2164      for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {
2165        var _ref18;
2166
2167        if (_isArray19) {
2168          if (_i20 >= _iterator19.length) break;
2169          _ref18 = _iterator19[_i20++];
2170        } else {
2171          _i20 = _iterator19.next();
2172          if (_i20.done) break;
2173          _ref18 = _i20.value;
2174        }
2175
2176        var file = _ref18;
2177
2178        file.processing = true; // Backwards compatibility
2179        file.status = Dropzone.UPLOADING;
2180
2181        this.emit("processing", file);
2182      }
2183
2184      if (this.options.uploadMultiple) {
2185        this.emit("processingmultiple", files);
2186      }
2187
2188      return this.uploadFiles(files);
2189    }
2190  }, {
2191    key: "_getFilesWithXhr",
2192    value: function _getFilesWithXhr(xhr) {
2193      var files = void 0;
2194      return files = this.files.filter(function (file) {
2195        return file.xhr === xhr;
2196      }).map(function (file) {
2197        return file;
2198      });
2199    }
2200
2201    // Cancels the file upload and sets the status to CANCELED
2202    // **if** the file is actually being uploaded.
2203    // If it's still in the queue, the file is being removed from it and the status
2204    // set to CANCELED.
2205
2206  }, {
2207    key: "cancelUpload",
2208    value: function cancelUpload(file) {
2209      if (file.status === Dropzone.UPLOADING) {
2210        var groupedFiles = this._getFilesWithXhr(file.xhr);
2211        for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {
2212          var _ref19;
2213
2214          if (_isArray20) {
2215            if (_i21 >= _iterator20.length) break;
2216            _ref19 = _iterator20[_i21++];
2217          } else {
2218            _i21 = _iterator20.next();
2219            if (_i21.done) break;
2220            _ref19 = _i21.value;
2221          }
2222
2223          var groupedFile = _ref19;
2224
2225          groupedFile.status = Dropzone.CANCELED;
2226        }
2227        if (typeof file.xhr !== 'undefined') {
2228          file.xhr.abort();
2229        }
2230        for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {
2231          var _ref20;
2232
2233          if (_isArray21) {
2234            if (_i22 >= _iterator21.length) break;
2235            _ref20 = _iterator21[_i22++];
2236          } else {
2237            _i22 = _iterator21.next();
2238            if (_i22.done) break;
2239            _ref20 = _i22.value;
2240          }
2241
2242          var _groupedFile = _ref20;
2243
2244          this.emit("canceled", _groupedFile);
2245        }
2246        if (this.options.uploadMultiple) {
2247          this.emit("canceledmultiple", groupedFiles);
2248        }
2249      } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {
2250        file.status = Dropzone.CANCELED;
2251        this.emit("canceled", file);
2252        if (this.options.uploadMultiple) {
2253          this.emit("canceledmultiple", [file]);
2254        }
2255      }
2256
2257      if (this.options.autoProcessQueue) {
2258        return this.processQueue();
2259      }
2260    }
2261  }, {
2262    key: "resolveOption",
2263    value: function resolveOption(option) {
2264      if (typeof option === 'function') {
2265        for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
2266          args[_key3 - 1] = arguments[_key3];
2267        }
2268
2269        return option.apply(this, args);
2270      }
2271      return option;
2272    }
2273  }, {
2274    key: "uploadFile",
2275    value: function uploadFile(file) {
2276      return this.uploadFiles([file]);
2277    }
2278  }, {
2279    key: "uploadFiles",
2280    value: function uploadFiles(files) {
2281      var _this14 = this;
2282
2283      this._transformFiles(files, function (transformedFiles) {
2284        if (files[0].upload.chunked) {
2285          // This file should be sent in chunks!
2286
2287          // If the chunking option is set, we **know** that there can only be **one** file, since
2288          // uploadMultiple is not allowed with this option.
2289          var file = files[0];
2290          var transformedFile = transformedFiles[0];
2291          var startedChunkCount = 0;
2292
2293          file.upload.chunks = [];
2294
2295          var handleNextChunk = function handleNextChunk() {
2296            var chunkIndex = 0;
2297
2298            // Find the next item in file.upload.chunks that is not defined yet.
2299            while (file.upload.chunks[chunkIndex] !== undefined) {
2300              chunkIndex++;
2301            }
2302
2303            // This means, that all chunks have already been started.
2304            if (chunkIndex >= file.upload.totalChunkCount) return;
2305
2306            startedChunkCount++;
2307
2308            var start = chunkIndex * _this14.options.chunkSize;
2309            var end = Math.min(start + _this14.options.chunkSize, file.size);
2310
2311            var dataBlock = {
2312              name: _this14._getParamName(0),
2313              data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),
2314              filename: file.upload.filename,
2315              chunkIndex: chunkIndex
2316            };
2317
2318            file.upload.chunks[chunkIndex] = {
2319              file: file,
2320              index: chunkIndex,
2321              dataBlock: dataBlock, // In case we want to retry.
2322              status: Dropzone.UPLOADING,
2323              progress: 0,
2324              retries: 0 // The number of times this block has been retried.
2325            };
2326
2327            _this14._uploadData(files, [dataBlock]);
2328          };
2329
2330          file.upload.finishedChunkUpload = function (chunk) {
2331            var allFinished = true;
2332            chunk.status = Dropzone.SUCCESS;
2333
2334            // Clear the data from the chunk
2335            chunk.dataBlock = null;
2336            // Leaving this reference to xhr intact here will cause memory leaks in some browsers
2337            chunk.xhr = null;
2338
2339            for (var i = 0; i < file.upload.totalChunkCount; i++) {
2340              if (file.upload.chunks[i] === undefined) {
2341                return handleNextChunk();
2342              }
2343              if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {
2344                allFinished = false;
2345              }
2346            }
2347
2348            if (allFinished) {
2349              _this14.options.chunksUploaded(file, function () {
2350                _this14._finished(files, '', null);
2351              });
2352            }
2353          };
2354
2355          if (_this14.options.parallelChunkUploads) {
2356            for (var i = 0; i < file.upload.totalChunkCount; i++) {
2357              handleNextChunk();
2358            }
2359          } else {
2360            handleNextChunk();
2361          }
2362        } else {
2363          var dataBlocks = [];
2364          for (var _i23 = 0; _i23 < files.length; _i23++) {
2365            dataBlocks[_i23] = {
2366              name: _this14._getParamName(_i23),
2367              data: transformedFiles[_i23],
2368              filename: files[_i23].upload.filename
2369            };
2370          }
2371          _this14._uploadData(files, dataBlocks);
2372        }
2373      });
2374    }
2375
2376    /// Returns the right chunk for given file and xhr
2377
2378  }, {
2379    key: "_getChunk",
2380    value: function _getChunk(file, xhr) {
2381      for (var i = 0; i < file.upload.totalChunkCount; i++) {
2382        if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {
2383          return file.upload.chunks[i];
2384        }
2385      }
2386    }
2387
2388    // This function actually uploads the file(s) to the server.
2389    // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed
2390    // files, or individual chunks for chunked upload).
2391
2392  }, {
2393    key: "_uploadData",
2394    value: function _uploadData(files, dataBlocks) {
2395      var _this15 = this;
2396
2397      var xhr = new XMLHttpRequest();
2398
2399      // Put the xhr object in the file objects to be able to reference it later.
2400      for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {
2401        var _ref21;
2402
2403        if (_isArray22) {
2404          if (_i24 >= _iterator22.length) break;
2405          _ref21 = _iterator22[_i24++];
2406        } else {
2407          _i24 = _iterator22.next();
2408          if (_i24.done) break;
2409          _ref21 = _i24.value;
2410        }
2411
2412        var file = _ref21;
2413
2414        file.xhr = xhr;
2415      }
2416      if (files[0].upload.chunked) {
2417        // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk
2418        files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;
2419      }
2420
2421      var method = this.resolveOption(this.options.method, files);
2422      var url = this.resolveOption(this.options.url, files);
2423      xhr.open(method, url, true);
2424
2425      // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8
2426      xhr.timeout = this.resolveOption(this.options.timeout, files);
2427
2428      // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
2429      xhr.withCredentials = !!this.options.withCredentials;
2430
2431      xhr.onload = function (e) {
2432        _this15._finishedUploading(files, xhr, e);
2433      };
2434
2435      xhr.onerror = function () {
2436        _this15._handleUploadError(files, xhr);
2437      };
2438
2439      // Some browsers do not have the .upload property
2440      var progressObj = xhr.upload != null ? xhr.upload : xhr;
2441      progressObj.onprogress = function (e) {
2442        return _this15._updateFilesUploadProgress(files, xhr, e);
2443      };
2444
2445      var headers = {
2446        "Accept": "application/json",
2447        "Cache-Control": "no-cache",
2448        "X-Requested-With": "XMLHttpRequest"
2449      };
2450
2451      if (this.options.headers) {
2452        Dropzone.extend(headers, this.options.headers);
2453      }
2454
2455      for (var headerName in headers) {
2456        var headerValue = headers[headerName];
2457        if (headerValue) {
2458          xhr.setRequestHeader(headerName, headerValue);
2459        }
2460      }
2461
2462      var formData = new FormData();
2463
2464      // Adding all @options parameters
2465      if (this.options.params) {
2466        var additionalParams = this.options.params;
2467        if (typeof additionalParams === 'function') {
2468          additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);
2469        }
2470
2471        for (var key in additionalParams) {
2472          var value = additionalParams[key];
2473          formData.append(key, value);
2474        }
2475      }
2476
2477      // Let the user add additional data if necessary
2478      for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {
2479        var _ref22;
2480
2481        if (_isArray23) {
2482          if (_i25 >= _iterator23.length) break;
2483          _ref22 = _iterator23[_i25++];
2484        } else {
2485          _i25 = _iterator23.next();
2486          if (_i25.done) break;
2487          _ref22 = _i25.value;
2488        }
2489
2490        var _file = _ref22;
2491
2492        this.emit("sending", _file, xhr, formData);
2493      }
2494      if (this.options.uploadMultiple) {
2495        this.emit("sendingmultiple", files, xhr, formData);
2496      }
2497
2498      this._addFormElementData(formData);
2499
2500      // Finally add the files
2501      // Has to be last because some servers (eg: S3) expect the file to be the last parameter
2502      for (var i = 0; i < dataBlocks.length; i++) {
2503        var dataBlock = dataBlocks[i];
2504        formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
2505      }
2506
2507      this.submitRequest(xhr, formData, files);
2508    }
2509
2510    // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.
2511
2512  }, {
2513    key: "_transformFiles",
2514    value: function _transformFiles(files, done) {
2515      var _this16 = this;
2516
2517      var transformedFiles = [];
2518      // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.
2519      var doneCounter = 0;
2520
2521      var _loop = function _loop(i) {
2522        _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {
2523          transformedFiles[i] = transformedFile;
2524          if (++doneCounter === files.length) {
2525            done(transformedFiles);
2526          }
2527        });
2528      };
2529
2530      for (var i = 0; i < files.length; i++) {
2531        _loop(i);
2532      }
2533    }
2534
2535    // Takes care of adding other input elements of the form to the AJAX request
2536
2537  }, {
2538    key: "_addFormElementData",
2539    value: function _addFormElementData(formData) {
2540      // Take care of other input elements
2541      if (this.element.tagName === "FORM") {
2542        for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {
2543          var _ref23;
2544
2545          if (_isArray24) {
2546            if (_i26 >= _iterator24.length) break;
2547            _ref23 = _iterator24[_i26++];
2548          } else {
2549            _i26 = _iterator24.next();
2550            if (_i26.done) break;
2551            _ref23 = _i26.value;
2552          }
2553
2554          var input = _ref23;
2555
2556          var inputName = input.getAttribute("name");
2557          var inputType = input.getAttribute("type");
2558          if (inputType) inputType = inputType.toLowerCase();
2559
2560          // If the input doesn't have a name, we can't use it.
2561          if (typeof inputName === 'undefined' || inputName === null) continue;
2562
2563          if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
2564            // Possibly multiple values
2565            for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {
2566              var _ref24;
2567
2568              if (_isArray25) {
2569                if (_i27 >= _iterator25.length) break;
2570                _ref24 = _iterator25[_i27++];
2571              } else {
2572                _i27 = _iterator25.next();
2573                if (_i27.done) break;
2574                _ref24 = _i27.value;
2575              }
2576
2577              var option = _ref24;
2578
2579              if (option.selected) {
2580                formData.append(inputName, option.value);
2581              }
2582            }
2583          } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) {
2584            formData.append(inputName, input.value);
2585          }
2586        }
2587      }
2588    }
2589
2590    // Invoked when there is new progress information about given files.
2591    // If e is not provided, it is assumed that the upload is finished.
2592
2593  }, {
2594    key: "_updateFilesUploadProgress",
2595    value: function _updateFilesUploadProgress(files, xhr, e) {
2596      var progress = void 0;
2597      if (typeof e !== 'undefined') {
2598        progress = 100 * e.loaded / e.total;
2599
2600        if (files[0].upload.chunked) {
2601          var file = files[0];
2602          // Since this is a chunked upload, we need to update the appropriate chunk progress.
2603          var chunk = this._getChunk(file, xhr);
2604          chunk.progress = progress;
2605          chunk.total = e.total;
2606          chunk.bytesSent = e.loaded;
2607          var fileProgress = 0,
2608              fileTotal = void 0,
2609              fileBytesSent = void 0;
2610          file.upload.progress = 0;
2611          file.upload.total = 0;
2612          file.upload.bytesSent = 0;
2613          for (var i = 0; i < file.upload.totalChunkCount; i++) {
2614            if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {
2615              file.upload.progress += file.upload.chunks[i].progress;
2616              file.upload.total += file.upload.chunks[i].total;
2617              file.upload.bytesSent += file.upload.chunks[i].bytesSent;
2618            }
2619          }
2620          file.upload.progress = file.upload.progress / file.upload.totalChunkCount;
2621        } else {
2622          for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {
2623            var _ref25;
2624
2625            if (_isArray26) {
2626              if (_i28 >= _iterator26.length) break;
2627              _ref25 = _iterator26[_i28++];
2628            } else {
2629              _i28 = _iterator26.next();
2630              if (_i28.done) break;
2631              _ref25 = _i28.value;
2632            }
2633
2634            var _file2 = _ref25;
2635
2636            _file2.upload.progress = progress;
2637            _file2.upload.total = e.total;
2638            _file2.upload.bytesSent = e.loaded;
2639          }
2640        }
2641        for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {
2642          var _ref26;
2643
2644          if (_isArray27) {
2645            if (_i29 >= _iterator27.length) break;
2646            _ref26 = _iterator27[_i29++];
2647          } else {
2648            _i29 = _iterator27.next();
2649            if (_i29.done) break;
2650            _ref26 = _i29.value;
2651          }
2652
2653          var _file3 = _ref26;
2654
2655          this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent);
2656        }
2657      } else {
2658        // Called when the file finished uploading
2659
2660        var allFilesFinished = true;
2661
2662        progress = 100;
2663
2664        for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {
2665          var _ref27;
2666
2667          if (_isArray28) {
2668            if (_i30 >= _iterator28.length) break;
2669            _ref27 = _iterator28[_i30++];
2670          } else {
2671            _i30 = _iterator28.next();
2672            if (_i30.done) break;
2673            _ref27 = _i30.value;
2674          }
2675
2676          var _file4 = _ref27;
2677
2678          if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {
2679            allFilesFinished = false;
2680          }
2681          _file4.upload.progress = progress;
2682          _file4.upload.bytesSent = _file4.upload.total;
2683        }
2684
2685        // Nothing to do, all files already at 100%
2686        if (allFilesFinished) {
2687          return;
2688        }
2689
2690        for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {
2691          var _ref28;
2692
2693          if (_isArray29) {
2694            if (_i31 >= _iterator29.length) break;
2695            _ref28 = _iterator29[_i31++];
2696          } else {
2697            _i31 = _iterator29.next();
2698            if (_i31.done) break;
2699            _ref28 = _i31.value;
2700          }
2701
2702          var _file5 = _ref28;
2703
2704          this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent);
2705        }
2706      }
2707    }
2708  }, {
2709    key: "_finishedUploading",
2710    value: function _finishedUploading(files, xhr, e) {
2711      var response = void 0;
2712
2713      if (files[0].status === Dropzone.CANCELED) {
2714        return;
2715      }
2716
2717      if (xhr.readyState !== 4) {
2718        return;
2719      }
2720
2721      if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {
2722        response = xhr.responseText;
2723
2724        if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
2725          try {
2726            response = JSON.parse(response);
2727          } catch (error) {
2728            e = error;
2729            response = "Invalid JSON response from server.";
2730          }
2731        }
2732      }
2733
2734      this._updateFilesUploadProgress(files);
2735
2736      if (!(200 <= xhr.status && xhr.status < 300)) {
2737        this._handleUploadError(files, xhr, response);
2738      } else {
2739        if (files[0].upload.chunked) {
2740          files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));
2741        } else {
2742          this._finished(files, response, e);
2743        }
2744      }
2745    }
2746  }, {
2747    key: "_handleUploadError",
2748    value: function _handleUploadError(files, xhr, response) {
2749      if (files[0].status === Dropzone.CANCELED) {
2750        return;
2751      }
2752
2753      if (files[0].upload.chunked && this.options.retryChunks) {
2754        var chunk = this._getChunk(files[0], xhr);
2755        if (chunk.retries++ < this.options.retryChunksLimit) {
2756          this._uploadData(files, [chunk.dataBlock]);
2757          return;
2758        } else {
2759          console.warn('Retried this chunk too often. Giving up.');
2760        }
2761      }
2762
2763      for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {
2764        var _ref29;
2765
2766        if (_isArray30) {
2767          if (_i32 >= _iterator30.length) break;
2768          _ref29 = _iterator30[_i32++];
2769        } else {
2770          _i32 = _iterator30.next();
2771          if (_i32.done) break;
2772          _ref29 = _i32.value;
2773        }
2774
2775        var file = _ref29;
2776
2777        this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr);
2778      }
2779    }
2780  }, {
2781    key: "submitRequest",
2782    value: function submitRequest(xhr, formData, files) {
2783      xhr.send(formData);
2784    }
2785
2786    // Called internally when processing is finished.
2787    // Individual callbacks have to be called in the appropriate sections.
2788
2789  }, {
2790    key: "_finished",
2791    value: function _finished(files, responseText, e) {
2792      for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {
2793        var _ref30;
2794
2795        if (_isArray31) {
2796          if (_i33 >= _iterator31.length) break;
2797          _ref30 = _iterator31[_i33++];
2798        } else {
2799          _i33 = _iterator31.next();
2800          if (_i33.done) break;
2801          _ref30 = _i33.value;
2802        }
2803
2804        var file = _ref30;
2805
2806        file.status = Dropzone.SUCCESS;
2807        this.emit("success", file, responseText, e);
2808        this.emit("complete", file);
2809      }
2810      if (this.options.uploadMultiple) {
2811        this.emit("successmultiple", files, responseText, e);
2812        this.emit("completemultiple", files);
2813      }
2814
2815      if (this.options.autoProcessQueue) {
2816        return this.processQueue();
2817      }
2818    }
2819
2820    // Called internally when processing is finished.
2821    // Individual callbacks have to be called in the appropriate sections.
2822
2823  }, {
2824    key: "_errorProcessing",
2825    value: function _errorProcessing(files, message, xhr) {
2826      for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {
2827        var _ref31;
2828
2829        if (_isArray32) {
2830          if (_i34 >= _iterator32.length) break;
2831          _ref31 = _iterator32[_i34++];
2832        } else {
2833          _i34 = _iterator32.next();
2834          if (_i34.done) break;
2835          _ref31 = _i34.value;
2836        }
2837
2838        var file = _ref31;
2839
2840        file.status = Dropzone.ERROR;
2841        this.emit("error", file, message, xhr);
2842        this.emit("complete", file);
2843      }
2844      if (this.options.uploadMultiple) {
2845        this.emit("errormultiple", files, message, xhr);
2846        this.emit("completemultiple", files);
2847      }
2848
2849      if (this.options.autoProcessQueue) {
2850        return this.processQueue();
2851      }
2852    }
2853  }], [{
2854    key: "uuidv4",
2855    value: function uuidv4() {
2856      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
2857        var r = Math.random() * 16 | 0,
2858            v = c === 'x' ? r : r & 0x3 | 0x8;
2859        return v.toString(16);
2860      });
2861    }
2862  }]);
2863
2864  return Dropzone;
2865}(Emitter);
2866
2867Dropzone.initClass();
2868
2869Dropzone.version = "5.5.0";
2870
2871// This is a map of options for your different dropzones. Add configurations
2872// to this object for your different dropzone elemens.
2873//
2874// Example:
2875//
2876//     Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };
2877//
2878// To disable autoDiscover for a specific element, you can set `false` as an option:
2879//
2880//     Dropzone.options.myDisabledElementId = false;
2881//
2882// And in html:
2883//
2884//     <form action="/upload" id="my-dropzone-element-id" class="dropzone"></form>
2885Dropzone.options = {};
2886
2887// Returns the options for an element or undefined if none available.
2888Dropzone.optionsForElement = function (element) {
2889  // Get the `Dropzone.options.elementId` for this element if it exists
2890  if (element.getAttribute("id")) {
2891    return Dropzone.options[camelize(element.getAttribute("id"))];
2892  } else {
2893    return undefined;
2894  }
2895};
2896
2897// Holds a list of all dropzone instances
2898Dropzone.instances = [];
2899
2900// Returns the dropzone for given element if any
2901Dropzone.forElement = function (element) {
2902  if (typeof element === "string") {
2903    element = document.querySelector(element);
2904  }
2905  if ((element != null ? element.dropzone : undefined) == null) {
2906    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.");
2907  }
2908  return element.dropzone;
2909};
2910
2911// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.
2912Dropzone.autoDiscover = true;
2913
2914// Looks for all .dropzone elements and creates a dropzone for them
2915Dropzone.discover = function () {
2916  var dropzones = void 0;
2917  if (document.querySelectorAll) {
2918    dropzones = document.querySelectorAll(".dropzone");
2919  } else {
2920    dropzones = [];
2921    // IE :(
2922    var checkElements = function checkElements(elements) {
2923      return function () {
2924        var result = [];
2925        for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {
2926          var _ref32;
2927
2928          if (_isArray33) {
2929            if (_i35 >= _iterator33.length) break;
2930            _ref32 = _iterator33[_i35++];
2931          } else {
2932            _i35 = _iterator33.next();
2933            if (_i35.done) break;
2934            _ref32 = _i35.value;
2935          }
2936
2937          var el = _ref32;
2938
2939          if (/(^| )dropzone($| )/.test(el.className)) {
2940            result.push(dropzones.push(el));
2941          } else {
2942            result.push(undefined);
2943          }
2944        }
2945        return result;
2946      }();
2947    };
2948    checkElements(document.getElementsByTagName("div"));
2949    checkElements(document.getElementsByTagName("form"));
2950  }
2951
2952  return function () {
2953    var result = [];
2954    for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {
2955      var _ref33;
2956
2957      if (_isArray34) {
2958        if (_i36 >= _iterator34.length) break;
2959        _ref33 = _iterator34[_i36++];
2960      } else {
2961        _i36 = _iterator34.next();
2962        if (_i36.done) break;
2963        _ref33 = _i36.value;
2964      }
2965
2966      var dropzone = _ref33;
2967
2968      // Create a dropzone unless auto discover has been disabled for specific element
2969      if (Dropzone.optionsForElement(dropzone) !== false) {
2970        result.push(new Dropzone(dropzone));
2971      } else {
2972        result.push(undefined);
2973      }
2974    }
2975    return result;
2976  }();
2977};
2978
2979// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,
2980// but not correctly.
2981// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.
2982// But what to do when browsers *theoretically* support an API, but crash
2983// when using it.
2984//
2985// This is a list of regular expressions tested against navigator.userAgent
2986//
2987// ** It should only be used on browser that *do* support the API, but
2988// incorrectly **
2989//
2990Dropzone.blacklistedBrowsers = [
2991// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.
2992/opera.*(Macintosh|Windows Phone).*version\/12/i];
2993
2994// Checks if the browser is supported
2995Dropzone.isBrowserSupported = function () {
2996  var capableBrowser = true;
2997
2998  if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
2999    if (!("classList" in document.createElement("a"))) {
3000      capableBrowser = false;
3001    } else {
3002      // The browser supports the API, but may be blacklisted.
3003      for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {
3004        var _ref34;
3005
3006        if (_isArray35) {
3007          if (_i37 >= _iterator35.length) break;
3008          _ref34 = _iterator35[_i37++];
3009        } else {
3010          _i37 = _iterator35.next();
3011          if (_i37.done) break;
3012          _ref34 = _i37.value;
3013        }
3014
3015        var regex = _ref34;
3016
3017        if (regex.test(navigator.userAgent)) {
3018          capableBrowser = false;
3019          continue;
3020        }
3021      }
3022    }
3023  } else {
3024    capableBrowser = false;
3025  }
3026
3027  return capableBrowser;
3028};
3029
3030Dropzone.dataURItoBlob = function (dataURI) {
3031  // convert base64 to raw binary data held in a string
3032  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
3033  var byteString = atob(dataURI.split(',')[1]);
3034
3035  // separate out the mime component
3036  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
3037
3038  // write the bytes of the string to an ArrayBuffer
3039  var ab = new ArrayBuffer(byteString.length);
3040  var ia = new Uint8Array(ab);
3041  for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
3042    ia[i] = byteString.charCodeAt(i);
3043  }
3044
3045  // write the ArrayBuffer to a blob
3046  return new Blob([ab], { type: mimeString });
3047};
3048
3049// Returns an array without the rejected item
3050var without = function without(list, rejectedItem) {
3051  return list.filter(function (item) {
3052    return item !== rejectedItem;
3053  }).map(function (item) {
3054    return item;
3055  });
3056};
3057
3058// abc-def_ghi -> abcDefGhi
3059var camelize = function camelize(str) {
3060  return str.replace(/[\-_](\w)/g, function (match) {
3061    return match.charAt(1).toUpperCase();
3062  });
3063};
3064
3065// Creates an element from string
3066Dropzone.createElement = function (string) {
3067  var div = document.createElement("div");
3068  div.innerHTML = string;
3069  return div.childNodes[0];
3070};
3071
3072// Tests if given element is inside (or simply is) the container
3073Dropzone.elementInside = function (element, container) {
3074  if (element === container) {
3075    return true;
3076  } // Coffeescript doesn't support do/while loops
3077  while (element = element.parentNode) {
3078    if (element === container) {
3079      return true;
3080    }
3081  }
3082  return false;
3083};
3084
3085Dropzone.getElement = function (el, name) {
3086  var element = void 0;
3087  if (typeof el === "string") {
3088    element = document.querySelector(el);
3089  } else if (el.nodeType != null) {
3090    element = el;
3091  }
3092  if (element == null) {
3093    throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
3094  }
3095  return element;
3096};
3097
3098Dropzone.getElements = function (els, name) {
3099  var el = void 0,
3100      elements = void 0;
3101  if (els instanceof Array) {
3102    elements = [];
3103    try {
3104      for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {
3105        if (_isArray36) {
3106          if (_i38 >= _iterator36.length) break;
3107          el = _iterator36[_i38++];
3108        } else {
3109          _i38 = _iterator36.next();
3110          if (_i38.done) break;
3111          el = _i38.value;
3112        }
3113
3114        elements.push(this.getElement(el, name));
3115      }
3116    } catch (e) {
3117      elements = null;
3118    }
3119  } else if (typeof els === "string") {
3120    elements = [];
3121    for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {
3122      if (_isArray37) {
3123        if (_i39 >= _iterator37.length) break;
3124        el = _iterator37[_i39++];
3125      } else {
3126        _i39 = _iterator37.next();
3127        if (_i39.done) break;
3128        el = _i39.value;
3129      }
3130
3131      elements.push(el);
3132    }
3133  } else if (els.nodeType != null) {
3134    elements = [els];
3135  }
3136
3137  if (elements == null || !elements.length) {
3138    throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
3139  }
3140
3141  return elements;
3142};
3143
3144// Asks the user the question and calls accepted or rejected accordingly
3145//
3146// The default implementation just uses `window.confirm` and then calls the
3147// appropriate callback.
3148Dropzone.confirm = function (question, accepted, rejected) {
3149  if (window.confirm(question)) {
3150    return accepted();
3151  } else if (rejected != null) {
3152    return rejected();
3153  }
3154};
3155
3156// Validates the mime type like this:
3157//
3158// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept
3159Dropzone.isValidFile = function (file, acceptedFiles) {
3160  if (!acceptedFiles) {
3161    return true;
3162  } // If there are no accepted mime types, it's OK
3163  acceptedFiles = acceptedFiles.split(",");
3164
3165  var mimeType = file.type;
3166  var baseMimeType = mimeType.replace(/\/.*$/, "");
3167
3168  for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {
3169    var _ref35;
3170
3171    if (_isArray38) {
3172      if (_i40 >= _iterator38.length) break;
3173      _ref35 = _iterator38[_i40++];
3174    } else {
3175      _i40 = _iterator38.next();
3176      if (_i40.done) break;
3177      _ref35 = _i40.value;
3178    }
3179
3180    var validType = _ref35;
3181
3182    validType = validType.trim();
3183    if (validType.charAt(0) === ".") {
3184      if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
3185        return true;
3186      }
3187    } else if (/\/\*$/.test(validType)) {
3188      // This is something like a image/* mime type
3189      if (baseMimeType === validType.replace(/\/.*$/, "")) {
3190        return true;
3191      }
3192    } else {
3193      if (mimeType === validType) {
3194        return true;
3195      }
3196    }
3197  }
3198
3199  return false;
3200};
3201
3202// Augment jQuery
3203if (typeof jQuery !== 'undefined' && jQuery !== null) {
3204  jQuery.fn.dropzone = function (options) {
3205    return this.each(function () {
3206      return new Dropzone(this, options);
3207    });
3208  };
3209}
3210
3211if (typeof module !== 'undefined' && module !== null) {
3212  module.exports = Dropzone;
3213} else {
3214  window.Dropzone = Dropzone;
3215}
3216
3217// Dropzone file status codes
3218Dropzone.ADDED = "added";
3219
3220Dropzone.QUEUED = "queued";
3221// For backwards compatibility. Now, if a file is accepted, it's either queued
3222// or uploading.
3223Dropzone.ACCEPTED = Dropzone.QUEUED;
3224
3225Dropzone.UPLOADING = "uploading";
3226Dropzone.PROCESSING = Dropzone.UPLOADING; // alias
3227
3228Dropzone.CANCELED = "canceled";
3229Dropzone.ERROR = "error";
3230Dropzone.SUCCESS = "success";
3231
3232/*
3233
3234 Bugfix for iOS 6 and 7
3235 Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
3236 based on the work of https://github.com/stomita/ios-imagefile-megapixel
3237
3238 */
3239
3240// Detecting vertical squash in loaded image.
3241// Fixes a bug which squash image vertically while drawing into canvas for some images.
3242// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel
3243var detectVerticalSquash = function detectVerticalSquash(img) {
3244  var iw = img.naturalWidth;
3245  var ih = img.naturalHeight;
3246  var canvas = document.createElement("canvas");
3247  canvas.width = 1;
3248  canvas.height = ih;
3249  var ctx = canvas.getContext("2d");
3250  ctx.drawImage(img, 0, 0);
3251
3252  var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),
3253      data = _ctx$getImageData.data;
3254
3255  // search image edge pixel position in case it is squashed vertically.
3256
3257
3258  var sy = 0;
3259  var ey = ih;
3260  var py = ih;
3261  while (py > sy) {
3262    var alpha = data[(py - 1) * 4 + 3];
3263
3264    if (alpha === 0) {
3265      ey = py;
3266    } else {
3267      sy = py;
3268    }
3269
3270    py = ey + sy >> 1;
3271  }
3272  var ratio = py / ih;
3273
3274  if (ratio === 0) {
3275    return 1;
3276  } else {
3277    return ratio;
3278  }
3279};
3280
3281// A replacement for context.drawImage
3282// (args are for source and destination).
3283var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
3284  var vertSquashRatio = detectVerticalSquash(img);
3285  return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
3286};
3287
3288// Based on MinifyJpeg
3289// Source: http://www.perry.cz/files/ExifRestorer.js
3290// http://elicon.blog57.fc2.com/blog-entry-206.html
3291
3292var ExifRestore = function () {
3293  function ExifRestore() {
3294    _classCallCheck(this, ExifRestore);
3295  }
3296
3297  _createClass(ExifRestore, null, [{
3298    key: "initClass",
3299    value: function initClass() {
3300      this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
vendor: 6,813 bytes, lines 3300-3532
3300+/=';
3301    }
3302  }, {
3303    key: "encode64",
3304    value: function encode64(input) {
3305      var output = '';
3306      var chr1 = undefined;
3307      var chr2 = undefined;
3308      var chr3 = '';
3309      var enc1 = undefined;
3310      var enc2 = undefined;
3311      var enc3 = undefined;
3312      var enc4 = '';
3313      var i = 0;
3314      while (true) {
3315        chr1 = input[i++];
3316        chr2 = input[i++];
3317        chr3 = input[i++];
3318        enc1 = chr1 >> 2;
3319        enc2 = (chr1 & 3) << 4 | chr2 >> 4;
3320        enc3 = (chr2 & 15) << 2 | chr3 >> 6;
3321        enc4 = chr3 & 63;
3322        if (isNaN(chr2)) {
3323          enc3 = enc4 = 64;
3324        } else if (isNaN(chr3)) {
3325          enc4 = 64;
3326        }
3327        output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
3328        chr1 = chr2 = chr3 = '';
3329        enc1 = enc2 = enc3 = enc4 = '';
3330        if (!(i < input.length)) {
3331          break;
3332        }
3333      }
3334      return output;
3335    }
3336  }, {
3337    key: "restore",
3338    value: function restore(origFileBase64, resizedFileBase64) {
3339      if (!origFileBase64.match('data:image/jpeg;base64,')) {
3340        return resizedFileBase64;
3341      }
3342      var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));
3343      var segments = this.slice2Segments(rawImage);
3344      var image = this.exifManipulation(resizedFileBase64, segments);
3345      return "data:image/jpeg;base64," + this.encode64(image);
3346    }
3347  }, {
3348    key: "exifManipulation",
3349    value: function exifManipulation(resizedFileBase64, segments) {
3350      var exifArray = this.getExifArray(segments);
3351      var newImageArray = this.insertExif(resizedFileBase64, exifArray);
3352      var aBuffer = new Uint8Array(newImageArray);
3353      return aBuffer;
3354    }
3355  }, {
3356    key: "getExifArray",
3357    value: function getExifArray(segments) {
3358      var seg = undefined;
3359      var x = 0;
3360      while (x < segments.length) {
3361        seg = segments[x];
3362        if (seg[0] === 255 & seg[1] === 225) {
3363          return seg;
3364        }
3365        x++;
3366      }
3367      return [];
3368    }
3369  }, {
3370    key: "insertExif",
3371    value: function insertExif(resizedFileBase64, exifArray) {
3372      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');
3373      var buf = this.decode64(imageData);
3374      var separatePoint = buf.indexOf(255, 3);
3375      var mae = buf.slice(0, separatePoint);
3376      var ato = buf.slice(separatePoint);
3377      var array = mae;
3378      array = array.concat(exifArray);
3379      array = array.concat(ato);
3380      return array;
3381    }
3382  }, {
3383    key: "slice2Segments",
3384    value: function slice2Segments(rawImageArray) {
3385      var head = 0;
3386      var segments = [];
3387      while (true) {
3388        var length;
3389        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
3390          break;
3391        }
3392        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
3393          head += 2;
3394        } else {
3395          length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
3396          var endPoint = head + length + 2;
3397          var seg = rawImageArray.slice(head, endPoint);
3398          segments.push(seg);
3399          head = endPoint;
3400        }
3401        if (head > rawImageArray.length) {
3402          break;
3403        }
3404      }
3405      return segments;
3406    }
3407  }, {
3408    key: "decode64",
3409    value: function decode64(input) {
3410      var output = '';
3411      var chr1 = undefined;
3412      var chr2 = undefined;
3413      var chr3 = '';
3414      var enc1 = undefined;
3415      var enc2 = undefined;
3416      var enc3 = undefined;
3417      var enc4 = '';
3418      var i = 0;
3419      var buf = [];
3420      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
3421      var base64test = /[^A-Za-z0-9\+\/\=]/g;
3422      if (base64test.exec(input)) {
3423        console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.');
3424      }
3425      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
3426      while (true) {
3427        enc1 = this.KEY_STR.indexOf(input.charAt(i++));
3428        enc2 = this.KEY_STR.indexOf(input.charAt(i++));
3429        enc3 = this.KEY_STR.indexOf(input.charAt(i++));
3430        enc4 = this.KEY_STR.indexOf(input.charAt(i++));
3431        chr1 = enc1 << 2 | enc2 >> 4;
3432        chr2 = (enc2 & 15) << 4 | enc3 >> 2;
3433        chr3 = (enc3 & 3) << 6 | enc4;
3434        buf.push(chr1);
3435        if (enc3 !== 64) {
3436          buf.push(chr2);
3437        }
3438        if (enc4 !== 64) {
3439          buf.push(chr3);
3440        }
3441        chr1 = chr2 = chr3 = '';
3442        enc1 = enc2 = enc3 = enc4 = '';
3443        if (!(i < input.length)) {
3444          break;
3445        }
3446      }
3447      return buf;
3448    }
3449  }]);
3450
3451  return ExifRestore;
3452}();
3453
3454ExifRestore.initClass();
3455
3456/*
3457 * contentloaded.js
3458 *
3459 * Author: Diego Perini (diego.perini at gmail.com)
3460 * Summary: cross-browser wrapper for DOMContentLoaded
3461 * Updated: 20101020
3462 * License: MIT
3463 * Version: 1.2
3464 *
3465 * URL:
3466 * http://javascript.nwbox.com/ContentLoaded/
3467 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
3468 */
3469
3470// @win window reference
3471// @fn function reference
3472var contentLoaded = function contentLoaded(win, fn) {
3473  var done = false;
3474  var top = true;
3475  var doc = win.document;
3476  var root = doc.documentElement;
3477  var add = doc.addEventListener ? "addEventListener" : "attachEvent";
3478  var rem = doc.addEventListener ? "removeEventListener" : "detachEvent";
3479  var pre = doc.addEventListener ? "" : "on";
3480  var init = function init(e) {
3481    if (e.type === "readystatechange" && doc.readyState !== "complete") {
3482      return;
3483    }
3484    (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
3485    if (!done && (done = true)) {
3486      return fn.call(win, e.type || e);
3487    }
3488  };
3489
3490  var poll = function poll() {
3491    try {
3492      root.doScroll("left");
3493    } catch (e) {
3494      setTimeout(poll, 50);
3495      return;
3496    }
3497    return init("poll");
3498  };
3499
3500  if (doc.readyState !== "complete") {
3501    if (doc.createEventObject && root.doScroll) {
3502      try {
3503        top = !win.frameElement;
3504      } catch (error) {}
3505      if (top) {
3506        poll();
3507      }
3508    }
3509    doc[add](pre + "DOMContentLoaded", init, false);
3510    doc[add](pre + "readystatechange", init, false);
3511    return win[add](pre + "load", init, false);
3512  }
3513};
3514
3515// As a single function to be able to write tests.
3516Dropzone._autoDiscoverFunction = function () {
3517  if (Dropzone.autoDiscover) {
3518    return Dropzone.discover();
3519  }
3520};
3521contentLoaded(window, Dropzone._autoDiscoverFunction);
3522
3523function __guard__(value, transform) {
3524  return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;
3525}
3526function __guardMethod__(obj, methodName, transform) {
3527  if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
3528    return transform(obj, methodName);
3529  } else {
3530    return undefined;
3531  }
3532}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.