diff --git a/Makefile b/Makefile index cc333f5..b0d1ce3 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ all: $(OUTPUT_FILES) @rsync -a node_modules/mathjax/es5 build/static/lib/mathjax @rsync -a node_modules/mermaid/dist/mermaid.min.js build/static/lib/ @rsync -a node_modules/jquery/dist/jquery.min.js build/static/lib/ + @rsync -a node_modules/dropzone/dist/min/dropzone* build/static/lib/ $(GO_OUT): $(GO_IN) cd src/go && go build ${LDFLAGS} -o ../../build/notes diff --git a/lib/dropzone.css b/lib/dropzone.css deleted file mode 100644 index 0494d1c..0000000 --- a/lib/dropzone.css +++ /dev/null @@ -1,388 +0,0 @@ -/* - * 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/lib/dropzone.js b/lib/dropzone.js deleted file mode 100644 index 54b3ba6..0000000 --- a/lib/dropzone.js +++ /dev/null @@ -1,3504 +0,0 @@ -"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: 2, - - /** - * 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: 256, - - /** - * 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: "file", - - /** - * Whether thumbnails for images should be generated - */ - createImageThumbnails: true, - - /** - * In MB. When the filename exceeds this limit, the thumbnail will not be generated. - */ - maxThumbnailFilesize: 10, - - /** - * 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: null, - - /** - * **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", - - /** - * 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 Check\n \n \n \n \n \n
\n
\n \n Error\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, "Upload canceled."); - }, - 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(); - - return this.files.map(function (file) { - return _this4.cancelUpload(file); - }); - } - }, { - key: "enable", - value: function enable() { - 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) { - var _this5 = this; - - return files.map(function (file) { - return _this5.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 _this6 = this; - - return function () { - var result = []; - for (var _iterator14 = items, _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 item = _ref13; - - var entry; - if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) { - if (entry.isFile) { - result.push(_this6.addFile(item.getAsFile())); - } else if (entry.isDirectory) { - // Append all files from that directory to files - result.push(_this6._addFilesFromDirectory(entry, entry.name)); - } else { - result.push(undefined); - } - } else if (item.getAsFile != null) { - if (item.kind == null || item.kind === "file") { - result.push(_this6.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 _this7 = 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 _iterator15 = entries, _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 entry = _ref14; - - if (entry.isFile) { - entry.file(function (file) { - if (_this7.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { - return; - } - file.fullPath = path + "/" + file.name; - return _this7.addFile(file); - }); - } else if (entry.isDirectory) { - _this7._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 _this8 = 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; - _this8._errorProcessing([file], error); // Will set the file.status - } else { - file.accepted = true; - if (_this8.options.autoQueue) { - _this8.enqueueFile(file); - } // Will set .accepted = true - } - return _this8._updateMaxFilesReachedClass(); - }); - } - - // Wrapper for enqueueFile - - }, { - key: "enqueueFiles", - value: function enqueueFiles(files) { - for (var _iterator16 = files, _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 file = _ref15; - - this.enqueueFile(file); - } - return null; - } - }, { - key: "enqueueFile", - value: function enqueueFile(file) { - var _this9 = this; - - if (file.status === Dropzone.ADDED && file.accepted === true) { - file.status = Dropzone.QUEUED; - if (this.options.autoProcessQueue) { - return setTimeout(function () { - return _this9.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 _this10 = this; - - if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { - this._thumbnailQueue.push(file); - return setTimeout(function () { - return _this10._processThumbnailQueue(); - }, 0); // Deferring the call - } - } - }, { - key: "_processThumbnailQueue", - value: function _processThumbnailQueue() { - var _this11 = 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) { - _this11.emit("thumbnail", file, dataUrl); - _this11._processingThumbnail = false; - return _this11._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 _iterator17 = this.files.slice(), _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; - - 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 _this12 = 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 = _this12.options.resizeMimeType; - - if (resizeMimeType == null) { - resizeMimeType = file.type; - } - var resizedDataURL = canvas.toDataURL(resizeMimeType, _this12.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 _this13 = 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 _this13.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback); - }; - - return fileReader.readAsDataURL(file); - } - }, { - key: "createThumbnailFromUrl", - value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) { - var _this14 = 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 = _this14.options.resize.call(_this14, 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 _iterator18 = files, _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; - - 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 _iterator19 = groupedFiles, _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 groupedFile = _ref18; - - groupedFile.status = Dropzone.CANCELED; - } - if (typeof file.xhr !== 'undefined') { - file.xhr.abort(); - } - 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; - - 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 _this15 = 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 * _this15.options.chunkSize; - var end = Math.min(start + _this15.options.chunkSize, file.size); - - var dataBlock = { - name: _this15._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. - }; - - _this15._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) { - _this15.options.chunksUploaded(file, function () { - _this15._finished(files, '', null); - }); - } - }; - - if (_this15.options.parallelChunkUploads) { - for (var i = 0; i < file.upload.totalChunkCount; i++) { - handleNextChunk(); - } - } else { - handleNextChunk(); - } - } else { - var dataBlocks = []; - for (var _i22 = 0; _i22 < files.length; _i22++) { - dataBlocks[_i22] = { - name: _this15._getParamName(_i22), - data: transformedFiles[_i22], - filename: files[_i22].upload.filename - }; - } - _this15._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 _this16 = this; - - var xhr = new XMLHttpRequest(); - - // Put the xhr object in the file objects to be able to reference it later. - for (var _iterator21 = files, _isArray21 = true, _i23 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) { - var _ref20; - - if (_isArray21) { - if (_i23 >= _iterator21.length) break; - _ref20 = _iterator21[_i23++]; - } else { - _i23 = _iterator21.next(); - if (_i23.done) break; - _ref20 = _i23.value; - } - - var file = _ref20; - - 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) { - _this16._finishedUploading(files, xhr, e); - }; - - xhr.onerror = function () { - _this16._handleUploadError(files, xhr); - }; - - // Some browsers do not have the .upload property - var progressObj = xhr.upload != null ? xhr.upload : xhr; - progressObj.onprogress = function (e) { - return _this16._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 _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; - - 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 _this17 = 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) { - _this17.options.transformFile.call(_this17, 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 _iterator23 = this.element.querySelectorAll("input, textarea, select, button"), _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 input = _ref22; - - 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 _iterator24 = input.options, _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 option = _ref23; - - 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 _iterator25 = files, _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 _file2 = _ref24; - - _file2.upload.progress = progress; - _file2.upload.total = e.total; - _file2.upload.bytesSent = e.loaded; - } - } - 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 _file3 = _ref25; - - this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent); - } - } else { - // Called when the file finished uploading - - var allFilesFinished = true; - - progress = 100; - - 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 _file4 = _ref26; - - 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 _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 _file5 = _ref27; - - 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 _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 file = _ref28; - - 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 _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; - - 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 _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.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 _iterator32 = elements, _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 el = _ref31; - - 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 _iterator33 = dropzones, _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 dropzone = _ref32; - - // 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 _iterator34 = Dropzone.blacklistedBrowsers, _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 regex = _ref33; - - 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 _iterator35 = els, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) { - if (_isArray35) { - if (_i37 >= _iterator35.length) break; - el = _iterator35[_i37++]; - } else { - _i37 = _iterator35.next(); - if (_i37.done) break; - el = _i37.value; - } - - elements.push(this.getElement(el, name)); - } - } catch (e) { - elements = null; - } - } else if (typeof els === "string") { - elements = []; - for (var _iterator36 = document.querySelectorAll(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(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 _iterator37 = acceptedFiles, _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) { - var _ref34; - - if (_isArray37) { - if (_i39 >= _iterator37.length) break; - _ref34 = _iterator37[_i39++]; - } else { - _i39 = _iterator37.next(); - if (_i39.done) break; - _ref34 = _i39.value; - } - - var validType = _ref34; - - 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/package-lock.json b/package-lock.json index 2d8ef0d..dbdde00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,6 +6,7 @@ "": { "dependencies": { "@fontsource/roboto": "^4.2.0", + "dropzone": "^5.7.6", "jquery": "^3.5.0", "mathjax": "^3.1.2", "mermaid": "^8.9.0", @@ -369,6 +370,11 @@ "node": ">=6.0" } }, + "node_modules/dropzone": { + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.6.tgz", + "integrity": "sha512-z38j+PZsH38rFGOK2rQ877t6c0cPos053fPp3RKaDvCDjAw4KflQQGn7BhCWeFq9Zl1hinB8khPrQdJ6cIBryQ==" + }, "node_modules/entity-decode": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/entity-decode/-/entity-decode-2.0.2.tgz", @@ -960,6 +966,11 @@ "ms": "2.1.2" } }, + "dropzone": { + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.6.tgz", + "integrity": "sha512-z38j+PZsH38rFGOK2rQ877t6c0cPos053fPp3RKaDvCDjAw4KflQQGn7BhCWeFq9Zl1hinB8khPrQdJ6cIBryQ==" + }, "entity-decode": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/entity-decode/-/entity-decode-2.0.2.tgz", diff --git a/package.json b/package.json index f888d3e..d95fe28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "dependencies": { "@fontsource/roboto": "^4.2.0", + "dropzone": "^5.7.6", "jquery": "^3.5.0", "mathjax": "^3.1.2", "mermaid": "^8.9.0", diff --git a/src/templates/index.tmpl b/src/templates/index.tmpl index 2e6291d..876dc10 100755 --- a/src/templates/index.tmpl +++ b/src/templates/index.tmpl @@ -12,7 +12,7 @@ }, true); - + @@ -21,7 +21,7 @@ - +