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 if (!_this.options.url) { 1066 throw new Error("No URL provided."); 1067 } 1068 1069 if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) { 1070 throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); 1071 } 1072 1073 if (_this.options.uploadMultiple && _this.options.chunking) { 1074 throw new Error('You cannot set both: uploadMultiple and chunking.'); 1075 } 1076 1077 // Backwards compatibility 1078 if (_this.options.acceptedMimeTypes) { 1079 _this.options.acceptedFiles = _this.options.acceptedMimeTypes; 1080 delete _this.options.acceptedMimeTypes; 1081 } 1082 1083 // Backwards compatibility 1084 if (_this.options.renameFilename != null) { 1085 _this.options.renameFile = function (file) { 1086 return _this.options.renameFilename.call(_this, file.name, file); 1087 }; 1088 } 1089 1090 _this.options.method = _this.options.method.toUpperCase(); 1091 1092 if ((fallback = _this.getExistingFallback()) && fallback.parentNode) { 1093 // Remove the fallback 1094 fallback.parentNode.removeChild(fallback); 1095 } 1096 1097 // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false 1098 if (_this.options.previewsContainer !== false) { 1099 if (_this.options.previewsContainer) { 1100 _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer"); 1101 } else { 1102 _this.previewsContainer = _this.element; 1103 } 1104 } 1105 1106 if (_this.options.clickable) { 1107 if (_this.options.clickable === true) { 1108 _this.clickableElements = [_this.element]; 1109 } else { 1110 _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable"); 1111 } 1112 } 1113 1114 _this.init(); 1115 return _this; 1116 } 1117 1118 // Returns all files that have been accepted 1119 1120 1121 _createClass(Dropzone, [{ 1122 key: "getAcceptedFiles", 1123 value: function getAcceptedFiles() { 1124 return this.files.filter(function (file) { 1125 return file.accepted; 1126 }).map(function (file) { 1127 return file; 1128 }); 1129 } 1130 1131 // Returns all files that have been rejected
1132 // Not sure when that's going to be useful, but added for completeness. 1133 1134 }, { 1135 key: "getRejectedFiles", 1136 value: function getRejectedFiles() { 1137 return this.files.filter(function (file) { 1138 return !file.accepted; 1139 }).map(function (file) { 1140 return file; 1141 }); 1142 } 1143 }, { 1144 key: "getFilesWithStatus", 1145 value: function getFilesWithStatus(status) { 1146 return this.files.filter(function (file) { 1147 return file.status === status; 1148 }).map(function (file) { 1149 return file; 1150 }); 1151 } 1152 1153 // Returns all files that are in the queue 1154 1155 }, { 1156 key: "getQueuedFiles", 1157 value: function getQueuedFiles() { 1158 return this.getFilesWithStatus(Dropzone.QUEUED); 1159 } 1160 }, { 1161 key: "getUploadingFiles", 1162 value: function getUploadingFiles() { 1163 return this.getFilesWithStatus(Dropzone.UPLOADING); 1164 } 1165 }, { 1166 key: "getAddedFiles", 1167 value: function getAddedFiles() { 1168 return this.getFilesWithStatus(Dropzone.ADDED); 1169 } 1170 1171 // Files that are either queued or uploading 1172 1173 }, { 1174 key: "getActiveFiles", 1175 value: function getActiveFiles() { 1176 return this.files.filter(function (file) { 1177 return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED; 1178 }).map(function (file) { 1179 return file; 1180 }); 1181 } 1182 1183 // The function that gets called when Dropzone is initialized. You 1184 // can (and should) setup event listeners inside this function. 1185 1186 }, { 1187 key: "init", 1188 value: function init() { 1189 var _this3 = this; 1190 1191 // In case it isn't set already 1192 if (this.element.tagName === "form") { 1193 this.element.setAttribute("enctype", "multipart/form-data"); 1194 } 1195 1196 if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { 1197 this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>")); 1198 } 1199 1200 if (this.clickableElements.length) { 1201 var setupHiddenFileInput = function setupHiddenFileInput() { 1202 if (_this3.hiddenFileInput) { 1203 _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput); 1204 } 1205 _this3.hiddenFileInput = document.createElement("input"); 1206 _this3.hiddenFileInput.setAttribute("type", "file"); 1207 if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) { 1208 _this3.hiddenFileInput.setAttribute("multiple", "multiple"); 1209 } 1210 _this3.hiddenFileInput.className = "dz-hidden-input"; 1211 1212 if (_this3.options.acceptedFiles !== null) { 1213 _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles); 1214 } 1215 if (_this3.options.capture !== null) { 1216 _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture); 1217 } 1218 1219 // Not setting `display="none"` because some browsers don't accept clicks 1220 // on elements that aren't displayed. 1221 _this3.hiddenFileInput.style.visibility = "hidden"; 1222 _this3.hiddenFileInput.style.position = "absolute"; 1223 _this3.hiddenFileInput.style.top = "0"; 1224 _this3.hiddenFileInput.style.left = "0"; 1225 _this3.hiddenFileInput.style.height = "0"; 1226 _this3.hiddenFileInput.style.width = "0"; 1227 Dropzone.getElement(_this3.options.hiddenInputContainer, 'hiddenInputContainer').appendChild(_this3.hiddenFileInput); 1228 return _this3.hiddenFileInput.addEventListener("change", function () { 1229 var files = _this3.hiddenFileInput.files; 1230 1231 if (files.length) { 1232 for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { 1233 var _ref9; 1234 1235 if (_isArray10) { 1236 if (_i10 >= _iterator10.length) break; 1237 _ref9 = _iterator10[_i10++]; 1238 } else { 1239 _i10 = _iterator10.next(); 1240 if (_i10.done) break; 1241 _ref9 = _i10.value; 1242 } 1243 1244 var file = _ref9; 1245 1246 _this3.addFile(file); 1247 } 1248 } 1249 _this3.emit("addedfiles", files); 1250 return setupHiddenFileInput(); 1251 }); 1252 }; 1253 setupHiddenFileInput(); 1254 } 1255 1256 this.URL = window.URL !== null ? window.URL : window.webkitURL; 1257 1258 // Setup all event listeners on the Dropzone object itself. 1259 // They're not in @setupEventListeners() because they shouldn't be removed 1260 // again when the dropzone gets disabled. 1261 for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) { 1262 var _ref10; 1263 1264 if (_isArray11) { 1265 if (_i11 >= _iterator11.length) break; 1266 _ref10 = _iterator11[_i11++]; 1267 } else { 1268 _i11 = _iterator11.next(); 1269 if (_i11.done) break; 1270 _ref10 = _i11.value; 1271 } 1272 1273 var eventName = _ref10; 1274 1275 this.on(eventName, this.options[eventName]); 1276 } 1277 1278 this.on("uploadprogress", function () { 1279 return _this3.updateTotalUploadProgress(); 1280 }); 1281 1282 this.on("removedfile", function () { 1283 return _this3.updateTotalUploadProgress(); 1284 }); 1285 1286 this.on("canceled", function (file) { 1287 return _this3.emit("complete", file); 1288 }); 1289 1290 // Emit a `queuecomplete` event if all files finished uploading. 1291 this.on("complete", function (file) { 1292 if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) { 1293 // This needs to be deferred so that `queuecomplete` really triggers after `complete` 1294 return setTimeout(function () { 1295 return _this3.emit("queuecomplete"); 1296 }, 0); 1297 } 1298 }); 1299 1300 var noPropagation = function noPropagation(e) { 1301 e.stopPropagation(); 1302 if (e.preventDefault) { 1303 return e.preventDefault(); 1304 } else { 1305 return e.returnValue = false;
1306 } 1307 }; 1308 1309 // Create the listeners 1310 this.listeners = [{ 1311 element: this.element, 1312 events: { 1313 "dragstart": function dragstart(e) { 1314 return _this3.emit("dragstart", e); 1315 }, 1316 "dragenter": function dragenter(e) { 1317 noPropagation(e); 1318 return _this3.emit("dragenter", e); 1319 }, 1320 "dragover": function dragover(e) { 1321 // Makes it possible to drag files from chrome's download bar 1322 // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar 1323 // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception) 1324 var efct = void 0; 1325 try { 1326 efct = e.dataTransfer.effectAllowed; 1327 } catch (error) {} 1328 e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; 1329 1330 noPropagation(e); 1331 return _this3.emit("dragover", e); 1332 }, 1333 "dragleave": function dragleave(e) { 1334 return _this3.emit("dragleave", e); 1335 }, 1336 "drop": function drop(e) { 1337 noPropagation(e); 1338 return _this3.drop(e); 1339 }, 1340 "dragend": function dragend(e) { 1341 return _this3.emit("dragend", e); 1342 } 1343 1344 // This is disabled right now, because the browsers don't implement it properly. 1345 // "paste": (e) => 1346 // noPropagation e 1347 // @paste e 1348 } }]; 1349 1350 this.clickableElements.forEach(function (clickableElement) { 1351 return _this3.listeners.push({ 1352 element: clickableElement, 1353 events: { 1354 "click": function click(evt) { 1355 // Only the actual dropzone or the message element should trigger file selection 1356 if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) { 1357 _this3.hiddenFileInput.click(); // Forward the click 1358 } 1359 return true; 1360 } 1361 } 1362 }); 1363 }); 1364 1365 this.enable(); 1366 1367 return this.options.init.call(this); 1368 } 1369 1370 // Not fully tested yet 1371 1372 }, { 1373 key: "destroy", 1374 value: function destroy() { 1375 this.disable(); 1376 this.removeAllFiles(true); 1377 if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) { 1378 this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); 1379 this.hiddenFileInput = null; 1380 } 1381 delete this.element.dropzone; 1382 return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); 1383 } 1384 }, { 1385 key: "updateTotalUploadProgress", 1386 value: function updateTotalUploadProgress() { 1387 var totalUploadProgress = void 0; 1388 var totalBytesSent = 0; 1389 var totalBytes = 0; 1390 1391 var activeFiles = this.getActiveFiles(); 1392 1393 if (activeFiles.length) { 1394 for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) { 1395 var _ref11; 1396 1397 if (_isArray12) { 1398 if (_i12 >= _iterator12.length) break; 1399 _ref11 = _iterator12[_i12++]; 1400 } else { 1401 _i12 = _iterator12.next(); 1402 if (_i12.done) break; 1403 _ref11 = _i12.value; 1404 } 1405 1406 var file = _ref11; 1407 1408 totalBytesSent += file.upload.bytesSent; 1409 totalBytes += file.upload.total; 1410 } 1411 totalUploadProgress = 100 * totalBytesSent / totalBytes; 1412 } else { 1413 totalUploadProgress = 100; 1414 } 1415 1416 return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); 1417 } 1418 1419 // @options.paramName can be a function taking one parameter rather than a string. 1420 // A parameter name for a file is obtained simply by calling this with an index number. 1421 1422 }, { 1423 key: "_getParamName", 1424 value: function _getParamName(n) { 1425 if (typeof this.options.paramName === "function") { 1426 return this.options.paramName(n); 1427 } else { 1428 return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : ""); 1429 } 1430 } 1431 1432 // If @options.renameFile is a function, 1433 // the function will be used to rename the file.name before appending it to the formData 1434 1435 }, { 1436 key: "_renameFile", 1437 value: function _renameFile(file) { 1438 if (typeof this.options.renameFile !== "function") { 1439 return file.name; 1440 } 1441 return this.options.renameFile(file); 1442 } 1443 1444 // Returns a form that can be used as fallback if the browser does not support DragnDrop 1445 // 1446 // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided. 1447 // This code has to pass in IE7 :( 1448 1449 }, { 1450 key: "getFallbackForm", 1451 value: function getFallbackForm() { 1452 var existingFallback = void 0, 1453 form = void 0; 1454 if (existingFallback = this.getExistingFallback()) { 1455 return existingFallback; 1456 } 1457 1458 var fieldsString = "<div class=\"dz-fallback\">"; 1459 if (this.options.dictFallbackText) { 1460 fieldsString += "<p>" + this.options.dictFallbackText + "</p>"; 1461 } 1462 fieldsString += "<input type=\"file\" name=\"" + this._getParamName(0) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : undefined) + " /><input type=\"submit\" value=\"Upload!\"></div>"; 1463 1464 var fields = Dropzone.createElement(fieldsString); 1465 if (this.element.tagName !== "FORM") { 1466 form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>"); 1467 form.appendChild(fields); 1468 } else { 1469 // Make sure that the enctype and method attributes are set properly 1470 this.element.setAttribute("enctype", "multipart/form-data"); 1471 this.element.setAttribute("method", this.options.method); 1472 } 1473 return form != null ? form : fields; 1474 } 1475 1476 // Returns the fallback elements if they exist already 1477 // 1478 // This code has to pass in IE7 :( 1479 1480 }, { 1481 key: "getExistingFallback", 1482 value: function getExistingFallback() { 1483 var getFallback = function getFallback(elements) { 1484 for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) { 1485 var _ref12; 1486 1487 if (_isArray13) { 1488 if (_i13 >= _iterator13.length) break; 1489 _ref12 = _iterator13[_i13++]; 1490 } else { 1491 _i13 = _iterator13.next(); 1492 if (_i13.done) break; 1493 _ref12 = _i13.value; 1494 } 1495 1496 var el = _ref12; 1497 1498 if (/(^| )fallback($| )/.test(el.className)) { 1499 return el; 1500 } 1501 } 1502 }; 1503 1504 var _arr = ["div", "form"]; 1505 for (var _i14 = 0; _i14 < _arr.length; _i14++) { 1506 var tagName = _arr[_i14]; 1507 var fallback; 1508 if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { 1509 return fallback; 1510 } 1511 } 1512 } 1513 1514 // Activates all listeners stored in @listeners 1515 1516 }, { 1517 key: "setupEventListeners", 1518 value: function setupEventListeners() { 1519 return this.listeners.map(function (elementListeners) { 1520 return function () { 1521 var result = []; 1522 for (var event in elementListeners.events) { 1523 var listener = elementListeners.events[event]; 1524 result.push(elementListeners.element.addEventListener(event, listener, false)); 1525 } 1526 return result; 1527 }(); 1528 }); 1529 } 1530 1531 // Deactivates all listeners stored in @listeners 1532 1533 }, { 1534 key: "removeEventListeners", 1535 value: function removeEventListeners() { 1536 return this.listeners.map(function (elementListeners) { 1537 return function () { 1538 var result = []; 1539 for (var event in elementListeners.events) { 1540 var listener = elementListeners.events[event]; 1541 result.push(elementListeners.element.removeEventListener(event, listener, false)); 1542 } 1543 return result; 1544 }(); 1545 }); 1546 } 1547 1548 // Removes all event listeners and cancels all files in the queue or being processed. 1549 1550 }, { 1551 key: "disable", 1552 value: function disable() { 1553 var _this4 = this; 1554
1555 this.clickableElements.forEach(function (element) { 1556 return element.classList.remove("dz-clickable"); 1557 }); 1558 this.removeEventListeners(); 1559 this.disabled = true; 1560 1561 return this.files.map(function (file) { 1562 return _this4.cancelUpload(file); 1563 }); 1564 } 1565 }, { 1566 key: "enable", 1567 value: function enable() { 1568 delete this.disabled; 1569 this.clickableElements.forEach(function (element) { 1570 return element.classList.add("dz-clickable"); 1571 }); 1572 return this.setupEventListeners(); 1573 } 1574 1575 // Returns a nicely formatted filesize 1576 1577 }, { 1578 key: "filesize", 1579 value: function filesize(size) { 1580 var selectedSize = 0; 1581 var selectedUnit = "b"; 1582 1583 if (size > 0) { 1584 var units = ['tb', 'gb', 'mb', 'kb', 'b']; 1585 1586 for (var i = 0; i < units.length; i++) { 1587 var unit = units[i]; 1588 var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10; 1589 1590 if (size >= cutoff) { 1591 selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i); 1592 selectedUnit = unit; 1593 break; 1594 } 1595 } 1596 1597 selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits 1598 } 1599 1600 return "<strong>" + selectedSize + "</strong> " + this.options.dictFileSizeUnits[selectedUnit]; 1601 } 1602 1603 // Adds or removes the `dz-max-files-reached` class from the form. 1604 1605 }, { 1606 key: "_updateMaxFilesReachedClass", 1607 value: function _updateMaxFilesReachedClass() { 1608 if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) { 1609 if (this.getAcceptedFiles().length === this.options.maxFiles) { 1610 this.emit('maxfilesreached', this.files); 1611 } 1612 return this.element.classList.add("dz-max-files-reached"); 1613 } else { 1614 return this.element.classList.remove("dz-max-files-reached"); 1615 } 1616 } 1617 }, { 1618 key: "drop", 1619 value: function drop(e) { 1620 if (!e.dataTransfer) { 1621 return; 1622 } 1623 this.emit("drop", e); 1624 1625 // Convert the FileList to an Array 1626 // This is necessary for IE11 1627 var files = []; 1628 for (var i = 0; i < e.dataTransfer.files.length; i++) { 1629 files[i] = e.dataTransfer.files[i]; 1630 } 1631 1632 this.emit("addedfiles", files); 1633 1634 // Even if it's a folder, files.length will contain the folders. 1635 if (files.length) { 1636 var items = e.dataTransfer.items; 1637 1638 if (items && items.length && items[0].webkitGetAsEntry != null) { 1639 // The browser supports dropping of folders, so handle items instead of files 1640 this._addFilesFromItems(items); 1641 } else { 1642 this.handleFiles(files); 1643 } 1644 } 1645 } 1646 }, { 1647 key: "paste", 1648 value: function paste(e) { 1649 if (__guard__(e != null ? e.clipboardData : undefined, function (x) { 1650 return x.items; 1651 }) == null) { 1652 return; 1653 } 1654 1655 this.emit("paste", e); 1656 var items = e.clipboardData.items; 1657 1658 1659 if (items.length) { 1660 return this._addFilesFromItems(items); 1661 } 1662 } 1663 }, { 1664 key: "handleFiles", 1665 value: function handleFiles(files) { 1666 for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) { 1667 var _ref13; 1668 1669 if (_isArray14) { 1670 if (_i15 >= _iterator14.length) break; 1671 _ref13 = _iterator14[_i15++]; 1672 } else { 1673 _i15 = _iterator14.next(); 1674 if (_i15.done) break; 1675 _ref13 = _i15.value; 1676 } 1677 1678 var file = _ref13; 1679 1680 this.addFile(file); 1681 } 1682 } 1683 1684 // When a folder is dropped (or files are pasted), items must be handled 1685 // instead of files. 1686 1687 }, { 1688 key: "_addFilesFromItems", 1689 value: function _addFilesFromItems(items) { 1690 var _this5 = this; 1691 1692 return function () { 1693 var result = []; 1694 for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) { 1695 var _ref14; 1696 1697 if (_isArray15) { 1698 if (_i16 >= _iterator15.length) break; 1699 _ref14 = _iterator15[_i16++]; 1700 } else { 1701 _i16 = _iterator15.next(); 1702 if (_i16.done) break; 1703 _ref14 = _i16.value; 1704 } 1705 1706 var item = _ref14; 1707 1708 var entry; 1709 if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) { 1710 if (entry.isFile) { 1711 result.push(_this5.addFile(item.getAsFile())); 1712 } else if (entry.isDirectory) { 1713 // Append all files from that directory to files 1714 result.push(_this5._addFilesFromDirectory(entry, entry.name)); 1715 } else { 1716 result.push(undefined); 1717 } 1718 } else if (item.getAsFile != null) { 1719 if (item.kind == null || item.kind === "file") { 1720 result.push(_this5.addFile(item.getAsFile())); 1721 } else { 1722 result.push(undefined); 1723 } 1724 } else { 1725 result.push(undefined); 1726 } 1727 } 1728 return result; 1729 }(); 1730 } 1731 1732 // Goes through the directory, and adds each file it finds recursively 1733 1734 }, { 1735 key: "_addFilesFromDirectory", 1736 value: function _addFilesFromDirectory(directory, path) { 1737 var _this6 = this; 1738 1739 var dirReader = directory.createReader(); 1740 1741 var errorHandler = function errorHandler(error) { 1742 return __guardMethod__(console, 'log', function (o) { 1743 return o.log(error); 1744 }); 1745 }; 1746 1747 var readEntries = function readEntries() { 1748 return dirReader.readEntries(function (entries) { 1749 if (entries.length > 0) { 1750 for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) { 1751 var _ref15; 1752 1753 if (_isArray16) { 1754 if (_i17 >= _iterator16.length) break; 1755 _ref15 = _iterator16[_i17++]; 1756 } else { 1757 _i17 = _iterator16.next(); 1758 if (_i17.done) break; 1759 _ref15 = _i17.value; 1760 } 1761 1762 var entry = _ref15; 1763 1764 if (entry.isFile) { 1765 entry.file(function (file) { 1766 if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { 1767 return; 1768 } 1769 file.fullPath = path + "/" + file.name; 1770 return _this6.addFile(file); 1771 }); 1772 } else if (entry.isDirectory) { 1773 _this6._addFilesFromDirectory(entry, path + "/" + entry.name); 1774 } 1775 } 1776 1777 // Recursively call readEntries() again, since browser only handle 1778 // the first 100 entries. 1779 // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries 1780 readEntries(); 1781 } 1782 return null; 1783 }, errorHandler); 1784 }; 1785 1786 return readEntries(); 1787 } 1788 1789 // If `done()` is called without argument the file is accepted 1790 // If you call it with an error message, the file is rejected 1791 // (This allows for asynchronous validation) 1792 // 1793 // This function checks the filesize, and if the file.type passes the 1794 // `acceptedFiles` check. 1795 1796 }, { 1797 key: "accept", 1798 value: function accept(file, done) { 1799 if (this.options.maxFilesize && file.size > this.options.maxFilesize * 1024 * 1024) { 1800 return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); 1801 } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { 1802 return done(this.options.dictInvalidFileType); 1803 } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) { 1804 done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
1805 return this.emit("maxfilesexceeded", file); 1806 } else { 1807 return this.options.accept.call(this, file, done); 1808 } 1809 } 1810 }, { 1811 key: "addFile", 1812 value: function addFile(file) { 1813 var _this7 = this; 1814 1815 file.upload = { 1816 uuid: Dropzone.uuidv4(), 1817 progress: 0, 1818 // Setting the total upload size to file.size for the beginning 1819 // It's actual different than the size to be transmitted. 1820 total: file.size, 1821 bytesSent: 0, 1822 filename: this._renameFile(file), 1823 chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize), 1824 totalChunkCount: Math.ceil(file.size / this.options.chunkSize) 1825 }; 1826 this.files.push(file); 1827 1828 file.status = Dropzone.ADDED; 1829 1830 this.emit("addedfile", file); 1831 1832 this._enqueueThumbnail(file); 1833 1834 return this.accept(file, function (error) { 1835 if (error) { 1836 file.accepted = false; 1837 _this7._errorProcessing([file], error); // Will set the file.status 1838 } else { 1839 file.accepted = true; 1840 if (_this7.options.autoQueue) { 1841 _this7.enqueueFile(file); 1842 } // Will set .accepted = true 1843 } 1844 return _this7._updateMaxFilesReachedClass(); 1845 }); 1846 } 1847 1848 // Wrapper for enqueueFile 1849 1850 }, { 1851 key: "enqueueFiles", 1852 value: function enqueueFiles(files) { 1853 for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) { 1854 var _ref16; 1855 1856 if (_isArray17) { 1857 if (_i18 >= _iterator17.length) break; 1858 _ref16 = _iterator17[_i18++]; 1859 } else { 1860 _i18 = _iterator17.next(); 1861 if (_i18.done) break; 1862 _ref16 = _i18.value; 1863 } 1864 1865 var file = _ref16; 1866 1867 this.enqueueFile(file); 1868 } 1869 return null; 1870 } 1871 }, { 1872 key: "enqueueFile", 1873 value: function enqueueFile(file) { 1874 var _this8 = this; 1875 1876 if (file.status === Dropzone.ADDED && file.accepted === true) { 1877 file.status = Dropzone.QUEUED; 1878 if (this.options.autoProcessQueue) { 1879 return setTimeout(function () { 1880 return _this8.processQueue(); 1881 }, 0); // Deferring the call 1882 } 1883 } else { 1884 throw new Error("This file can't be queued because it has already been processed or was rejected."); 1885 } 1886 } 1887 }, { 1888 key: "_enqueueThumbnail", 1889 value: function _enqueueThumbnail(file) { 1890 var _this9 = this; 1891 1892 if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { 1893 this._thumbnailQueue.push(file); 1894 return setTimeout(function () { 1895 return _this9._processThumbnailQueue(); 1896 }, 0); // Deferring the call 1897 } 1898 } 1899 }, { 1900 key: "_processThumbnailQueue", 1901 value: function _processThumbnailQueue() { 1902 var _this10 = this; 1903 1904 if (this._processingThumbnail || this._thumbnailQueue.length === 0) { 1905 return; 1906 } 1907 1908 this._processingThumbnail = true; 1909 var file = this._thumbnailQueue.shift(); 1910 return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) { 1911 _this10.emit("thumbnail", file, dataUrl); 1912 _this10._processingThumbnail = false; 1913 return _this10._processThumbnailQueue(); 1914 }); 1915 } 1916 1917 // Can be called by the user to remove a file 1918 1919 }, { 1920 key: "removeFile", 1921 value: function removeFile(file) { 1922 if (file.status === Dropzone.UPLOADING) { 1923 this.cancelUpload(file); 1924 } 1925 this.files = without(this.files, file); 1926 1927 this.emit("removedfile", file); 1928 if (this.files.length === 0) { 1929 return this.emit("reset"); 1930 } 1931 } 1932 1933 // Removes all files that aren't currently processed from the list 1934 1935 }, { 1936 key: "removeAllFiles", 1937 value: function removeAllFiles(cancelIfNecessary) { 1938 // Create a copy of files since removeFile() changes the @files array. 1939 if (cancelIfNecessary == null) { 1940 cancelIfNecessary = false;
1941 } 1942 for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) { 1943 var _ref17; 1944 1945 if (_isArray18) { 1946 if (_i19 >= _iterator18.length) break; 1947 _ref17 = _iterator18[_i19++]; 1948 } else { 1949 _i19 = _iterator18.next(); 1950 if (_i19.done) break; 1951 _ref17 = _i19.value; 1952 } 1953 1954 var file = _ref17; 1955 1956 if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { 1957 this.removeFile(file); 1958 } 1959 } 1960 return null; 1961 } 1962 1963 // Resizes an image before it gets sent to the server. This function is the default behavior of 1964 // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with 1965 // the resized blob. 1966 1967 }, { 1968 key: "resizeImage", 1969 value: function resizeImage(file, width, height, resizeMethod, callback) { 1970 var _this11 = this; 1971 1972 return this.createThumbnail(file, width, height, resizeMethod, true, function (dataUrl, canvas) { 1973 if (canvas == null) { 1974 // The image has not been resized 1975 return callback(file); 1976 } else { 1977 var resizeMimeType = _this11.options.resizeMimeType; 1978 1979 if (resizeMimeType == null) { 1980 resizeMimeType = file.type; 1981 } 1982 var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality); 1983 if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') { 1984 // Now add the original EXIF information 1985 resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL); 1986 } 1987 return callback(Dropzone.dataURItoBlob(resizedDataURL)); 1988 } 1989 }); 1990 } 1991 }, { 1992 key: "createThumbnail", 1993 value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) { 1994 var _this12 = this; 1995 1996 var fileReader = new FileReader(); 1997 1998 fileReader.onload = function () { 1999 2000 file.dataURL = fileReader.result; 2001 2002 // Don't bother creating a thumbnail for SVG images since they're vector 2003 if (file.type === "image/svg+xml") { 2004 if (callback != null) { 2005 callback(fileReader.result); 2006 } 2007 return; 2008 } 2009 2010 return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback); 2011 }; 2012 2013 return fileReader.readAsDataURL(file); 2014 } 2015 }, { 2016 key: "createThumbnailFromUrl", 2017 value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) { 2018 var _this13 = this; 2019 2020 // Not using `new Image` here because of a bug in latest Chrome versions. 2021 // See https://github.com/enyo/dropzone/pull/226 2022 var img = document.createElement("img"); 2023 2024 if (crossOrigin) { 2025 img.crossOrigin = crossOrigin; 2026 } 2027 2028 img.onload = function () { 2029 var loadExif = function loadExif(callback) { 2030 return callback(1); 2031 }; 2032 if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) { 2033 loadExif = function loadExif(callback) { 2034 return EXIF.getData(img, function () { 2035 return callback(EXIF.getTag(this, 'Orientation')); 2036 }); 2037 }; 2038 } 2039 2040 return loadExif(function (orientation) { 2041 file.width = img.width; 2042 file.height = img.height; 2043 2044 var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod); 2045 2046 var canvas = document.createElement("canvas"); 2047 var ctx = canvas.getContext("2d"); 2048 2049 canvas.width = resizeInfo.trgWidth; 2050 canvas.height = resizeInfo.trgHeight; 2051 2052 if (orientation > 4) { 2053 canvas.width = resizeInfo.trgHeight; 2054 canvas.height = resizeInfo.trgWidth; 2055 } 2056 2057 switch (orientation) { 2058 case 2: 2059 // horizontal flip 2060 ctx.translate(canvas.width, 0); 2061 ctx.scale(-1, 1); 2062 break; 2063 case 3: 2064 // 180° rotate left 2065 ctx.translate(canvas.width, canvas.height); 2066 ctx.rotate(Math.PI); 2067 break; 2068 case 4: 2069 // vertical flip 2070 ctx.translate(0, canvas.height); 2071 ctx.scale(1, -1); 2072 break; 2073 case 5: 2074 // vertical flip + 90 rotate right 2075 ctx.rotate(0.5 * Math.PI); 2076 ctx.scale(1, -1); 2077 break; 2078 case 6: 2079 // 90° rotate right 2080 ctx.rotate(0.5 * Math.PI); 2081 ctx.translate(0, -canvas.width); 2082 break; 2083 case 7: 2084 // horizontal flip + 90 rotate right 2085 ctx.rotate(0.5 * Math.PI); 2086 ctx.translate(canvas.height, -canvas.width); 2087 ctx.scale(-1, 1); 2088 break; 2089 case 8: 2090 // 90° rotate left 2091 ctx.rotate(-0.5 * Math.PI); 2092 ctx.translate(-canvas.height, 0); 2093 break; 2094 } 2095 2096 // This is a bugfix for iOS' scaling bug. 2097 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); 2098 2099 var thumbnail = canvas.toDataURL("image/png"); 2100 2101 if (callback != null) {
2102 return callback(thumbnail, canvas); 2103 } 2104 }); 2105 }; 2106 2107 if (callback != null) { 2108 img.onerror = callback; 2109 } 2110 2111 return img.src = file.dataURL; 2112 } 2113 2114 // Goes through the queue and processes files if there aren't too many already. 2115 2116 }, { 2117 key: "processQueue", 2118 value: function processQueue() { 2119 var parallelUploads = this.options.parallelUploads; 2120 2121 var processingLength = this.getUploadingFiles().length; 2122 var i = processingLength; 2123 2124 // There are already at least as many files uploading than should be 2125 if (processingLength >= parallelUploads) { 2126 return; 2127 } 2128 2129 var queuedFiles = this.getQueuedFiles(); 2130 2131 if (!(queuedFiles.length > 0)) { 2132 return; 2133 } 2134 2135 if (this.options.uploadMultiple) { 2136 // The files should be uploaded in one request 2137 return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); 2138 } else { 2139 while (i < parallelUploads) { 2140 if (!queuedFiles.length) { 2141 return; 2142 } // Nothing left to process 2143 this.processFile(queuedFiles.shift()); 2144 i++; 2145 } 2146 } 2147 } 2148 2149 // Wrapper for `processFiles` 2150 2151 }, { 2152 key: "processFile", 2153 value: function processFile(file) { 2154 return this.processFiles([file]); 2155 } 2156 2157 // Loads the file, then calls finishedLoading() 2158 2159 }, { 2160 key: "processFiles", 2161 value: function processFiles(files) { 2162 for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) { 2163 var _ref18; 2164 2165 if (_isArray19) { 2166 if (_i20 >= _iterator19.length) break; 2167 _ref18 = _iterator19[_i20++]; 2168 } else { 2169 _i20 = _iterator19.next(); 2170 if (_i20.done) break; 2171 _ref18 = _i20.value; 2172 } 2173 2174 var file = _ref18; 2175 2176 file.processing = true; // Backwards compatibility 2177 file.status = Dropzone.UPLOADING; 2178 2179 this.emit("processing", file); 2180 } 2181 2182 if (this.options.uploadMultiple) { 2183 this.emit("processingmultiple", files); 2184 } 2185 2186 return this.uploadFiles(files); 2187 } 2188 }, { 2189 key: "_getFilesWithXhr", 2190 value: function _getFilesWithXhr(xhr) { 2191 var files = void 0; 2192 return files = this.files.filter(function (file) { 2193 return file.xhr === xhr; 2194 }).map(function (file) { 2195 return file; 2196 }); 2197 } 2198 2199 // Cancels the file upload and sets the status to CANCELED 2200 // **if** the file is actually being uploaded. 2201 // If it's still in the queue, the file is being removed from it and the status 2202 // set to CANCELED. 2203 2204 }, { 2205 key: "cancelUpload", 2206 value: function cancelUpload(file) { 2207 if (file.status === Dropzone.UPLOADING) { 2208 var groupedFiles = this._getFilesWithXhr(file.xhr); 2209 for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) { 2210 var _ref19; 2211 2212 if (_isArray20) { 2213 if (_i21 >= _iterator20.length) break; 2214 _ref19 = _iterator20[_i21++]; 2215 } else { 2216 _i21 = _iterator20.next(); 2217 if (_i21.done) break; 2218 _ref19 = _i21.value; 2219 } 2220 2221 var groupedFile = _ref19; 2222 2223 groupedFile.status = Dropzone.CANCELED; 2224 } 2225 if (typeof file.xhr !== 'undefined') { 2226 file.xhr.abort(); 2227 } 2228 for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) { 2229 var _ref20; 2230 2231 if (_isArray21) { 2232 if (_i22 >= _iterator21.length) break; 2233 _ref20 = _iterator21[_i22++]; 2234 } else { 2235 _i22 = _iterator21.next(); 2236 if (_i22.done) break; 2237 _ref20 = _i22.value; 2238 } 2239 2240 var _groupedFile = _ref20; 2241 2242 this.emit("canceled", _groupedFile); 2243 } 2244 if (this.options.uploadMultiple) { 2245 this.emit("canceledmultiple", groupedFiles); 2246 } 2247 } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) { 2248 file.status = Dropzone.CANCELED;
2249 this.emit("canceled", file); 2250 if (this.options.uploadMultiple) { 2251 this.emit("canceledmultiple", [file]); 2252 } 2253 } 2254 2255 if (this.options.autoProcessQueue) { 2256 return this.processQueue(); 2257 } 2258 } 2259 }, { 2260 key: "resolveOption", 2261 value: function resolveOption(option) { 2262 if (typeof option === 'function') { 2263 for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { 2264 args[_key3 - 1] = arguments[_key3]; 2265 } 2266 2267 return option.apply(this, args); 2268 } 2269 return option; 2270 } 2271 }, { 2272 key: "uploadFile", 2273 value: function uploadFile(file) { 2274 return this.uploadFiles([file]); 2275 } 2276 }, { 2277 key: "uploadFiles", 2278 value: function uploadFiles(files) { 2279 var _this14 = this; 2280 2281 this._transformFiles(files, function (transformedFiles) { 2282 if (files[0].upload.chunked) { 2283 // This file should be sent in chunks! 2284 2285 // If the chunking option is set, we **know** that there can only be **one** file, since 2286 // uploadMultiple is not allowed with this option. 2287 var file = files[0]; 2288 var transformedFile = transformedFiles[0]; 2289 var startedChunkCount = 0; 2290 2291 file.upload.chunks = []; 2292 2293 var handleNextChunk = function handleNextChunk() { 2294 var chunkIndex = 0; 2295 2296 // Find the next item in file.upload.chunks that is not defined yet. 2297 while (file.upload.chunks[chunkIndex] !== undefined) { 2298 chunkIndex++; 2299 } 2300 2301 // This means, that all chunks have already been started. 2302 if (chunkIndex >= file.upload.totalChunkCount) return; 2303 2304 startedChunkCount++; 2305 2306 var start = chunkIndex * _this14.options.chunkSize; 2307 var end = Math.min(start + _this14.options.chunkSize, file.size); 2308 2309 var dataBlock = { 2310 name: _this14._getParamName(0), 2311 data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end), 2312 filename: file.upload.filename, 2313 chunkIndex: chunkIndex 2314 }; 2315 2316 file.upload.chunks[chunkIndex] = { 2317 file: file, 2318 index: chunkIndex, 2319 dataBlock: dataBlock, // In case we want to retry. 2320 status: Dropzone.UPLOADING, 2321 progress: 0, 2322 retries: 0 // The number of times this block has been retried. 2323 }; 2324 2325 _this14._uploadData(files, [dataBlock]); 2326 }; 2327 2328 file.upload.finishedChunkUpload = function (chunk) { 2329 var allFinished = true; 2330 chunk.status = Dropzone.SUCCESS; 2331 2332 // Clear the data from the chunk 2333 chunk.dataBlock = null; 2334 // Leaving this reference to xhr intact here will cause memory leaks in some browsers 2335 chunk.xhr = null; 2336 2337 for (var i = 0; i < file.upload.totalChunkCount; i++) { 2338 if (file.upload.chunks[i] === undefined) { 2339 return handleNextChunk(); 2340 } 2341 if (file.upload.chunks[i].status !== Dropzone.SUCCESS) { 2342 allFinished = false; 2343 } 2344 } 2345 2346 if (allFinished) { 2347 _this14.options.chunksUploaded(file, function () { 2348 _this14._finished(files, '', null); 2349 }); 2350 } 2351 }; 2352 2353 if (_this14.options.parallelChunkUploads) { 2354 for (var i = 0; i < file.upload.totalChunkCount; i++) { 2355 handleNextChunk(); 2356 } 2357 } else { 2358 handleNextChunk(); 2359 } 2360 } else { 2361 var dataBlocks = []; 2362 for (var _i23 = 0; _i23 < files.length; _i23++) { 2363 dataBlocks[_i23] = { 2364 name: _this14._getParamName(_i23), 2365 data: transformedFiles[_i23], 2366 filename: files[_i23].upload.filename 2367 }; 2368 } 2369 _this14._uploadData(files, dataBlocks); 2370 } 2371 }); 2372 } 2373 2374 /// Returns the right chunk for given file and xhr 2375 2376 }, { 2377 key: "_getChunk", 2378 value: function _getChunk(file, xhr) { 2379 for (var i = 0; i < file.upload.totalChunkCount; i++) { 2380 if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) { 2381 return file.upload.chunks[i]; 2382 } 2383 } 2384 } 2385 2386 // This function actually uploads the file(s) to the server. 2387 // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed 2388 // files, or individual chunks for chunked upload). 2389 2390 }, { 2391 key: "_uploadData", 2392 value: function _uploadData(files, dataBlocks) { 2393 var _this15 = this; 2394 2395 var xhr = new XMLHttpRequest(); 2396 2397 // Put the xhr object in the file objects to be able to reference it later. 2398 for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) { 2399 var _ref21; 2400 2401 if (_isArray22) { 2402 if (_i24 >= _iterator22.length) break; 2403 _ref21 = _iterator22[_i24++]; 2404 } else { 2405 _i24 = _iterator22.next(); 2406 if (_i24.done) break; 2407 _ref21 = _i24.value; 2408 } 2409 2410 var file = _ref21; 2411 2412 file.xhr = xhr; 2413 } 2414 if (files[0].upload.chunked) { 2415 // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk 2416 files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr; 2417 } 2418 2419 var method = this.resolveOption(this.options.method, files); 2420 var url = this.resolveOption(this.options.url, files); 2421 xhr.open(method, url, true); 2422 2423 // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8 2424 xhr.timeout = this.resolveOption(this.options.timeout, files); 2425 2426 // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179 2427 xhr.withCredentials = !!this.options.withCredentials; 2428 2429 xhr.onload = function (e) { 2430 _this15._finishedUploading(files, xhr, e); 2431 }; 2432 2433 xhr.onerror = function () { 2434 _this15._handleUploadError(files, xhr); 2435 }; 2436 2437 // Some browsers do not have the .upload property 2438 var progressObj = xhr.upload != null ? xhr.upload : xhr; 2439 progressObj.onprogress = function (e) { 2440 return _this15._updateFilesUploadProgress(files, xhr, e); 2441 }; 2442 2443 var headers = { 2444 "Accept": "application/json", 2445 "Cache-Control": "no-cache", 2446 "X-Requested-With": "XMLHttpRequest" 2447 }; 2448 2449 if (this.options.headers) { 2450 Dropzone.extend(headers, this.options.headers); 2451 } 2452 2453 for (var headerName in headers) { 2454 var headerValue = headers[headerName]; 2455 if (headerValue) { 2456 xhr.setRequestHeader(headerName, headerValue); 2457 } 2458 } 2459 2460 var formData = new FormData(); 2461 2462 // Adding all @options parameters 2463 if (this.options.params) { 2464 var additionalParams = this.options.params; 2465 if (typeof additionalParams === 'function') { 2466 additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null); 2467 } 2468 2469 for (var key in additionalParams) { 2470 var value = additionalParams[key]; 2471 formData.append(key, value); 2472 } 2473 } 2474 2475 // Let the user add additional data if necessary
2476 for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) { 2477 var _ref22; 2478 2479 if (_isArray23) { 2480 if (_i25 >= _iterator23.length) break; 2481 _ref22 = _iterator23[_i25++]; 2482 } else { 2483 _i25 = _iterator23.next(); 2484 if (_i25.done) break; 2485 _ref22 = _i25.value; 2486 } 2487 2488 var _file = _ref22; 2489 2490 this.emit("sending", _file, xhr, formData); 2491 } 2492 if (this.options.uploadMultiple) { 2493 this.emit("sendingmultiple", files, xhr, formData); 2494 } 2495 2496 this._addFormElementData(formData); 2497 2498 // Finally add the files 2499 // Has to be last because some servers (eg: S3) expect the file to be the last parameter 2500 for (var i = 0; i < dataBlocks.length; i++) { 2501 var dataBlock = dataBlocks[i]; 2502 formData.append(dataBlock.name, dataBlock.data, dataBlock.filename); 2503 } 2504 2505 this.submitRequest(xhr, formData, files); 2506 } 2507 2508 // Transforms all files with this.options.transformFile and invokes done with the transformed files when done. 2509 2510 }, { 2511 key: "_transformFiles", 2512 value: function _transformFiles(files, done) { 2513 var _this16 = this; 2514 2515 var transformedFiles = []; 2516 // Clumsy way of handling asynchronous calls, until I get to add a proper Future library. 2517 var doneCounter = 0; 2518 2519 var _loop = function _loop(i) { 2520 _this16.options.transformFile.call(_this16, files[i], function (transformedFile) { 2521 transformedFiles[i] = transformedFile; 2522 if (++doneCounter === files.length) { 2523 done(transformedFiles); 2524 } 2525 }); 2526 }; 2527 2528 for (var i = 0; i < files.length; i++) { 2529 _loop(i); 2530 } 2531 } 2532 2533 // Takes care of adding other input elements of the form to the AJAX request 2534 2535 }, { 2536 key: "_addFormElementData", 2537 value: function _addFormElementData(formData) { 2538 // Take care of other input elements 2539 if (this.element.tagName === "FORM") { 2540 for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) { 2541 var _ref23; 2542 2543 if (_isArray24) { 2544 if (_i26 >= _iterator24.length) break; 2545 _ref23 = _iterator24[_i26++]; 2546 } else { 2547 _i26 = _iterator24.next(); 2548 if (_i26.done) break; 2549 _ref23 = _i26.value; 2550 } 2551 2552 var input = _ref23; 2553 2554 var inputName = input.getAttribute("name"); 2555 var inputType = input.getAttribute("type"); 2556 if (inputType) inputType = inputType.toLowerCase(); 2557 2558 // If the input doesn't have a name, we can't use it. 2559 if (typeof inputName === 'undefined' || inputName === null) continue; 2560 2561 if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { 2562 // Possibly multiple values 2563 for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) { 2564 var _ref24; 2565 2566 if (_isArray25) { 2567 if (_i27 >= _iterator25.length) break; 2568 _ref24 = _iterator25[_i27++]; 2569 } else { 2570 _i27 = _iterator25.next(); 2571 if (_i27.done) break; 2572 _ref24 = _i27.value; 2573 } 2574 2575 var option = _ref24; 2576 2577 if (option.selected) { 2578 formData.append(inputName, option.value); 2579 } 2580 } 2581 } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) { 2582 formData.append(inputName, input.value); 2583 } 2584 } 2585 } 2586 } 2587 2588 // Invoked when there is new progress information about given files. 2589 // If e is not provided, it is assumed that the upload is finished. 2590 2591 }, { 2592 key: "_updateFilesUploadProgress", 2593 value: function _updateFilesUploadProgress(files, xhr, e) { 2594 var progress = void 0; 2595 if (typeof e !== 'undefined') { 2596 progress = 100 * e.loaded / e.total; 2597 2598 if (files[0].upload.chunked) { 2599 var file = files[0]; 2600 // Since this is a chunked upload, we need to update the appropriate chunk progress. 2601 var chunk = this._getChunk(file, xhr); 2602 chunk.progress = progress; 2603 chunk.total = e.total; 2604 chunk.bytesSent = e.loaded; 2605 var fileProgress = 0, 2606 fileTotal = void 0, 2607 fileBytesSent = void 0; 2608 file.upload.progress = 0; 2609 file.upload.total = 0;
2610 file.upload.bytesSent = 0; 2611 for (var i = 0; i < file.upload.totalChunkCount; i++) { 2612 if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) { 2613 file.upload.progress += file.upload.chunks[i].progress; 2614 file.upload.total += file.upload.chunks[i].total; 2615 file.upload.bytesSent += file.upload.chunks[i].bytesSent; 2616 } 2617 } 2618 file.upload.progress = file.upload.progress / file.upload.totalChunkCount; 2619 } else { 2620 for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) { 2621 var _ref25; 2622 2623 if (_isArray26) { 2624 if (_i28 >= _iterator26.length) break; 2625 _ref25 = _iterator26[_i28++]; 2626 } else { 2627 _i28 = _iterator26.next(); 2628 if (_i28.done) break; 2629 _ref25 = _i28.value; 2630 } 2631 2632 var _file2 = _ref25; 2633 2634 _file2.upload.progress = progress; 2635 _file2.upload.total = e.total; 2636 _file2.upload.bytesSent = e.loaded; 2637 } 2638 } 2639 for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) { 2640 var _ref26; 2641 2642 if (_isArray27) { 2643 if (_i29 >= _iterator27.length) break; 2644 _ref26 = _iterator27[_i29++]; 2645 } else { 2646 _i29 = _iterator27.next(); 2647 if (_i29.done) break; 2648 _ref26 = _i29.value; 2649 } 2650 2651 var _file3 = _ref26; 2652 2653 this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent); 2654 } 2655 } else { 2656 // Called when the file finished uploading 2657 2658 var allFilesFinished = true; 2659 2660 progress = 100; 2661 2662 for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) { 2663 var _ref27; 2664 2665 if (_isArray28) { 2666 if (_i30 >= _iterator28.length) break; 2667 _ref27 = _iterator28[_i30++]; 2668 } else { 2669 _i30 = _iterator28.next(); 2670 if (_i30.done) break; 2671 _ref27 = _i30.value; 2672 } 2673 2674 var _file4 = _ref27; 2675 2676 if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) { 2677 allFilesFinished = false; 2678 } 2679 _file4.upload.progress = progress; 2680 _file4.upload.bytesSent = _file4.upload.total; 2681 } 2682 2683 // Nothing to do, all files already at 100% 2684 if (allFilesFinished) { 2685 return; 2686 } 2687 2688 for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) { 2689 var _ref28; 2690 2691 if (_isArray29) { 2692 if (_i31 >= _iterator29.length) break; 2693 _ref28 = _iterator29[_i31++]; 2694 } else { 2695 _i31 = _iterator29.next(); 2696 if (_i31.done) break; 2697 _ref28 = _i31.value; 2698 } 2699 2700 var _file5 = _ref28; 2701 2702 this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent); 2703 } 2704 } 2705 } 2706 }, { 2707 key: "_finishedUploading", 2708 value: function _finishedUploading(files, xhr, e) { 2709 var response = void 0; 2710 2711 if (files[0].status === Dropzone.CANCELED) { 2712 return; 2713 } 2714 2715 if (xhr.readyState !== 4) { 2716 return; 2717 } 2718 2719 if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') { 2720 response = xhr.responseText; 2721 2722 if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { 2723 try { 2724 response = JSON.parse(response); 2725 } catch (error) { 2726 e = error; 2727 response = "Invalid JSON response from server."; 2728 } 2729 } 2730 } 2731 2732 this._updateFilesUploadProgress(files); 2733 2734 if (!(200 <= xhr.status && xhr.status < 300)) { 2735 this._handleUploadError(files, xhr, response); 2736 } else { 2737 if (files[0].upload.chunked) { 2738 files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr)); 2739 } else { 2740 this._finished(files, response, e); 2741 } 2742 } 2743 } 2744 }, { 2745 key: "_handleUploadError", 2746 value: function _handleUploadError(files, xhr, response) { 2747 if (files[0].status === Dropzone.CANCELED) { 2748 return; 2749 } 2750 2751 if (files[0].upload.chunked && this.options.retryChunks) { 2752 var chunk = this._getChunk(files[0], xhr); 2753 if (chunk.retries++ < this.options.retryChunksLimit) { 2754 this._uploadData(files, [chunk.dataBlock]); 2755 return; 2756 } else { 2757 console.warn('Retried this chunk too often. Giving up.'); 2758 } 2759 } 2760 2761 for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) { 2762 var _ref29; 2763 2764 if (_isArray30) { 2765 if (_i32 >= _iterator30.length) break; 2766 _ref29 = _iterator30[_i32++]; 2767 } else { 2768 _i32 = _iterator30.next(); 2769 if (_i32.done) break; 2770 _ref29 = _i32.value; 2771 } 2772 2773 var file = _ref29; 2774 2775 this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr); 2776 } 2777 } 2778 }, { 2779 key: "submitRequest", 2780 value: function submitRequest(xhr, formData, files) { 2781 xhr.send(formData); 2782 } 2783
2784 // Called internally when processing is finished. 2785 // Individual callbacks have to be called in the appropriate sections. 2786 2787 }, { 2788 key: "_finished", 2789 value: function _finished(files, responseText, e) { 2790 for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) { 2791 var _ref30; 2792 2793 if (_isArray31) { 2794 if (_i33 >= _iterator31.length) break; 2795 _ref30 = _iterator31[_i33++]; 2796 } else { 2797 _i33 = _iterator31.next(); 2798 if (_i33.done) break; 2799 _ref30 = _i33.value; 2800 } 2801 2802 var file = _ref30; 2803 2804 file.status = Dropzone.SUCCESS; 2805 this.emit("success", file, responseText, e); 2806 this.emit("complete", file); 2807 } 2808 if (this.options.uploadMultiple) { 2809 this.emit("successmultiple", files, responseText, e); 2810 this.emit("completemultiple", files); 2811 } 2812 2813 if (this.options.autoProcessQueue) { 2814 return this.processQueue(); 2815 } 2816 } 2817 2818 // Called internally when processing is finished. 2819 // Individual callbacks have to be called in the appropriate sections. 2820 2821 }, { 2822 key: "_errorProcessing", 2823 value: function _errorProcessing(files, message, xhr) { 2824 for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) { 2825 var _ref31; 2826 2827 if (_isArray32) { 2828 if (_i34 >= _iterator32.length) break; 2829 _ref31 = _iterator32[_i34++]; 2830 } else { 2831 _i34 = _iterator32.next(); 2832 if (_i34.done) break; 2833 _ref31 = _i34.value; 2834 } 2835 2836 var file = _ref31; 2837 2838 file.status = Dropzone.ERROR; 2839 this.emit("error", file, message, xhr); 2840 this.emit("complete", file); 2841 } 2842 if (this.options.uploadMultiple) { 2843 this.emit("errormultiple", files, message, xhr); 2844 this.emit("completemultiple", files); 2845 } 2846 2847 if (this.options.autoProcessQueue) { 2848 return this.processQueue(); 2849 } 2850 } 2851 }], [{ 2852 key: "uuidv4", 2853 value: function uuidv4() { 2854 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 2855 var r = Math.random() * 16 | 0, 2856 v = c === 'x' ? r : r & 0x3 | 0x8; 2857 return v.toString(16); 2858 }); 2859 } 2860 }]); 2861 2862 return Dropzone; 2863}(Emitter); 2864 2865Dropzone.initClass(); 2866 2867Dropzone.version = "5.5.0"; 2868 2869// This is a map of options for your different dropzones. Add configurations 2870// to this object for your different dropzone elemens. 2871// 2872// Example: 2873// 2874// Dropzone.options.myDropzoneElementId = { maxFilesize: 1 }; 2875// 2876// To disable autoDiscover for a specific element, you can set `false` as an option: 2877// 2878// Dropzone.options.myDisabledElementId = false; 2879// 2880// And in html: 2881// 2882// <form action="/upload" id="my-dropzone-element-id" class="dropzone"></form> 2883Dropzone.options = {}; 2884 2885// Returns the options for an element or undefined if none available. 2886Dropzone.optionsForElement = function (element) { 2887 // Get the `Dropzone.options.elementId` for this element if it exists 2888 if (element.getAttribute("id")) { 2889 return Dropzone.options[camelize(element.getAttribute("id"))]; 2890 } else { 2891 return undefined; 2892 } 2893}; 2894 2895// Holds a list of all dropzone instances 2896Dropzone.instances = []; 2897 2898// Returns the dropzone for given element if any 2899Dropzone.forElement = function (element) { 2900 if (typeof element === "string") { 2901 element = document.querySelector(element); 2902 } 2903 if ((element != null ? element.dropzone : undefined) == null) { 2904 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."); 2905 } 2906 return element.dropzone; 2907}; 2908 2909// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements. 2910Dropzone.autoDiscover = true; 2911 2912// Looks for all .dropzone elements and creates a dropzone for them 2913Dropzone.discover = function () { 2914 var dropzones = void 0; 2915 if (document.querySelectorAll) { 2916 dropzones = document.querySelectorAll(".dropzone"); 2917 } else { 2918 dropzones = []; 2919 // IE :( 2920 var checkElements = function checkElements(elements) { 2921 return function () { 2922 var result = []; 2923 for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) { 2924 var _ref32; 2925 2926 if (_isArray33) { 2927 if (_i35 >= _iterator33.length) break; 2928 _ref32 = _iterator33[_i35++]; 2929 } else { 2930 _i35 = _iterator33.next(); 2931 if (_i35.done) break; 2932 _ref32 = _i35.value; 2933 } 2934 2935 var el = _ref32; 2936 2937 if (/(^| )dropzone($| )/.test(el.className)) { 2938 result.push(dropzones.push(el)); 2939 } else { 2940 result.push(undefined); 2941 } 2942 } 2943 return result; 2944 }(); 2945 }; 2946 checkElements(document.getElementsByTagName("div")); 2947 checkElements(document.getElementsByTagName("form")); 2948 } 2949 2950 return function () { 2951 var result = []; 2952 for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) { 2953 var _ref33; 2954 2955 if (_isArray34) { 2956 if (_i36 >= _iterator34.length) break; 2957 _ref33 = _iterator34[_i36++]; 2958 } else { 2959 _i36 = _iterator34.next(); 2960 if (_i36.done) break; 2961 _ref33 = _i36.value; 2962 } 2963 2964 var dropzone = _ref33; 2965 2966 // Create a dropzone unless auto discover has been disabled for specific element 2967 if (Dropzone.optionsForElement(dropzone) !== false) { 2968 result.push(new Dropzone(dropzone)); 2969 } else { 2970 result.push(undefined); 2971 } 2972 } 2973 return result; 2974 }(); 2975}; 2976 2977// Since the whole Drag'n'Drop API is pretty new, some browsers implement it, 2978// but not correctly. 2979// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know. 2980// But what to do when browsers *theoretically* support an API, but crash 2981// when using it. 2982// 2983// This is a list of regular expressions tested against navigator.userAgent 2984// 2985// ** It should only be used on browser that *do* support the API, but 2986// incorrectly ** 2987// 2988Dropzone.blacklistedBrowsers = [ 2989// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API. 2990/opera.*(Macintosh|Windows Phone).*version\/12/i]; 2991 2992// Checks if the browser is supported 2993Dropzone.isBrowserSupported = function () { 2994 var capableBrowser = true; 2995 2996 if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { 2997 if (!("classList" in document.createElement("a"))) { 2998 capableBrowser = false;
2999 } else { 3000 // The browser supports the API, but may be blacklisted. 3001 for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) { 3002 var _ref34; 3003 3004 if (_isArray35) { 3005 if (_i37 >= _iterator35.length) break; 3006 _ref34 = _iterator35[_i37++]; 3007 } else { 3008 _i37 = _iterator35.next(); 3009 if (_i37.done) break; 3010 _ref34 = _i37.value; 3011 } 3012 3013 var regex = _ref34; 3014 3015 if (regex.test(navigator.userAgent)) { 3016 capableBrowser = false; 3017 continue; 3018 } 3019 } 3020 } 3021 } else { 3022 capableBrowser = false; 3023 } 3024 3025 return capableBrowser; 3026}; 3027 3028Dropzone.dataURItoBlob = function (dataURI) { 3029 // convert base64 to raw binary data held in a string 3030 // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this 3031 var byteString = atob(dataURI.split(',')[1]); 3032 3033 // separate out the mime component 3034 var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 3035 3036 // write the bytes of the string to an ArrayBuffer 3037 var ab = new ArrayBuffer(byteString.length); 3038 var ia = new Uint8Array(ab); 3039 for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) { 3040 ia[i] = byteString.charCodeAt(i); 3041 } 3042 3043 // write the ArrayBuffer to a blob 3044 return new Blob([ab], { type: mimeString }); 3045}; 3046 3047// Returns an array without the rejected item 3048var without = function without(list, rejectedItem) { 3049 return list.filter(function (item) { 3050 return item !== rejectedItem; 3051 }).map(function (item) { 3052 return item; 3053 }); 3054}; 3055 3056// abc-def_ghi -> abcDefGhi 3057var camelize = function camelize(str) { 3058 return str.replace(/[\-_](\w)/g, function (match) { 3059 return match.charAt(1).toUpperCase(); 3060 }); 3061}; 3062 3063// Creates an element from string 3064Dropzone.createElement = function (string) { 3065 var div = document.createElement("div"); 3066 div.innerHTML = string; 3067 return div.childNodes[0]; 3068}; 3069 3070// Tests if given element is inside (or simply is) the container 3071Dropzone.elementInside = function (element, container) { 3072 if (element === container) { 3073 return true; 3074 } // Coffeescript doesn't support do/while loops 3075 while (element = element.parentNode) { 3076 if (element === container) { 3077 return true; 3078 } 3079 } 3080 return false; 3081}; 3082 3083Dropzone.getElement = function (el, name) { 3084 var element = void 0; 3085 if (typeof el === "string") { 3086 element = document.querySelector(el); 3087 } else if (el.nodeType != null) { 3088 element = el; 3089 } 3090 if (element == null) { 3091 throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); 3092 } 3093 return element; 3094}; 3095 3096Dropzone.getElements = function (els, name) { 3097 var el = void 0, 3098 elements = void 0; 3099 if (els instanceof Array) { 3100 elements = []; 3101 try { 3102 for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) { 3103 if (_isArray36) { 3104 if (_i38 >= _iterator36.length) break; 3105 el = _iterator36[_i38++]; 3106 } else { 3107 _i38 = _iterator36.next(); 3108 if (_i38.done) break; 3109 el = _i38.value; 3110 } 3111 3112 elements.push(this.getElement(el, name)); 3113 } 3114 } catch (e) { 3115 elements = null; 3116 } 3117 } else if (typeof els === "string") { 3118 elements = [];
3119 for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) { 3120 if (_isArray37) { 3121 if (_i39 >= _iterator37.length) break; 3122 el = _iterator37[_i39++]; 3123 } else { 3124 _i39 = _iterator37.next(); 3125 if (_i39.done) break; 3126 el = _i39.value; 3127 } 3128 3129 elements.push(el); 3130 } 3131 } else if (els.nodeType != null) { 3132 elements = [els]; 3133 } 3134 3135 if (elements == null || !elements.length) { 3136 throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); 3137 } 3138 3139 return elements; 3140}; 3141 3142// Asks the user the question and calls accepted or rejected accordingly 3143// 3144// The default implementation just uses `window.confirm` and then calls the 3145// appropriate callback. 3146Dropzone.confirm = function (question, accepted, rejected) { 3147 if (window.confirm(question)) { 3148 return accepted(); 3149 } else if (rejected != null) { 3150 return rejected(); 3151 } 3152}; 3153 3154// Validates the mime type like this: 3155// 3156// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept 3157Dropzone.isValidFile = function (file, acceptedFiles) { 3158 if (!acceptedFiles) { 3159 return true; 3160 } // If there are no accepted mime types, it's OK 3161 acceptedFiles = acceptedFiles.split(","); 3162 3163 var mimeType = file.type; 3164 var baseMimeType = mimeType.replace(/\/.*$/, ""); 3165 3166 for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) { 3167 var _ref35; 3168 3169 if (_isArray38) { 3170 if (_i40 >= _iterator38.length) break; 3171 _ref35 = _iterator38[_i40++]; 3172 } else { 3173 _i40 = _iterator38.next(); 3174 if (_i40.done) break; 3175 _ref35 = _i40.value; 3176 } 3177 3178 var validType = _ref35; 3179 3180 validType = validType.trim(); 3181 if (validType.charAt(0) === ".") { 3182 if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) { 3183 return true; 3184 } 3185 } else if (/\/\*$/.test(validType)) { 3186 // This is something like a image/* mime type 3187 if (baseMimeType === validType.replace(/\/.*$/, "")) { 3188 return true; 3189 } 3190 } else { 3191 if (mimeType === validType) { 3192 return true; 3193 } 3194 } 3195 } 3196 3197 return false; 3198}; 3199 3200// Augment jQuery 3201if (typeof jQuery !== 'undefined' && jQuery !== null) { 3202 jQuery.fn.dropzone = function (options) { 3203 return this.each(function () { 3204 return new Dropzone(this, options); 3205 }); 3206 }; 3207} 3208 3209if (typeof module !== 'undefined' && module !== null) { 3210 module.exports = Dropzone; 3211} else { 3212 window.Dropzone = Dropzone; 3213} 3214 3215// Dropzone file status codes 3216Dropzone.ADDED = "added"; 3217 3218Dropzone.QUEUED = "queued"; 3219// For backwards compatibility. Now, if a file is accepted, it's either queued 3220// or uploading. 3221Dropzone.ACCEPTED = Dropzone.QUEUED; 3222 3223Dropzone.UPLOADING = "uploading"; 3224Dropzone.PROCESSING = Dropzone.UPLOADING; // alias 3225 3226Dropzone.CANCELED = "canceled"; 3227Dropzone.ERROR = "error"; 3228Dropzone.SUCCESS = "success"; 3229 3230/* 3231 3232 Bugfix for iOS 6 and 7 3233 Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios 3234 based on the work of https://github.com/stomita/ios-imagefile-megapixel 3235 3236 */ 3237 3238// Detecting vertical squash in loaded image. 3239// Fixes a bug which squash image vertically while drawing into canvas for some images. 3240// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel 3241var detectVerticalSquash = function detectVerticalSquash(img) { 3242 var iw = img.naturalWidth; 3243 var ih = img.naturalHeight; 3244 var canvas = document.createElement("canvas"); 3245 canvas.width = 1; 3246 canvas.height = ih; 3247 var ctx = canvas.getContext("2d"); 3248 ctx.drawImage(img, 0, 0); 3249 3250 var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih), 3251 data = _ctx$getImageData.data; 3252 3253 // search image edge pixel position in case it is squashed vertically. 3254 3255 3256 var sy = 0; 3257 var ey = ih; 3258 var py = ih; 3259 while (py > sy) { 3260 var alpha = data[(py - 1) * 4 + 3]; 3261 3262 if (alpha === 0) { 3263 ey = py; 3264 } else { 3265 sy = py; 3266 } 3267 3268 py = ey + sy >> 1; 3269 } 3270 var ratio = py / ih; 3271 3272 if (ratio === 0) { 3273 return 1; 3274 } else { 3275 return ratio; 3276 } 3277}; 3278 3279// A replacement for context.drawImage 3280// (args are for source and destination). 3281var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { 3282 var vertSquashRatio = detectVerticalSquash(img); 3283 return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); 3284}; 3285 3286// Based on MinifyJpeg 3287// Source: http://www.perry.cz/files/ExifRestorer.js 3288// http://elicon.blog57.fc2.com/blog-entry-206.html 3289 3290var ExifRestore = function () { 3291 function ExifRestore() { 3292 _classCallCheck(this, ExifRestore); 3293 } 3294 3295 _createClass(ExifRestore, null, [{ 3296 key: "initClass", 3297 value: function initClass() { 3298 this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
vendor: 6,814 bytes, lines 3298-3530
3298+/='; 3299 } 3300 }, { 3301 key: "encode64", 3302 value: function encode64(input) { 3303 var output = ''; 3304 var chr1 = undefined; 3305 var chr2 = undefined; 3306 var chr3 = ''; 3307 var enc1 = undefined; 3308 var enc2 = undefined; 3309 var enc3 = undefined; 3310 var enc4 = ''; 3311 var i = 0; 3312 while (true) { 3313 chr1 = input[i++]; 3314 chr2 = input[i++]; 3315 chr3 = input[i++]; 3316 enc1 = chr1 >> 2; 3317 enc2 = (chr1 & 3) << 4 | chr2 >> 4; 3318 enc3 = (chr2 & 15) << 2 | chr3 >> 6; 3319 enc4 = chr3 & 63; 3320 if (isNaN(chr2)) { 3321 enc3 = enc4 = 64; 3322 } else if (isNaN(chr3)) { 3323 enc4 = 64; 3324 } 3325 output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4); 3326 chr1 = chr2 = chr3 = ''; 3327 enc1 = enc2 = enc3 = enc4 = ''; 3328 if (!(i < input.length)) { 3329 break; 3330 } 3331 } 3332 return output; 3333 } 3334 }, { 3335 key: "restore", 3336 value: function restore(origFileBase64, resizedFileBase64) { 3337 if (!origFileBase64.match('data:image/jpeg;base64,')) { 3338 return resizedFileBase64; 3339 } 3340 var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', '')); 3341 var segments = this.slice2Segments(rawImage); 3342 var image = this.exifManipulation(resizedFileBase64, segments); 3343 return "data:image/jpeg;base64," + this.encode64(image); 3344 } 3345 }, { 3346 key: "exifManipulation", 3347 value: function exifManipulation(resizedFileBase64, segments) { 3348 var exifArray = this.getExifArray(segments); 3349 var newImageArray = this.insertExif(resizedFileBase64, exifArray); 3350 var aBuffer = new Uint8Array(newImageArray); 3351 return aBuffer; 3352 } 3353 }, { 3354 key: "getExifArray", 3355 value: function getExifArray(segments) { 3356 var seg = undefined; 3357 var x = 0; 3358 while (x < segments.length) { 3359 seg = segments[x]; 3360 if (seg[0] === 255 & seg[1] === 225) { 3361 return seg; 3362 } 3363 x++; 3364 } 3365 return []; 3366 } 3367 }, { 3368 key: "insertExif", 3369 value: function insertExif(resizedFileBase64, exifArray) { 3370 var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', ''); 3371 var buf = this.decode64(imageData); 3372 var separatePoint = buf.indexOf(255, 3); 3373 var mae = buf.slice(0, separatePoint); 3374 var ato = buf.slice(separatePoint); 3375 var array = mae; 3376 array = array.concat(exifArray); 3377 array = array.concat(ato); 3378 return array; 3379 } 3380 }, { 3381 key: "slice2Segments", 3382 value: function slice2Segments(rawImageArray) { 3383 var head = 0; 3384 var segments = []; 3385 while (true) { 3386 var length; 3387 if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) { 3388 break; 3389 } 3390 if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) { 3391 head += 2; 3392 } else { 3393 length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3]; 3394 var endPoint = head + length + 2; 3395 var seg = rawImageArray.slice(head, endPoint); 3396 segments.push(seg); 3397 head = endPoint; 3398 } 3399 if (head > rawImageArray.length) { 3400 break; 3401 } 3402 } 3403 return segments; 3404 } 3405 }, { 3406 key: "decode64", 3407 value: function decode64(input) { 3408 var output = ''; 3409 var chr1 = undefined; 3410 var chr2 = undefined; 3411 var chr3 = ''; 3412 var enc1 = undefined; 3413 var enc2 = undefined; 3414 var enc3 = undefined; 3415 var enc4 = ''; 3416 var i = 0; 3417 var buf = []; 3418 // remove all characters that are not A-Z, a-z, 0-9, +, /, or = 3419 var base64test = /[^A-Za-z0-9\+\/\=]/g; 3420 if (base64test.exec(input)) { 3421 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.'); 3422 } 3423 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); 3424 while (true) { 3425 enc1 = this.KEY_STR.indexOf(input.charAt(i++)); 3426 enc2 = this.KEY_STR.indexOf(input.charAt(i++)); 3427 enc3 = this.KEY_STR.indexOf(input.charAt(i++)); 3428 enc4 = this.KEY_STR.indexOf(input.charAt(i++)); 3429 chr1 = enc1 << 2 | enc2 >> 4; 3430 chr2 = (enc2 & 15) << 4 | enc3 >> 2; 3431 chr3 = (enc3 & 3) << 6 | enc4; 3432 buf.push(chr1); 3433 if (enc3 !== 64) { 3434 buf.push(chr2); 3435 } 3436 if (enc4 !== 64) { 3437 buf.push(chr3); 3438 } 3439 chr1 = chr2 = chr3 = ''; 3440 enc1 = enc2 = enc3 = enc4 = ''; 3441 if (!(i < input.length)) { 3442 break; 3443 } 3444 } 3445 return buf; 3446 } 3447 }]); 3448 3449 return ExifRestore; 3450}(); 3451 3452ExifRestore.initClass(); 3453 3454/* 3455 * contentloaded.js 3456 * 3457 * Author: Diego Perini (diego.perini at gmail.com) 3458 * Summary: cross-browser wrapper for DOMContentLoaded 3459 * Updated: 20101020 3460 * License: MIT 3461 * Version: 1.2 3462 * 3463 * URL: 3464 * http://javascript.nwbox.com/ContentLoaded/ 3465 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE 3466 */ 3467 3468// @win window reference 3469// @fn function reference 3470var contentLoaded = function contentLoaded(win, fn) { 3471 var done = false; 3472 var top = true; 3473 var doc = win.document; 3474 var root = doc.documentElement; 3475 var add = doc.addEventListener ? "addEventListener" : "attachEvent"; 3476 var rem = doc.addEventListener ? "removeEventListener" : "detachEvent"; 3477 var pre = doc.addEventListener ? "" : "on"; 3478 var init = function init(e) { 3479 if (e.type === "readystatechange" && doc.readyState !== "complete") { 3480 return; 3481 } 3482 (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); 3483 if (!done && (done = true)) { 3484 return fn.call(win, e.type || e); 3485 } 3486 }; 3487 3488 var poll = function poll() { 3489 try { 3490 root.doScroll("left"); 3491 } catch (e) { 3492 setTimeout(poll, 50); 3493 return; 3494 } 3495 return init("poll"); 3496 }; 3497 3498 if (doc.readyState !== "complete") { 3499 if (doc.createEventObject && root.doScroll) { 3500 try { 3501 top = !win.frameElement; 3502 } catch (error) {} 3503 if (top) { 3504 poll(); 3505 } 3506 } 3507 doc[add](pre + "DOMContentLoaded", init, false); 3508 doc[add](pre + "readystatechange", init, false); 3509 return win[add](pre + "load", init, false); 3510 } 3511}; 3512 3513// As a single function to be able to write tests. 3514Dropzone._autoDiscoverFunction = function () { 3515 if (Dropzone.autoDiscover) { 3516 return Dropzone.discover(); 3517 } 3518}; 3519contentLoaded(window, Dropzone._autoDiscoverFunction); 3520 3521function __guard__(value, transform) { 3522 return typeof value !== 'undefined' && value !== null ? transform(value) : undefined; 3523} 3524function __guardMethod__(obj, methodName, transform) { 3525 if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') { 3526 return transform(obj, methodName); 3527 } else { 3528 return undefined; 3529 } 3530}
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.