Skip to content

Instantly share code, notes, and snippets.

@chrise86
Forked from pizzarob/01_DropZone.jsx
Created August 20, 2016 17:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chrise86/1a8a76476bb88249801ceb3491fde20e to your computer and use it in GitHub Desktop.
Save chrise86/1a8a76476bb88249801ceb3491fde20e to your computer and use it in GitHub Desktop.
HTML5 Drag and Drop React Component
$primary: blue;
$secondary: red;
.drop-it-wrap{
width: 100%;
border: 5px dashed #ececec;
height: 250px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.loader{
display: none;
}
&.uploading{
.loader{
display: block;
}
.default{
display: none;
}
}
&.active{
border-color: $primary;
}
&:hover{
border: 5px dashed darken(#ececec, 10%);
}
}
.drop-it-input{
position: absolute;
top: -99999999px;
}
@keyframes disco {
0% {
background: $primary;
}
100% {
background: $secondary;
}
}
.batch {
cursor: crosshair;
&.uploading {
animation: disco .1s infinite alternate;
}
background: #ffffff;
}
import React, {PropTypes} from 'react';
import classNames from 'classnames';
class BatchDropZone extends React.Component {
static propTypes = {
// function that recieves an array of files
receiveFiles: PropTypes.func.isRequired,
// if single is set then file input will NOT be multiple
single: PropTypes.bool,
// text message that will appear in drop zone
copy: PropTypes.string,
className: PropTypes.string,
}
constructor() {
super();
this.state = {};
this.handleDragOver = this.handleDragOver.bind(this);
this.handleDrop = this.handleDrop.bind(this);
this.handleDragLeave = this.handleDragLeave.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleDragOver(e) {
e.preventDefault();
if (this.state.inDropZone)
return;
this.setState({inDropZone: true});
}
handleDrop(e) {
e.preventDefault();
const { dataTransfer } = e;
const files = [];
if (dataTransfer.items) {
for (let i = this.props.single ? dataTransfer.items.length - 1 : 0; i < dataTransfer.items.length; i ++) {
if (dataTransfer.items[i].kind == "file") {
let file = dataTransfer.items[i].getAsFile();
files.push(file);
}
}
} else {
for (let i = this.props.single ? dataTransfer.files.length - 1 : 0; i < dataTransfer.files.length; i ++) {
files.push(dataTransfer.files[i]);
}
}
this.setState({
uploading: true
});
setTimeout(() => {
this.setState({
uploading: false
});
this.props.receiveFiles(files);
}, 1000);
}
handleDragLeave() {
if (!this.state.inDropZone)
return;
this.setState({inDropZone: false});
}
handleClick() {
this.refs.fileInput.click();
}
handleFilesFromInput(e) {
let files = [];
Array.from(e.currentTarget.files).forEach(file => {
files.push(file);
});
this.props.receiveFiles(files);
}
render() {
let classes = classNames(`drop-it-wrap batch ${this.props.className || ''}`, {
'active': this.state.inDropZone,
'uploading': this.state.uploading
});
const dropEvents = {
onDrop: this.handleDrop,
onDragOver: this.handleDragOver,
onDragLeave: this.handleDragLeave,
onClick: this.handleClick
};
let err;
if(this.state.error){
err = (
<div className="notification danger">
{this.state.error}
</div>
);
}
const fileInputAttrs = {
ref: 'fileInput',
type: 'file',
onChange: this.handleFilesFromInput.bind(this),
style: { position: 'absolute', left: -99999999 },
};
if (!this.props.single) {
fileInputAttrs.multiple = true;
}
return (
<div style={{width:'100%', height: '100%'}}>
{err}
<div className={classes} {...dropEvents}>
<div className="loader">
Processing ...
</div>
<input {...fileInputAttrs} />
<div className="default">
{this.props.copy || 'Drop image files here or click'}
</div>
</div>
</div>
);
}
}
export default BatchDropZone;
import DropZone from './DropZone';
export const readAsBase64 = (file) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.addEventListener('load', () => {
resolve({file, dataURL: reader.result});
});
reader.readAsDataURL(file);
});
}
export default DropZone;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment