index.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import Plugin from './../Plugin'
  2. import { toArray } from '../../core/Utils'
  3. import dragDrop from 'drag-drop'
  4. import html from '../../core/html'
  5. /**
  6. * Drag & Drop plugin
  7. *
  8. */
  9. export default class DragDrop extends Plugin {
  10. constructor (core, opts, props) {
  11. super(core, opts)
  12. this.type = 'acquirer'
  13. this.id = 'DragDrop'
  14. this.title = 'Drag & Drop'
  15. this.props = props
  16. this.icon = html`
  17. <svg class="UppyIcon" width="28" height="28" viewBox="0 0 16 16">
  18. <path d="M15.982 2.97c0-.02 0-.02-.018-.037 0-.017-.017-.035-.035-.053 0 0 0-.018-.02-.018-.017-.018-.034-.053-.052-.07L13.19.123c-.017-.017-.034-.035-.07-.053h-.018c-.018-.017-.035-.017-.053-.034h-.02c-.017 0-.034-.018-.052-.018h-6.31a.415.415 0 0 0-.446.426V11.11c0 .25.196.446.445.446h8.89A.44.44 0 0 0 16 11.11V3.023c-.018-.018-.018-.035-.018-.053zm-2.65-1.46l1.157 1.157h-1.157V1.51zm1.78 9.157h-8V.89h5.332v2.22c0 .25.196.446.445.446h2.22v7.11z"/>
  19. <path d="M9.778 12.89H4V2.666a.44.44 0 0 0-.444-.445.44.44 0 0 0-.445.445v10.666c0 .25.197.445.446.445h6.222a.44.44 0 0 0 .444-.445.44.44 0 0 0-.444-.444z"/>
  20. <path d="M.444 16h6.223a.44.44 0 0 0 .444-.444.44.44 0 0 0-.443-.445H.89V4.89a.44.44 0 0 0-.446-.446A.44.44 0 0 0 0 4.89v10.666c0 .248.196.444.444.444z"/>
  21. </svg>
  22. `
  23. // Default options
  24. const defaultOpts = {
  25. target: '.UppyDragDrop'
  26. }
  27. // Merge default options with the ones set by user
  28. this.opts = Object.assign({}, defaultOpts, opts)
  29. // Check for browser dragDrop support
  30. this.isDragDropSupported = this.checkDragDropSupport()
  31. // Bind `this` to class methods
  32. this.handleDrop = this.handleDrop.bind(this)
  33. this.checkDragDropSupport = this.checkDragDropSupport.bind(this)
  34. this.handleInputChange = this.handleInputChange.bind(this)
  35. this.render = this.render.bind(this)
  36. }
  37. /**
  38. * Checks if the browser supports Drag & Drop (not supported on mobile devices, for example).
  39. * @return {Boolean} true if supported, false otherwise
  40. */
  41. checkDragDropSupport () {
  42. const div = document.createElement('div')
  43. if (!('draggable' in div) || !('ondragstart' in div && 'ondrop' in div)) {
  44. return false
  45. }
  46. if (!('FormData' in window)) {
  47. return false
  48. }
  49. if (!('FileReader' in window)) {
  50. return false
  51. }
  52. return true
  53. }
  54. handleDrop (files) {
  55. this.core.log('All right, someone dropped something...')
  56. files.forEach((file) => {
  57. this.props.addFile({
  58. source: this.id,
  59. name: file.name,
  60. type: file.type,
  61. data: file
  62. })
  63. // this.core.emitter.emit('file-add', {
  64. // source: this.id,
  65. // name: file.name,
  66. // type: file.type,
  67. // data: file
  68. // })
  69. })
  70. }
  71. handleInputChange (ev) {
  72. this.core.log('All right, something selected through input...')
  73. const files = toArray(ev.target.files)
  74. files.forEach((file) => {
  75. console.log(file)
  76. this.core.emitter.emit('file-add', {
  77. source: this.id,
  78. name: file.name,
  79. type: file.type,
  80. data: file
  81. })
  82. })
  83. }
  84. focus () {
  85. const firstInput = document.querySelector(`${this.target} .UppyDragDrop-focus`)
  86. // only works for the first time if wrapped in setTimeout for some reason
  87. // firstInput.focus()
  88. setTimeout(function () {
  89. firstInput.focus()
  90. }, 10)
  91. }
  92. render (state) {
  93. // Another way not to render next/upload button — if Modal is used as a target
  94. const target = this.opts.target.name
  95. const onSelect = (ev) => {
  96. const input = document.querySelector(`${this.target} .UppyDragDrop-input`)
  97. input.click()
  98. }
  99. const next = (ev) => {
  100. ev.preventDefault()
  101. ev.stopPropagation()
  102. this.core.emitter.emit('core:upload')
  103. }
  104. const onSubmit = (ev) => {
  105. ev.preventDefault()
  106. }
  107. return html`
  108. <div class="UppyDragDrop-container ${this.isDragDropSupported ? 'is-dragdrop-supported' : ''}">
  109. <form class="UppyDragDrop-inner"
  110. onsubmit=${onSubmit}>
  111. <input class="UppyDragDrop-input UppyDragDrop-focus"
  112. type="file"
  113. name="files[]"
  114. multiple="true"
  115. value=""
  116. onchange=${this.handleInputChange.bind(this)} />
  117. <label class="UppyDragDrop-label" onclick=${onSelect}>
  118. <strong>${this.core.i18n('chooseFile')}</strong>
  119. <span class="UppyDragDrop-dragText">${this.core.i18n('orDragDrop')}</span>
  120. </label>
  121. ${!this.core.opts.autoProceed && target !== 'Dashboard'
  122. ? html`<button class="UppyDragDrop-uploadBtn UppyNextBtn"
  123. type="submit"
  124. onclick=${next}>
  125. ${this.core.i18n('upload')}
  126. </button>`
  127. : ''}
  128. </form>
  129. </div>
  130. `
  131. }
  132. install () {
  133. const target = this.opts.target
  134. const plugin = this
  135. this.target = this.mount(target, plugin)
  136. dragDrop(`${this.target} .UppyDragDrop-container`, (files) => {
  137. this.handleDrop(files)
  138. this.core.log(files)
  139. })
  140. }
  141. }