Last active
October 6, 2023 13:03
-
-
Save daliborgogic/f2709d6923f1103b0e0dcaeac87c6fee to your computer and use it in GitHub Desktop.
Input type file component with drag and drop (Vue.js)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div ref="div"> | |
<label> | |
<strong v-if="progress === 0"> | |
{{ label }} | |
<svg width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg> | |
</strong> | |
<strong v-if="progress > 0 && progress < 100"> {{ progress }}%</strong> | |
<span v-else>{{ name }}</span> | |
<input ref="input" type="file" :accept="accept" @change="onFileChange"/> | |
</label> | |
<svg v-if="progress === 100" @click="removeFile" width="24" height="24" viewBox="0 0 24 24"> | |
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path> | |
<path d="M0 0h24v24H0z" fill="none"></path> | |
</svg> | |
<pre>{{ error }}</pre> | |
</div> | |
</template> | |
<script> | |
export default { | |
props: { | |
label: { | |
type: String, | |
default: 'Drag and Drop' | |
}, | |
accept: { | |
type: String, | |
default: '*' // image/png, image/jpeg, application/pdf, application/vnd.ms-excel | |
} | |
}, | |
data () { | |
return { | |
file: null, | |
name: null, | |
progress: 0, | |
error: null, | |
dragAndDropCapable: true | |
} | |
}, | |
mounted () { | |
const { div } = this.$refs | |
// Determine if drag and drop functionality is capable in the browser | |
this.dragAndDropCapable = this.isDragAndDropCapable() | |
if(this.dragAndDropCapable) { | |
['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach( event => { | |
document.body.addEventListener(event, e => { | |
e.preventDefault() | |
e.stopPropagation() | |
// if (e.type === 'dragover') { | |
// console.log('dragover', div) // eslint-disable-line | |
// div.classList.add('dragover') | |
// } | |
}) | |
}) | |
div.addEventListener('drop', e => { | |
this.onFileChange(e) | |
}) | |
} | |
}, | |
methods: { | |
isDragAndDropCapable () { | |
const { div } = this.$refs | |
return (('draggable' in div) | |
|| ('ondragstart' in div && 'ondrop' in div)) | |
&& 'FormData' in window | |
&& 'FileReader' in window | |
}, | |
onFileChange(e) { | |
// e.preventDefault() | |
const files = e.target.files || e.dataTransfer.files | |
if (!files.length) | |
return | |
this.createFile(files[0]) | |
}, | |
createFile(file) { | |
const reader = new FileReader() | |
const vm = this | |
reader.onprogress = e => { | |
if (e.lengthComputable) { | |
vm.trackProgress(e.loaded, e.total) | |
} | |
} | |
reader.onloadend = e => { | |
const { error } = e.target | |
if (error != null) { | |
switch (error.code) { | |
case error.ENCODING_ERR: | |
vm.error = 'Encoding error!' | |
break | |
case error.NOT_FOUND_ERR: | |
vm.error = 'File not found!' | |
break | |
case error.NOT_READABLE_ERR: | |
vm.error = 'File could not be read!' | |
break | |
case error.SECURITY_ERR: | |
vm.error = 'Security issue with file!' | |
break | |
default: | |
vm.error = 'I have no idea what\'s wrong!' | |
} | |
} | |
vm.trackProgress(e.loaded, e.total) | |
} | |
reader.onload = e => { | |
const { result } = e.target | |
vm.file = result | |
// this.$emit('load', result) | |
vm.name = file.name | |
} | |
reader.readAsBinaryString(file) | |
}, | |
trackProgress (loaded, total) { | |
this.progress = parseInt(((loaded / total) * 100), 10) | |
}, | |
removeFile () { | |
this.progress = 0 | |
this.file = '' | |
this.name = null | |
// this.$emit('load', null) | |
} | |
} | |
} | |
</script> | |
<style scoped> | |
input[type="file"] { | |
display: none; | |
} | |
strong, | |
svg { | |
vertical-align: middle; | |
} | |
</style> |
Author
daliborgogic
commented
Sep 26, 2018
•
- handle errors
- UI for non capable browsers
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment