diff --git a/addonstyle/_dropzone.js b/addonstyle/_dropzone.js
new file mode 100644
index 0000000..a497d62
--- /dev/null
+++ b/addonstyle/_dropzone.js
@@ -0,0 +1,3521 @@
+"use strict";
+
+var _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; }; }();
+
+function _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; }
+
+function _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; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/*
+ *
+ * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
+ *
+ * Copyright (c) 2012, Matias Meno
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+// The Emitter class provides the ability to call `.on()` on Dropzone to listen
+// to events.
+// It is strongly based on component's emitter class, and I removed the
+// functionality because of the dependency hell with different frameworks.
+var Emitter = function () {
+ function Emitter() {
+ _classCallCheck(this, Emitter);
+ }
+
+ _createClass(Emitter, [{
+ key: "on",
+
+ // Add an event listener for given event
+ value: function on(event, fn) {
+ this._callbacks = this._callbacks || {};
+ // Create namespace for this event
+ if (!this._callbacks[event]) {
+ this._callbacks[event] = [];
+ }
+ this._callbacks[event].push(fn);
+ return this;
+ }
+ }, {
+ key: "emit",
+ value: function emit(event) {
+ this._callbacks = this._callbacks || {};
+ var callbacks = this._callbacks[event];
+
+ if (callbacks) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
+ var _ref;
+
+ if (_isArray) {
+ if (_i >= _iterator.length) break;
+ _ref = _iterator[_i++];
+ } else {
+ _i = _iterator.next();
+ if (_i.done) break;
+ _ref = _i.value;
+ }
+
+ var callback = _ref;
+
+ callback.apply(this, args);
+ }
+ }
+
+ return this;
+ }
+
+ // Remove event listener for given event. If fn is not provided, all event
+ // listeners for that event will be removed. If neither is provided, all
+ // event listeners will be removed.
+
+ }, {
+ key: "off",
+ value: function off(event, fn) {
+ if (!this._callbacks || arguments.length === 0) {
+ this._callbacks = {};
+ return this;
+ }
+
+ // specific event
+ var callbacks = this._callbacks[event];
+ if (!callbacks) {
+ return this;
+ }
+
+ // remove all handlers
+ if (arguments.length === 1) {
+ delete this._callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ for (var i = 0; i < callbacks.length; i++) {
+ var callback = callbacks[i];
+ if (callback === fn) {
+ callbacks.splice(i, 1);
+ break;
+ }
+ }
+
+ return this;
+ }
+ }]);
+
+ return Emitter;
+}();
+
+var Dropzone = function (_Emitter) {
+ _inherits(Dropzone, _Emitter);
+
+ _createClass(Dropzone, null, [{
+ key: "initClass",
+ value: function initClass() {
+
+ // Exposing the emitter class, mainly for tests
+ this.prototype.Emitter = Emitter;
+
+ /*
+ This is a list of all available events you can register on a dropzone object.
+ You can register an event handler like this:
+ dropzone.on("dragEnter", function() { });
+ */
+ 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"];
+
+ this.prototype.defaultOptions = {
+ /**
+ * Has to be specified on elements other than form (or when the form
+ * doesn't have an `action` attribute). You can also
+ * provide a function that will be called with `files` and
+ * must return the url (since `v3.12.0`)
+ */
+ url: null,
+
+ /**
+ * Can be changed to `"put"` if necessary. You can also provide a function
+ * that will be called with `files` and must return the method (since `v3.12.0`).
+ */
+ method: "post",
+
+ /**
+ * Will be set on the XHRequest.
+ */
+ withCredentials: false,
+
+ /**
+ * The timeout for the XHR requests in milliseconds (since `v4.4.0`).
+ */
+ timeout: 30000,
+
+ /**
+ * How many file uploads to process in parallel (See the
+ * Enqueuing file uploads* documentation section for more info)
+ */
+ parallelUploads: 1,
+
+ /**
+ * Whether to send multiple files in one request. If
+ * this it set to true, then the fallback file input element will
+ * have the `multiple` attribute as well. This option will
+ * also trigger additional events (like `processingmultiple`). See the events
+ * documentation section for more information.
+ */
+ uploadMultiple: false,
+
+ /**
+ * Whether you want files to be uploaded in chunks to your server. This can't be
+ * used in combination with `uploadMultiple`.
+ *
+ * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.
+ */
+ chunking: false,
+
+ /**
+ * If `chunking` is enabled, this defines whether **every** file should be chunked,
+ * even if the file size is below chunkSize. This means, that the additional chunk
+ * form data will be submitted and the `chunksUploaded` callback will be invoked.
+ */
+ forceChunking: false,
+
+ /**
+ * If `chunking` is `true`, then this defines the chunk size in bytes.
+ */
+ chunkSize: 2000000,
+
+ /**
+ * If `true`, the individual chunks of a file are being uploaded simultaneously.
+ */
+ parallelChunkUploads: false,
+
+ /**
+ * Whether a chunk should be retried if it fails.
+ */
+ retryChunks: false,
+
+ /**
+ * If `retryChunks` is true, how many times should it be retried.
+ */
+ retryChunksLimit: 3,
+
+ /**
+ * If not `null` defines how many files this Dropzone handles. If it exceeds,
+ * the event `maxfilesexceeded` will be called. The dropzone element gets the
+ * class `dz-max-files-reached` accordingly so you can provide visual feedback.
+ */
+ maxFilesize: 1,
+
+ /**
+ * The name of the file param that gets transferred.
+ * **NOTE**: If you have the option `uploadMultiple` set to `true`, then
+ * Dropzone will append `[]` to the name.
+ */
+ paramName: "fileToUpload",
+
+ /**
+ * Whether thumbnails for images should be generated
+ */
+ createImageThumbnails: true,
+
+ /**
+ * In MB. When the filename exceeds this limit, the thumbnail will not be generated.
+ */
+ maxThumbnailFilesize: 4,
+
+ /**
+ * If `null`, the ratio of the image will be used to calculate it.
+ */
+ thumbnailWidth: 120,
+
+ /**
+ * The same as `thumbnailWidth`. If both are null, images will not be resized.
+ */
+ thumbnailHeight: 120,
+
+ /**
+ * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.
+ * Can be either `contain` or `crop`.
+ */
+ thumbnailMethod: 'crop',
+
+ /**
+ * If set, images will be resized to these dimensions before being **uploaded**.
+ * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect
+ * ratio of the file will be preserved.
+ *
+ * The `options.transformFile` function uses these options, so if the `transformFile` function
+ * is overridden, these options don't do anything.
+ */
+ resizeWidth: null,
+
+ /**
+ * See `resizeWidth`.
+ */
+ resizeHeight: null,
+
+ /**
+ * The mime type of the resized image (before it gets uploaded to the server).
+ * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.
+ * See `resizeWidth` for more information.
+ */
+ resizeMimeType: null,
+
+ /**
+ * The quality of the resized images. See `resizeWidth`.
+ */
+ resizeQuality: 0.8,
+
+ /**
+ * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.
+ * Can be either `contain` or `crop`.
+ */
+ resizeMethod: 'contain',
+
+ /**
+ * The base that is used to calculate the filesize. You can change this to
+ * 1024 if you would rather display kibibytes, mebibytes, etc...
+ * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.
+ * You can change this to `1024` if you don't care about validity.
+ */
+ filesizeBase: 1000,
+
+ /**
+ * Can be used to limit the maximum number of files that will be handled by this Dropzone
+ */
+ maxFiles: null,
+
+ /**
+ * An optional object to send additional headers to the server. Eg:
+ * `{ "My-Awesome-Header": "header value" }`
+ */
+ headers: null,
+
+ /**
+ * If `true`, the dropzone element itself will be clickable, if `false`
+ * nothing will be clickable.
+ *
+ * You can also pass an HTML element, a CSS selector (for multiple elements)
+ * or an array of those. In that case, all of those elements will trigger an
+ * upload when clicked.
+ */
+ clickable: true,
+
+ /**
+ * Whether hidden files in directories should be ignored.
+ */
+ ignoreHiddenFiles: true,
+
+ /**
+ * The default implementation of `accept` checks the file's mime type or
+ * extension against this list. This is a comma separated list of mime
+ * types or file extensions.
+ *
+ * Eg.: `image/*,application/pdf,.psd`
+ *
+ * If the Dropzone is `clickable` this option will also be used as
+ * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)
+ * parameter on the hidden file input as well.
+ */
+ acceptedFiles: 'image/*',
+
+ /**
+ * **Deprecated!**
+ * Use acceptedFiles instead.
+ */
+ acceptedMimeTypes: null,
+
+ /**
+ * If false, files will be added to the queue but the queue will not be
+ * processed automatically.
+ * This can be useful if you need some additional user input before sending
+ * files (or if you want want all files sent at once).
+ * If you're ready to send the file simply call `myDropzone.processQueue()`.
+ *
+ * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation
+ * section for more information.
+ */
+ autoProcessQueue: true,
+
+ /**
+ * If false, files added to the dropzone will not be queued by default.
+ * You'll have to call `enqueueFile(file)` manually.
+ */
+ autoQueue: true,
+
+ /**
+ * If `true`, this will add a link to every file preview to remove or cancel (if
+ * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`
+ * and `dictRemoveFile` options are used for the wording.
+ */
+ addRemoveLinks: false,
+
+ /**
+ * Defines where to display the file previews – if `null` the
+ * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS
+ * selector. The element should have the `dropzone-previews` class so
+ * the previews are displayed properly.
+ */
+ previewsContainer: null,
+
+ /**
+ * This is the element the hidden input field (which is used when clicking on the
+ * dropzone to trigger file selection) will be appended to. This might
+ * be important in case you use frameworks to switch the content of your page.
+ */
+ hiddenInputContainer: "body",
+
+ /**
+ * If null, no capture type will be specified
+ * If camera, mobile devices will skip the file selection and choose camera
+ * If microphone, mobile devices will skip the file selection and choose the microphone
+ * If camcorder, mobile devices will skip the file selection and choose the camera in video mode
+ * On apple devices multiple must be set to false. AcceptedFiles may need to
+ * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").
+ */
+ capture: null,
+
+ /**
+ * **Deprecated**. Use `renameFile` instead.
+ */
+ renameFilename: null,
+
+ /**
+ * A function that is invoked before the file is uploaded to the server and renames the file.
+ * This function gets the `File` as argument and can use the `file.name`. The actual name of the
+ * file that gets used during the upload can be accessed through `file.upload.filename`.
+ */
+ renameFile: null,
+
+ /**
+ * If `true` the fallback will be forced. This is very useful to test your server
+ * implementations first and make sure that everything works as
+ * expected without dropzone if you experience problems, and to test
+ * how your fallbacks will look.
+ */
+ forceFallback: false,
+
+ /**
+ * The text used before any files are dropped.
+ */
+ dictDefaultMessage: "Drop files here to upload",
+
+ /**
+ * The text that replaces the default message text it the browser is not supported.
+ */
+ dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
+
+ /**
+ * The text that will be added before the fallback form.
+ * If you provide a fallback element yourself, or if this option is `null` this will
+ * be ignored.
+ */
+ dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.",
+
+ /**
+ * If the filesize is too big.
+ * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.
+ */
+ dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
+
+ /**
+ * If the file doesn't match the file type.
+ */
+ dictInvalidFileType: "You can't upload files of this type.",
+
+ /**
+ * If the server response was invalid.
+ * `{{statusCode}}` will be replaced with the servers status code.
+ */
+ dictResponseError: "Server responded with {{statusCode}} code.",
+
+ /**
+ * If `addRemoveLinks` is true, the text to be used for the cancel upload link.
+ */
+ dictCancelUpload: "Cancel upload",
+
+ /**
+ * The text that is displayed if an upload was manually canceled
+ */
+ dictUploadCanceled: "Upload canceled.",
+
+ /**
+ * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.
+ */
+ dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
+
+ /**
+ * If `addRemoveLinks` is true, the text to be used to remove a file.
+ */
+ dictRemoveFile: "Remove file",
+
+ /**
+ * If this is not null, then the user will be prompted before removing a file.
+ */
+ dictRemoveFileConfirmation: null,
+
+ /**
+ * Displayed if `maxFiles` is st and exceeded.
+ * The string `{{maxFiles}}` will be replaced by the configuration value.
+ */
+ dictMaxFilesExceeded: "You can not upload any more files.",
+
+ /**
+ * Allows you to translate the different units. Starting with `tb` for terabytes and going down to
+ * `b` for bytes.
+ */
+ dictFileSizeUnits: { tb: "TB", gb: "GB", mb: "MB", kb: "KB", b: "b" },
+ /**
+ * Called when dropzone initialized
+ * You can add event listeners here
+ */
+ init: function init() {},
+
+
+ /**
+ * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`
+ * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case
+ * of a function, this needs to return a map.
+ *
+ * The default implementation does nothing for normal uploads, but adds relevant information for
+ * chunked uploads.
+ *
+ * This is the same as adding hidden input fields in the form element.
+ */
+ params: function params(files, xhr, chunk) {
+ if (chunk) {
+ return {
+ dzuuid: chunk.file.upload.uuid,
+ dzchunkindex: chunk.index,
+ dztotalfilesize: chunk.file.size,
+ dzchunksize: this.options.chunkSize,
+ dztotalchunkcount: chunk.file.upload.totalChunkCount,
+ dzchunkbyteoffset: chunk.index * this.options.chunkSize
+ };
+ }
+ },
+
+
+ /**
+ * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)
+ * and a `done` function as parameters.
+ *
+ * If the done function is invoked without arguments, the file is "accepted" and will
+ * be processed. If you pass an error message, the file is rejected, and the error
+ * message will be displayed.
+ * This function will not be called if the file is too big or doesn't match the mime types.
+ */
+ accept: function accept(file, done) {
+ return done();
+ },
+
+
+ /**
+ * The callback that will be invoked when all chunks have been uploaded for a file.
+ * It gets the file for which the chunks have been uploaded as the first parameter,
+ * and the `done` function as second. `done()` needs to be invoked when everything
+ * needed to finish the upload process is done.
+ */
+ chunksUploaded: function chunksUploaded(file, done) {
+ done();
+ },
+
+ /**
+ * Gets called when the browser is not supported.
+ * The default implementation shows the fallback input field and adds
+ * a text.
+ */
+ fallback: function fallback() {
+ // This code should pass in IE7... :(
+ var messageElement = void 0;
+ this.element.className = this.element.className + " dz-browser-not-supported";
+
+ for (var _iterator2 = this.element.getElementsByTagName("div"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
+ var _ref2;
+
+ if (_isArray2) {
+ if (_i2 >= _iterator2.length) break;
+ _ref2 = _iterator2[_i2++];
+ } else {
+ _i2 = _iterator2.next();
+ if (_i2.done) break;
+ _ref2 = _i2.value;
+ }
+
+ var child = _ref2;
+
+ if (/(^| )dz-message($| )/.test(child.className)) {
+ messageElement = child;
+ child.className = "dz-message"; // Removes the 'dz-default' class
+ break;
+ }
+ }
+ if (!messageElement) {
+ messageElement = Dropzone.createElement("
");
+ this.element.appendChild(messageElement);
+ }
+
+ var span = messageElement.getElementsByTagName("span")[0];
+ if (span) {
+ if (span.textContent != null) {
+ span.textContent = this.options.dictFallbackMessage;
+ } else if (span.innerText != null) {
+ span.innerText = this.options.dictFallbackMessage;
+ }
+ }
+
+ return this.element.appendChild(this.getFallbackForm());
+ },
+
+
+ /**
+ * Gets called to calculate the thumbnail dimensions.
+ *
+ * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:
+ *
+ * - `srcWidth` & `srcHeight` (required)
+ * - `trgWidth` & `trgHeight` (required)
+ * - `srcX` & `srcY` (optional, default `0`)
+ * - `trgX` & `trgY` (optional, default `0`)
+ *
+ * Those values are going to be used by `ctx.drawImage()`.
+ */
+ resize: function resize(file, width, height, resizeMethod) {
+ var info = {
+ srcX: 0,
+ srcY: 0,
+ srcWidth: file.width,
+ srcHeight: file.height
+ };
+
+ var srcRatio = file.width / file.height;
+
+ // Automatically calculate dimensions if not specified
+ if (width == null && height == null) {
+ width = info.srcWidth;
+ height = info.srcHeight;
+ } else if (width == null) {
+ width = height * srcRatio;
+ } else if (height == null) {
+ height = width / srcRatio;
+ }
+
+ // Make sure images aren't upscaled
+ width = Math.min(width, info.srcWidth);
+ height = Math.min(height, info.srcHeight);
+
+ var trgRatio = width / height;
+
+ if (info.srcWidth > width || info.srcHeight > height) {
+ // Image is bigger and needs rescaling
+ if (resizeMethod === 'crop') {
+ if (srcRatio > trgRatio) {
+ info.srcHeight = file.height;
+ info.srcWidth = info.srcHeight * trgRatio;
+ } else {
+ info.srcWidth = file.width;
+ info.srcHeight = info.srcWidth / trgRatio;
+ }
+ } else if (resizeMethod === 'contain') {
+ // Method 'contain'
+ if (srcRatio > trgRatio) {
+ height = width / srcRatio;
+ } else {
+ width = height * srcRatio;
+ }
+ } else {
+ throw new Error("Unknown resizeMethod '" + resizeMethod + "'");
+ }
+ }
+
+ info.srcX = (file.width - info.srcWidth) / 2;
+ info.srcY = (file.height - info.srcHeight) / 2;
+
+ info.trgWidth = width;
+ info.trgHeight = height;
+
+ return info;
+ },
+
+
+ /**
+ * Can be used to transform the file (for example, resize an image if necessary).
+ *
+ * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes
+ * images according to those dimensions.
+ *
+ * Gets the `file` as the first parameter, and a `done()` function as the second, that needs
+ * to be invoked with the file when the transformation is done.
+ */
+ transformFile: function transformFile(file, done) {
+ if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
+ return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
+ } else {
+ return done(file);
+ }
+ },
+
+
+ /**
+ * A string that contains the template used for each dropped
+ * file. Change it to fulfill your needs but make sure to properly
+ * provide all elements.
+ *
+ * If you want to use an actual HTML element instead of providing a String
+ * as a config option, you could create a div with the id `tpl`,
+ * put the template inside it and provide the element like this:
+ *
+ * document
+ * .querySelector('#tpl')
+ * .innerHTML
+ *
+ */
+ previewTemplate: "
\n \n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
",
+
+ // END OPTIONS
+ // (Required by the dropzone documentation parser)
+
+
+ /*
+ Those functions register themselves to the events on init and handle all
+ the user interface specific stuff. Overwriting them won't break the upload
+ but can break the way it's displayed.
+ You can overwrite them if you don't like the default behavior. If you just
+ want to add an additional event handler, register it on the dropzone object
+ and don't overwrite those options.
+ */
+
+ // Those are self explanatory and simply concern the DragnDrop.
+ drop: function drop(e) {
+ return this.element.classList.remove("dz-drag-hover");
+ },
+ dragstart: function dragstart(e) {},
+ dragend: function dragend(e) {
+ return this.element.classList.remove("dz-drag-hover");
+ },
+ dragenter: function dragenter(e) {
+ return this.element.classList.add("dz-drag-hover");
+ },
+ dragover: function dragover(e) {
+ return this.element.classList.add("dz-drag-hover");
+ },
+ dragleave: function dragleave(e) {
+ return this.element.classList.remove("dz-drag-hover");
+ },
+ paste: function paste(e) {},
+
+
+ // Called whenever there are no files left in the dropzone anymore, and the
+ // dropzone should be displayed as if in the initial state.
+ reset: function reset() {
+ return this.element.classList.remove("dz-started");
+ },
+
+
+ // Called when a file is added to the queue
+ // Receives `file`
+ addedfile: function addedfile(file) {
+ var _this2 = this;
+
+ if (this.element === this.previewsContainer) {
+ this.element.classList.add("dz-started");
+ }
+
+ if (this.previewsContainer) {
+ file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
+ file.previewTemplate = file.previewElement; // Backwards compatibility
+
+ this.previewsContainer.appendChild(file.previewElement);
+ for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
+ var _ref3;
+
+ if (_isArray3) {
+ if (_i3 >= _iterator3.length) break;
+ _ref3 = _iterator3[_i3++];
+ } else {
+ _i3 = _iterator3.next();
+ if (_i3.done) break;
+ _ref3 = _i3.value;
+ }
+
+ var node = _ref3;
+
+ node.textContent = file.name;
+ }
+ for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
+ if (_isArray4) {
+ if (_i4 >= _iterator4.length) break;
+ node = _iterator4[_i4++];
+ } else {
+ _i4 = _iterator4.next();
+ if (_i4.done) break;
+ node = _i4.value;
+ }
+
+ node.innerHTML = this.filesize(file.size);
+ }
+
+ if (this.options.addRemoveLinks) {
+ file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + "");
+ file.previewElement.appendChild(file._removeLink);
+ }
+
+ var removeFileEvent = function removeFileEvent(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if (file.status === Dropzone.UPLOADING) {
+ return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {
+ return _this2.removeFile(file);
+ });
+ } else {
+ if (_this2.options.dictRemoveFileConfirmation) {
+ return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {
+ return _this2.removeFile(file);
+ });
+ } else {
+ return _this2.removeFile(file);
+ }
+ }
+ };
+
+ for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
+ var _ref4;
+
+ if (_isArray5) {
+ if (_i5 >= _iterator5.length) break;
+ _ref4 = _iterator5[_i5++];
+ } else {
+ _i5 = _iterator5.next();
+ if (_i5.done) break;
+ _ref4 = _i5.value;
+ }
+
+ var removeLink = _ref4;
+
+ removeLink.addEventListener("click", removeFileEvent);
+ }
+ }
+ },
+
+
+ // Called whenever a file is removed.
+ removedfile: function removedfile(file) {
+ if (file.previewElement != null && file.previewElement.parentNode != null) {
+ file.previewElement.parentNode.removeChild(file.previewElement);
+ }
+ return this._updateMaxFilesReachedClass();
+ },
+
+
+ // Called when a thumbnail has been generated
+ // Receives `file` and `dataUrl`
+ thumbnail: function thumbnail(file, dataUrl) {
+ if (file.previewElement) {
+ file.previewElement.classList.remove("dz-file-preview");
+ for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
+ var _ref5;
+
+ if (_isArray6) {
+ if (_i6 >= _iterator6.length) break;
+ _ref5 = _iterator6[_i6++];
+ } else {
+ _i6 = _iterator6.next();
+ if (_i6.done) break;
+ _ref5 = _i6.value;
+ }
+
+ var thumbnailElement = _ref5;
+
+ thumbnailElement.alt = file.name;
+ thumbnailElement.src = dataUrl;
+ }
+
+ return setTimeout(function () {
+ return file.previewElement.classList.add("dz-image-preview");
+ }, 1);
+ }
+ },
+
+
+ // Called whenever an error occurs
+ // Receives `file` and `message`
+ error: function error(file, message) {
+ if (file.previewElement) {
+ file.previewElement.classList.add("dz-error");
+ if (typeof message !== "String" && message.error) {
+ message = message.error;
+ }
+ for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
+ var _ref6;
+
+ if (_isArray7) {
+ if (_i7 >= _iterator7.length) break;
+ _ref6 = _iterator7[_i7++];
+ } else {
+ _i7 = _iterator7.next();
+ if (_i7.done) break;
+ _ref6 = _i7.value;
+ }
+
+ var node = _ref6;
+
+ node.textContent = message;
+ }
+ }
+ },
+ errormultiple: function errormultiple() {},
+
+
+ // Called when a file gets processed. Since there is a cue, not all added
+ // files are processed immediately.
+ // Receives `file`
+ processing: function processing(file) {
+ if (file.previewElement) {
+ file.previewElement.classList.add("dz-processing");
+ if (file._removeLink) {
+ return file._removeLink.textContent = this.options.dictCancelUpload;
+ }
+ }
+ },
+ processingmultiple: function processingmultiple() {},
+
+
+ // Called whenever the upload progress gets updated.
+ // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.
+ // To get the total number of bytes of the file, use `file.size`
+ uploadprogress: function uploadprogress(file, progress, bytesSent) {
+ if (file.previewElement) {
+ for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
+ var _ref7;
+
+ if (_isArray8) {
+ if (_i8 >= _iterator8.length) break;
+ _ref7 = _iterator8[_i8++];
+ } else {
+ _i8 = _iterator8.next();
+ if (_i8.done) break;
+ _ref7 = _i8.value;
+ }
+
+ var node = _ref7;
+
+ node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + "%";
+ }
+ }
+ },
+
+
+ // Called whenever the total upload progress gets updated.
+ // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent
+ totaluploadprogress: function totaluploadprogress() {},
+
+
+ // Called just before the file is sent. Gets the `xhr` object as second
+ // parameter, so you can modify it (for example to add a CSRF token) and a
+ // `formData` object to add additional information.
+ sending: function sending() {},
+ sendingmultiple: function sendingmultiple() {},
+
+
+ // When the complete upload is finished and successful
+ // Receives `file`
+ success: function success(file) {
+ if (file.previewElement) {
+ return file.previewElement.classList.add("dz-success");
+ }
+ },
+ successmultiple: function successmultiple() {},
+
+
+ // When the upload is canceled.
+ canceled: function canceled(file) {
+ return this.emit("error", file, this.options.dictUploadCanceled);
+ },
+ canceledmultiple: function canceledmultiple() {},
+
+
+ // When the upload is finished, either with success or an error.
+ // Receives `file`
+ complete: function complete(file) {
+ if (file._removeLink) {
+ file._removeLink.textContent = this.options.dictRemoveFile;
+ }
+ if (file.previewElement) {
+ return file.previewElement.classList.add("dz-complete");
+ }
+ },
+ completemultiple: function completemultiple() {},
+ maxfilesexceeded: function maxfilesexceeded() {},
+ maxfilesreached: function maxfilesreached() {},
+ queuecomplete: function queuecomplete() {},
+ addedfiles: function addedfiles() {}
+ };
+
+ this.prototype._thumbnailQueue = [];
+ this.prototype._processingThumbnail = false;
+ }
+
+ // global utility
+
+ }, {
+ key: "extend",
+ value: function extend(target) {
+ for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+ objects[_key2 - 1] = arguments[_key2];
+ }
+
+ for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
+ var _ref8;
+
+ if (_isArray9) {
+ if (_i9 >= _iterator9.length) break;
+ _ref8 = _iterator9[_i9++];
+ } else {
+ _i9 = _iterator9.next();
+ if (_i9.done) break;
+ _ref8 = _i9.value;
+ }
+
+ var object = _ref8;
+
+ for (var key in object) {
+ var val = object[key];
+ target[key] = val;
+ }
+ }
+ return target;
+ }
+ }]);
+
+ function Dropzone(el, options) {
+ _classCallCheck(this, Dropzone);
+
+ var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));
+
+ var fallback = void 0,
+ left = void 0;
+ _this.element = el;
+ // For backwards compatibility since the version was in the prototype previously
+ _this.version = Dropzone.version;
+
+ _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, "");
+
+ _this.clickableElements = [];
+ _this.listeners = [];
+ _this.files = []; // All files
+
+ if (typeof _this.element === "string") {
+ _this.element = document.querySelector(_this.element);
+ }
+
+ // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.
+ if (!_this.element || _this.element.nodeType == null) {
+ throw new Error("Invalid dropzone element.");
+ }
+
+ if (_this.element.dropzone) {
+ throw new Error("Dropzone already attached.");
+ }
+
+ // Now add this dropzone to the instances.
+ Dropzone.instances.push(_this);
+
+ // Put the dropzone inside the element itself.
+ _this.element.dropzone = _this;
+
+ var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};
+
+ _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});
+
+ // If the browser failed, just call the fallback and leave
+ if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {
+ var _ret;
+
+ return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);
+ }
+
+ // @options.url = @element.getAttribute "action" unless @options.url?
+ if (_this.options.url == null) {
+ _this.options.url = _this.element.getAttribute("action");
+ }
+
+ if (!_this.options.url) {
+ throw new Error("No URL provided.");
+ }
+
+ if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {
+ throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
+ }
+
+ if (_this.options.uploadMultiple && _this.options.chunking) {
+ throw new Error('You cannot set both: uploadMultiple and chunking.');
+ }
+
+ // Backwards compatibility
+ if (_this.options.acceptedMimeTypes) {
+ _this.options.acceptedFiles = _this.options.acceptedMimeTypes;
+ delete _this.options.acceptedMimeTypes;
+ }
+
+ // Backwards compatibility
+ if (_this.options.renameFilename != null) {
+ _this.options.renameFile = function (file) {
+ return _this.options.renameFilename.call(_this, file.name, file);
+ };
+ }
+
+ _this.options.method = _this.options.method.toUpperCase();
+
+ if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {
+ // Remove the fallback
+ fallback.parentNode.removeChild(fallback);
+ }
+
+ // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false
+ if (_this.options.previewsContainer !== false) {
+ if (_this.options.previewsContainer) {
+ _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer");
+ } else {
+ _this.previewsContainer = _this.element;
+ }
+ }
+
+ if (_this.options.clickable) {
+ if (_this.options.clickable === true) {
+ _this.clickableElements = [_this.element];
+ } else {
+ _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable");
+ }
+ }
+
+ _this.init();
+ return _this;
+ }
+
+ // Returns all files that have been accepted
+
+
+ _createClass(Dropzone, [{
+ key: "getAcceptedFiles",
+ value: function getAcceptedFiles() {
+ return this.files.filter(function (file) {
+ return file.accepted;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // Returns all files that have been rejected
+ // Not sure when that's going to be useful, but added for completeness.
+
+ }, {
+ key: "getRejectedFiles",
+ value: function getRejectedFiles() {
+ return this.files.filter(function (file) {
+ return !file.accepted;
+ }).map(function (file) {
+ return file;
+ });
+ }
+ }, {
+ key: "getFilesWithStatus",
+ value: function getFilesWithStatus(status) {
+ return this.files.filter(function (file) {
+ return file.status === status;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // Returns all files that are in the queue
+
+ }, {
+ key: "getQueuedFiles",
+ value: function getQueuedFiles() {
+ return this.getFilesWithStatus(Dropzone.QUEUED);
+ }
+ }, {
+ key: "getUploadingFiles",
+ value: function getUploadingFiles() {
+ return this.getFilesWithStatus(Dropzone.UPLOADING);
+ }
+ }, {
+ key: "getAddedFiles",
+ value: function getAddedFiles() {
+ return this.getFilesWithStatus(Dropzone.ADDED);
+ }
+
+ // Files that are either queued or uploading
+
+ }, {
+ key: "getActiveFiles",
+ value: function getActiveFiles() {
+ return this.files.filter(function (file) {
+ return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // The function that gets called when Dropzone is initialized. You
+ // can (and should) setup event listeners inside this function.
+
+ }, {
+ key: "init",
+ value: function init() {
+ var _this3 = this;
+
+ // In case it isn't set already
+ if (this.element.tagName === "form") {
+ this.element.setAttribute("enctype", "multipart/form-data");
+ }
+
+ if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
+ this.element.appendChild(Dropzone.createElement("
" + this.options.dictDefaultMessage + "
"));
+ }
+
+ if (this.clickableElements.length) {
+ var setupHiddenFileInput = function setupHiddenFileInput() {
+ if (_this3.hiddenFileInput) {
+ _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
+ }
+ _this3.hiddenFileInput = document.createElement("input");
+ _this3.hiddenFileInput.setAttribute("type", "file");
+ if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
+ _this3.hiddenFileInput.setAttribute("multiple", "multiple");
+ }
+ _this3.hiddenFileInput.className = "dz-hidden-input";
+
+ if (_this3.options.acceptedFiles !== null) {
+ _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles);
+ }
+ if (_this3.options.capture !== null) {
+ _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture);
+ }
+
+ // Not setting `display="none"` because some browsers don't accept clicks
+ // on elements that aren't displayed.
+ _this3.hiddenFileInput.style.visibility = "hidden";
+ _this3.hiddenFileInput.style.position = "absolute";
+ _this3.hiddenFileInput.style.top = "0";
+ _this3.hiddenFileInput.style.left = "0";
+ _this3.hiddenFileInput.style.height = "0";
+ _this3.hiddenFileInput.style.width = "0";
+ document.querySelector(_this3.options.hiddenInputContainer).appendChild(_this3.hiddenFileInput);
+ return _this3.hiddenFileInput.addEventListener("change", function () {
+ var files = _this3.hiddenFileInput.files;
+
+ if (files.length) {
+ for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
+ var _ref9;
+
+ if (_isArray10) {
+ if (_i10 >= _iterator10.length) break;
+ _ref9 = _iterator10[_i10++];
+ } else {
+ _i10 = _iterator10.next();
+ if (_i10.done) break;
+ _ref9 = _i10.value;
+ }
+
+ var file = _ref9;
+
+ _this3.addFile(file);
+ }
+ }
+ _this3.emit("addedfiles", files);
+ return setupHiddenFileInput();
+ });
+ };
+ setupHiddenFileInput();
+ }
+
+ this.URL = window.URL !== null ? window.URL : window.webkitURL;
+
+ // Setup all event listeners on the Dropzone object itself.
+ // They're not in @setupEventListeners() because they shouldn't be removed
+ // again when the dropzone gets disabled.
+ for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
+ var _ref10;
+
+ if (_isArray11) {
+ if (_i11 >= _iterator11.length) break;
+ _ref10 = _iterator11[_i11++];
+ } else {
+ _i11 = _iterator11.next();
+ if (_i11.done) break;
+ _ref10 = _i11.value;
+ }
+
+ var eventName = _ref10;
+
+ this.on(eventName, this.options[eventName]);
+ }
+
+ this.on("uploadprogress", function () {
+ return _this3.updateTotalUploadProgress();
+ });
+
+ this.on("removedfile", function () {
+ return _this3.updateTotalUploadProgress();
+ });
+
+ this.on("canceled", function (file) {
+ return _this3.emit("complete", file);
+ });
+
+ // Emit a `queuecomplete` event if all files finished uploading.
+ this.on("complete", function (file) {
+ if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {
+ // This needs to be deferred so that `queuecomplete` really triggers after `complete`
+ return setTimeout(function () {
+ return _this3.emit("queuecomplete");
+ }, 0);
+ }
+ });
+
+ var noPropagation = function noPropagation(e) {
+ e.stopPropagation();
+ if (e.preventDefault) {
+ return e.preventDefault();
+ } else {
+ return e.returnValue = false;
+ }
+ };
+
+ // Create the listeners
+ this.listeners = [{
+ element: this.element,
+ events: {
+ "dragstart": function dragstart(e) {
+ return _this3.emit("dragstart", e);
+ },
+ "dragenter": function dragenter(e) {
+ noPropagation(e);
+ return _this3.emit("dragenter", e);
+ },
+ "dragover": function dragover(e) {
+ // Makes it possible to drag files from chrome's download bar
+ // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar
+ // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)
+ var efct = void 0;
+ try {
+ efct = e.dataTransfer.effectAllowed;
+ } catch (error) {}
+ e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
+
+ noPropagation(e);
+ return _this3.emit("dragover", e);
+ },
+ "dragleave": function dragleave(e) {
+ return _this3.emit("dragleave", e);
+ },
+ "drop": function drop(e) {
+ noPropagation(e);
+ return _this3.drop(e);
+ },
+ "dragend": function dragend(e) {
+ return _this3.emit("dragend", e);
+ }
+
+ // This is disabled right now, because the browsers don't implement it properly.
+ // "paste": (e) =>
+ // noPropagation e
+ // @paste e
+ } }];
+
+ this.clickableElements.forEach(function (clickableElement) {
+ return _this3.listeners.push({
+ element: clickableElement,
+ events: {
+ "click": function click(evt) {
+ // Only the actual dropzone or the message element should trigger file selection
+ if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) {
+ _this3.hiddenFileInput.click(); // Forward the click
+ }
+ return true;
+ }
+ }
+ });
+ });
+
+ this.enable();
+
+ return this.options.init.call(this);
+ }
+
+ // Not fully tested yet
+
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.disable();
+ this.removeAllFiles(true);
+ if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {
+ this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
+ this.hiddenFileInput = null;
+ }
+ delete this.element.dropzone;
+ return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
+ }
+ }, {
+ key: "updateTotalUploadProgress",
+ value: function updateTotalUploadProgress() {
+ var totalUploadProgress = void 0;
+ var totalBytesSent = 0;
+ var totalBytes = 0;
+
+ var activeFiles = this.getActiveFiles();
+
+ if (activeFiles.length) {
+ for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
+ var _ref11;
+
+ if (_isArray12) {
+ if (_i12 >= _iterator12.length) break;
+ _ref11 = _iterator12[_i12++];
+ } else {
+ _i12 = _iterator12.next();
+ if (_i12.done) break;
+ _ref11 = _i12.value;
+ }
+
+ var file = _ref11;
+
+ totalBytesSent += file.upload.bytesSent;
+ totalBytes += file.upload.total;
+ }
+ totalUploadProgress = 100 * totalBytesSent / totalBytes;
+ } else {
+ totalUploadProgress = 100;
+ }
+
+ return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
+ }
+
+ // @options.paramName can be a function taking one parameter rather than a string.
+ // A parameter name for a file is obtained simply by calling this with an index number.
+
+ }, {
+ key: "_getParamName",
+ value: function _getParamName(n) {
+ if (typeof this.options.paramName === "function") {
+ return this.options.paramName(n);
+ } else {
+ return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
+ }
+ }
+
+ // If @options.renameFile is a function,
+ // the function will be used to rename the file.name before appending it to the formData
+
+ }, {
+ key: "_renameFile",
+ value: function _renameFile(file) {
+ if (typeof this.options.renameFile !== "function") {
+ return file.name;
+ }
+ return this.options.renameFile(file);
+ }
+
+ // Returns a form that can be used as fallback if the browser does not support DragnDrop
+ //
+ // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
+ // This code has to pass in IE7 :(
+
+ }, {
+ key: "getFallbackForm",
+ value: function getFallbackForm() {
+ var existingFallback = void 0,
+ form = void 0;
+ if (existingFallback = this.getExistingFallback()) {
+ return existingFallback;
+ }
+
+ var fieldsString = "
";
+ if (this.options.dictFallbackText) {
+ fieldsString += "
" + this.options.dictFallbackText + "
";
+ }
+ fieldsString += "
";
+
+ var fields = Dropzone.createElement(fieldsString);
+ if (this.element.tagName !== "FORM") {
+ form = Dropzone.createElement("");
+ form.appendChild(fields);
+ } else {
+ // Make sure that the enctype and method attributes are set properly
+ this.element.setAttribute("enctype", "multipart/form-data");
+ this.element.setAttribute("method", this.options.method);
+ }
+ return form != null ? form : fields;
+ }
+
+ // Returns the fallback elements if they exist already
+ //
+ // This code has to pass in IE7 :(
+
+ }, {
+ key: "getExistingFallback",
+ value: function getExistingFallback() {
+ var getFallback = function getFallback(elements) {
+ for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {
+ var _ref12;
+
+ if (_isArray13) {
+ if (_i13 >= _iterator13.length) break;
+ _ref12 = _iterator13[_i13++];
+ } else {
+ _i13 = _iterator13.next();
+ if (_i13.done) break;
+ _ref12 = _i13.value;
+ }
+
+ var el = _ref12;
+
+ if (/(^| )fallback($| )/.test(el.className)) {
+ return el;
+ }
+ }
+ };
+
+ var _arr = ["div", "form"];
+ for (var _i14 = 0; _i14 < _arr.length; _i14++) {
+ var tagName = _arr[_i14];
+ var fallback;
+ if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
+ return fallback;
+ }
+ }
+ }
+
+ // Activates all listeners stored in @listeners
+
+ }, {
+ key: "setupEventListeners",
+ value: function setupEventListeners() {
+ return this.listeners.map(function (elementListeners) {
+ return function () {
+ var result = [];
+ for (var event in elementListeners.events) {
+ var listener = elementListeners.events[event];
+ result.push(elementListeners.element.addEventListener(event, listener, false));
+ }
+ return result;
+ }();
+ });
+ }
+
+ // Deactivates all listeners stored in @listeners
+
+ }, {
+ key: "removeEventListeners",
+ value: function removeEventListeners() {
+ return this.listeners.map(function (elementListeners) {
+ return function () {
+ var result = [];
+ for (var event in elementListeners.events) {
+ var listener = elementListeners.events[event];
+ result.push(elementListeners.element.removeEventListener(event, listener, false));
+ }
+ return result;
+ }();
+ });
+ }
+
+ // Removes all event listeners and cancels all files in the queue or being processed.
+
+ }, {
+ key: "disable",
+ value: function disable() {
+ var _this4 = this;
+
+ this.clickableElements.forEach(function (element) {
+ return element.classList.remove("dz-clickable");
+ });
+ this.removeEventListeners();
+ this.disabled = true;
+
+ return this.files.map(function (file) {
+ return _this4.cancelUpload(file);
+ });
+ }
+ }, {
+ key: "enable",
+ value: function enable() {
+ delete this.disabled;
+ this.clickableElements.forEach(function (element) {
+ return element.classList.add("dz-clickable");
+ });
+ return this.setupEventListeners();
+ }
+
+ // Returns a nicely formatted filesize
+
+ }, {
+ key: "filesize",
+ value: function filesize(size) {
+ var selectedSize = 0;
+ var selectedUnit = "b";
+
+ if (size > 0) {
+ var units = ['tb', 'gb', 'mb', 'kb', 'b'];
+
+ for (var i = 0; i < units.length; i++) {
+ var unit = units[i];
+ var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
+
+ if (size >= cutoff) {
+ selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
+ selectedUnit = unit;
+ break;
+ }
+ }
+
+ selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits
+ }
+
+ return "" + selectedSize + " " + this.options.dictFileSizeUnits[selectedUnit];
+ }
+
+ // Adds or removes the `dz-max-files-reached` class from the form.
+
+ }, {
+ key: "_updateMaxFilesReachedClass",
+ value: function _updateMaxFilesReachedClass() {
+ if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
+ if (this.getAcceptedFiles().length === this.options.maxFiles) {
+ this.emit('maxfilesreached', this.files);
+ }
+ return this.element.classList.add("dz-max-files-reached");
+ } else {
+ return this.element.classList.remove("dz-max-files-reached");
+ }
+ }
+ }, {
+ key: "drop",
+ value: function drop(e) {
+ if (!e.dataTransfer) {
+ return;
+ }
+ this.emit("drop", e);
+
+ var files = e.dataTransfer.files;
+
+ this.emit("addedfiles", files);
+
+ // Even if it's a folder, files.length will contain the folders.
+ if (files.length) {
+ var items = e.dataTransfer.items;
+
+ if (items && items.length && items[0].webkitGetAsEntry != null) {
+ // The browser supports dropping of folders, so handle items instead of files
+ this._addFilesFromItems(items);
+ } else {
+ this.handleFiles(files);
+ }
+ }
+ }
+ }, {
+ key: "paste",
+ value: function paste(e) {
+ if (__guard__(e != null ? e.clipboardData : undefined, function (x) {
+ return x.items;
+ }) == null) {
+ return;
+ }
+
+ this.emit("paste", e);
+ var items = e.clipboardData.items;
+
+
+ if (items.length) {
+ return this._addFilesFromItems(items);
+ }
+ }
+ }, {
+ key: "handleFiles",
+ value: function handleFiles(files) {
+ for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {
+ var _ref13;
+
+ if (_isArray14) {
+ if (_i15 >= _iterator14.length) break;
+ _ref13 = _iterator14[_i15++];
+ } else {
+ _i15 = _iterator14.next();
+ if (_i15.done) break;
+ _ref13 = _i15.value;
+ }
+
+ var file = _ref13;
+
+ this.addFile(file);
+ }
+ }
+
+ // When a folder is dropped (or files are pasted), items must be handled
+ // instead of files.
+
+ }, {
+ key: "_addFilesFromItems",
+ value: function _addFilesFromItems(items) {
+ var _this5 = this;
+
+ return function () {
+ var result = [];
+ for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {
+ var _ref14;
+
+ if (_isArray15) {
+ if (_i16 >= _iterator15.length) break;
+ _ref14 = _iterator15[_i16++];
+ } else {
+ _i16 = _iterator15.next();
+ if (_i16.done) break;
+ _ref14 = _i16.value;
+ }
+
+ var item = _ref14;
+
+ var entry;
+ if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {
+ if (entry.isFile) {
+ result.push(_this5.addFile(item.getAsFile()));
+ } else if (entry.isDirectory) {
+ // Append all files from that directory to files
+ result.push(_this5._addFilesFromDirectory(entry, entry.name));
+ } else {
+ result.push(undefined);
+ }
+ } else if (item.getAsFile != null) {
+ if (item.kind == null || item.kind === "file") {
+ result.push(_this5.addFile(item.getAsFile()));
+ } else {
+ result.push(undefined);
+ }
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+ }();
+ }
+
+ // Goes through the directory, and adds each file it finds recursively
+
+ }, {
+ key: "_addFilesFromDirectory",
+ value: function _addFilesFromDirectory(directory, path) {
+ var _this6 = this;
+
+ var dirReader = directory.createReader();
+
+ var errorHandler = function errorHandler(error) {
+ return __guardMethod__(console, 'log', function (o) {
+ return o.log(error);
+ });
+ };
+
+ var readEntries = function readEntries() {
+ return dirReader.readEntries(function (entries) {
+ if (entries.length > 0) {
+ for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {
+ var _ref15;
+
+ if (_isArray16) {
+ if (_i17 >= _iterator16.length) break;
+ _ref15 = _iterator16[_i17++];
+ } else {
+ _i17 = _iterator16.next();
+ if (_i17.done) break;
+ _ref15 = _i17.value;
+ }
+
+ var entry = _ref15;
+
+ if (entry.isFile) {
+ entry.file(function (file) {
+ if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
+ return;
+ }
+ file.fullPath = path + "/" + file.name;
+ return _this6.addFile(file);
+ });
+ } else if (entry.isDirectory) {
+ _this6._addFilesFromDirectory(entry, path + "/" + entry.name);
+ }
+ }
+
+ // Recursively call readEntries() again, since browser only handle
+ // the first 100 entries.
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries
+ readEntries();
+ }
+ return null;
+ }, errorHandler);
+ };
+
+ return readEntries();
+ }
+
+ // If `done()` is called without argument the file is accepted
+ // If you call it with an error message, the file is rejected
+ // (This allows for asynchronous validation)
+ //
+ // This function checks the filesize, and if the file.type passes the
+ // `acceptedFiles` check.
+
+ }, {
+ key: "accept",
+ value: function accept(file, done) {
+ if (file.size > this.options.maxFilesize * 1024 * 1024) {
+ return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
+ } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
+ return done(this.options.dictInvalidFileType);
+ } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
+ done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
+ return this.emit("maxfilesexceeded", file);
+ } else {
+ return this.options.accept.call(this, file, done);
+ }
+ }
+ }, {
+ key: "addFile",
+ value: function addFile(file) {
+ var _this7 = this;
+
+ file.upload = {
+ uuid: Dropzone.uuidv4(),
+ progress: 0,
+ // Setting the total upload size to file.size for the beginning
+ // It's actual different than the size to be transmitted.
+ total: file.size,
+ bytesSent: 0,
+ filename: this._renameFile(file),
+ chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),
+ totalChunkCount: Math.ceil(file.size / this.options.chunkSize)
+ };
+ this.files.push(file);
+
+ file.status = Dropzone.ADDED;
+
+ this.emit("addedfile", file);
+
+ this._enqueueThumbnail(file);
+
+ return this.accept(file, function (error) {
+ if (error) {
+ file.accepted = false;
+ _this7._errorProcessing([file], error); // Will set the file.status
+ } else {
+ file.accepted = true;
+ if (_this7.options.autoQueue) {
+ _this7.enqueueFile(file);
+ } // Will set .accepted = true
+ }
+ return _this7._updateMaxFilesReachedClass();
+ });
+ }
+
+ // Wrapper for enqueueFile
+
+ }, {
+ key: "enqueueFiles",
+ value: function enqueueFiles(files) {
+ for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {
+ var _ref16;
+
+ if (_isArray17) {
+ if (_i18 >= _iterator17.length) break;
+ _ref16 = _iterator17[_i18++];
+ } else {
+ _i18 = _iterator17.next();
+ if (_i18.done) break;
+ _ref16 = _i18.value;
+ }
+
+ var file = _ref16;
+
+ this.enqueueFile(file);
+ }
+ return null;
+ }
+ }, {
+ key: "enqueueFile",
+ value: function enqueueFile(file) {
+ var _this8 = this;
+
+ if (file.status === Dropzone.ADDED && file.accepted === true) {
+ file.status = Dropzone.QUEUED;
+ if (this.options.autoProcessQueue) {
+ return setTimeout(function () {
+ return _this8.processQueue();
+ }, 0); // Deferring the call
+ }
+ } else {
+ throw new Error("This file can't be queued because it has already been processed or was rejected.");
+ }
+ }
+ }, {
+ key: "_enqueueThumbnail",
+ value: function _enqueueThumbnail(file) {
+ var _this9 = this;
+
+ if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
+ this._thumbnailQueue.push(file);
+ return setTimeout(function () {
+ return _this9._processThumbnailQueue();
+ }, 0); // Deferring the call
+ }
+ }
+ }, {
+ key: "_processThumbnailQueue",
+ value: function _processThumbnailQueue() {
+ var _this10 = this;
+
+ if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
+ return;
+ }
+
+ this._processingThumbnail = true;
+ var file = this._thumbnailQueue.shift();
+ return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {
+ _this10.emit("thumbnail", file, dataUrl);
+ _this10._processingThumbnail = false;
+ return _this10._processThumbnailQueue();
+ });
+ }
+
+ // Can be called by the user to remove a file
+
+ }, {
+ key: "removeFile",
+ value: function removeFile(file) {
+ if (file.status === Dropzone.UPLOADING) {
+ this.cancelUpload(file);
+ }
+ this.files = without(this.files, file);
+
+ this.emit("removedfile", file);
+ if (this.files.length === 0) {
+ return this.emit("reset");
+ }
+ }
+
+ // Removes all files that aren't currently processed from the list
+
+ }, {
+ key: "removeAllFiles",
+ value: function removeAllFiles(cancelIfNecessary) {
+ // Create a copy of files since removeFile() changes the @files array.
+ if (cancelIfNecessary == null) {
+ cancelIfNecessary = false;
+ }
+ for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {
+ var _ref17;
+
+ if (_isArray18) {
+ if (_i19 >= _iterator18.length) break;
+ _ref17 = _iterator18[_i19++];
+ } else {
+ _i19 = _iterator18.next();
+ if (_i19.done) break;
+ _ref17 = _i19.value;
+ }
+
+ var file = _ref17;
+
+ if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
+ this.removeFile(file);
+ }
+ }
+ return null;
+ }
+
+ // Resizes an image before it gets sent to the server. This function is the default behavior of
+ // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with
+ // the resized blob.
+
+ }, {
+ key: "resizeImage",
+ value: function resizeImage(file, width, height, resizeMethod, callback) {
+ var _this11 = this;
+
+ return this.createThumbnail(file, width, height, resizeMethod, false, function (dataUrl, canvas) {
+ if (canvas == null) {
+ // The image has not been resized
+ return callback(file);
+ } else {
+ var resizeMimeType = _this11.options.resizeMimeType;
+
+ if (resizeMimeType == null) {
+ resizeMimeType = file.type;
+ }
+ var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);
+ if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {
+ // Now add the original EXIF information
+ resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
+ }
+ return callback(Dropzone.dataURItoBlob(resizedDataURL));
+ }
+ });
+ }
+ }, {
+ key: "createThumbnail",
+ value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {
+ var _this12 = this;
+
+ var fileReader = new FileReader();
+
+ fileReader.onload = function () {
+
+ file.dataURL = fileReader.result;
+
+ // Don't bother creating a thumbnail for SVG images since they're vector
+ if (file.type === "image/svg+xml") {
+ if (callback != null) {
+ callback(fileReader.result);
+ }
+ return;
+ }
+
+ return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
+ };
+
+ return fileReader.readAsDataURL(file);
+ }
+ }, {
+ key: "createThumbnailFromUrl",
+ value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
+ var _this13 = this;
+
+ // Not using `new Image` here because of a bug in latest Chrome versions.
+ // See https://github.com/enyo/dropzone/pull/226
+ var img = document.createElement("img");
+
+ if (crossOrigin) {
+ img.crossOrigin = crossOrigin;
+ }
+
+ img.onload = function () {
+ var loadExif = function loadExif(callback) {
+ return callback(1);
+ };
+ if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {
+ loadExif = function loadExif(callback) {
+ return EXIF.getData(img, function () {
+ return callback(EXIF.getTag(this, 'Orientation'));
+ });
+ };
+ }
+
+ return loadExif(function (orientation) {
+ file.width = img.width;
+ file.height = img.height;
+
+ var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);
+
+ var canvas = document.createElement("canvas");
+ var ctx = canvas.getContext("2d");
+
+ canvas.width = resizeInfo.trgWidth;
+ canvas.height = resizeInfo.trgHeight;
+
+ if (orientation > 4) {
+ canvas.width = resizeInfo.trgHeight;
+ canvas.height = resizeInfo.trgWidth;
+ }
+
+ switch (orientation) {
+ case 2:
+ // horizontal flip
+ ctx.translate(canvas.width, 0);
+ ctx.scale(-1, 1);
+ break;
+ case 3:
+ // 180° rotate left
+ ctx.translate(canvas.width, canvas.height);
+ ctx.rotate(Math.PI);
+ break;
+ case 4:
+ // vertical flip
+ ctx.translate(0, canvas.height);
+ ctx.scale(1, -1);
+ break;
+ case 5:
+ // vertical flip + 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.scale(1, -1);
+ break;
+ case 6:
+ // 90° rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.translate(0, -canvas.height);
+ break;
+ case 7:
+ // horizontal flip + 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.translate(canvas.width, -canvas.height);
+ ctx.scale(-1, 1);
+ break;
+ case 8:
+ // 90° rotate left
+ ctx.rotate(-0.5 * Math.PI);
+ ctx.translate(-canvas.width, 0);
+ break;
+ }
+
+ // This is a bugfix for iOS' scaling bug.
+ 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);
+
+ var thumbnail = canvas.toDataURL("image/png");
+
+ if (callback != null) {
+ return callback(thumbnail, canvas);
+ }
+ });
+ };
+
+ if (callback != null) {
+ img.onerror = callback;
+ }
+
+ return img.src = file.dataURL;
+ }
+
+ // Goes through the queue and processes files if there aren't too many already.
+
+ }, {
+ key: "processQueue",
+ value: function processQueue() {
+ var parallelUploads = this.options.parallelUploads;
+
+ var processingLength = this.getUploadingFiles().length;
+ var i = processingLength;
+
+ // There are already at least as many files uploading than should be
+ if (processingLength >= parallelUploads) {
+ return;
+ }
+
+ var queuedFiles = this.getQueuedFiles();
+
+ if (!(queuedFiles.length > 0)) {
+ return;
+ }
+
+ if (this.options.uploadMultiple) {
+ // The files should be uploaded in one request
+ return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
+ } else {
+ while (i < parallelUploads) {
+ if (!queuedFiles.length) {
+ return;
+ } // Nothing left to process
+ this.processFile(queuedFiles.shift());
+ i++;
+ }
+ }
+ }
+
+ // Wrapper for `processFiles`
+
+ }, {
+ key: "processFile",
+ value: function processFile(file) {
+ return this.processFiles([file]);
+ }
+
+ // Loads the file, then calls finishedLoading()
+
+ }, {
+ key: "processFiles",
+ value: function processFiles(files) {
+ for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {
+ var _ref18;
+
+ if (_isArray19) {
+ if (_i20 >= _iterator19.length) break;
+ _ref18 = _iterator19[_i20++];
+ } else {
+ _i20 = _iterator19.next();
+ if (_i20.done) break;
+ _ref18 = _i20.value;
+ }
+
+ var file = _ref18;
+
+ file.processing = true; // Backwards compatibility
+ file.status = Dropzone.UPLOADING;
+
+ this.emit("processing", file);
+ }
+
+ if (this.options.uploadMultiple) {
+ this.emit("processingmultiple", files);
+ }
+
+ return this.uploadFiles(files);
+ }
+ }, {
+ key: "_getFilesWithXhr",
+ value: function _getFilesWithXhr(xhr) {
+ var files = void 0;
+ return files = this.files.filter(function (file) {
+ return file.xhr === xhr;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // Cancels the file upload and sets the status to CANCELED
+ // **if** the file is actually being uploaded.
+ // If it's still in the queue, the file is being removed from it and the status
+ // set to CANCELED.
+
+ }, {
+ key: "cancelUpload",
+ value: function cancelUpload(file) {
+ if (file.status === Dropzone.UPLOADING) {
+ var groupedFiles = this._getFilesWithXhr(file.xhr);
+ for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {
+ var _ref19;
+
+ if (_isArray20) {
+ if (_i21 >= _iterator20.length) break;
+ _ref19 = _iterator20[_i21++];
+ } else {
+ _i21 = _iterator20.next();
+ if (_i21.done) break;
+ _ref19 = _i21.value;
+ }
+
+ var groupedFile = _ref19;
+
+ groupedFile.status = Dropzone.CANCELED;
+ }
+ if (typeof file.xhr !== 'undefined') {
+ file.xhr.abort();
+ }
+ for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {
+ var _ref20;
+
+ if (_isArray21) {
+ if (_i22 >= _iterator21.length) break;
+ _ref20 = _iterator21[_i22++];
+ } else {
+ _i22 = _iterator21.next();
+ if (_i22.done) break;
+ _ref20 = _i22.value;
+ }
+
+ var _groupedFile = _ref20;
+
+ this.emit("canceled", _groupedFile);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("canceledmultiple", groupedFiles);
+ }
+ } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {
+ file.status = Dropzone.CANCELED;
+ this.emit("canceled", file);
+ if (this.options.uploadMultiple) {
+ this.emit("canceledmultiple", [file]);
+ }
+ }
+
+ if (this.options.autoProcessQueue) {
+ return this.processQueue();
+ }
+ }
+ }, {
+ key: "resolveOption",
+ value: function resolveOption(option) {
+ if (typeof option === 'function') {
+ for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
+ args[_key3 - 1] = arguments[_key3];
+ }
+
+ return option.apply(this, args);
+ }
+ return option;
+ }
+ }, {
+ key: "uploadFile",
+ value: function uploadFile(file) {
+ return this.uploadFiles([file]);
+ }
+ }, {
+ key: "uploadFiles",
+ value: function uploadFiles(files) {
+ var _this14 = this;
+
+ this._transformFiles(files, function (transformedFiles) {
+ if (files[0].upload.chunked) {
+ // This file should be sent in chunks!
+
+ // If the chunking option is set, we **know** that there can only be **one** file, since
+ // uploadMultiple is not allowed with this option.
+ var file = files[0];
+ var transformedFile = transformedFiles[0];
+ var startedChunkCount = 0;
+
+ file.upload.chunks = [];
+
+ var handleNextChunk = function handleNextChunk() {
+ var chunkIndex = 0;
+
+ // Find the next item in file.upload.chunks that is not defined yet.
+ while (file.upload.chunks[chunkIndex] !== undefined) {
+ chunkIndex++;
+ }
+
+ // This means, that all chunks have already been started.
+ if (chunkIndex >= file.upload.totalChunkCount) return;
+
+ startedChunkCount++;
+
+ var start = chunkIndex * _this14.options.chunkSize;
+ var end = Math.min(start + _this14.options.chunkSize, file.size);
+
+ var dataBlock = {
+ name: _this14._getParamName(0),
+ data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),
+ filename: file.upload.filename,
+ chunkIndex: chunkIndex
+ };
+
+ file.upload.chunks[chunkIndex] = {
+ file: file,
+ index: chunkIndex,
+ dataBlock: dataBlock, // In case we want to retry.
+ status: Dropzone.UPLOADING,
+ progress: 0,
+ retries: 0 // The number of times this block has been retried.
+ };
+
+ _this14._uploadData(files, [dataBlock]);
+ };
+
+ file.upload.finishedChunkUpload = function (chunk) {
+ var allFinished = true;
+ chunk.status = Dropzone.SUCCESS;
+
+ // Clear the data from the chunk
+ chunk.dataBlock = null;
+
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ if (file.upload.chunks[i] === undefined) {
+ return handleNextChunk();
+ }
+ if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {
+ allFinished = false;
+ }
+ }
+
+ if (allFinished) {
+ _this14.options.chunksUploaded(file, function () {
+ _this14._finished(files, '', null);
+ });
+ }
+ };
+
+ if (_this14.options.parallelChunkUploads) {
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ handleNextChunk();
+ }
+ } else {
+ handleNextChunk();
+ }
+ } else {
+ var dataBlocks = [];
+ for (var _i23 = 0; _i23 < files.length; _i23++) {
+ dataBlocks[_i23] = {
+ name: _this14._getParamName(_i23),
+ data: transformedFiles[_i23],
+ filename: files[_i23].upload.filename
+ };
+ }
+ _this14._uploadData(files, dataBlocks);
+ }
+ });
+ }
+
+ /// Returns the right chunk for given file and xhr
+
+ }, {
+ key: "_getChunk",
+ value: function _getChunk(file, xhr) {
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {
+ return file.upload.chunks[i];
+ }
+ }
+ }
+
+ // This function actually uploads the file(s) to the server.
+ // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed
+ // files, or individual chunks for chunked upload).
+
+ }, {
+ key: "_uploadData",
+ value: function _uploadData(files, dataBlocks) {
+ var _this15 = this;
+
+ var xhr = new XMLHttpRequest();
+
+ // Put the xhr object in the file objects to be able to reference it later.
+ for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {
+ var _ref21;
+
+ if (_isArray22) {
+ if (_i24 >= _iterator22.length) break;
+ _ref21 = _iterator22[_i24++];
+ } else {
+ _i24 = _iterator22.next();
+ if (_i24.done) break;
+ _ref21 = _i24.value;
+ }
+
+ var file = _ref21;
+
+ file.xhr = xhr;
+ }
+ if (files[0].upload.chunked) {
+ // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk
+ files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;
+ }
+
+ var method = this.resolveOption(this.options.method, files);
+ var url = this.resolveOption(this.options.url, files);
+ xhr.open(method, url, true);
+
+ // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8
+ xhr.timeout = this.resolveOption(this.options.timeout, files);
+
+ // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
+ xhr.withCredentials = !!this.options.withCredentials;
+
+ xhr.onload = function (e) {
+ _this15._finishedUploading(files, xhr, e);
+ };
+
+ xhr.onerror = function () {
+ _this15._handleUploadError(files, xhr);
+ };
+
+ // Some browsers do not have the .upload property
+ var progressObj = xhr.upload != null ? xhr.upload : xhr;
+ progressObj.onprogress = function (e) {
+ return _this15._updateFilesUploadProgress(files, xhr, e);
+ };
+
+ var headers = {
+ "Accept": "application/json",
+ "Cache-Control": "no-cache",
+ "X-Requested-With": "XMLHttpRequest"
+ };
+
+ if (this.options.headers) {
+ Dropzone.extend(headers, this.options.headers);
+ }
+
+ for (var headerName in headers) {
+ var headerValue = headers[headerName];
+ if (headerValue) {
+ xhr.setRequestHeader(headerName, headerValue);
+ }
+ }
+
+ var formData = new FormData();
+
+ // Adding all @options parameters
+ if (this.options.params) {
+ var additionalParams = this.options.params;
+ if (typeof additionalParams === 'function') {
+ additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);
+ }
+
+ for (var key in additionalParams) {
+ var value = additionalParams[key];
+ formData.append(key, value);
+ }
+ }
+
+ // Let the user add additional data if necessary
+ for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {
+ var _ref22;
+
+ if (_isArray23) {
+ if (_i25 >= _iterator23.length) break;
+ _ref22 = _iterator23[_i25++];
+ } else {
+ _i25 = _iterator23.next();
+ if (_i25.done) break;
+ _ref22 = _i25.value;
+ }
+
+ var _file = _ref22;
+
+ this.emit("sending", _file, xhr, formData);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("sendingmultiple", files, xhr, formData);
+ }
+
+ this._addFormElementData(formData);
+
+ // Finally add the files
+ // Has to be last because some servers (eg: S3) expect the file to be the last parameter
+ for (var i = 0; i < dataBlocks.length; i++) {
+ var dataBlock = dataBlocks[i];
+ formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
+ }
+
+ this.submitRequest(xhr, formData, files);
+ }
+
+ // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.
+
+ }, {
+ key: "_transformFiles",
+ value: function _transformFiles(files, done) {
+ var _this16 = this;
+
+ var transformedFiles = [];
+ // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.
+ var doneCounter = 0;
+
+ var _loop = function _loop(i) {
+ _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {
+ transformedFiles[i] = transformedFile;
+ if (++doneCounter === files.length) {
+ done(transformedFiles);
+ }
+ });
+ };
+
+ for (var i = 0; i < files.length; i++) {
+ _loop(i);
+ }
+ }
+
+ // Takes care of adding other input elements of the form to the AJAX request
+
+ }, {
+ key: "_addFormElementData",
+ value: function _addFormElementData(formData) {
+ // Take care of other input elements
+ if (this.element.tagName === "FORM") {
+ for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {
+ var _ref23;
+
+ if (_isArray24) {
+ if (_i26 >= _iterator24.length) break;
+ _ref23 = _iterator24[_i26++];
+ } else {
+ _i26 = _iterator24.next();
+ if (_i26.done) break;
+ _ref23 = _i26.value;
+ }
+
+ var input = _ref23;
+
+ var inputName = input.getAttribute("name");
+ var inputType = input.getAttribute("type");
+ if (inputType) inputType = inputType.toLowerCase();
+
+ // If the input doesn't have a name, we can't use it.
+ if (typeof inputName === 'undefined' || inputName === null) continue;
+
+ if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
+ // Possibly multiple values
+ for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {
+ var _ref24;
+
+ if (_isArray25) {
+ if (_i27 >= _iterator25.length) break;
+ _ref24 = _iterator25[_i27++];
+ } else {
+ _i27 = _iterator25.next();
+ if (_i27.done) break;
+ _ref24 = _i27.value;
+ }
+
+ var option = _ref24;
+
+ if (option.selected) {
+ formData.append(inputName, option.value);
+ }
+ }
+ } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) {
+ formData.append(inputName, input.value);
+ }
+ }
+ }
+ }
+
+ // Invoked when there is new progress information about given files.
+ // If e is not provided, it is assumed that the upload is finished.
+
+ }, {
+ key: "_updateFilesUploadProgress",
+ value: function _updateFilesUploadProgress(files, xhr, e) {
+ var progress = void 0;
+ if (typeof e !== 'undefined') {
+ progress = 100 * e.loaded / e.total;
+
+ if (files[0].upload.chunked) {
+ var file = files[0];
+ // Since this is a chunked upload, we need to update the appropriate chunk progress.
+ var chunk = this._getChunk(file, xhr);
+ chunk.progress = progress;
+ chunk.total = e.total;
+ chunk.bytesSent = e.loaded;
+ var fileProgress = 0,
+ fileTotal = void 0,
+ fileBytesSent = void 0;
+ file.upload.progress = 0;
+ file.upload.total = 0;
+ file.upload.bytesSent = 0;
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {
+ file.upload.progress += file.upload.chunks[i].progress;
+ file.upload.total += file.upload.chunks[i].total;
+ file.upload.bytesSent += file.upload.chunks[i].bytesSent;
+ }
+ }
+ file.upload.progress = file.upload.progress / file.upload.totalChunkCount;
+ } else {
+ for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {
+ var _ref25;
+
+ if (_isArray26) {
+ if (_i28 >= _iterator26.length) break;
+ _ref25 = _iterator26[_i28++];
+ } else {
+ _i28 = _iterator26.next();
+ if (_i28.done) break;
+ _ref25 = _i28.value;
+ }
+
+ var _file2 = _ref25;
+
+ _file2.upload.progress = progress;
+ _file2.upload.total = e.total;
+ _file2.upload.bytesSent = e.loaded;
+ }
+ }
+ for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {
+ var _ref26;
+
+ if (_isArray27) {
+ if (_i29 >= _iterator27.length) break;
+ _ref26 = _iterator27[_i29++];
+ } else {
+ _i29 = _iterator27.next();
+ if (_i29.done) break;
+ _ref26 = _i29.value;
+ }
+
+ var _file3 = _ref26;
+
+ this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent);
+ }
+ } else {
+ // Called when the file finished uploading
+
+ var allFilesFinished = true;
+
+ progress = 100;
+
+ for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {
+ var _ref27;
+
+ if (_isArray28) {
+ if (_i30 >= _iterator28.length) break;
+ _ref27 = _iterator28[_i30++];
+ } else {
+ _i30 = _iterator28.next();
+ if (_i30.done) break;
+ _ref27 = _i30.value;
+ }
+
+ var _file4 = _ref27;
+
+ if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {
+ allFilesFinished = false;
+ }
+ _file4.upload.progress = progress;
+ _file4.upload.bytesSent = _file4.upload.total;
+ }
+
+ // Nothing to do, all files already at 100%
+ if (allFilesFinished) {
+ return;
+ }
+
+ for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {
+ var _ref28;
+
+ if (_isArray29) {
+ if (_i31 >= _iterator29.length) break;
+ _ref28 = _iterator29[_i31++];
+ } else {
+ _i31 = _iterator29.next();
+ if (_i31.done) break;
+ _ref28 = _i31.value;
+ }
+
+ var _file5 = _ref28;
+
+ this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent);
+ }
+ }
+ }
+ }, {
+ key: "_finishedUploading",
+ value: function _finishedUploading(files, xhr, e) {
+ var response = void 0;
+
+ if (files[0].status === Dropzone.CANCELED) {
+ return;
+ }
+
+ if (xhr.readyState !== 4) {
+ return;
+ }
+
+ if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {
+ response = xhr.responseText;
+
+ if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
+ try {
+ response = JSON.parse(response);
+ } catch (error) {
+ e = error;
+ response = "Invalid JSON response from server.";
+ }
+ }
+ }
+
+ this._updateFilesUploadProgress(files);
+
+ if (!(200 <= xhr.status && xhr.status < 300)) {
+ this._handleUploadError(files, xhr, response);
+ } else {
+ if (files[0].upload.chunked) {
+ files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));
+ } else {
+ this._finished(files, response, e);
+ }
+ }
+ }
+ }, {
+ key: "_handleUploadError",
+ value: function _handleUploadError(files, xhr, response) {
+ if (files[0].status === Dropzone.CANCELED) {
+ return;
+ }
+
+ if (files[0].upload.chunked && this.options.retryChunks) {
+ var chunk = this._getChunk(files[0], xhr);
+ if (chunk.retries++ < this.options.retryChunksLimit) {
+ this._uploadData(files, [chunk.dataBlock]);
+ return;
+ } else {
+ console.warn('Retried this chunk too often. Giving up.');
+ }
+ }
+
+ for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {
+ var _ref29;
+
+ if (_isArray30) {
+ if (_i32 >= _iterator30.length) break;
+ _ref29 = _iterator30[_i32++];
+ } else {
+ _i32 = _iterator30.next();
+ if (_i32.done) break;
+ _ref29 = _i32.value;
+ }
+
+ var file = _ref29;
+
+ this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr);
+ }
+ }
+ }, {
+ key: "submitRequest",
+ value: function submitRequest(xhr, formData, files) {
+ xhr.send(formData);
+ }
+
+ // Called internally when processing is finished.
+ // Individual callbacks have to be called in the appropriate sections.
+
+ }, {
+ key: "_finished",
+ value: function _finished(files, responseText, e) {
+ for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {
+ var _ref30;
+
+ if (_isArray31) {
+ if (_i33 >= _iterator31.length) break;
+ _ref30 = _iterator31[_i33++];
+ } else {
+ _i33 = _iterator31.next();
+ if (_i33.done) break;
+ _ref30 = _i33.value;
+ }
+
+ var file = _ref30;
+
+ file.status = Dropzone.SUCCESS;
+ this.emit("success", file, responseText, e);
+ this.emit("complete", file);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("successmultiple", files, responseText, e);
+ this.emit("completemultiple", files);
+ }
+
+ if (this.options.autoProcessQueue) {
+ return this.processQueue();
+ }
+ }
+
+ // Called internally when processing is finished.
+ // Individual callbacks have to be called in the appropriate sections.
+
+ }, {
+ key: "_errorProcessing",
+ value: function _errorProcessing(files, message, xhr) {
+ for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {
+ var _ref31;
+
+ if (_isArray32) {
+ if (_i34 >= _iterator32.length) break;
+ _ref31 = _iterator32[_i34++];
+ } else {
+ _i34 = _iterator32.next();
+ if (_i34.done) break;
+ _ref31 = _i34.value;
+ }
+
+ var file = _ref31;
+
+ file.status = Dropzone.ERROR;
+ this.emit("error", file, message, xhr);
+ this.emit("complete", file);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("errormultiple", files, message, xhr);
+ this.emit("completemultiple", files);
+ }
+
+ if (this.options.autoProcessQueue) {
+ return this.processQueue();
+ }
+ }
+ }], [{
+ key: "uuidv4",
+ value: function uuidv4() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+ var r = Math.random() * 16 | 0,
+ v = c === 'x' ? r : r & 0x3 | 0x8;
+ return v.toString(16);
+ });
+ }
+ }]);
+
+ return Dropzone;
+}(Emitter);
+
+Dropzone.initClass();
+
+Dropzone.version = "5.3.0";
+
+// This is a map of options for your different dropzones. Add configurations
+// to this object for your different dropzone elemens.
+//
+// Example:
+//
+// Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };
+//
+// To disable autoDiscover for a specific element, you can set `false` as an option:
+//
+// Dropzone.options.myDisabledElementId = false;
+//
+// And in html:
+//
+//
+Dropzone.options = {};
+
+// Returns the options for an element or undefined if none available.
+Dropzone.optionsForElement = function (element) {
+ // Get the `Dropzone.options.elementId` for this element if it exists
+ if (element.getAttribute("id")) {
+ return Dropzone.options[camelize(element.getAttribute("id"))];
+ } else {
+ return undefined;
+ }
+};
+
+// Holds a list of all dropzone instances
+Dropzone.instances = [];
+
+// Returns the dropzone for given element if any
+Dropzone.forElement = function (element) {
+ if (typeof element === "string") {
+ element = document.querySelector(element);
+ }
+ if ((element != null ? element.dropzone : undefined) == null) {
+ 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.");
+ }
+ return element.dropzone;
+};
+
+// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.
+Dropzone.autoDiscover = true;
+
+// Looks for all .dropzone elements and creates a dropzone for them
+Dropzone.discover = function () {
+ var dropzones = void 0;
+ if (document.querySelectorAll) {
+ dropzones = document.querySelectorAll(".dropzone");
+ } else {
+ dropzones = [];
+ // IE :(
+ var checkElements = function checkElements(elements) {
+ return function () {
+ var result = [];
+ for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {
+ var _ref32;
+
+ if (_isArray33) {
+ if (_i35 >= _iterator33.length) break;
+ _ref32 = _iterator33[_i35++];
+ } else {
+ _i35 = _iterator33.next();
+ if (_i35.done) break;
+ _ref32 = _i35.value;
+ }
+
+ var el = _ref32;
+
+ if (/(^| )dropzone($| )/.test(el.className)) {
+ result.push(dropzones.push(el));
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+ }();
+ };
+ checkElements(document.getElementsByTagName("div"));
+ checkElements(document.getElementsByTagName("form"));
+ }
+
+ return function () {
+ var result = [];
+ for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {
+ var _ref33;
+
+ if (_isArray34) {
+ if (_i36 >= _iterator34.length) break;
+ _ref33 = _iterator34[_i36++];
+ } else {
+ _i36 = _iterator34.next();
+ if (_i36.done) break;
+ _ref33 = _i36.value;
+ }
+
+ var dropzone = _ref33;
+
+ // Create a dropzone unless auto discover has been disabled for specific element
+ if (Dropzone.optionsForElement(dropzone) !== false) {
+ result.push(new Dropzone(dropzone));
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+ }();
+};
+
+// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,
+// but not correctly.
+// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.
+// But what to do when browsers *theoretically* support an API, but crash
+// when using it.
+//
+// This is a list of regular expressions tested against navigator.userAgent
+//
+// ** It should only be used on browser that *do* support the API, but
+// incorrectly **
+//
+Dropzone.blacklistedBrowsers = [
+// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.
+/opera.*(Macintosh|Windows Phone).*version\/12/i];
+
+// Checks if the browser is supported
+Dropzone.isBrowserSupported = function () {
+ var capableBrowser = true;
+
+ if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
+ if (!("classList" in document.createElement("a"))) {
+ capableBrowser = false;
+ } else {
+ // The browser supports the API, but may be blacklisted.
+ for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {
+ var _ref34;
+
+ if (_isArray35) {
+ if (_i37 >= _iterator35.length) break;
+ _ref34 = _iterator35[_i37++];
+ } else {
+ _i37 = _iterator35.next();
+ if (_i37.done) break;
+ _ref34 = _i37.value;
+ }
+
+ var regex = _ref34;
+
+ if (regex.test(navigator.userAgent)) {
+ capableBrowser = false;
+ continue;
+ }
+ }
+ }
+ } else {
+ capableBrowser = false;
+ }
+
+ return capableBrowser;
+};
+
+Dropzone.dataURItoBlob = function (dataURI) {
+ // convert base64 to raw binary data held in a string
+ // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
+ var byteString = atob(dataURI.split(',')[1]);
+
+ // separate out the mime component
+ var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
+
+ // write the bytes of the string to an ArrayBuffer
+ var ab = new ArrayBuffer(byteString.length);
+ var ia = new Uint8Array(ab);
+ for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
+ ia[i] = byteString.charCodeAt(i);
+ }
+
+ // write the ArrayBuffer to a blob
+ return new Blob([ab], { type: mimeString });
+};
+
+// Returns an array without the rejected item
+var without = function without(list, rejectedItem) {
+ return list.filter(function (item) {
+ return item !== rejectedItem;
+ }).map(function (item) {
+ return item;
+ });
+};
+
+// abc-def_ghi -> abcDefGhi
+var camelize = function camelize(str) {
+ return str.replace(/[\-_](\w)/g, function (match) {
+ return match.charAt(1).toUpperCase();
+ });
+};
+
+// Creates an element from string
+Dropzone.createElement = function (string) {
+ var div = document.createElement("div");
+ div.innerHTML = string;
+ return div.childNodes[0];
+};
+
+// Tests if given element is inside (or simply is) the container
+Dropzone.elementInside = function (element, container) {
+ if (element === container) {
+ return true;
+ } // Coffeescript doesn't support do/while loops
+ while (element = element.parentNode) {
+ if (element === container) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Dropzone.getElement = function (el, name) {
+ var element = void 0;
+ if (typeof el === "string") {
+ element = document.querySelector(el);
+ } else if (el.nodeType != null) {
+ element = el;
+ }
+ if (element == null) {
+ throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
+ }
+ return element;
+};
+
+Dropzone.getElements = function (els, name) {
+ var el = void 0,
+ elements = void 0;
+ if (els instanceof Array) {
+ elements = [];
+ try {
+ for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {
+ if (_isArray36) {
+ if (_i38 >= _iterator36.length) break;
+ el = _iterator36[_i38++];
+ } else {
+ _i38 = _iterator36.next();
+ if (_i38.done) break;
+ el = _i38.value;
+ }
+
+ elements.push(this.getElement(el, name));
+ }
+ } catch (e) {
+ elements = null;
+ }
+ } else if (typeof els === "string") {
+ elements = [];
+ for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {
+ if (_isArray37) {
+ if (_i39 >= _iterator37.length) break;
+ el = _iterator37[_i39++];
+ } else {
+ _i39 = _iterator37.next();
+ if (_i39.done) break;
+ el = _i39.value;
+ }
+
+ elements.push(el);
+ }
+ } else if (els.nodeType != null) {
+ elements = [els];
+ }
+
+ if (elements == null || !elements.length) {
+ throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
+ }
+
+ return elements;
+};
+
+// Asks the user the question and calls accepted or rejected accordingly
+//
+// The default implementation just uses `window.confirm` and then calls the
+// appropriate callback.
+Dropzone.confirm = function (question, accepted, rejected) {
+ if (window.confirm(question)) {
+ return accepted();
+ } else if (rejected != null) {
+ return rejected();
+ }
+};
+
+// Validates the mime type like this:
+//
+// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept
+Dropzone.isValidFile = function (file, acceptedFiles) {
+ if (!acceptedFiles) {
+ return true;
+ } // If there are no accepted mime types, it's OK
+ acceptedFiles = acceptedFiles.split(",");
+
+ var mimeType = file.type;
+ var baseMimeType = mimeType.replace(/\/.*$/, "");
+
+ for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {
+ var _ref35;
+
+ if (_isArray38) {
+ if (_i40 >= _iterator38.length) break;
+ _ref35 = _iterator38[_i40++];
+ } else {
+ _i40 = _iterator38.next();
+ if (_i40.done) break;
+ _ref35 = _i40.value;
+ }
+
+ var validType = _ref35;
+
+ validType = validType.trim();
+ if (validType.charAt(0) === ".") {
+ if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
+ return true;
+ }
+ } else if (/\/\*$/.test(validType)) {
+ // This is something like a image/* mime type
+ if (baseMimeType === validType.replace(/\/.*$/, "")) {
+ return true;
+ }
+ } else {
+ if (mimeType === validType) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+};
+
+// Augment jQuery
+if (typeof jQuery !== 'undefined' && jQuery !== null) {
+ jQuery.fn.dropzone = function (options) {
+ return this.each(function () {
+ return new Dropzone(this, options);
+ });
+ };
+}
+
+if (typeof module !== 'undefined' && module !== null) {
+ module.exports = Dropzone;
+} else {
+ window.Dropzone = Dropzone;
+}
+
+// Dropzone file status codes
+Dropzone.ADDED = "added";
+
+Dropzone.QUEUED = "queued";
+// For backwards compatibility. Now, if a file is accepted, it's either queued
+// or uploading.
+Dropzone.ACCEPTED = Dropzone.QUEUED;
+
+Dropzone.UPLOADING = "uploading";
+Dropzone.PROCESSING = Dropzone.UPLOADING; // alias
+
+Dropzone.CANCELED = "canceled";
+Dropzone.ERROR = "error";
+Dropzone.SUCCESS = "success";
+
+/*
+
+ Bugfix for iOS 6 and 7
+ Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
+ based on the work of https://github.com/stomita/ios-imagefile-megapixel
+
+ */
+
+// Detecting vertical squash in loaded image.
+// Fixes a bug which squash image vertically while drawing into canvas for some images.
+// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel
+var detectVerticalSquash = function detectVerticalSquash(img) {
+ var iw = img.naturalWidth;
+ var ih = img.naturalHeight;
+ var canvas = document.createElement("canvas");
+ canvas.width = 1;
+ canvas.height = ih;
+ var ctx = canvas.getContext("2d");
+ ctx.drawImage(img, 0, 0);
+
+ var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),
+ data = _ctx$getImageData.data;
+
+ // search image edge pixel position in case it is squashed vertically.
+
+
+ var sy = 0;
+ var ey = ih;
+ var py = ih;
+ while (py > sy) {
+ var alpha = data[(py - 1) * 4 + 3];
+
+ if (alpha === 0) {
+ ey = py;
+ } else {
+ sy = py;
+ }
+
+ py = ey + sy >> 1;
+ }
+ var ratio = py / ih;
+
+ if (ratio === 0) {
+ return 1;
+ } else {
+ return ratio;
+ }
+};
+
+// A replacement for context.drawImage
+// (args are for source and destination).
+var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
+ var vertSquashRatio = detectVerticalSquash(img);
+ return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
+};
+
+// Based on MinifyJpeg
+// Source: http://www.perry.cz/files/ExifRestorer.js
+// http://elicon.blog57.fc2.com/blog-entry-206.html
+
+var ExifRestore = function () {
+ function ExifRestore() {
+ _classCallCheck(this, ExifRestore);
+ }
+
+ _createClass(ExifRestore, null, [{
+ key: "initClass",
+ value: function initClass() {
+ this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ }
+ }, {
+ key: "encode64",
+ value: function encode64(input) {
+ var output = '';
+ var chr1 = undefined;
+ var chr2 = undefined;
+ var chr3 = '';
+ var enc1 = undefined;
+ var enc2 = undefined;
+ var enc3 = undefined;
+ var enc4 = '';
+ var i = 0;
+ while (true) {
+ chr1 = input[i++];
+ chr2 = input[i++];
+ chr3 = input[i++];
+ enc1 = chr1 >> 2;
+ enc2 = (chr1 & 3) << 4 | chr2 >> 4;
+ enc3 = (chr2 & 15) << 2 | chr3 >> 6;
+ enc4 = chr3 & 63;
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+ output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
+ chr1 = chr2 = chr3 = '';
+ enc1 = enc2 = enc3 = enc4 = '';
+ if (!(i < input.length)) {
+ break;
+ }
+ }
+ return output;
+ }
+ }, {
+ key: "restore",
+ value: function restore(origFileBase64, resizedFileBase64) {
+ if (!origFileBase64.match('data:image/jpeg;base64,')) {
+ return resizedFileBase64;
+ }
+ var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));
+ var segments = this.slice2Segments(rawImage);
+ var image = this.exifManipulation(resizedFileBase64, segments);
+ return "data:image/jpeg;base64," + this.encode64(image);
+ }
+ }, {
+ key: "exifManipulation",
+ value: function exifManipulation(resizedFileBase64, segments) {
+ var exifArray = this.getExifArray(segments);
+ var newImageArray = this.insertExif(resizedFileBase64, exifArray);
+ var aBuffer = new Uint8Array(newImageArray);
+ return aBuffer;
+ }
+ }, {
+ key: "getExifArray",
+ value: function getExifArray(segments) {
+ var seg = undefined;
+ var x = 0;
+ while (x < segments.length) {
+ seg = segments[x];
+ if (seg[0] === 255 & seg[1] === 225) {
+ return seg;
+ }
+ x++;
+ }
+ return [];
+ }
+ }, {
+ key: "insertExif",
+ value: function insertExif(resizedFileBase64, exifArray) {
+ var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');
+ var buf = this.decode64(imageData);
+ var separatePoint = buf.indexOf(255, 3);
+ var mae = buf.slice(0, separatePoint);
+ var ato = buf.slice(separatePoint);
+ var array = mae;
+ array = array.concat(exifArray);
+ array = array.concat(ato);
+ return array;
+ }
+ }, {
+ key: "slice2Segments",
+ value: function slice2Segments(rawImageArray) {
+ var head = 0;
+ var segments = [];
+ while (true) {
+ var length;
+ if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
+ break;
+ }
+ if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
+ head += 2;
+ } else {
+ length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
+ var endPoint = head + length + 2;
+ var seg = rawImageArray.slice(head, endPoint);
+ segments.push(seg);
+ head = endPoint;
+ }
+ if (head > rawImageArray.length) {
+ break;
+ }
+ }
+ return segments;
+ }
+ }, {
+ key: "decode64",
+ value: function decode64(input) {
+ var output = '';
+ var chr1 = undefined;
+ var chr2 = undefined;
+ var chr3 = '';
+ var enc1 = undefined;
+ var enc2 = undefined;
+ var enc3 = undefined;
+ var enc4 = '';
+ var i = 0;
+ var buf = [];
+ // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+ var base64test = /[^A-Za-z0-9\+\/\=]/g;
+ if (base64test.exec(input)) {
+ 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.');
+ }
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
+ while (true) {
+ enc1 = this.KEY_STR.indexOf(input.charAt(i++));
+ enc2 = this.KEY_STR.indexOf(input.charAt(i++));
+ enc3 = this.KEY_STR.indexOf(input.charAt(i++));
+ enc4 = this.KEY_STR.indexOf(input.charAt(i++));
+ chr1 = enc1 << 2 | enc2 >> 4;
+ chr2 = (enc2 & 15) << 4 | enc3 >> 2;
+ chr3 = (enc3 & 3) << 6 | enc4;
+ buf.push(chr1);
+ if (enc3 !== 64) {
+ buf.push(chr2);
+ }
+ if (enc4 !== 64) {
+ buf.push(chr3);
+ }
+ chr1 = chr2 = chr3 = '';
+ enc1 = enc2 = enc3 = enc4 = '';
+ if (!(i < input.length)) {
+ break;
+ }
+ }
+ return buf;
+ }
+ }]);
+
+ return ExifRestore;
+}();
+
+ExifRestore.initClass();
+
+/*
+ * contentloaded.js
+ *
+ * Author: Diego Perini (diego.perini at gmail.com)
+ * Summary: cross-browser wrapper for DOMContentLoaded
+ * Updated: 20101020
+ * License: MIT
+ * Version: 1.2
+ *
+ * URL:
+ * http://javascript.nwbox.com/ContentLoaded/
+ * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
+ */
+
+// @win window reference
+// @fn function reference
+var contentLoaded = function contentLoaded(win, fn) {
+ var done = false;
+ var top = true;
+ var doc = win.document;
+ var root = doc.documentElement;
+ var add = doc.addEventListener ? "addEventListener" : "attachEvent";
+ var rem = doc.addEventListener ? "removeEventListener" : "detachEvent";
+ var pre = doc.addEventListener ? "" : "on";
+ var init = function init(e) {
+ if (e.type === "readystatechange" && doc.readyState !== "complete") {
+ return;
+ }
+ (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
+ if (!done && (done = true)) {
+ return fn.call(win, e.type || e);
+ }
+ };
+
+ var poll = function poll() {
+ try {
+ root.doScroll("left");
+ } catch (e) {
+ setTimeout(poll, 50);
+ return;
+ }
+ return init("poll");
+ };
+
+ if (doc.readyState !== "complete") {
+ if (doc.createEventObject && root.doScroll) {
+ try {
+ top = !win.frameElement;
+ } catch (error) {}
+ if (top) {
+ poll();
+ }
+ }
+ doc[add](pre + "DOMContentLoaded", init, false);
+ doc[add](pre + "readystatechange", init, false);
+ return win[add](pre + "load", init, false);
+ }
+};
+
+// As a single function to be able to write tests.
+Dropzone._autoDiscoverFunction = function () {
+ if (Dropzone.autoDiscover) {
+ return Dropzone.discover();
+ }
+};
+contentLoaded(window, Dropzone._autoDiscoverFunction);
+
+function __guard__(value, transform) {
+ return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;
+}
+function __guardMethod__(obj, methodName, transform) {
+ if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
+ return transform(obj, methodName);
+ } else {
+ return undefined;
+ }
+}
diff --git a/addonstyle/basic.css b/addonstyle/basic.css
new file mode 100644
index 0000000..b72d7de
--- /dev/null
+++ b/addonstyle/basic.css
@@ -0,0 +1,39 @@
+/*
+ * The MIT License
+ * Copyright (c) 2012 Matias Meno
+ */
+.dropzone, .dropzone * {
+ box-sizing: border-box; }
+
+.dropzone {
+ position: relative; }
+ .dropzone .dz-preview {
+ position: relative;
+ display: inline-block;
+ width: 120px;
+ margin: 0.5em; }
+ .dropzone .dz-preview .dz-progress {
+ display: block;
+ height: 15px;
+ border: 1px solid #aaa; }
+ .dropzone .dz-preview .dz-progress .dz-upload {
+ display: block;
+ height: 100%;
+ width: 0;
+ background: green; }
+ .dropzone .dz-preview .dz-error-message {
+ color: red;
+ display: none; }
+ .dropzone .dz-preview.dz-error .dz-error-message, .dropzone .dz-preview.dz-error .dz-error-mark {
+ display: block; }
+ .dropzone .dz-preview.dz-success .dz-success-mark {
+ display: block; }
+ .dropzone .dz-preview .dz-error-mark, .dropzone .dz-preview .dz-success-mark {
+ position: absolute;
+ display: none;
+ left: 30px;
+ top: 30px;
+ width: 54px;
+ height: 58px;
+ left: 50%;
+ margin-left: -27px; }
diff --git a/addonstyle/dropzone.css b/addonstyle/dropzone.css
new file mode 100644
index 0000000..0494d1c
--- /dev/null
+++ b/addonstyle/dropzone.css
@@ -0,0 +1,388 @@
+/*
+ * The MIT License
+ * Copyright (c) 2012 Matias Meno
+ */
+@-webkit-keyframes passing-through {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(40px);
+ -moz-transform: translateY(40px);
+ -ms-transform: translateY(40px);
+ -o-transform: translateY(40px);
+ transform: translateY(40px); }
+ 30%, 70% {
+ opacity: 1;
+ -webkit-transform: translateY(0px);
+ -moz-transform: translateY(0px);
+ -ms-transform: translateY(0px);
+ -o-transform: translateY(0px);
+ transform: translateY(0px); }
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-40px);
+ -moz-transform: translateY(-40px);
+ -ms-transform: translateY(-40px);
+ -o-transform: translateY(-40px);
+ transform: translateY(-40px); } }
+@-moz-keyframes passing-through {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(40px);
+ -moz-transform: translateY(40px);
+ -ms-transform: translateY(40px);
+ -o-transform: translateY(40px);
+ transform: translateY(40px); }
+ 30%, 70% {
+ opacity: 1;
+ -webkit-transform: translateY(0px);
+ -moz-transform: translateY(0px);
+ -ms-transform: translateY(0px);
+ -o-transform: translateY(0px);
+ transform: translateY(0px); }
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-40px);
+ -moz-transform: translateY(-40px);
+ -ms-transform: translateY(-40px);
+ -o-transform: translateY(-40px);
+ transform: translateY(-40px); } }
+@keyframes passing-through {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(40px);
+ -moz-transform: translateY(40px);
+ -ms-transform: translateY(40px);
+ -o-transform: translateY(40px);
+ transform: translateY(40px); }
+ 30%, 70% {
+ opacity: 1;
+ -webkit-transform: translateY(0px);
+ -moz-transform: translateY(0px);
+ -ms-transform: translateY(0px);
+ -o-transform: translateY(0px);
+ transform: translateY(0px); }
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-40px);
+ -moz-transform: translateY(-40px);
+ -ms-transform: translateY(-40px);
+ -o-transform: translateY(-40px);
+ transform: translateY(-40px); } }
+@-webkit-keyframes slide-in {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(40px);
+ -moz-transform: translateY(40px);
+ -ms-transform: translateY(40px);
+ -o-transform: translateY(40px);
+ transform: translateY(40px); }
+ 30% {
+ opacity: 1;
+ -webkit-transform: translateY(0px);
+ -moz-transform: translateY(0px);
+ -ms-transform: translateY(0px);
+ -o-transform: translateY(0px);
+ transform: translateY(0px); } }
+@-moz-keyframes slide-in {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(40px);
+ -moz-transform: translateY(40px);
+ -ms-transform: translateY(40px);
+ -o-transform: translateY(40px);
+ transform: translateY(40px); }
+ 30% {
+ opacity: 1;
+ -webkit-transform: translateY(0px);
+ -moz-transform: translateY(0px);
+ -ms-transform: translateY(0px);
+ -o-transform: translateY(0px);
+ transform: translateY(0px); } }
+@keyframes slide-in {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(40px);
+ -moz-transform: translateY(40px);
+ -ms-transform: translateY(40px);
+ -o-transform: translateY(40px);
+ transform: translateY(40px); }
+ 30% {
+ opacity: 1;
+ -webkit-transform: translateY(0px);
+ -moz-transform: translateY(0px);
+ -ms-transform: translateY(0px);
+ -o-transform: translateY(0px);
+ transform: translateY(0px); } }
+@-webkit-keyframes pulse {
+ 0% {
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1); }
+ 10% {
+ -webkit-transform: scale(1.1);
+ -moz-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ transform: scale(1.1); }
+ 20% {
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1); } }
+@-moz-keyframes pulse {
+ 0% {
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1); }
+ 10% {
+ -webkit-transform: scale(1.1);
+ -moz-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ transform: scale(1.1); }
+ 20% {
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1); } }
+@keyframes pulse {
+ 0% {
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1); }
+ 10% {
+ -webkit-transform: scale(1.1);
+ -moz-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ transform: scale(1.1); }
+ 20% {
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1); } }
+.dropzone, .dropzone * {
+ box-sizing: border-box; }
+
+.dropzone {
+ min-height: 150px;
+ border: 2px solid rgba(0, 0, 0, 0.3);
+ background: white;
+ padding: 20px 20px; }
+ .dropzone.dz-clickable {
+ cursor: pointer; }
+ .dropzone.dz-clickable * {
+ cursor: default; }
+ .dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
+ cursor: pointer; }
+ .dropzone.dz-started .dz-message {
+ display: none; }
+ .dropzone.dz-drag-hover {
+ border-style: solid; }
+ .dropzone.dz-drag-hover .dz-message {
+ opacity: 0.5; }
+ .dropzone .dz-message {
+ text-align: center;
+ margin: 2em 0; }
+ .dropzone .dz-preview {
+ position: relative;
+ display: inline-block;
+ vertical-align: top;
+ margin: 16px;
+ min-height: 100px; }
+ .dropzone .dz-preview:hover {
+ z-index: 1000; }
+ .dropzone .dz-preview:hover .dz-details {
+ opacity: 1; }
+ .dropzone .dz-preview.dz-file-preview .dz-image {
+ border-radius: 20px;
+ background: #999;
+ background: linear-gradient(to bottom, #eee, #ddd); }
+ .dropzone .dz-preview.dz-file-preview .dz-details {
+ opacity: 1; }
+ .dropzone .dz-preview.dz-image-preview {
+ background: white; }
+ .dropzone .dz-preview.dz-image-preview .dz-details {
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -ms-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear; }
+ .dropzone .dz-preview .dz-remove {
+ font-size: 14px;
+ text-align: center;
+ display: block;
+ cursor: pointer;
+ border: none; }
+ .dropzone .dz-preview .dz-remove:hover {
+ text-decoration: underline; }
+ .dropzone .dz-preview:hover .dz-details {
+ opacity: 1; }
+ .dropzone .dz-preview .dz-details {
+ z-index: 20;
+ position: absolute;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ font-size: 13px;
+ min-width: 100%;
+ max-width: 100%;
+ padding: 2em 1em;
+ text-align: center;
+ color: rgba(0, 0, 0, 0.9);
+ line-height: 150%; }
+ .dropzone .dz-preview .dz-details .dz-size {
+ margin-bottom: 1em;
+ font-size: 16px; }
+ .dropzone .dz-preview .dz-details .dz-filename {
+ white-space: nowrap; }
+ .dropzone .dz-preview .dz-details .dz-filename:hover span {
+ border: 1px solid rgba(200, 200, 200, 0.8);
+ background-color: rgba(255, 255, 255, 0.8); }
+ .dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
+ overflow: hidden;
+ text-overflow: ellipsis; }
+ .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
+ border: 1px solid transparent; }
+ .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
+ background-color: rgba(255, 255, 255, 0.4);
+ padding: 0 0.4em;
+ border-radius: 3px; }
+ .dropzone .dz-preview:hover .dz-image img {
+ -webkit-transform: scale(1.05, 1.05);
+ -moz-transform: scale(1.05, 1.05);
+ -ms-transform: scale(1.05, 1.05);
+ -o-transform: scale(1.05, 1.05);
+ transform: scale(1.05, 1.05);
+ -webkit-filter: blur(8px);
+ filter: blur(8px); }
+ .dropzone .dz-preview .dz-image {
+ border-radius: 20px;
+ overflow: hidden;
+ width: 120px;
+ height: 120px;
+ position: relative;
+ display: block;
+ z-index: 10; }
+ .dropzone .dz-preview .dz-image img {
+ display: block; }
+ .dropzone .dz-preview.dz-success .dz-success-mark {
+ -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+ -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+ -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+ -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+ animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
+ .dropzone .dz-preview.dz-error .dz-error-mark {
+ opacity: 1;
+ -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+ -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+ -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+ -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+ animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
+ .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
+ pointer-events: none;
+ opacity: 0;
+ z-index: 500;
+ position: absolute;
+ display: block;
+ top: 50%;
+ left: 50%;
+ margin-left: -27px;
+ margin-top: -27px; }
+ .dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
+ display: block;
+ width: 54px;
+ height: 54px; }
+ .dropzone .dz-preview.dz-processing .dz-progress {
+ opacity: 1;
+ -webkit-transition: all 0.2s linear;
+ -moz-transition: all 0.2s linear;
+ -ms-transition: all 0.2s linear;
+ -o-transition: all 0.2s linear;
+ transition: all 0.2s linear; }
+ .dropzone .dz-preview.dz-complete .dz-progress {
+ opacity: 0;
+ -webkit-transition: opacity 0.4s ease-in;
+ -moz-transition: opacity 0.4s ease-in;
+ -ms-transition: opacity 0.4s ease-in;
+ -o-transition: opacity 0.4s ease-in;
+ transition: opacity 0.4s ease-in; }
+ .dropzone .dz-preview:not(.dz-processing) .dz-progress {
+ -webkit-animation: pulse 6s ease infinite;
+ -moz-animation: pulse 6s ease infinite;
+ -ms-animation: pulse 6s ease infinite;
+ -o-animation: pulse 6s ease infinite;
+ animation: pulse 6s ease infinite; }
+ .dropzone .dz-preview .dz-progress {
+ opacity: 1;
+ z-index: 1000;
+ pointer-events: none;
+ position: absolute;
+ height: 16px;
+ left: 50%;
+ top: 50%;
+ margin-top: -8px;
+ width: 80px;
+ margin-left: -40px;
+ background: rgba(255, 255, 255, 0.9);
+ -webkit-transform: scale(1);
+ border-radius: 8px;
+ overflow: hidden; }
+ .dropzone .dz-preview .dz-progress .dz-upload {
+ background: #333;
+ background: linear-gradient(to bottom, #666, #444);
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 0;
+ -webkit-transition: width 300ms ease-in-out;
+ -moz-transition: width 300ms ease-in-out;
+ -ms-transition: width 300ms ease-in-out;
+ -o-transition: width 300ms ease-in-out;
+ transition: width 300ms ease-in-out; }
+ .dropzone .dz-preview.dz-error .dz-error-message {
+ display: block; }
+ .dropzone .dz-preview.dz-error:hover .dz-error-message {
+ opacity: 1;
+ pointer-events: auto; }
+ .dropzone .dz-preview .dz-error-message {
+ pointer-events: none;
+ z-index: 1000;
+ position: absolute;
+ display: block;
+ display: none;
+ opacity: 0;
+ -webkit-transition: opacity 0.3s ease;
+ -moz-transition: opacity 0.3s ease;
+ -ms-transition: opacity 0.3s ease;
+ -o-transition: opacity 0.3s ease;
+ transition: opacity 0.3s ease;
+ border-radius: 8px;
+ font-size: 13px;
+ top: 130px;
+ left: -10px;
+ width: 140px;
+ background: #be2626;
+ background: linear-gradient(to bottom, #be2626, #a92222);
+ padding: 0.5em 1.2em;
+ color: white; }
+ .dropzone .dz-preview .dz-error-message:after {
+ content: '';
+ position: absolute;
+ top: -6px;
+ left: 64px;
+ width: 0;
+ height: 0;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid #be2626; }
diff --git a/addonstyle/dropzone.js b/addonstyle/dropzone.js
new file mode 100644
index 0000000..1e643af
--- /dev/null
+++ b/addonstyle/dropzone.js
@@ -0,0 +1,3531 @@
+"use strict";
+
+var _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; }; }();
+
+function _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; }
+
+function _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; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/*
+ *
+ * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
+ *
+ * Copyright (c) 2012, Matias Meno
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+// The Emitter class provides the ability to call `.on()` on Dropzone to listen
+// to events.
+// It is strongly based on component's emitter class, and I removed the
+// functionality because of the dependency hell with different frameworks.
+var Emitter = function () {
+ function Emitter() {
+ _classCallCheck(this, Emitter);
+ }
+
+ _createClass(Emitter, [{
+ key: "on",
+
+ // Add an event listener for given event
+ value: function on(event, fn) {
+ this._callbacks = this._callbacks || {};
+ // Create namespace for this event
+ if (!this._callbacks[event]) {
+ this._callbacks[event] = [];
+ }
+ this._callbacks[event].push(fn);
+ return this;
+ }
+ }, {
+ key: "emit",
+ value: function emit(event) {
+ this._callbacks = this._callbacks || {};
+ var callbacks = this._callbacks[event];
+
+ if (callbacks) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
+ var _ref;
+
+ if (_isArray) {
+ if (_i >= _iterator.length) break;
+ _ref = _iterator[_i++];
+ } else {
+ _i = _iterator.next();
+ if (_i.done) break;
+ _ref = _i.value;
+ }
+
+ var callback = _ref;
+
+ callback.apply(this, args);
+ }
+ }
+
+ return this;
+ }
+
+ // Remove event listener for given event. If fn is not provided, all event
+ // listeners for that event will be removed. If neither is provided, all
+ // event listeners will be removed.
+
+ }, {
+ key: "off",
+ value: function off(event, fn) {
+ if (!this._callbacks || arguments.length === 0) {
+ this._callbacks = {};
+ return this;
+ }
+
+ // specific event
+ var callbacks = this._callbacks[event];
+ if (!callbacks) {
+ return this;
+ }
+
+ // remove all handlers
+ if (arguments.length === 1) {
+ delete this._callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ for (var i = 0; i < callbacks.length; i++) {
+ var callback = callbacks[i];
+ if (callback === fn) {
+ callbacks.splice(i, 1);
+ break;
+ }
+ }
+
+ return this;
+ }
+ }]);
+
+ return Emitter;
+}();
+
+var Dropzone = function (_Emitter) {
+ _inherits(Dropzone, _Emitter);
+
+ _createClass(Dropzone, null, [{
+ key: "initClass",
+ value: function initClass() {
+
+ // Exposing the emitter class, mainly for tests
+ this.prototype.Emitter = Emitter;
+
+ /*
+ This is a list of all available events you can register on a dropzone object.
+ You can register an event handler like this:
+ dropzone.on("dragEnter", function() { });
+ */
+ 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"];
+
+ this.prototype.defaultOptions = {
+ /**
+ * Has to be specified on elements other than form (or when the form
+ * doesn't have an `action` attribute). You can also
+ * provide a function that will be called with `files` and
+ * must return the url (since `v3.12.0`)
+ */
+ url: null,
+
+ /**
+ * Can be changed to `"put"` if necessary. You can also provide a function
+ * that will be called with `files` and must return the method (since `v3.12.0`).
+ */
+ method: "post",
+
+ /**
+ * Will be set on the XHRequest.
+ */
+ withCredentials: false,
+
+ /**
+ * The timeout for the XHR requests in milliseconds (since `v4.4.0`).
+ */
+ timeout: 30000,
+
+ /**
+ * How many file uploads to process in parallel (See the
+ * Enqueuing file uploads* documentation section for more info)
+ */
+ parallelUploads: 1,
+
+ /**
+ * Whether to send multiple files in one request. If
+ * this it set to true, then the fallback file input element will
+ * have the `multiple` attribute as well. This option will
+ * also trigger additional events (like `processingmultiple`). See the events
+ * documentation section for more information.
+ */
+ uploadMultiple: false,
+
+ /**
+ * Whether you want files to be uploaded in chunks to your server. This can't be
+ * used in combination with `uploadMultiple`.
+ *
+ * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.
+ */
+ chunking: false,
+
+ /**
+ * If `chunking` is enabled, this defines whether **every** file should be chunked,
+ * even if the file size is below chunkSize. This means, that the additional chunk
+ * form data will be submitted and the `chunksUploaded` callback will be invoked.
+ */
+ forceChunking: false,
+
+ /**
+ * If `chunking` is `true`, then this defines the chunk size in bytes.
+ */
+ chunkSize: 2000000,
+
+ /**
+ * If `true`, the individual chunks of a file are being uploaded simultaneously.
+ */
+ parallelChunkUploads: false,
+
+ /**
+ * Whether a chunk should be retried if it fails.
+ */
+ retryChunks: false,
+
+ /**
+ * If `retryChunks` is true, how many times should it be retried.
+ */
+ retryChunksLimit: 3,
+
+ /**
+ * If not `null` defines how many files this Dropzone handles. If it exceeds,
+ * the event `maxfilesexceeded` will be called. The dropzone element gets the
+ * class `dz-max-files-reached` accordingly so you can provide visual feedback.
+ */
+ maxFilesize: 6,
+
+ /**
+ * The name of the file param that gets transferred.
+ * **NOTE**: If you have the option `uploadMultiple` set to `true`, then
+ * Dropzone will append `[]` to the name.
+ */
+ paramName: "fileToUpload",
+
+ /**
+ * Whether thumbnails for images should be generated
+ */
+ createImageThumbnails: true,
+
+ /**
+ * In MB. When the filename exceeds this limit, the thumbnail will not be generated.
+ */
+ maxThumbnailFilesize: 4,
+
+ /**
+ * If `null`, the ratio of the image will be used to calculate it.
+ */
+ thumbnailWidth: 120,
+
+ /**
+ * The same as `thumbnailWidth`. If both are null, images will not be resized.
+ */
+ thumbnailHeight: 120,
+
+ /**
+ * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.
+ * Can be either `contain` or `crop`.
+ */
+ thumbnailMethod: 'crop',
+
+ /**
+ * If set, images will be resized to these dimensions before being **uploaded**.
+ * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect
+ * ratio of the file will be preserved.
+ *
+ * The `options.transformFile` function uses these options, so if the `transformFile` function
+ * is overridden, these options don't do anything.
+ */
+ resizeWidth: null,
+
+ /**
+ * See `resizeWidth`.
+ */
+ resizeHeight: null,
+
+ /**
+ * The mime type of the resized image (before it gets uploaded to the server).
+ * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.
+ * See `resizeWidth` for more information.
+ */
+ resizeMimeType: null,
+
+ /**
+ * The quality of the resized images. See `resizeWidth`.
+ */
+ resizeQuality: 0.8,
+
+ /**
+ * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.
+ * Can be either `contain` or `crop`.
+ */
+ resizeMethod: 'contain',
+
+ /**
+ * The base that is used to calculate the filesize. You can change this to
+ * 1024 if you would rather display kibibytes, mebibytes, etc...
+ * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.
+ * You can change this to `1024` if you don't care about validity.
+ */
+ filesizeBase: 1000,
+
+ /**
+ * Can be used to limit the maximum number of files that will be handled by this Dropzone
+ */
+ maxFiles: 1,
+
+ /**
+ * An optional object to send additional headers to the server. Eg:
+ * `{ "My-Awesome-Header": "header value" }`
+ */
+ headers: null,
+
+ /**
+ * If `true`, the dropzone element itself will be clickable, if `false`
+ * nothing will be clickable.
+ *
+ * You can also pass an HTML element, a CSS selector (for multiple elements)
+ * or an array of those. In that case, all of those elements will trigger an
+ * upload when clicked.
+ */
+ clickable: true,
+
+ /**
+ * Whether hidden files in directories should be ignored.
+ */
+ ignoreHiddenFiles: true,
+
+ /**
+ * The default implementation of `accept` checks the file's mime type or
+ * extension against this list. This is a comma separated list of mime
+ * types or file extensions.
+ *
+ * Eg.: `image/*,application/pdf,.psd`
+ *
+ * If the Dropzone is `clickable` this option will also be used as
+ * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)
+ * parameter on the hidden file input as well.
+ */
+ acceptedFiles: 'image/*',
+
+ /**
+ * **Deprecated!**
+ * Use acceptedFiles instead.
+ */
+ acceptedMimeTypes: null,
+
+ /**
+ * If false, files will be added to the queue but the queue will not be
+ * processed automatically.
+ * This can be useful if you need some additional user input before sending
+ * files (or if you want want all files sent at once).
+ * If you're ready to send the file simply call `myDropzone.processQueue()`.
+ *
+ * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation
+ * section for more information.
+ */
+ autoProcessQueue: true,
+
+ /**
+ * If false, files added to the dropzone will not be queued by default.
+ * You'll have to call `enqueueFile(file)` manually.
+ */
+ autoQueue: true,
+
+ /**
+ * If `true`, this will add a link to every file preview to remove or cancel (if
+ * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`
+ * and `dictRemoveFile` options are used for the wording.
+ */
+ addRemoveLinks: false,
+
+ /**
+ * Defines where to display the file previews – if `null` the
+ * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS
+ * selector. The element should have the `dropzone-previews` class so
+ * the previews are displayed properly.
+ */
+ previewsContainer: null,
+
+ /**
+ * This is the element the hidden input field (which is used when clicking on the
+ * dropzone to trigger file selection) will be appended to. This might
+ * be important in case you use frameworks to switch the content of your page.
+ */
+ hiddenInputContainer: "body",
+
+ /**
+ * If null, no capture type will be specified
+ * If camera, mobile devices will skip the file selection and choose camera
+ * If microphone, mobile devices will skip the file selection and choose the microphone
+ * If camcorder, mobile devices will skip the file selection and choose the camera in video mode
+ * On apple devices multiple must be set to false. AcceptedFiles may need to
+ * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").
+ */
+ capture: null,
+
+ /**
+ * **Deprecated**. Use `renameFile` instead.
+ */
+ renameFilename: null,
+
+ /**
+ * A function that is invoked before the file is uploaded to the server and renames the file.
+ * This function gets the `File` as argument and can use the `file.name`. The actual name of the
+ * file that gets used during the upload can be accessed through `file.upload.filename`.
+ */
+ renameFile: null,
+
+ /**
+ * If `true` the fallback will be forced. This is very useful to test your server
+ * implementations first and make sure that everything works as
+ * expected without dropzone if you experience problems, and to test
+ * how your fallbacks will look.
+ */
+ forceFallback: false,
+
+ /**
+ * The text used before any files are dropped.
+ */
+ dictDefaultMessage: "Drop an image or click here to upload",
+
+ /**
+ * The text that replaces the default message text it the browser is not supported.
+ */
+ dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
+
+ /**
+ * The text that will be added before the fallback form.
+ * If you provide a fallback element yourself, or if this option is `null` this will
+ * be ignored.
+ */
+ dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.",
+
+ /**
+ * If the filesize is too big.
+ * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.
+ */
+ dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
+
+ /**
+ * If the file doesn't match the file type.
+ */
+ dictInvalidFileType: "You can't upload files of this type.",
+
+ /**
+ * If the server response was invalid.
+ * `{{statusCode}}` will be replaced with the servers status code.
+ */
+ dictResponseError: "Server responded with code {{statusCode}}.",
+
+ /**
+ * If `addRemoveLinks` is true, the text to be used for the cancel upload link.
+ */
+ dictCancelUpload: "Cancel upload",
+
+ /**
+ * The text that is displayed if an upload was manually canceled
+ */
+ dictUploadCanceled: "Upload canceled.",
+
+ /**
+ * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.
+ */
+ dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
+
+ /**
+ * If `addRemoveLinks` is true, the text to be used to remove a file.
+ */
+ dictRemoveFile: "Remove file",
+
+ /**
+ * If this is not null, then the user will be prompted before removing a file.
+ */
+ dictRemoveFileConfirmation: null,
+
+ /**
+ * Displayed if `maxFiles` is st and exceeded.
+ * The string `{{maxFiles}}` will be replaced by the configuration value.
+ */
+ dictMaxFilesExceeded: "Please only upload {{maxFiles}} files at a time.",
+
+ /**
+ * Allows you to translate the different units. Starting with `tb` for terabytes and going down to
+ * `b` for bytes.
+ */
+ dictFileSizeUnits: { tb: "TB", gb: "GB", mb: "MB", kb: "KB", b: "b" },
+ /**
+ * Called when dropzone initialized
+ * You can add event listeners here
+ */
+ init: function init() {
+ this.on("success", (file, response, xhr) => {
+ if (!response.location) {
+ // do nothing if there's no location supplied (optional)
+ window.location.href = "./failed.php"
+ return;
+ }
+ //window.location.href = response.location
+ setTimeout(function(){window.location.href=response.location},1500);
+ })
+ },
+
+
+ /**
+ * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`
+ * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case
+ * of a function, this needs to return a map.
+ *
+ * The default implementation does nothing for normal uploads, but adds relevant information for
+ * chunked uploads.
+ *
+ * This is the same as adding hidden input fields in the form element.
+ */
+ params: function params(files, xhr, chunk) {
+ if (chunk) {
+ return {
+ dzuuid: chunk.file.upload.uuid,
+ dzchunkindex: chunk.index,
+ dztotalfilesize: chunk.file.size,
+ dzchunksize: this.options.chunkSize,
+ dztotalchunkcount: chunk.file.upload.totalChunkCount,
+ dzchunkbyteoffset: chunk.index * this.options.chunkSize
+ };
+ }
+ },
+
+
+ /**
+ * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)
+ * and a `done` function as parameters.
+ *
+ * If the done function is invoked without arguments, the file is "accepted" and will
+ * be processed. If you pass an error message, the file is rejected, and the error
+ * message will be displayed.
+ * This function will not be called if the file is too big or doesn't match the mime types.
+ */
+ accept: function accept(file, done) {
+ return done();
+ },
+
+
+ /**
+ * The callback that will be invoked when all chunks have been uploaded for a file.
+ * It gets the file for which the chunks have been uploaded as the first parameter,
+ * and the `done` function as second. `done()` needs to be invoked when everything
+ * needed to finish the upload process is done.
+ */
+ chunksUploaded: function chunksUploaded(file, done) {
+ done();
+ },
+
+ /**
+ * Gets called when the browser is not supported.
+ * The default implementation shows the fallback input field and adds
+ * a text.
+ */
+ fallback: function fallback() {
+ // This code should pass in IE7... :(
+ var messageElement = void 0;
+ this.element.className = this.element.className + " dz-browser-not-supported";
+
+ for (var _iterator2 = this.element.getElementsByTagName("div"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
+ var _ref2;
+
+ if (_isArray2) {
+ if (_i2 >= _iterator2.length) break;
+ _ref2 = _iterator2[_i2++];
+ } else {
+ _i2 = _iterator2.next();
+ if (_i2.done) break;
+ _ref2 = _i2.value;
+ }
+
+ var child = _ref2;
+
+ if (/(^| )dz-message($| )/.test(child.className)) {
+ messageElement = child;
+ child.className = "dz-message"; // Removes the 'dz-default' class
+ break;
+ }
+ }
+ if (!messageElement) {
+ messageElement = Dropzone.createElement("
");
+ this.element.appendChild(messageElement);
+ }
+
+ var span = messageElement.getElementsByTagName("span")[0];
+ if (span) {
+ if (span.textContent != null) {
+ span.textContent = this.options.dictFallbackMessage;
+ } else if (span.innerText != null) {
+ span.innerText = this.options.dictFallbackMessage;
+ }
+ }
+
+ return this.element.appendChild(this.getFallbackForm());
+ },
+
+
+ /**
+ * Gets called to calculate the thumbnail dimensions.
+ *
+ * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:
+ *
+ * - `srcWidth` & `srcHeight` (required)
+ * - `trgWidth` & `trgHeight` (required)
+ * - `srcX` & `srcY` (optional, default `0`)
+ * - `trgX` & `trgY` (optional, default `0`)
+ *
+ * Those values are going to be used by `ctx.drawImage()`.
+ */
+ resize: function resize(file, width, height, resizeMethod) {
+ var info = {
+ srcX: 0,
+ srcY: 0,
+ srcWidth: file.width,
+ srcHeight: file.height
+ };
+
+ var srcRatio = file.width / file.height;
+
+ // Automatically calculate dimensions if not specified
+ if (width == null && height == null) {
+ width = info.srcWidth;
+ height = info.srcHeight;
+ } else if (width == null) {
+ width = height * srcRatio;
+ } else if (height == null) {
+ height = width / srcRatio;
+ }
+
+ // Make sure images aren't upscaled
+ width = Math.min(width, info.srcWidth);
+ height = Math.min(height, info.srcHeight);
+
+ var trgRatio = width / height;
+
+ if (info.srcWidth > width || info.srcHeight > height) {
+ // Image is bigger and needs rescaling
+ if (resizeMethod === 'crop') {
+ if (srcRatio > trgRatio) {
+ info.srcHeight = file.height;
+ info.srcWidth = info.srcHeight * trgRatio;
+ } else {
+ info.srcWidth = file.width;
+ info.srcHeight = info.srcWidth / trgRatio;
+ }
+ } else if (resizeMethod === 'contain') {
+ // Method 'contain'
+ if (srcRatio > trgRatio) {
+ height = width / srcRatio;
+ } else {
+ width = height * srcRatio;
+ }
+ } else {
+ throw new Error("Unknown resizeMethod '" + resizeMethod + "'");
+ }
+ }
+
+ info.srcX = (file.width - info.srcWidth) / 2;
+ info.srcY = (file.height - info.srcHeight) / 2;
+
+ info.trgWidth = width;
+ info.trgHeight = height;
+
+ return info;
+ },
+
+
+ /**
+ * Can be used to transform the file (for example, resize an image if necessary).
+ *
+ * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes
+ * images according to those dimensions.
+ *
+ * Gets the `file` as the first parameter, and a `done()` function as the second, that needs
+ * to be invoked with the file when the transformation is done.
+ */
+ transformFile: function transformFile(file, done) {
+ if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
+ return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
+ } else {
+ return done(file);
+ }
+ },
+
+
+ /**
+ * A string that contains the template used for each dropped
+ * file. Change it to fulfill your needs but make sure to properly
+ * provide all elements.
+ *
+ * If you want to use an actual HTML element instead of providing a String
+ * as a config option, you could create a div with the id `tpl`,
+ * put the template inside it and provide the element like this:
+ *
+ * document
+ * .querySelector('#tpl')
+ * .innerHTML
+ *
+ */
+ previewTemplate: "
\n \n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
",
+
+ // END OPTIONS
+ // (Required by the dropzone documentation parser)
+
+
+ /*
+ Those functions register themselves to the events on init and handle all
+ the user interface specific stuff. Overwriting them won't break the upload
+ but can break the way it's displayed.
+ You can overwrite them if you don't like the default behavior. If you just
+ want to add an additional event handler, register it on the dropzone object
+ and don't overwrite those options.
+ */
+
+ // Those are self explanatory and simply concern the DragnDrop.
+ drop: function drop(e) {
+ return this.element.classList.remove("dz-drag-hover");
+ },
+ dragstart: function dragstart(e) {},
+ dragend: function dragend(e) {
+ return this.element.classList.remove("dz-drag-hover");
+ },
+ dragenter: function dragenter(e) {
+ return this.element.classList.add("dz-drag-hover");
+ },
+ dragover: function dragover(e) {
+ return this.element.classList.add("dz-drag-hover");
+ },
+ dragleave: function dragleave(e) {
+ return this.element.classList.remove("dz-drag-hover");
+ },
+ paste: function paste(e) {},
+
+
+ // Called whenever there are no files left in the dropzone anymore, and the
+ // dropzone should be displayed as if in the initial state.
+ reset: function reset() {
+ return this.element.classList.remove("dz-started");
+ },
+
+
+ // Called when a file is added to the queue
+ // Receives `file`
+ addedfile: function addedfile(file) {
+ var _this2 = this;
+
+ if (this.element === this.previewsContainer) {
+ this.element.classList.add("dz-started");
+ }
+
+ if (this.previewsContainer) {
+ file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
+ file.previewTemplate = file.previewElement; // Backwards compatibility
+
+ this.previewsContainer.appendChild(file.previewElement);
+ for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
+ var _ref3;
+
+ if (_isArray3) {
+ if (_i3 >= _iterator3.length) break;
+ _ref3 = _iterator3[_i3++];
+ } else {
+ _i3 = _iterator3.next();
+ if (_i3.done) break;
+ _ref3 = _i3.value;
+ }
+
+ var node = _ref3;
+
+ node.textContent = file.name;
+ }
+ for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
+ if (_isArray4) {
+ if (_i4 >= _iterator4.length) break;
+ node = _iterator4[_i4++];
+ } else {
+ _i4 = _iterator4.next();
+ if (_i4.done) break;
+ node = _i4.value;
+ }
+
+ node.innerHTML = this.filesize(file.size);
+ }
+
+ if (this.options.addRemoveLinks) {
+ file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + "");
+ file.previewElement.appendChild(file._removeLink);
+ }
+
+ var removeFileEvent = function removeFileEvent(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if (file.status === Dropzone.UPLOADING) {
+ return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {
+ return _this2.removeFile(file);
+ });
+ } else {
+ if (_this2.options.dictRemoveFileConfirmation) {
+ return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {
+ return _this2.removeFile(file);
+ });
+ } else {
+ return _this2.removeFile(file);
+ }
+ }
+ };
+
+ for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
+ var _ref4;
+
+ if (_isArray5) {
+ if (_i5 >= _iterator5.length) break;
+ _ref4 = _iterator5[_i5++];
+ } else {
+ _i5 = _iterator5.next();
+ if (_i5.done) break;
+ _ref4 = _i5.value;
+ }
+
+ var removeLink = _ref4;
+
+ removeLink.addEventListener("click", removeFileEvent);
+ }
+ }
+ },
+
+
+ // Called whenever a file is removed.
+ removedfile: function removedfile(file) {
+ if (file.previewElement != null && file.previewElement.parentNode != null) {
+ file.previewElement.parentNode.removeChild(file.previewElement);
+ }
+ return this._updateMaxFilesReachedClass();
+ },
+
+
+ // Called when a thumbnail has been generated
+ // Receives `file` and `dataUrl`
+ thumbnail: function thumbnail(file, dataUrl) {
+ if (file.previewElement) {
+ file.previewElement.classList.remove("dz-file-preview");
+ for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
+ var _ref5;
+
+ if (_isArray6) {
+ if (_i6 >= _iterator6.length) break;
+ _ref5 = _iterator6[_i6++];
+ } else {
+ _i6 = _iterator6.next();
+ if (_i6.done) break;
+ _ref5 = _i6.value;
+ }
+
+ var thumbnailElement = _ref5;
+
+ thumbnailElement.alt = file.name;
+ thumbnailElement.src = dataUrl;
+ }
+
+ return setTimeout(function () {
+ return file.previewElement.classList.add("dz-image-preview");
+ }, 1);
+ }
+ },
+
+
+ // Called whenever an error occurs
+ // Receives `file` and `message`
+ error: function error(file, message) {
+ if (file.previewElement) {
+ file.previewElement.classList.add("dz-error");
+ if (typeof message !== "String" && message.error) {
+ message = message.error;
+ }
+ for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
+ var _ref6;
+
+ if (_isArray7) {
+ if (_i7 >= _iterator7.length) break;
+ _ref6 = _iterator7[_i7++];
+ } else {
+ _i7 = _iterator7.next();
+ if (_i7.done) break;
+ _ref6 = _i7.value;
+ }
+
+ var node = _ref6;
+
+ node.textContent = message;
+ }
+ }
+ },
+ errormultiple: function errormultiple() {},
+
+
+ // Called when a file gets processed. Since there is a cue, not all added
+ // files are processed immediately.
+ // Receives `file`
+ processing: function processing(file) {
+ if (file.previewElement) {
+ file.previewElement.classList.add("dz-processing");
+ if (file._removeLink) {
+ return file._removeLink.textContent = this.options.dictCancelUpload;
+ }
+ }
+ },
+ processingmultiple: function processingmultiple() {},
+
+
+ // Called whenever the upload progress gets updated.
+ // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.
+ // To get the total number of bytes of the file, use `file.size`
+ uploadprogress: function uploadprogress(file, progress, bytesSent) {
+ if (file.previewElement) {
+ for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
+ var _ref7;
+
+ if (_isArray8) {
+ if (_i8 >= _iterator8.length) break;
+ _ref7 = _iterator8[_i8++];
+ } else {
+ _i8 = _iterator8.next();
+ if (_i8.done) break;
+ _ref7 = _i8.value;
+ }
+
+ var node = _ref7;
+
+ node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + "%";
+ }
+ }
+ },
+
+
+ // Called whenever the total upload progress gets updated.
+ // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent
+ totaluploadprogress: function totaluploadprogress() {},
+
+
+ // Called just before the file is sent. Gets the `xhr` object as second
+ // parameter, so you can modify it (for example to add a CSRF token) and a
+ // `formData` object to add additional information.
+ sending: function sending() {},
+ sendingmultiple: function sendingmultiple() {},
+
+
+ // When the complete upload is finished and successful
+ // Receives `file`
+ success: function success(file) {
+ if (file.previewElement) {
+ return file.previewElement.classList.add("dz-success");
+ }
+ },
+ successmultiple: function successmultiple() {},
+
+
+ // When the upload is canceled.
+ canceled: function canceled(file) {
+ return this.emit("error", file, this.options.dictUploadCanceled);
+ },
+ canceledmultiple: function canceledmultiple() {},
+
+
+ // When the upload is finished, either with success or an error.
+ // Receives `file`
+ complete: function complete(file) {
+ if (file._removeLink) {
+ file._removeLink.textContent = this.options.dictRemoveFile;
+ }
+ if (file.previewElement) {
+ return file.previewElement.classList.add("dz-complete");
+ }
+ },
+ completemultiple: function completemultiple() {},
+ maxfilesexceeded: function maxfilesexceeded() {},
+ maxfilesreached: function maxfilesreached() {},
+ queuecomplete: function queuecomplete() {},
+ addedfiles: function addedfiles() {}
+ };
+
+ this.prototype._thumbnailQueue = [];
+ this.prototype._processingThumbnail = false;
+ }
+
+ // global utility
+
+ }, {
+ key: "extend",
+ value: function extend(target) {
+ for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+ objects[_key2 - 1] = arguments[_key2];
+ }
+
+ for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
+ var _ref8;
+
+ if (_isArray9) {
+ if (_i9 >= _iterator9.length) break;
+ _ref8 = _iterator9[_i9++];
+ } else {
+ _i9 = _iterator9.next();
+ if (_i9.done) break;
+ _ref8 = _i9.value;
+ }
+
+ var object = _ref8;
+
+ for (var key in object) {
+ var val = object[key];
+ target[key] = val;
+ }
+ }
+ return target;
+ }
+ }]);
+
+ function Dropzone(el, options) {
+ _classCallCheck(this, Dropzone);
+
+ var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));
+
+ var fallback = void 0,
+ left = void 0;
+ _this.element = el;
+ // For backwards compatibility since the version was in the prototype previously
+ _this.version = Dropzone.version;
+
+ _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, "");
+
+ _this.clickableElements = [];
+ _this.listeners = [];
+ _this.files = []; // All files
+
+ if (typeof _this.element === "string") {
+ _this.element = document.querySelector(_this.element);
+ }
+
+ // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.
+ if (!_this.element || _this.element.nodeType == null) {
+ throw new Error("Invalid dropzone element.");
+ }
+
+ if (_this.element.dropzone) {
+ throw new Error("Dropzone already attached.");
+ }
+
+ // Now add this dropzone to the instances.
+ Dropzone.instances.push(_this);
+
+ // Put the dropzone inside the element itself.
+ _this.element.dropzone = _this;
+
+ var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};
+
+ _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});
+
+ // If the browser failed, just call the fallback and leave
+ if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {
+ var _ret;
+
+ return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);
+ }
+
+ // @options.url = @element.getAttribute "action" unless @options.url?
+ if (_this.options.url == null) {
+ _this.options.url = _this.element.getAttribute("action");
+ }
+
+ if (!_this.options.url) {
+ throw new Error("No URL provided.");
+ }
+
+ if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {
+ throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
+ }
+
+ if (_this.options.uploadMultiple && _this.options.chunking) {
+ throw new Error('You cannot set both: uploadMultiple and chunking.');
+ }
+
+ // Backwards compatibility
+ if (_this.options.acceptedMimeTypes) {
+ _this.options.acceptedFiles = _this.options.acceptedMimeTypes;
+ delete _this.options.acceptedMimeTypes;
+ }
+
+ // Backwards compatibility
+ if (_this.options.renameFilename != null) {
+ _this.options.renameFile = function (file) {
+ return _this.options.renameFilename.call(_this, file.name, file);
+ };
+ }
+
+ _this.options.method = _this.options.method.toUpperCase();
+
+ if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {
+ // Remove the fallback
+ fallback.parentNode.removeChild(fallback);
+ }
+
+ // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false
+ if (_this.options.previewsContainer !== false) {
+ if (_this.options.previewsContainer) {
+ _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer");
+ } else {
+ _this.previewsContainer = _this.element;
+ }
+ }
+
+ if (_this.options.clickable) {
+ if (_this.options.clickable === true) {
+ _this.clickableElements = [_this.element];
+ } else {
+ _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable");
+ }
+ }
+
+ _this.init();
+ return _this;
+ }
+
+ // Returns all files that have been accepted
+
+
+ _createClass(Dropzone, [{
+ key: "getAcceptedFiles",
+ value: function getAcceptedFiles() {
+ return this.files.filter(function (file) {
+ return file.accepted;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // Returns all files that have been rejected
+ // Not sure when that's going to be useful, but added for completeness.
+
+ }, {
+ key: "getRejectedFiles",
+ value: function getRejectedFiles() {
+ return this.files.filter(function (file) {
+ return !file.accepted;
+ }).map(function (file) {
+ return file;
+ });
+ }
+ }, {
+ key: "getFilesWithStatus",
+ value: function getFilesWithStatus(status) {
+ return this.files.filter(function (file) {
+ return file.status === status;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // Returns all files that are in the queue
+
+ }, {
+ key: "getQueuedFiles",
+ value: function getQueuedFiles() {
+ return this.getFilesWithStatus(Dropzone.QUEUED);
+ }
+ }, {
+ key: "getUploadingFiles",
+ value: function getUploadingFiles() {
+ return this.getFilesWithStatus(Dropzone.UPLOADING);
+ }
+ }, {
+ key: "getAddedFiles",
+ value: function getAddedFiles() {
+ return this.getFilesWithStatus(Dropzone.ADDED);
+ }
+
+ // Files that are either queued or uploading
+
+ }, {
+ key: "getActiveFiles",
+ value: function getActiveFiles() {
+ return this.files.filter(function (file) {
+ return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // The function that gets called when Dropzone is initialized. You
+ // can (and should) setup event listeners inside this function.
+
+ }, {
+ key: "init",
+ value: function init() {
+ var _this3 = this;
+
+ // In case it isn't set already
+ if (this.element.tagName === "form") {
+ this.element.setAttribute("enctype", "multipart/form-data");
+ }
+
+ if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
+ this.element.appendChild(Dropzone.createElement("
" + this.options.dictDefaultMessage + "
"));
+ }
+
+ if (this.clickableElements.length) {
+ var setupHiddenFileInput = function setupHiddenFileInput() {
+ if (_this3.hiddenFileInput) {
+ _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
+ }
+ _this3.hiddenFileInput = document.createElement("input");
+ _this3.hiddenFileInput.setAttribute("type", "file");
+ if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
+ _this3.hiddenFileInput.setAttribute("multiple", "multiple");
+ }
+ _this3.hiddenFileInput.className = "dz-hidden-input";
+
+ if (_this3.options.acceptedFiles !== null) {
+ _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles);
+ }
+ if (_this3.options.capture !== null) {
+ _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture);
+ }
+
+ // Not setting `display="none"` because some browsers don't accept clicks
+ // on elements that aren't displayed.
+ _this3.hiddenFileInput.style.visibility = "hidden";
+ _this3.hiddenFileInput.style.position = "absolute";
+ _this3.hiddenFileInput.style.top = "0";
+ _this3.hiddenFileInput.style.left = "0";
+ _this3.hiddenFileInput.style.height = "0";
+ _this3.hiddenFileInput.style.width = "0";
+ document.querySelector(_this3.options.hiddenInputContainer).appendChild(_this3.hiddenFileInput);
+ return _this3.hiddenFileInput.addEventListener("change", function () {
+ var files = _this3.hiddenFileInput.files;
+
+ if (files.length) {
+ for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
+ var _ref9;
+
+ if (_isArray10) {
+ if (_i10 >= _iterator10.length) break;
+ _ref9 = _iterator10[_i10++];
+ } else {
+ _i10 = _iterator10.next();
+ if (_i10.done) break;
+ _ref9 = _i10.value;
+ }
+
+ var file = _ref9;
+
+ _this3.addFile(file);
+ }
+ }
+ _this3.emit("addedfiles", files);
+ return setupHiddenFileInput();
+ });
+ };
+ setupHiddenFileInput();
+ }
+
+ this.URL = window.URL !== null ? window.URL : window.webkitURL;
+
+ // Setup all event listeners on the Dropzone object itself.
+ // They're not in @setupEventListeners() because they shouldn't be removed
+ // again when the dropzone gets disabled.
+ for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
+ var _ref10;
+
+ if (_isArray11) {
+ if (_i11 >= _iterator11.length) break;
+ _ref10 = _iterator11[_i11++];
+ } else {
+ _i11 = _iterator11.next();
+ if (_i11.done) break;
+ _ref10 = _i11.value;
+ }
+
+ var eventName = _ref10;
+
+ this.on(eventName, this.options[eventName]);
+ }
+
+ this.on("uploadprogress", function () {
+ return _this3.updateTotalUploadProgress();
+ });
+
+ this.on("removedfile", function () {
+ return _this3.updateTotalUploadProgress();
+ });
+
+ this.on("canceled", function (file) {
+ return _this3.emit("complete", file);
+ });
+
+ // Emit a `queuecomplete` event if all files finished uploading.
+ this.on("complete", function (file) {
+ if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {
+ // This needs to be deferred so that `queuecomplete` really triggers after `complete`
+ return setTimeout(function () {
+ return _this3.emit("queuecomplete");
+ }, 0);
+ }
+ });
+
+ var noPropagation = function noPropagation(e) {
+ e.stopPropagation();
+ if (e.preventDefault) {
+ return e.preventDefault();
+ } else {
+ return e.returnValue = false;
+ }
+ };
+
+ // Create the listeners
+ this.listeners = [{
+ element: this.element,
+ events: {
+ "dragstart": function dragstart(e) {
+ return _this3.emit("dragstart", e);
+ },
+ "dragenter": function dragenter(e) {
+ noPropagation(e);
+ return _this3.emit("dragenter", e);
+ },
+ "dragover": function dragover(e) {
+ // Makes it possible to drag files from chrome's download bar
+ // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar
+ // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)
+ var efct = void 0;
+ try {
+ efct = e.dataTransfer.effectAllowed;
+ } catch (error) {}
+ e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
+
+ noPropagation(e);
+ return _this3.emit("dragover", e);
+ },
+ "dragleave": function dragleave(e) {
+ return _this3.emit("dragleave", e);
+ },
+ "drop": function drop(e) {
+ noPropagation(e);
+ return _this3.drop(e);
+ },
+ "dragend": function dragend(e) {
+ return _this3.emit("dragend", e);
+ }
+
+ // This is disabled right now, because the browsers don't implement it properly.
+ // "paste": (e) =>
+ // noPropagation e
+ // @paste e
+ } }];
+
+ this.clickableElements.forEach(function (clickableElement) {
+ return _this3.listeners.push({
+ element: clickableElement,
+ events: {
+ "click": function click(evt) {
+ // Only the actual dropzone or the message element should trigger file selection
+ if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) {
+ _this3.hiddenFileInput.click(); // Forward the click
+ }
+ return true;
+ }
+ }
+ });
+ });
+
+ this.enable();
+
+ return this.options.init.call(this);
+ }
+
+ // Not fully tested yet
+
+ }, {
+ key: "destroy",
+ value: function destroy() {
+ this.disable();
+ this.removeAllFiles(true);
+ if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {
+ this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
+ this.hiddenFileInput = null;
+ }
+ delete this.element.dropzone;
+ return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
+ }
+ }, {
+ key: "updateTotalUploadProgress",
+ value: function updateTotalUploadProgress() {
+ var totalUploadProgress = void 0;
+ var totalBytesSent = 0;
+ var totalBytes = 0;
+
+ var activeFiles = this.getActiveFiles();
+
+ if (activeFiles.length) {
+ for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
+ var _ref11;
+
+ if (_isArray12) {
+ if (_i12 >= _iterator12.length) break;
+ _ref11 = _iterator12[_i12++];
+ } else {
+ _i12 = _iterator12.next();
+ if (_i12.done) break;
+ _ref11 = _i12.value;
+ }
+
+ var file = _ref11;
+
+ totalBytesSent += file.upload.bytesSent;
+ totalBytes += file.upload.total;
+ }
+ totalUploadProgress = 100 * totalBytesSent / totalBytes;
+ } else {
+ totalUploadProgress = 100;
+ }
+
+ return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
+ }
+
+ // @options.paramName can be a function taking one parameter rather than a string.
+ // A parameter name for a file is obtained simply by calling this with an index number.
+
+ }, {
+ key: "_getParamName",
+ value: function _getParamName(n) {
+ if (typeof this.options.paramName === "function") {
+ return this.options.paramName(n);
+ } else {
+ return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
+ }
+ }
+
+ // If @options.renameFile is a function,
+ // the function will be used to rename the file.name before appending it to the formData
+
+ }, {
+ key: "_renameFile",
+ value: function _renameFile(file) {
+ if (typeof this.options.renameFile !== "function") {
+ return file.name;
+ }
+ return this.options.renameFile(file);
+ }
+
+ // Returns a form that can be used as fallback if the browser does not support DragnDrop
+ //
+ // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
+ // This code has to pass in IE7 :(
+
+ }, {
+ key: "getFallbackForm",
+ value: function getFallbackForm() {
+ var existingFallback = void 0,
+ form = void 0;
+ if (existingFallback = this.getExistingFallback()) {
+ return existingFallback;
+ }
+
+ var fieldsString = "
";
+ if (this.options.dictFallbackText) {
+ fieldsString += "
" + this.options.dictFallbackText + "
";
+ }
+ fieldsString += "
";
+
+ var fields = Dropzone.createElement(fieldsString);
+ if (this.element.tagName !== "FORM") {
+ form = Dropzone.createElement("");
+ form.appendChild(fields);
+ } else {
+ // Make sure that the enctype and method attributes are set properly
+ this.element.setAttribute("enctype", "multipart/form-data");
+ this.element.setAttribute("method", this.options.method);
+ }
+ return form != null ? form : fields;
+ }
+
+ // Returns the fallback elements if they exist already
+ //
+ // This code has to pass in IE7 :(
+
+ }, {
+ key: "getExistingFallback",
+ value: function getExistingFallback() {
+ var getFallback = function getFallback(elements) {
+ for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {
+ var _ref12;
+
+ if (_isArray13) {
+ if (_i13 >= _iterator13.length) break;
+ _ref12 = _iterator13[_i13++];
+ } else {
+ _i13 = _iterator13.next();
+ if (_i13.done) break;
+ _ref12 = _i13.value;
+ }
+
+ var el = _ref12;
+
+ if (/(^| )fallback($| )/.test(el.className)) {
+ return el;
+ }
+ }
+ };
+
+ var _arr = ["div", "form"];
+ for (var _i14 = 0; _i14 < _arr.length; _i14++) {
+ var tagName = _arr[_i14];
+ var fallback;
+ if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
+ return fallback;
+ }
+ }
+ }
+
+ // Activates all listeners stored in @listeners
+
+ }, {
+ key: "setupEventListeners",
+ value: function setupEventListeners() {
+ return this.listeners.map(function (elementListeners) {
+ return function () {
+ var result = [];
+ for (var event in elementListeners.events) {
+ var listener = elementListeners.events[event];
+ result.push(elementListeners.element.addEventListener(event, listener, false));
+ }
+ return result;
+ }();
+ });
+ }
+
+ // Deactivates all listeners stored in @listeners
+
+ }, {
+ key: "removeEventListeners",
+ value: function removeEventListeners() {
+ return this.listeners.map(function (elementListeners) {
+ return function () {
+ var result = [];
+ for (var event in elementListeners.events) {
+ var listener = elementListeners.events[event];
+ result.push(elementListeners.element.removeEventListener(event, listener, false));
+ }
+ return result;
+ }();
+ });
+ }
+
+ // Removes all event listeners and cancels all files in the queue or being processed.
+
+ }, {
+ key: "disable",
+ value: function disable() {
+ var _this4 = this;
+
+ this.clickableElements.forEach(function (element) {
+ return element.classList.remove("dz-clickable");
+ });
+ this.removeEventListeners();
+ this.disabled = true;
+
+ return this.files.map(function (file) {
+ return _this4.cancelUpload(file);
+ });
+ }
+ }, {
+ key: "enable",
+ value: function enable() {
+ delete this.disabled;
+ this.clickableElements.forEach(function (element) {
+ return element.classList.add("dz-clickable");
+ });
+ return this.setupEventListeners();
+ }
+
+ // Returns a nicely formatted filesize
+
+ }, {
+ key: "filesize",
+ value: function filesize(size) {
+ var selectedSize = 0;
+ var selectedUnit = "b";
+
+ if (size > 0) {
+ var units = ['tb', 'gb', 'mb', 'kb', 'b'];
+
+ for (var i = 0; i < units.length; i++) {
+ var unit = units[i];
+ var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
+
+ if (size >= cutoff) {
+ selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
+ selectedUnit = unit;
+ break;
+ }
+ }
+
+ selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits
+ }
+
+ return "" + selectedSize + " " + this.options.dictFileSizeUnits[selectedUnit];
+ }
+
+ // Adds or removes the `dz-max-files-reached` class from the form.
+
+ }, {
+ key: "_updateMaxFilesReachedClass",
+ value: function _updateMaxFilesReachedClass() {
+ if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
+ if (this.getAcceptedFiles().length === this.options.maxFiles) {
+ this.emit('maxfilesreached', this.files);
+ }
+ return this.element.classList.add("dz-max-files-reached");
+ } else {
+ return this.element.classList.remove("dz-max-files-reached");
+ }
+ }
+ }, {
+ key: "drop",
+ value: function drop(e) {
+ if (!e.dataTransfer) {
+ return;
+ }
+ this.emit("drop", e);
+
+ var files = e.dataTransfer.files;
+
+ this.emit("addedfiles", files);
+
+ // Even if it's a folder, files.length will contain the folders.
+ if (files.length) {
+ var items = e.dataTransfer.items;
+
+ if (items && items.length && items[0].webkitGetAsEntry != null) {
+ // The browser supports dropping of folders, so handle items instead of files
+ this._addFilesFromItems(items);
+ } else {
+ this.handleFiles(files);
+ }
+ }
+ }
+ }, {
+ key: "paste",
+ value: function paste(e) {
+ if (__guard__(e != null ? e.clipboardData : undefined, function (x) {
+ return x.items;
+ }) == null) {
+ return;
+ }
+
+ this.emit("paste", e);
+ var items = e.clipboardData.items;
+
+
+ if (items.length) {
+ return this._addFilesFromItems(items);
+ }
+ }
+ }, {
+ key: "handleFiles",
+ value: function handleFiles(files) {
+ for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {
+ var _ref13;
+
+ if (_isArray14) {
+ if (_i15 >= _iterator14.length) break;
+ _ref13 = _iterator14[_i15++];
+ } else {
+ _i15 = _iterator14.next();
+ if (_i15.done) break;
+ _ref13 = _i15.value;
+ }
+
+ var file = _ref13;
+
+ this.addFile(file);
+ }
+ }
+
+ // When a folder is dropped (or files are pasted), items must be handled
+ // instead of files.
+
+ }, {
+ key: "_addFilesFromItems",
+ value: function _addFilesFromItems(items) {
+ var _this5 = this;
+
+ return function () {
+ var result = [];
+ for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {
+ var _ref14;
+
+ if (_isArray15) {
+ if (_i16 >= _iterator15.length) break;
+ _ref14 = _iterator15[_i16++];
+ } else {
+ _i16 = _iterator15.next();
+ if (_i16.done) break;
+ _ref14 = _i16.value;
+ }
+
+ var item = _ref14;
+
+ var entry;
+ if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {
+ if (entry.isFile) {
+ result.push(_this5.addFile(item.getAsFile()));
+ } else if (entry.isDirectory) {
+ // Append all files from that directory to files
+ result.push(_this5._addFilesFromDirectory(entry, entry.name));
+ } else {
+ result.push(undefined);
+ }
+ } else if (item.getAsFile != null) {
+ if (item.kind == null || item.kind === "file") {
+ result.push(_this5.addFile(item.getAsFile()));
+ } else {
+ result.push(undefined);
+ }
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+ }();
+ }
+
+ // Goes through the directory, and adds each file it finds recursively
+
+ }, {
+ key: "_addFilesFromDirectory",
+ value: function _addFilesFromDirectory(directory, path) {
+ var _this6 = this;
+
+ var dirReader = directory.createReader();
+
+ var errorHandler = function errorHandler(error) {
+ return __guardMethod__(console, 'log', function (o) {
+ return o.log(error);
+ });
+ };
+
+ var readEntries = function readEntries() {
+ return dirReader.readEntries(function (entries) {
+ if (entries.length > 0) {
+ for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {
+ var _ref15;
+
+ if (_isArray16) {
+ if (_i17 >= _iterator16.length) break;
+ _ref15 = _iterator16[_i17++];
+ } else {
+ _i17 = _iterator16.next();
+ if (_i17.done) break;
+ _ref15 = _i17.value;
+ }
+
+ var entry = _ref15;
+
+ if (entry.isFile) {
+ entry.file(function (file) {
+ if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
+ return;
+ }
+ file.fullPath = path + "/" + file.name;
+ return _this6.addFile(file);
+ });
+ } else if (entry.isDirectory) {
+ _this6._addFilesFromDirectory(entry, path + "/" + entry.name);
+ }
+ }
+
+ // Recursively call readEntries() again, since browser only handle
+ // the first 100 entries.
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries
+ readEntries();
+ }
+ return null;
+ }, errorHandler);
+ };
+
+ return readEntries();
+ }
+
+ // If `done()` is called without argument the file is accepted
+ // If you call it with an error message, the file is rejected
+ // (This allows for asynchronous validation)
+ //
+ // This function checks the filesize, and if the file.type passes the
+ // `acceptedFiles` check.
+
+ }, {
+ key: "accept",
+ value: function accept(file, done) {
+ if (file.size > this.options.maxFilesize * 1024 * 1024) {
+ return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
+ } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
+ return done(this.options.dictInvalidFileType);
+ } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
+ done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
+ return this.emit("maxfilesexceeded", file);
+ } else {
+ return this.options.accept.call(this, file, done);
+ }
+ }
+ }, {
+ key: "addFile",
+ value: function addFile(file) {
+ var _this7 = this;
+
+ file.upload = {
+ uuid: Dropzone.uuidv4(),
+ progress: 0,
+ // Setting the total upload size to file.size for the beginning
+ // It's actual different than the size to be transmitted.
+ total: file.size,
+ bytesSent: 0,
+ filename: this._renameFile(file),
+ chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),
+ totalChunkCount: Math.ceil(file.size / this.options.chunkSize)
+ };
+ this.files.push(file);
+
+ file.status = Dropzone.ADDED;
+
+ this.emit("addedfile", file);
+
+ this._enqueueThumbnail(file);
+
+ return this.accept(file, function (error) {
+ if (error) {
+ file.accepted = false;
+ _this7._errorProcessing([file], error); // Will set the file.status
+ } else {
+ file.accepted = true;
+ if (_this7.options.autoQueue) {
+ _this7.enqueueFile(file);
+ } // Will set .accepted = true
+ }
+ return _this7._updateMaxFilesReachedClass();
+ });
+ }
+
+ // Wrapper for enqueueFile
+
+ }, {
+ key: "enqueueFiles",
+ value: function enqueueFiles(files) {
+ for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {
+ var _ref16;
+
+ if (_isArray17) {
+ if (_i18 >= _iterator17.length) break;
+ _ref16 = _iterator17[_i18++];
+ } else {
+ _i18 = _iterator17.next();
+ if (_i18.done) break;
+ _ref16 = _i18.value;
+ }
+
+ var file = _ref16;
+
+ this.enqueueFile(file);
+ }
+ return null;
+ }
+ }, {
+ key: "enqueueFile",
+ value: function enqueueFile(file) {
+ var _this8 = this;
+
+ if (file.status === Dropzone.ADDED && file.accepted === true) {
+ file.status = Dropzone.QUEUED;
+ if (this.options.autoProcessQueue) {
+ return setTimeout(function () {
+ return _this8.processQueue();
+ }, 0); // Deferring the call
+ }
+ } else {
+ throw new Error("This file can't be queued because it has already been processed or was rejected.");
+ }
+ }
+ }, {
+ key: "_enqueueThumbnail",
+ value: function _enqueueThumbnail(file) {
+ var _this9 = this;
+
+ if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
+ this._thumbnailQueue.push(file);
+ return setTimeout(function () {
+ return _this9._processThumbnailQueue();
+ }, 0); // Deferring the call
+ }
+ }
+ }, {
+ key: "_processThumbnailQueue",
+ value: function _processThumbnailQueue() {
+ var _this10 = this;
+
+ if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
+ return;
+ }
+
+ this._processingThumbnail = true;
+ var file = this._thumbnailQueue.shift();
+ return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {
+ _this10.emit("thumbnail", file, dataUrl);
+ _this10._processingThumbnail = false;
+ return _this10._processThumbnailQueue();
+ });
+ }
+
+ // Can be called by the user to remove a file
+
+ }, {
+ key: "removeFile",
+ value: function removeFile(file) {
+ if (file.status === Dropzone.UPLOADING) {
+ this.cancelUpload(file);
+ }
+ this.files = without(this.files, file);
+
+ this.emit("removedfile", file);
+ if (this.files.length === 0) {
+ return this.emit("reset");
+ }
+ }
+
+ // Removes all files that aren't currently processed from the list
+
+ }, {
+ key: "removeAllFiles",
+ value: function removeAllFiles(cancelIfNecessary) {
+ // Create a copy of files since removeFile() changes the @files array.
+ if (cancelIfNecessary == null) {
+ cancelIfNecessary = false;
+ }
+ for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {
+ var _ref17;
+
+ if (_isArray18) {
+ if (_i19 >= _iterator18.length) break;
+ _ref17 = _iterator18[_i19++];
+ } else {
+ _i19 = _iterator18.next();
+ if (_i19.done) break;
+ _ref17 = _i19.value;
+ }
+
+ var file = _ref17;
+
+ if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
+ this.removeFile(file);
+ }
+ }
+ return null;
+ }
+
+ // Resizes an image before it gets sent to the server. This function is the default behavior of
+ // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with
+ // the resized blob.
+
+ }, {
+ key: "resizeImage",
+ value: function resizeImage(file, width, height, resizeMethod, callback) {
+ var _this11 = this;
+
+ return this.createThumbnail(file, width, height, resizeMethod, false, function (dataUrl, canvas) {
+ if (canvas == null) {
+ // The image has not been resized
+ return callback(file);
+ } else {
+ var resizeMimeType = _this11.options.resizeMimeType;
+
+ if (resizeMimeType == null) {
+ resizeMimeType = file.type;
+ }
+ var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);
+ if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {
+ // Now add the original EXIF information
+ resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
+ }
+ return callback(Dropzone.dataURItoBlob(resizedDataURL));
+ }
+ });
+ }
+ }, {
+ key: "createThumbnail",
+ value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {
+ var _this12 = this;
+
+ var fileReader = new FileReader();
+
+ fileReader.onload = function () {
+
+ file.dataURL = fileReader.result;
+
+ // Don't bother creating a thumbnail for SVG images since they're vector
+ if (file.type === "image/svg+xml") {
+ if (callback != null) {
+ callback(fileReader.result);
+ }
+ return;
+ }
+
+ return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
+ };
+
+ return fileReader.readAsDataURL(file);
+ }
+ }, {
+ key: "createThumbnailFromUrl",
+ value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
+ var _this13 = this;
+
+ // Not using `new Image` here because of a bug in latest Chrome versions.
+ // See https://github.com/enyo/dropzone/pull/226
+ var img = document.createElement("img");
+
+ if (crossOrigin) {
+ img.crossOrigin = crossOrigin;
+ }
+
+ img.onload = function () {
+ var loadExif = function loadExif(callback) {
+ return callback(1);
+ };
+ if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {
+ loadExif = function loadExif(callback) {
+ return EXIF.getData(img, function () {
+ return callback(EXIF.getTag(this, 'Orientation'));
+ });
+ };
+ }
+
+ return loadExif(function (orientation) {
+ file.width = img.width;
+ file.height = img.height;
+
+ var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);
+
+ var canvas = document.createElement("canvas");
+ var ctx = canvas.getContext("2d");
+
+ canvas.width = resizeInfo.trgWidth;
+ canvas.height = resizeInfo.trgHeight;
+
+ if (orientation > 4) {
+ canvas.width = resizeInfo.trgHeight;
+ canvas.height = resizeInfo.trgWidth;
+ }
+
+ switch (orientation) {
+ case 2:
+ // horizontal flip
+ ctx.translate(canvas.width, 0);
+ ctx.scale(-1, 1);
+ break;
+ case 3:
+ // 180° rotate left
+ ctx.translate(canvas.width, canvas.height);
+ ctx.rotate(Math.PI);
+ break;
+ case 4:
+ // vertical flip
+ ctx.translate(0, canvas.height);
+ ctx.scale(1, -1);
+ break;
+ case 5:
+ // vertical flip + 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.scale(1, -1);
+ break;
+ case 6:
+ // 90° rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.translate(0, -canvas.height);
+ break;
+ case 7:
+ // horizontal flip + 90 rotate right
+ ctx.rotate(0.5 * Math.PI);
+ ctx.translate(canvas.width, -canvas.height);
+ ctx.scale(-1, 1);
+ break;
+ case 8:
+ // 90° rotate left
+ ctx.rotate(-0.5 * Math.PI);
+ ctx.translate(-canvas.width, 0);
+ break;
+ }
+
+ // This is a bugfix for iOS' scaling bug.
+ 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);
+
+ var thumbnail = canvas.toDataURL("image/png");
+
+ if (callback != null) {
+ return callback(thumbnail, canvas);
+ }
+ });
+ };
+
+ if (callback != null) {
+ img.onerror = callback;
+ }
+
+ return img.src = file.dataURL;
+ }
+
+ // Goes through the queue and processes files if there aren't too many already.
+
+ }, {
+ key: "processQueue",
+ value: function processQueue() {
+ var parallelUploads = this.options.parallelUploads;
+
+ var processingLength = this.getUploadingFiles().length;
+ var i = processingLength;
+
+ // There are already at least as many files uploading than should be
+ if (processingLength >= parallelUploads) {
+ return;
+ }
+
+ var queuedFiles = this.getQueuedFiles();
+
+ if (!(queuedFiles.length > 0)) {
+ return;
+ }
+
+ if (this.options.uploadMultiple) {
+ // The files should be uploaded in one request
+ return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
+ } else {
+ while (i < parallelUploads) {
+ if (!queuedFiles.length) {
+ return;
+ } // Nothing left to process
+ this.processFile(queuedFiles.shift());
+ i++;
+ }
+ }
+ }
+
+ // Wrapper for `processFiles`
+
+ }, {
+ key: "processFile",
+ value: function processFile(file) {
+ return this.processFiles([file]);
+ }
+
+ // Loads the file, then calls finishedLoading()
+
+ }, {
+ key: "processFiles",
+ value: function processFiles(files) {
+ for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {
+ var _ref18;
+
+ if (_isArray19) {
+ if (_i20 >= _iterator19.length) break;
+ _ref18 = _iterator19[_i20++];
+ } else {
+ _i20 = _iterator19.next();
+ if (_i20.done) break;
+ _ref18 = _i20.value;
+ }
+
+ var file = _ref18;
+
+ file.processing = true; // Backwards compatibility
+ file.status = Dropzone.UPLOADING;
+
+ this.emit("processing", file);
+ }
+
+ if (this.options.uploadMultiple) {
+ this.emit("processingmultiple", files);
+ }
+
+ return this.uploadFiles(files);
+ }
+ }, {
+ key: "_getFilesWithXhr",
+ value: function _getFilesWithXhr(xhr) {
+ var files = void 0;
+ return files = this.files.filter(function (file) {
+ return file.xhr === xhr;
+ }).map(function (file) {
+ return file;
+ });
+ }
+
+ // Cancels the file upload and sets the status to CANCELED
+ // **if** the file is actually being uploaded.
+ // If it's still in the queue, the file is being removed from it and the status
+ // set to CANCELED.
+
+ }, {
+ key: "cancelUpload",
+ value: function cancelUpload(file) {
+ if (file.status === Dropzone.UPLOADING) {
+ var groupedFiles = this._getFilesWithXhr(file.xhr);
+ for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {
+ var _ref19;
+
+ if (_isArray20) {
+ if (_i21 >= _iterator20.length) break;
+ _ref19 = _iterator20[_i21++];
+ } else {
+ _i21 = _iterator20.next();
+ if (_i21.done) break;
+ _ref19 = _i21.value;
+ }
+
+ var groupedFile = _ref19;
+
+ groupedFile.status = Dropzone.CANCELED;
+ }
+ if (typeof file.xhr !== 'undefined') {
+ file.xhr.abort();
+ }
+ for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {
+ var _ref20;
+
+ if (_isArray21) {
+ if (_i22 >= _iterator21.length) break;
+ _ref20 = _iterator21[_i22++];
+ } else {
+ _i22 = _iterator21.next();
+ if (_i22.done) break;
+ _ref20 = _i22.value;
+ }
+
+ var _groupedFile = _ref20;
+
+ this.emit("canceled", _groupedFile);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("canceledmultiple", groupedFiles);
+ }
+ } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {
+ file.status = Dropzone.CANCELED;
+ this.emit("canceled", file);
+ if (this.options.uploadMultiple) {
+ this.emit("canceledmultiple", [file]);
+ }
+ }
+
+ if (this.options.autoProcessQueue) {
+ return this.processQueue();
+ }
+ }
+ }, {
+ key: "resolveOption",
+ value: function resolveOption(option) {
+ if (typeof option === 'function') {
+ for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
+ args[_key3 - 1] = arguments[_key3];
+ }
+
+ return option.apply(this, args);
+ }
+ return option;
+ }
+ }, {
+ key: "uploadFile",
+ value: function uploadFile(file) {
+ return this.uploadFiles([file]);
+ }
+ }, {
+ key: "uploadFiles",
+ value: function uploadFiles(files) {
+ var _this14 = this;
+
+ this._transformFiles(files, function (transformedFiles) {
+ if (files[0].upload.chunked) {
+ // This file should be sent in chunks!
+
+ // If the chunking option is set, we **know** that there can only be **one** file, since
+ // uploadMultiple is not allowed with this option.
+ var file = files[0];
+ var transformedFile = transformedFiles[0];
+ var startedChunkCount = 0;
+
+ file.upload.chunks = [];
+
+ var handleNextChunk = function handleNextChunk() {
+ var chunkIndex = 0;
+
+ // Find the next item in file.upload.chunks that is not defined yet.
+ while (file.upload.chunks[chunkIndex] !== undefined) {
+ chunkIndex++;
+ }
+
+ // This means, that all chunks have already been started.
+ if (chunkIndex >= file.upload.totalChunkCount) return;
+
+ startedChunkCount++;
+
+ var start = chunkIndex * _this14.options.chunkSize;
+ var end = Math.min(start + _this14.options.chunkSize, file.size);
+
+ var dataBlock = {
+ name: _this14._getParamName(0),
+ data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),
+ filename: file.upload.filename,
+ chunkIndex: chunkIndex
+ };
+
+ file.upload.chunks[chunkIndex] = {
+ file: file,
+ index: chunkIndex,
+ dataBlock: dataBlock, // In case we want to retry.
+ status: Dropzone.UPLOADING,
+ progress: 0,
+ retries: 0 // The number of times this block has been retried.
+ };
+
+ _this14._uploadData(files, [dataBlock]);
+ };
+
+ file.upload.finishedChunkUpload = function (chunk) {
+ var allFinished = true;
+ chunk.status = Dropzone.SUCCESS;
+
+ // Clear the data from the chunk
+ chunk.dataBlock = null;
+
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ if (file.upload.chunks[i] === undefined) {
+ return handleNextChunk();
+ }
+ if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {
+ allFinished = false;
+ }
+ }
+
+ if (allFinished) {
+ _this14.options.chunksUploaded(file, function () {
+ _this14._finished(files, '', null);
+ });
+ }
+ };
+
+ if (_this14.options.parallelChunkUploads) {
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ handleNextChunk();
+ }
+ } else {
+ handleNextChunk();
+ }
+ } else {
+ var dataBlocks = [];
+ for (var _i23 = 0; _i23 < files.length; _i23++) {
+ dataBlocks[_i23] = {
+ name: _this14._getParamName(_i23),
+ data: transformedFiles[_i23],
+ filename: files[_i23].upload.filename
+ };
+ }
+ _this14._uploadData(files, dataBlocks);
+ }
+ });
+ }
+
+ /// Returns the right chunk for given file and xhr
+
+ }, {
+ key: "_getChunk",
+ value: function _getChunk(file, xhr) {
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {
+ return file.upload.chunks[i];
+ }
+ }
+ }
+
+ // This function actually uploads the file(s) to the server.
+ // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed
+ // files, or individual chunks for chunked upload).
+
+ }, {
+ key: "_uploadData",
+ value: function _uploadData(files, dataBlocks) {
+ var _this15 = this;
+
+ var xhr = new XMLHttpRequest();
+
+ // Put the xhr object in the file objects to be able to reference it later.
+ for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {
+ var _ref21;
+
+ if (_isArray22) {
+ if (_i24 >= _iterator22.length) break;
+ _ref21 = _iterator22[_i24++];
+ } else {
+ _i24 = _iterator22.next();
+ if (_i24.done) break;
+ _ref21 = _i24.value;
+ }
+
+ var file = _ref21;
+
+ file.xhr = xhr;
+ }
+ if (files[0].upload.chunked) {
+ // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk
+ files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;
+ }
+
+ var method = this.resolveOption(this.options.method, files);
+ var url = this.resolveOption(this.options.url, files);
+ xhr.open(method, url, true);
+
+ // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8
+ xhr.timeout = this.resolveOption(this.options.timeout, files);
+
+ // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
+ xhr.withCredentials = !!this.options.withCredentials;
+
+ xhr.onload = function (e) {
+ _this15._finishedUploading(files, xhr, e);
+ };
+
+ xhr.onerror = function () {
+ _this15._handleUploadError(files, xhr);
+ };
+
+ // Some browsers do not have the .upload property
+ var progressObj = xhr.upload != null ? xhr.upload : xhr;
+ progressObj.onprogress = function (e) {
+ return _this15._updateFilesUploadProgress(files, xhr, e);
+ };
+
+ var headers = {
+ "Accept": "application/json",
+ "Cache-Control": "no-cache",
+ "X-Requested-With": "XMLHttpRequest"
+ };
+
+ if (this.options.headers) {
+ Dropzone.extend(headers, this.options.headers);
+ }
+
+ for (var headerName in headers) {
+ var headerValue = headers[headerName];
+ if (headerValue) {
+ xhr.setRequestHeader(headerName, headerValue);
+ }
+ }
+
+ var formData = new FormData();
+
+ // Adding all @options parameters
+ if (this.options.params) {
+ var additionalParams = this.options.params;
+ if (typeof additionalParams === 'function') {
+ additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);
+ }
+
+ for (var key in additionalParams) {
+ var value = additionalParams[key];
+ formData.append(key, value);
+ }
+ }
+
+ // Let the user add additional data if necessary
+ for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {
+ var _ref22;
+
+ if (_isArray23) {
+ if (_i25 >= _iterator23.length) break;
+ _ref22 = _iterator23[_i25++];
+ } else {
+ _i25 = _iterator23.next();
+ if (_i25.done) break;
+ _ref22 = _i25.value;
+ }
+
+ var _file = _ref22;
+
+ this.emit("sending", _file, xhr, formData);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("sendingmultiple", files, xhr, formData);
+ }
+
+ this._addFormElementData(formData);
+
+ // Finally add the files
+ // Has to be last because some servers (eg: S3) expect the file to be the last parameter
+ for (var i = 0; i < dataBlocks.length; i++) {
+ var dataBlock = dataBlocks[i];
+ formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
+ }
+
+ this.submitRequest(xhr, formData, files);
+ }
+
+ // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.
+
+ }, {
+ key: "_transformFiles",
+ value: function _transformFiles(files, done) {
+ var _this16 = this;
+
+ var transformedFiles = [];
+ // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.
+ var doneCounter = 0;
+
+ var _loop = function _loop(i) {
+ _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {
+ transformedFiles[i] = transformedFile;
+ if (++doneCounter === files.length) {
+ done(transformedFiles);
+ }
+ });
+ };
+
+ for (var i = 0; i < files.length; i++) {
+ _loop(i);
+ }
+ }
+
+ // Takes care of adding other input elements of the form to the AJAX request
+
+ }, {
+ key: "_addFormElementData",
+ value: function _addFormElementData(formData) {
+ // Take care of other input elements
+ if (this.element.tagName === "FORM") {
+ for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {
+ var _ref23;
+
+ if (_isArray24) {
+ if (_i26 >= _iterator24.length) break;
+ _ref23 = _iterator24[_i26++];
+ } else {
+ _i26 = _iterator24.next();
+ if (_i26.done) break;
+ _ref23 = _i26.value;
+ }
+
+ var input = _ref23;
+
+ var inputName = input.getAttribute("name");
+ var inputType = input.getAttribute("type");
+ if (inputType) inputType = inputType.toLowerCase();
+
+ // If the input doesn't have a name, we can't use it.
+ if (typeof inputName === 'undefined' || inputName === null) continue;
+
+ if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
+ // Possibly multiple values
+ for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {
+ var _ref24;
+
+ if (_isArray25) {
+ if (_i27 >= _iterator25.length) break;
+ _ref24 = _iterator25[_i27++];
+ } else {
+ _i27 = _iterator25.next();
+ if (_i27.done) break;
+ _ref24 = _i27.value;
+ }
+
+ var option = _ref24;
+
+ if (option.selected) {
+ formData.append(inputName, option.value);
+ }
+ }
+ } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) {
+ formData.append(inputName, input.value);
+ }
+ }
+ }
+ }
+
+ // Invoked when there is new progress information about given files.
+ // If e is not provided, it is assumed that the upload is finished.
+
+ }, {
+ key: "_updateFilesUploadProgress",
+ value: function _updateFilesUploadProgress(files, xhr, e) {
+ var progress = void 0;
+ if (typeof e !== 'undefined') {
+ progress = 100 * e.loaded / e.total;
+
+ if (files[0].upload.chunked) {
+ var file = files[0];
+ // Since this is a chunked upload, we need to update the appropriate chunk progress.
+ var chunk = this._getChunk(file, xhr);
+ chunk.progress = progress;
+ chunk.total = e.total;
+ chunk.bytesSent = e.loaded;
+ var fileProgress = 0,
+ fileTotal = void 0,
+ fileBytesSent = void 0;
+ file.upload.progress = 0;
+ file.upload.total = 0;
+ file.upload.bytesSent = 0;
+ for (var i = 0; i < file.upload.totalChunkCount; i++) {
+ if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {
+ file.upload.progress += file.upload.chunks[i].progress;
+ file.upload.total += file.upload.chunks[i].total;
+ file.upload.bytesSent += file.upload.chunks[i].bytesSent;
+ }
+ }
+ file.upload.progress = file.upload.progress / file.upload.totalChunkCount;
+ } else {
+ for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {
+ var _ref25;
+
+ if (_isArray26) {
+ if (_i28 >= _iterator26.length) break;
+ _ref25 = _iterator26[_i28++];
+ } else {
+ _i28 = _iterator26.next();
+ if (_i28.done) break;
+ _ref25 = _i28.value;
+ }
+
+ var _file2 = _ref25;
+
+ _file2.upload.progress = progress;
+ _file2.upload.total = e.total;
+ _file2.upload.bytesSent = e.loaded;
+ }
+ }
+ for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {
+ var _ref26;
+
+ if (_isArray27) {
+ if (_i29 >= _iterator27.length) break;
+ _ref26 = _iterator27[_i29++];
+ } else {
+ _i29 = _iterator27.next();
+ if (_i29.done) break;
+ _ref26 = _i29.value;
+ }
+
+ var _file3 = _ref26;
+
+ this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent);
+ }
+ } else {
+ // Called when the file finished uploading
+
+ var allFilesFinished = true;
+
+ progress = 100;
+
+ for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {
+ var _ref27;
+
+ if (_isArray28) {
+ if (_i30 >= _iterator28.length) break;
+ _ref27 = _iterator28[_i30++];
+ } else {
+ _i30 = _iterator28.next();
+ if (_i30.done) break;
+ _ref27 = _i30.value;
+ }
+
+ var _file4 = _ref27;
+
+ if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {
+ allFilesFinished = false;
+ }
+ _file4.upload.progress = progress;
+ _file4.upload.bytesSent = _file4.upload.total;
+ }
+
+ // Nothing to do, all files already at 100%
+ if (allFilesFinished) {
+ return;
+ }
+
+ for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {
+ var _ref28;
+
+ if (_isArray29) {
+ if (_i31 >= _iterator29.length) break;
+ _ref28 = _iterator29[_i31++];
+ } else {
+ _i31 = _iterator29.next();
+ if (_i31.done) break;
+ _ref28 = _i31.value;
+ }
+
+ var _file5 = _ref28;
+
+ this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent);
+ }
+ }
+ }
+ }, {
+ key: "_finishedUploading",
+ value: function _finishedUploading(files, xhr, e) {
+ var response = void 0;
+
+ if (files[0].status === Dropzone.CANCELED) {
+ return;
+ }
+
+ if (xhr.readyState !== 4) {
+ return;
+ }
+
+ if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {
+ response = xhr.responseText;
+
+ if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
+ try {
+ response = JSON.parse(response);
+ } catch (error) {
+ e = error;
+ response = "Invalid JSON response from server.";
+ }
+ }
+ }
+
+ this._updateFilesUploadProgress(files);
+
+ if (!(200 <= xhr.status && xhr.status < 300)) {
+ this._handleUploadError(files, xhr, response);
+ } else {
+ if (files[0].upload.chunked) {
+ files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));
+ } else {
+ this._finished(files, response, e);
+ }
+ }
+ }
+ }, {
+ key: "_handleUploadError",
+ value: function _handleUploadError(files, xhr, response) {
+ if (files[0].status === Dropzone.CANCELED) {
+ return;
+ }
+
+ if (files[0].upload.chunked && this.options.retryChunks) {
+ var chunk = this._getChunk(files[0], xhr);
+ if (chunk.retries++ < this.options.retryChunksLimit) {
+ this._uploadData(files, [chunk.dataBlock]);
+ return;
+ } else {
+ console.warn('Retried this chunk too often. Giving up.');
+ }
+ }
+
+ for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {
+ var _ref29;
+
+ if (_isArray30) {
+ if (_i32 >= _iterator30.length) break;
+ _ref29 = _iterator30[_i32++];
+ } else {
+ _i32 = _iterator30.next();
+ if (_i32.done) break;
+ _ref29 = _i32.value;
+ }
+
+ var file = _ref29;
+
+ this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr);
+ }
+ }
+ }, {
+ key: "submitRequest",
+ value: function submitRequest(xhr, formData, files) {
+ xhr.send(formData);
+ }
+
+ // Called internally when processing is finished.
+ // Individual callbacks have to be called in the appropriate sections.
+
+ }, {
+ key: "_finished",
+ value: function _finished(files, responseText, e) {
+ for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {
+ var _ref30;
+
+ if (_isArray31) {
+ if (_i33 >= _iterator31.length) break;
+ _ref30 = _iterator31[_i33++];
+ } else {
+ _i33 = _iterator31.next();
+ if (_i33.done) break;
+ _ref30 = _i33.value;
+ }
+
+ var file = _ref30;
+
+ file.status = Dropzone.SUCCESS;
+ this.emit("success", file, responseText, e);
+ this.emit("complete", file);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("successmultiple", files, responseText, e);
+ this.emit("completemultiple", files);
+ }
+
+ if (this.options.autoProcessQueue) {
+ return this.processQueue();
+ }
+ }
+
+ // Called internally when processing is finished.
+ // Individual callbacks have to be called in the appropriate sections.
+
+ }, {
+ key: "_errorProcessing",
+ value: function _errorProcessing(files, message, xhr) {
+ for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {
+ var _ref31;
+
+ if (_isArray32) {
+ if (_i34 >= _iterator32.length) break;
+ _ref31 = _iterator32[_i34++];
+ } else {
+ _i34 = _iterator32.next();
+ if (_i34.done) break;
+ _ref31 = _i34.value;
+ }
+
+ var file = _ref31;
+
+ file.status = Dropzone.ERROR;
+ this.emit("error", file, message, xhr);
+ this.emit("complete", file);
+ }
+ if (this.options.uploadMultiple) {
+ this.emit("errormultiple", files, message, xhr);
+ this.emit("completemultiple", files);
+ }
+
+ if (this.options.autoProcessQueue) {
+ return this.processQueue();
+ }
+ }
+ }], [{
+ key: "uuidv4",
+ value: function uuidv4() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
+ var r = Math.random() * 16 | 0,
+ v = c === 'x' ? r : r & 0x3 | 0x8;
+ return v.toString(16);
+ });
+ }
+ }]);
+
+ return Dropzone;
+}(Emitter);
+
+Dropzone.initClass();
+
+Dropzone.version = "5.3.0";
+
+// This is a map of options for your different dropzones. Add configurations
+// to this object for your different dropzone elemens.
+//
+// Example:
+//
+// Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };
+//
+// To disable autoDiscover for a specific element, you can set `false` as an option:
+//
+// Dropzone.options.myDisabledElementId = false;
+//
+// And in html:
+//
+//
+Dropzone.options = {};
+
+// Returns the options for an element or undefined if none available.
+Dropzone.optionsForElement = function (element) {
+ // Get the `Dropzone.options.elementId` for this element if it exists
+ if (element.getAttribute("id")) {
+ return Dropzone.options[camelize(element.getAttribute("id"))];
+ } else {
+ return undefined;
+ }
+};
+
+// Holds a list of all dropzone instances
+Dropzone.instances = [];
+
+// Returns the dropzone for given element if any
+Dropzone.forElement = function (element) {
+ if (typeof element === "string") {
+ element = document.querySelector(element);
+ }
+ if ((element != null ? element.dropzone : undefined) == null) {
+ 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.");
+ }
+ return element.dropzone;
+};
+
+// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.
+Dropzone.autoDiscover = true;
+
+// Looks for all .dropzone elements and creates a dropzone for them
+Dropzone.discover = function () {
+ var dropzones = void 0;
+ if (document.querySelectorAll) {
+ dropzones = document.querySelectorAll(".dropzone");
+ } else {
+ dropzones = [];
+ // IE :(
+ var checkElements = function checkElements(elements) {
+ return function () {
+ var result = [];
+ for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {
+ var _ref32;
+
+ if (_isArray33) {
+ if (_i35 >= _iterator33.length) break;
+ _ref32 = _iterator33[_i35++];
+ } else {
+ _i35 = _iterator33.next();
+ if (_i35.done) break;
+ _ref32 = _i35.value;
+ }
+
+ var el = _ref32;
+
+ if (/(^| )dropzone($| )/.test(el.className)) {
+ result.push(dropzones.push(el));
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+ }();
+ };
+ checkElements(document.getElementsByTagName("div"));
+ checkElements(document.getElementsByTagName("form"));
+ }
+
+ return function () {
+ var result = [];
+ for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {
+ var _ref33;
+
+ if (_isArray34) {
+ if (_i36 >= _iterator34.length) break;
+ _ref33 = _iterator34[_i36++];
+ } else {
+ _i36 = _iterator34.next();
+ if (_i36.done) break;
+ _ref33 = _i36.value;
+ }
+
+ var dropzone = _ref33;
+
+ // Create a dropzone unless auto discover has been disabled for specific element
+ if (Dropzone.optionsForElement(dropzone) !== false) {
+ result.push(new Dropzone(dropzone));
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+ }();
+};
+
+// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,
+// but not correctly.
+// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.
+// But what to do when browsers *theoretically* support an API, but crash
+// when using it.
+//
+// This is a list of regular expressions tested against navigator.userAgent
+//
+// ** It should only be used on browser that *do* support the API, but
+// incorrectly **
+//
+Dropzone.blacklistedBrowsers = [
+// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.
+/opera.*(Macintosh|Windows Phone).*version\/12/i];
+
+// Checks if the browser is supported
+Dropzone.isBrowserSupported = function () {
+ var capableBrowser = true;
+
+ if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
+ if (!("classList" in document.createElement("a"))) {
+ capableBrowser = false;
+ } else {
+ // The browser supports the API, but may be blacklisted.
+ for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {
+ var _ref34;
+
+ if (_isArray35) {
+ if (_i37 >= _iterator35.length) break;
+ _ref34 = _iterator35[_i37++];
+ } else {
+ _i37 = _iterator35.next();
+ if (_i37.done) break;
+ _ref34 = _i37.value;
+ }
+
+ var regex = _ref34;
+
+ if (regex.test(navigator.userAgent)) {
+ capableBrowser = false;
+ continue;
+ }
+ }
+ }
+ } else {
+ capableBrowser = false;
+ }
+
+ return capableBrowser;
+};
+
+Dropzone.dataURItoBlob = function (dataURI) {
+ // convert base64 to raw binary data held in a string
+ // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
+ var byteString = atob(dataURI.split(',')[1]);
+
+ // separate out the mime component
+ var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
+
+ // write the bytes of the string to an ArrayBuffer
+ var ab = new ArrayBuffer(byteString.length);
+ var ia = new Uint8Array(ab);
+ for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
+ ia[i] = byteString.charCodeAt(i);
+ }
+
+ // write the ArrayBuffer to a blob
+ return new Blob([ab], { type: mimeString });
+};
+
+// Returns an array without the rejected item
+var without = function without(list, rejectedItem) {
+ return list.filter(function (item) {
+ return item !== rejectedItem;
+ }).map(function (item) {
+ return item;
+ });
+};
+
+// abc-def_ghi -> abcDefGhi
+var camelize = function camelize(str) {
+ return str.replace(/[\-_](\w)/g, function (match) {
+ return match.charAt(1).toUpperCase();
+ });
+};
+
+// Creates an element from string
+Dropzone.createElement = function (string) {
+ var div = document.createElement("div");
+ div.innerHTML = string;
+ return div.childNodes[0];
+};
+
+// Tests if given element is inside (or simply is) the container
+Dropzone.elementInside = function (element, container) {
+ if (element === container) {
+ return true;
+ } // Coffeescript doesn't support do/while loops
+ while (element = element.parentNode) {
+ if (element === container) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Dropzone.getElement = function (el, name) {
+ var element = void 0;
+ if (typeof el === "string") {
+ element = document.querySelector(el);
+ } else if (el.nodeType != null) {
+ element = el;
+ }
+ if (element == null) {
+ throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
+ }
+ return element;
+};
+
+Dropzone.getElements = function (els, name) {
+ var el = void 0,
+ elements = void 0;
+ if (els instanceof Array) {
+ elements = [];
+ try {
+ for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {
+ if (_isArray36) {
+ if (_i38 >= _iterator36.length) break;
+ el = _iterator36[_i38++];
+ } else {
+ _i38 = _iterator36.next();
+ if (_i38.done) break;
+ el = _i38.value;
+ }
+
+ elements.push(this.getElement(el, name));
+ }
+ } catch (e) {
+ elements = null;
+ }
+ } else if (typeof els === "string") {
+ elements = [];
+ for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {
+ if (_isArray37) {
+ if (_i39 >= _iterator37.length) break;
+ el = _iterator37[_i39++];
+ } else {
+ _i39 = _iterator37.next();
+ if (_i39.done) break;
+ el = _i39.value;
+ }
+
+ elements.push(el);
+ }
+ } else if (els.nodeType != null) {
+ elements = [els];
+ }
+
+ if (elements == null || !elements.length) {
+ throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
+ }
+
+ return elements;
+};
+
+// Asks the user the question and calls accepted or rejected accordingly
+//
+// The default implementation just uses `window.confirm` and then calls the
+// appropriate callback.
+Dropzone.confirm = function (question, accepted, rejected) {
+ if (window.confirm(question)) {
+ return accepted();
+ } else if (rejected != null) {
+ return rejected();
+ }
+};
+
+// Validates the mime type like this:
+//
+// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept
+Dropzone.isValidFile = function (file, acceptedFiles) {
+ if (!acceptedFiles) {
+ return true;
+ } // If there are no accepted mime types, it's OK
+ acceptedFiles = acceptedFiles.split(",");
+
+ var mimeType = file.type;
+ var baseMimeType = mimeType.replace(/\/.*$/, "");
+
+ for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {
+ var _ref35;
+
+ if (_isArray38) {
+ if (_i40 >= _iterator38.length) break;
+ _ref35 = _iterator38[_i40++];
+ } else {
+ _i40 = _iterator38.next();
+ if (_i40.done) break;
+ _ref35 = _i40.value;
+ }
+
+ var validType = _ref35;
+
+ validType = validType.trim();
+ if (validType.charAt(0) === ".") {
+ if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
+ return true;
+ }
+ } else if (/\/\*$/.test(validType)) {
+ // This is something like a image/* mime type
+ if (baseMimeType === validType.replace(/\/.*$/, "")) {
+ return true;
+ }
+ } else {
+ if (mimeType === validType) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+};
+
+// Augment jQuery
+if (typeof jQuery !== 'undefined' && jQuery !== null) {
+ jQuery.fn.dropzone = function (options) {
+ return this.each(function () {
+ return new Dropzone(this, options);
+ });
+ };
+}
+
+if (typeof module !== 'undefined' && module !== null) {
+ module.exports = Dropzone;
+} else {
+ window.Dropzone = Dropzone;
+}
+
+// Dropzone file status codes
+Dropzone.ADDED = "added";
+
+Dropzone.QUEUED = "queued";
+// For backwards compatibility. Now, if a file is accepted, it's either queued
+// or uploading.
+Dropzone.ACCEPTED = Dropzone.QUEUED;
+
+Dropzone.UPLOADING = "uploading";
+Dropzone.PROCESSING = Dropzone.UPLOADING; // alias
+
+Dropzone.CANCELED = "canceled";
+Dropzone.ERROR = "error";
+Dropzone.SUCCESS = "success";
+
+/*
+
+ Bugfix for iOS 6 and 7
+ Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
+ based on the work of https://github.com/stomita/ios-imagefile-megapixel
+
+ */
+
+// Detecting vertical squash in loaded image.
+// Fixes a bug which squash image vertically while drawing into canvas for some images.
+// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel
+var detectVerticalSquash = function detectVerticalSquash(img) {
+ var iw = img.naturalWidth;
+ var ih = img.naturalHeight;
+ var canvas = document.createElement("canvas");
+ canvas.width = 1;
+ canvas.height = ih;
+ var ctx = canvas.getContext("2d");
+ ctx.drawImage(img, 0, 0);
+
+ var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),
+ data = _ctx$getImageData.data;
+
+ // search image edge pixel position in case it is squashed vertically.
+
+
+ var sy = 0;
+ var ey = ih;
+ var py = ih;
+ while (py > sy) {
+ var alpha = data[(py - 1) * 4 + 3];
+
+ if (alpha === 0) {
+ ey = py;
+ } else {
+ sy = py;
+ }
+
+ py = ey + sy >> 1;
+ }
+ var ratio = py / ih;
+
+ if (ratio === 0) {
+ return 1;
+ } else {
+ return ratio;
+ }
+};
+
+// A replacement for context.drawImage
+// (args are for source and destination).
+var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
+ var vertSquashRatio = detectVerticalSquash(img);
+ return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
+};
+
+// Based on MinifyJpeg
+// Source: http://www.perry.cz/files/ExifRestorer.js
+// http://elicon.blog57.fc2.com/blog-entry-206.html
+
+var ExifRestore = function () {
+ function ExifRestore() {
+ _classCallCheck(this, ExifRestore);
+ }
+
+ _createClass(ExifRestore, null, [{
+ key: "initClass",
+ value: function initClass() {
+ this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ }
+ }, {
+ key: "encode64",
+ value: function encode64(input) {
+ var output = '';
+ var chr1 = undefined;
+ var chr2 = undefined;
+ var chr3 = '';
+ var enc1 = undefined;
+ var enc2 = undefined;
+ var enc3 = undefined;
+ var enc4 = '';
+ var i = 0;
+ while (true) {
+ chr1 = input[i++];
+ chr2 = input[i++];
+ chr3 = input[i++];
+ enc1 = chr1 >> 2;
+ enc2 = (chr1 & 3) << 4 | chr2 >> 4;
+ enc3 = (chr2 & 15) << 2 | chr3 >> 6;
+ enc4 = chr3 & 63;
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+ output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
+ chr1 = chr2 = chr3 = '';
+ enc1 = enc2 = enc3 = enc4 = '';
+ if (!(i < input.length)) {
+ break;
+ }
+ }
+ return output;
+ }
+ }, {
+ key: "restore",
+ value: function restore(origFileBase64, resizedFileBase64) {
+ if (!origFileBase64.match('data:image/jpeg;base64,')) {
+ return resizedFileBase64;
+ }
+ var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));
+ var segments = this.slice2Segments(rawImage);
+ var image = this.exifManipulation(resizedFileBase64, segments);
+ return "data:image/jpeg;base64," + this.encode64(image);
+ }
+ }, {
+ key: "exifManipulation",
+ value: function exifManipulation(resizedFileBase64, segments) {
+ var exifArray = this.getExifArray(segments);
+ var newImageArray = this.insertExif(resizedFileBase64, exifArray);
+ var aBuffer = new Uint8Array(newImageArray);
+ return aBuffer;
+ }
+ }, {
+ key: "getExifArray",
+ value: function getExifArray(segments) {
+ var seg = undefined;
+ var x = 0;
+ while (x < segments.length) {
+ seg = segments[x];
+ if (seg[0] === 255 & seg[1] === 225) {
+ return seg;
+ }
+ x++;
+ }
+ return [];
+ }
+ }, {
+ key: "insertExif",
+ value: function insertExif(resizedFileBase64, exifArray) {
+ var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');
+ var buf = this.decode64(imageData);
+ var separatePoint = buf.indexOf(255, 3);
+ var mae = buf.slice(0, separatePoint);
+ var ato = buf.slice(separatePoint);
+ var array = mae;
+ array = array.concat(exifArray);
+ array = array.concat(ato);
+ return array;
+ }
+ }, {
+ key: "slice2Segments",
+ value: function slice2Segments(rawImageArray) {
+ var head = 0;
+ var segments = [];
+ while (true) {
+ var length;
+ if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
+ break;
+ }
+ if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
+ head += 2;
+ } else {
+ length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
+ var endPoint = head + length + 2;
+ var seg = rawImageArray.slice(head, endPoint);
+ segments.push(seg);
+ head = endPoint;
+ }
+ if (head > rawImageArray.length) {
+ break;
+ }
+ }
+ return segments;
+ }
+ }, {
+ key: "decode64",
+ value: function decode64(input) {
+ var output = '';
+ var chr1 = undefined;
+ var chr2 = undefined;
+ var chr3 = '';
+ var enc1 = undefined;
+ var enc2 = undefined;
+ var enc3 = undefined;
+ var enc4 = '';
+ var i = 0;
+ var buf = [];
+ // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+ var base64test = /[^A-Za-z0-9\+\/\=]/g;
+ if (base64test.exec(input)) {
+ 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.');
+ }
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
+ while (true) {
+ enc1 = this.KEY_STR.indexOf(input.charAt(i++));
+ enc2 = this.KEY_STR.indexOf(input.charAt(i++));
+ enc3 = this.KEY_STR.indexOf(input.charAt(i++));
+ enc4 = this.KEY_STR.indexOf(input.charAt(i++));
+ chr1 = enc1 << 2 | enc2 >> 4;
+ chr2 = (enc2 & 15) << 4 | enc3 >> 2;
+ chr3 = (enc3 & 3) << 6 | enc4;
+ buf.push(chr1);
+ if (enc3 !== 64) {
+ buf.push(chr2);
+ }
+ if (enc4 !== 64) {
+ buf.push(chr3);
+ }
+ chr1 = chr2 = chr3 = '';
+ enc1 = enc2 = enc3 = enc4 = '';
+ if (!(i < input.length)) {
+ break;
+ }
+ }
+ return buf;
+ }
+ }]);
+
+ return ExifRestore;
+}();
+
+ExifRestore.initClass();
+
+/*
+ * contentloaded.js
+ *
+ * Author: Diego Perini (diego.perini at gmail.com)
+ * Summary: cross-browser wrapper for DOMContentLoaded
+ * Updated: 20101020
+ * License: MIT
+ * Version: 1.2
+ *
+ * URL:
+ * http://javascript.nwbox.com/ContentLoaded/
+ * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
+ */
+
+// @win window reference
+// @fn function reference
+var contentLoaded = function contentLoaded(win, fn) {
+ var done = false;
+ var top = true;
+ var doc = win.document;
+ var root = doc.documentElement;
+ var add = doc.addEventListener ? "addEventListener" : "attachEvent";
+ var rem = doc.addEventListener ? "removeEventListener" : "detachEvent";
+ var pre = doc.addEventListener ? "" : "on";
+ var init = function init(e) {
+ if (e.type === "readystatechange" && doc.readyState !== "complete") {
+ return;
+ }
+ (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
+ if (!done && (done = true)) {
+ return fn.call(win, e.type || e);
+ }
+ };
+
+ var poll = function poll() {
+ try {
+ root.doScroll("left");
+ } catch (e) {
+ setTimeout(poll, 50);
+ return;
+ }
+ return init("poll");
+ };
+
+ if (doc.readyState !== "complete") {
+ if (doc.createEventObject && root.doScroll) {
+ try {
+ top = !win.frameElement;
+ } catch (error) {}
+ if (top) {
+ poll();
+ }
+ }
+ doc[add](pre + "DOMContentLoaded", init, false);
+ doc[add](pre + "readystatechange", init, false);
+ return win[add](pre + "load", init, false);
+ }
+};
+
+// As a single function to be able to write tests.
+Dropzone._autoDiscoverFunction = function () {
+ if (Dropzone.autoDiscover) {
+ return Dropzone.discover();
+ }
+};
+contentLoaded(window, Dropzone._autoDiscoverFunction);
+
+function __guard__(value, transform) {
+ return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;
+}
+function __guardMethod__(obj, methodName, transform) {
+ if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
+ return transform(obj, methodName);
+ } else {
+ return undefined;
+ }
+}
diff --git a/addonstyle/min/basic.min.css b/addonstyle/min/basic.min.css
new file mode 100644
index 0000000..5238d5c
--- /dev/null
+++ b/addonstyle/min/basic.min.css
@@ -0,0 +1 @@
+.dropzone,.dropzone *{box-sizing:border-box}.dropzone{position:relative}.dropzone .dz-preview{position:relative;display:inline-block;width:120px;margin:0.5em}.dropzone .dz-preview .dz-progress{display:block;height:15px;border:1px solid #aaa}.dropzone .dz-preview .dz-progress .dz-upload{display:block;height:100%;width:0;background:green}.dropzone .dz-preview .dz-error-message{color:red;display:none}.dropzone .dz-preview.dz-error .dz-error-message,.dropzone .dz-preview.dz-error .dz-error-mark{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{display:block}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{position:absolute;display:none;left:30px;top:30px;width:54px;height:58px;left:50%;margin-left:-27px}
diff --git a/addonstyle/min/dropzone.min.css b/addonstyle/min/dropzone.min.css
new file mode 100644
index 0000000..d04515e
--- /dev/null
+++ b/addonstyle/min/dropzone.min.css
@@ -0,0 +1 @@
+@-webkit-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-moz-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-moz-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-moz-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:2px solid rgba(0,0,0,0.3);background:white;padding:20px 20px}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:0.5}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom, #eee, #ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:white}.dropzone .dz-preview.dz-image-preview .dz-details{-webkit-transition:opacity 0.2s linear;-moz-transition:opacity 0.2s linear;-ms-transition:opacity 0.2s linear;-o-transition:opacity 0.2s linear;transition:opacity 0.2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,0.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,0.8);background-color:rgba(255,255,255,0.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:rgba(255,255,255,0.4);padding:0 0.4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{-webkit-transform:scale(1.05, 1.05);-moz-transform:scale(1.05, 1.05);-ms-transform:scale(1.05, 1.05);-o-transform:scale(1.05, 1.05);transform:scale(1.05, 1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview .dz-success-mark,.dropzone .dz-preview .dz-error-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-success-mark svg,.dropzone .dz-preview .dz-error-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;-webkit-transition:all 0.2s linear;-moz-transition:all 0.2s linear;-ms-transition:all 0.2s linear;-o-transition:all 0.2s linear;transition:all 0.2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;-webkit-transition:opacity 0.4s ease-in;-moz-transition:opacity 0.4s ease-in;-ms-transition:opacity 0.4s ease-in;-o-transition:opacity 0.4s ease-in;transition:opacity 0.4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;-moz-animation:pulse 6s ease infinite;-ms-animation:pulse 6s ease infinite;-o-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:rgba(255,255,255,0.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(to bottom, #666, #444);position:absolute;top:0;left:0;bottom:0;width:0;-webkit-transition:width 300ms ease-in-out;-moz-transition:width 300ms ease-in-out;-ms-transition:width 300ms ease-in-out;-o-transition:width 300ms ease-in-out;transition:width 300ms ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;-webkit-transition:opacity 0.3s ease;-moz-transition:opacity 0.3s ease;-ms-transition:opacity 0.3s ease;-o-transition:opacity 0.3s ease;transition:opacity 0.3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(to bottom, #be2626, #a92222);padding:0.5em 1.2em;color:white}.dropzone .dz-preview .dz-error-message:after{content:'';position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626}
diff --git a/addonstyle/min/dropzone.min.js b/addonstyle/min/dropzone.min.js
new file mode 100644
index 0000000..4f490c7
--- /dev/null
+++ b/addonstyle/min/dropzone.min.js
@@ -0,0 +1,2 @@
+"use strict";function _possibleConstructorReturn(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function _inherits(a,b){if("function"!=typeof b&&null!==b)throw new TypeError("Super expression must either be null or a function, not "+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}function __guard__(a,b){return void 0!==a&&null!==a?b(a):void 0}function __guardMethod__(a,b,c){return void 0!==a&&null!==a&&"function"==typeof a[b]?c(a,b):void 0}var _createClass=function(){function a(a,b){for(var c=0;c1?c-1:0),e=1;e=f.length)break;h=f[g++];h.apply(this,d)}}return this}},{key:"off",value:function(a,b){if(!this._callbacks||0===arguments.length)return this._callbacks={},this;var c=this._callbacks[a];if(!c)return this;if(1===arguments.length)return delete this._callbacks[a],this;for(var d=0;d=c.length)break;e=c[d++];var f=e;if(/(^| )dz-message($| )/.test(f.className)){a=f,f.className="dz-message";break}}a||(a=b.createElement('
'),this.element.appendChild(a));var g=a.getElementsByTagName("span")[0];return g&&(null!=g.textContent?g.textContent=this.options.dictFallbackMessage:null!=g.innerText&&(g.innerText=this.options.dictFallbackMessage)),this.element.appendChild(this.getFallbackForm())},resize:function(a,b,c,d){var e={srcX:0,srcY:0,srcWidth:a.width,srcHeight:a.height},f=a.width/a.height;null==b&&null==c?(b=e.srcWidth,c=e.srcHeight):null==b?b=c*f:null==c&&(c=b/f),b=Math.min(b,e.srcWidth),c=Math.min(c,e.srcHeight);var g=b/c;if(e.srcWidth>b||e.srcHeight>c)if("crop"===d)f>g?(e.srcHeight=a.height,e.srcWidth=e.srcHeight*g):(e.srcWidth=a.width,e.srcHeight=e.srcWidth/g);else{if("contain"!==d)throw new Error("Unknown resizeMethod '"+d+"'");f>g?c=b/f:b=c*f}return e.srcX=(a.width-e.srcWidth)/2,e.srcY=(a.height-e.srcHeight)/2,e.trgWidth=b,e.trgHeight=c,e},transformFile:function(a,b){return(this.options.resizeWidth||this.options.resizeHeight)&&a.type.match(/image.*/)?this.resizeImage(a,this.options.resizeWidth,this.options.resizeHeight,this.options.resizeMethod,b):b(a)},previewTemplate:'