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