Skip to content

Instantly share code, notes, and snippets.

@trackleaf
Created June 26, 2019 15:21
Show Gist options
  • Save trackleaf/844916952cd54084a3796deb033ee23b to your computer and use it in GitHub Desktop.
Save trackleaf/844916952cd54084a3796deb033ee23b to your computer and use it in GitHub Desktop.
Drag and Drop Web Component // source https://jsbin.com/wonohof
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Drag and Drop Web Component</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.1.1/webcomponents-lite.js"></script>
</head>
<body>
<drag-drop url="/uploads/process"></drag-drop>
<drag-drop-file-list>
<drag-drop-file name="my_photo.png" size="34M" progress="26"></drag-drop-file>
</drag-drop-file-list>
<script id="jsbin-javascript">
window.customElements.define('drag-drop', class extends HTMLElement {
constructor() {
super(); // always call super
// set markup
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(this.render());
}
// lifecycle method that creates our event listeners
connectedCallback() {
// click to upload
this.addEventListener('click', this.clickUpload, false);
// prevent defaults on following events
;['dragenter', 'dragover', 'drop', 'dragleave'].forEach(eventName => {
this.addEventListener(eventName, this.preventDefaults, false)
});
// highlight
;['dragenter', 'dragover'].forEach(eventName => {
this.addEventListener(eventName, this.highlight, false)
});
// unhighlight
;['dragleave', 'drop'].forEach(eventName => {
this.addEventListener(eventName, this.unhighlight, false)
});
// file drop
this.addEventListener('drop', this.handleFileDrop);
}
disconnectedCallback() {
// TODO: REMOVE ALL event listeners
this.removeEventListener('click', this.clickUpload);
// prevent defaults on following events
;['dragenter', 'dragover', 'drop', 'dragleave'].forEach(eventName => {
this.removeEventListener(eventName, this.preventDefaults)
});
// highlight
;['dragenter', 'dragover'].forEach(eventName => {
this.removeEventListener(eventName, this.highlight)
});
// unhighlight
;['dragleave', 'drop'].forEach(eventName => {
this.removeEventListener(eventName, this.unhighlight)
});
// file drop
this.removeEventListener('drop', this.handleFileDrop);
}
static get observedAttributes() {
return ['url'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
this[attrName] = newVal;
}
clickUpload(evt) {
console.log('open dialog');
}
handleFileDrop(evt) {
let dt = evt.dataTransfer
let files = dt.files
this.handleFiles(files)
}
handleFiles(files) {
([...files]).forEach(this.uploadFile.bind(this));
}
uploadFile(file) {
let url = this._url;
let formData = new FormData();
console.log(url, file);
//formData.append('file', file)
// fetch(url, {
// method: 'POST',
// body: formData
// })
// .then(() => { console.log('Done. Inform the user'); })
// .catch(() => { console.log('Error. Inform the user'); });
}
highlight(evt) {
//console.log('highlight');
}
unhighlight(evt) {
//console.log('unhighlight');
}
preventDefaults(evt) {
evt.preventDefault()
evt.stopPropagation()
}
set url(url) {
if (this._url === url) return;
this._url = url;
/* Update the DOM as necessary or dispatch event if needed */
}
get url() {
return this._url;
}
/*
Method to render the template for Sahow DOM
*/
render() {
// create the template
let tmpl = document.createElement('template');
// add the stuff
tmpl.innerHTML = `
<style>
:host>div {
border: 1px dashed grey;
border-radius: 4px;
height: 125px;
width: 300px;
text-align: center;
display: grid;
grid-template-columns: 1fr;
cursor: pointer;
}
:host>div:hover {
background-color: pink;
}
#main {
font-weight: 600;
}
#text {
color: blue;
text-decoration: underline;
font-size: small;
}
#arrow-up {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid black;
margin-left: 50%;
margin-right: 50%;
padding-top: 20px;
}
</style>
<div>
<div><div id="arrow-up"></div></div>
<div id="main">Drag and Drop files here</div>
<div id="text">or select a file</div>
</div>
`;
// return the stuff for use with shadowRoot.appendChild
return tmpl.content.cloneNode(true);
}
});
</script>
<script id="jsbin-source-javascript" type="text/javascript">window.customElements.define('drag-drop', class extends HTMLElement {
constructor() {
super(); // always call super
// set markup
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(this.render());
}
// lifecycle method that creates our event listeners
connectedCallback() {
// click to upload
this.addEventListener('click', this.clickUpload, false);
// prevent defaults on following events
;['dragenter', 'dragover', 'drop', 'dragleave'].forEach(eventName => {
this.addEventListener(eventName, this.preventDefaults, false)
});
// highlight
;['dragenter', 'dragover'].forEach(eventName => {
this.addEventListener(eventName, this.highlight, false)
});
// unhighlight
;['dragleave', 'drop'].forEach(eventName => {
this.addEventListener(eventName, this.unhighlight, false)
});
// file drop
this.addEventListener('drop', this.handleFileDrop);
}
disconnectedCallback() {
// TODO: REMOVE ALL event listeners
this.removeEventListener('click', this.clickUpload);
// prevent defaults on following events
;['dragenter', 'dragover', 'drop', 'dragleave'].forEach(eventName => {
this.removeEventListener(eventName, this.preventDefaults)
});
// highlight
;['dragenter', 'dragover'].forEach(eventName => {
this.removeEventListener(eventName, this.highlight)
});
// unhighlight
;['dragleave', 'drop'].forEach(eventName => {
this.removeEventListener(eventName, this.unhighlight)
});
// file drop
this.removeEventListener('drop', this.handleFileDrop);
}
static get observedAttributes() {
return ['url'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
this[attrName] = newVal;
}
clickUpload(evt) {
console.log('open dialog');
}
handleFileDrop(evt) {
let dt = evt.dataTransfer
let files = dt.files
this.handleFiles(files)
}
handleFiles(files) {
([...files]).forEach(this.uploadFile.bind(this));
}
uploadFile(file) {
let url = this._url;
let formData = new FormData();
console.log(url, file);
//formData.append('file', file)
// fetch(url, {
// method: 'POST',
// body: formData
// })
// .then(() => { console.log('Done. Inform the user'); })
// .catch(() => { console.log('Error. Inform the user'); });
}
highlight(evt) {
//console.log('highlight');
}
unhighlight(evt) {
//console.log('unhighlight');
}
preventDefaults(evt) {
evt.preventDefault()
evt.stopPropagation()
}
set url(url) {
if (this._url === url) return;
this._url = url;
/* Update the DOM as necessary or dispatch event if needed */
}
get url() {
return this._url;
}
/*
Method to render the template for Sahow DOM
*/
render() {
// create the template
let tmpl = document.createElement('template');
// add the stuff
tmpl.innerHTML = `
<style>
:host>div {
border: 1px dashed grey;
border-radius: 4px;
height: 125px;
width: 300px;
text-align: center;
display: grid;
grid-template-columns: 1fr;
cursor: pointer;
}
:host>div:hover {
background-color: pink;
}
#main {
font-weight: 600;
}
#text {
color: blue;
text-decoration: underline;
font-size: small;
}
#arrow-up {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid black;
margin-left: 50%;
margin-right: 50%;
padding-top: 20px;
}
</style>
<div>
<div><div id="arrow-up"></div></div>
<div id="main">Drag and Drop files here</div>
<div id="text">or select a file</div>
</div>
`;
// return the stuff for use with shadowRoot.appendChild
return tmpl.content.cloneNode(true);
}
});</script></body>
</html>
window.customElements.define('drag-drop', class extends HTMLElement {
constructor() {
super(); // always call super
// set markup
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(this.render());
}
// lifecycle method that creates our event listeners
connectedCallback() {
// click to upload
this.addEventListener('click', this.clickUpload, false);
// prevent defaults on following events
;['dragenter', 'dragover', 'drop', 'dragleave'].forEach(eventName => {
this.addEventListener(eventName, this.preventDefaults, false)
});
// highlight
;['dragenter', 'dragover'].forEach(eventName => {
this.addEventListener(eventName, this.highlight, false)
});
// unhighlight
;['dragleave', 'drop'].forEach(eventName => {
this.addEventListener(eventName, this.unhighlight, false)
});
// file drop
this.addEventListener('drop', this.handleFileDrop);
}
disconnectedCallback() {
// TODO: REMOVE ALL event listeners
this.removeEventListener('click', this.clickUpload);
// prevent defaults on following events
;['dragenter', 'dragover', 'drop', 'dragleave'].forEach(eventName => {
this.removeEventListener(eventName, this.preventDefaults)
});
// highlight
;['dragenter', 'dragover'].forEach(eventName => {
this.removeEventListener(eventName, this.highlight)
});
// unhighlight
;['dragleave', 'drop'].forEach(eventName => {
this.removeEventListener(eventName, this.unhighlight)
});
// file drop
this.removeEventListener('drop', this.handleFileDrop);
}
static get observedAttributes() {
return ['url'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
this[attrName] = newVal;
}
clickUpload(evt) {
console.log('open dialog');
}
handleFileDrop(evt) {
let dt = evt.dataTransfer
let files = dt.files
this.handleFiles(files)
}
handleFiles(files) {
([...files]).forEach(this.uploadFile.bind(this));
}
uploadFile(file) {
let url = this._url;
let formData = new FormData();
console.log(url, file);
//formData.append('file', file)
// fetch(url, {
// method: 'POST',
// body: formData
// })
// .then(() => { console.log('Done. Inform the user'); })
// .catch(() => { console.log('Error. Inform the user'); });
}
highlight(evt) {
//console.log('highlight');
}
unhighlight(evt) {
//console.log('unhighlight');
}
preventDefaults(evt) {
evt.preventDefault()
evt.stopPropagation()
}
set url(url) {
if (this._url === url) return;
this._url = url;
/* Update the DOM as necessary or dispatch event if needed */
}
get url() {
return this._url;
}
/*
Method to render the template for Sahow DOM
*/
render() {
// create the template
let tmpl = document.createElement('template');
// add the stuff
tmpl.innerHTML = `
<style>
:host>div {
border: 1px dashed grey;
border-radius: 4px;
height: 125px;
width: 300px;
text-align: center;
display: grid;
grid-template-columns: 1fr;
cursor: pointer;
}
:host>div:hover {
background-color: pink;
}
#main {
font-weight: 600;
}
#text {
color: blue;
text-decoration: underline;
font-size: small;
}
#arrow-up {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid black;
margin-left: 50%;
margin-right: 50%;
padding-top: 20px;
}
</style>
<div>
<div><div id="arrow-up"></div></div>
<div id="main">Drag and Drop files here</div>
<div id="text">or select a file</div>
</div>
`;
// return the stuff for use with shadowRoot.appendChild
return tmpl.content.cloneNode(true);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment