uppy
Version:
Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:
159 lines (136 loc) • 4.2 kB
JavaScript
const Plugin = require('../../core/Plugin')
const Translator = require('../../core/Translator')
const { toArray } = require('../../core/Utils')
const dragDrop = require('drag-drop')
const { h } = require('preact')
/**
* Drag & Drop plugin
*
*/
module.exports = class DragDrop extends Plugin {
constructor (uppy, opts) {
super(uppy, opts)
this.type = 'acquirer'
this.id = this.opts.id || 'DragDrop'
this.title = 'Drag & Drop'
const defaultLocale = {
strings: {
dropHereOr: 'Drop files here or',
browse: 'browse'
}
}
// Default options
const defaultOpts = {
target: null,
width: '100%',
height: '100%',
note: '',
locale: defaultLocale
}
// Merge default options with the ones set by user
this.opts = Object.assign({}, defaultOpts, opts)
// Check for browser dragDrop support
this.isDragDropSupported = this.checkDragDropSupport()
this.locale = Object.assign({}, defaultLocale, this.opts.locale)
this.locale.strings = Object.assign({}, defaultLocale.strings, this.opts.locale.strings)
// i18n
this.translator = new Translator({locale: this.locale})
this.i18n = this.translator.translate.bind(this.translator)
// Bind `this` to class methods
this.handleDrop = this.handleDrop.bind(this)
this.handleBrowseClick = this.handleBrowseClick.bind(this)
this.handleInputChange = this.handleInputChange.bind(this)
this.checkDragDropSupport = this.checkDragDropSupport.bind(this)
this.render = this.render.bind(this)
}
/**
* Checks if the browser supports Drag & Drop (not supported on mobile devices, for example).
* @return {Boolean}
*/
checkDragDropSupport () {
const div = document.createElement('div')
if (!('draggable' in div) || !('ondragstart' in div && 'ondrop' in div)) {
return false
}
if (!('FormData' in window)) {
return false
}
if (!('FileReader' in window)) {
return false
}
return true
}
handleDrop (files) {
this.uppy.log('[DragDrop] Files dropped')
files.forEach((file) => {
this.uppy.addFile({
source: this.id,
name: file.name,
type: file.type,
data: file
}).catch(() => {
// Ignore
})
})
}
handleInputChange (ev) {
this.uppy.log('[DragDrop] Files selected through input')
const files = toArray(ev.target.files)
files.forEach((file) => {
this.uppy.addFile({
source: this.id,
name: file.name,
type: file.type,
data: file
}).catch(() => {
// Ignore
})
})
}
handleBrowseClick (ev) {
ev.stopPropagation()
this.input.click()
}
render (state) {
const DragDropClass = `uppy uppy-DragDrop-container ${this.isDragDropSupported ? 'is-dragdrop-supported' : ''}`
const DragDropStyle = {
width: this.opts.width,
height: this.opts.height
}
return (
<div class={DragDropClass} style={DragDropStyle}>
<div class="uppy-DragDrop-inner">
<svg aria-hidden="true" class="UppyIcon uppy-DragDrop-arrow" width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M11 10V0H5v10H2l6 6 6-6h-3zm0 0" fill-rule="evenodd" />
</svg>
<input class="uppy-DragDrop-input"
type="file"
name="files[]"
multiple="true"
ref={(input) => {
this.input = input
}}
onchange={this.handleInputChange} />
<label class="uppy-DragDrop-label" onclick={this.handleBrowseClick}>
{this.i18n('dropHereOr')} <span class="uppy-DragDrop-dragText">{this.i18n('browse')}</span>
</label>
<span class="uppy-DragDrop-note">{this.opts.note}</span>
</div>
</div>
)
}
install () {
const target = this.opts.target
if (target) {
this.mount(target, this)
}
this.removeDragDropListener = dragDrop(this.el, (files) => {
this.handleDrop(files)
this.uppy.log(files)
})
}
uninstall () {
this.unmount()
this.removeDragDropListener()
}
}