Native Drag n Drop
by amindunited
HTML
<drag-subject srcElement=true>Drag Subject 01</drag-subject>
<drag-subject srcElement=true>Drag Subject 02</drag-subject>
<drag-subject srcElement=true>Drag Subject 03</drag-subject>
<hr/>
<drag-subject>Drag to here</drag-subject>
CSS
drag-subject {
display: inline-block;
padding: 8px;
margin: 8px;
border: solid 1px green;
}
drop-target {
display: block;
width: 200px;
height: 200px;
border: solid 1px green;
}
.hovered {
background-color: azure;
}
.drag-placeholder {
border: dashed 1px gray;
min-height: 200px;
min-width: 50%;
}
JavaScript
class DragSubject extends HTMLElement {
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open'});
}
render () {
const frag = document.createDocumentFragment();
const container = document.createElement('slot');
frag.appendChild(container);
this.shadow.appendChild(frag);
}
/**
* When this element is Dragged
*/
handleDrag (e) {
e.stopImmediatePropagation();
console.log('im being dragged');
e.dataTransfer.setData('tag-name', this.tagName);
e.dataTransfer.setData('text/html', this.innerHTML);
}
handleDragEnd (e) {
e.preventDefault();
// e.stopImmediatePropagation();
console.log('drag End', e, this);
console.log('is srcElement', e);
// If this isn't a srElement we are moving it, so we remove the original
if (!e.target.getAttribute('srcElement')) {
this.parentElement.removeChild(this);
}
}
removeOldPlaceHolder () {
const oldPlaceholders = this.querySelectorAll('.drag-placeholder');
[...oldPlaceholders].forEach((oldPlaceholder) => {
if (oldPlaceholder && oldPlaceholder.parentElement === this) {
this.removeChild(oldPlaceholder);
}
});
}
createPlaceholder (e) {
const placeholder = document.createElement('div');
placeholder.classList.add('drag-placeholder');
if (this.childSubjects && this.childSubjects.length > 0) {
console.log('has child subjects');
// It will never be over a child, because the child will take the drag over event
const childToInsertBefore = this.childSubjects.find((elm) => {
if ((e.pageX < elm.offsetLeft) || (e.pageY < elm.offsetTop)) {
return true;
}
return false;
});
this.removeOldPlaceHolder();
this.insertBefore(placeholder, childToInsertBefore);
} else {
const currentPlaceholder = [...this.childNodes].find((elm) => {
return (elm.classList && elm.classList.contains('drag-placeholder'));
...