Skip to content

Instantly share code, notes, and snippets.

@lgfa29
Last active April 8, 2020 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lgfa29/6f1a5806647fee19765bdcc8a49f1733 to your computer and use it in GitHub Desktop.
Save lgfa29/6f1a5806647fee19765bdcc8a49f1733 to your computer and use it in GitHub Desktop.
(function(dragClass, dropZoneId) {
//
// Classes
//
// Point is a representation of (X, Y) coordinates
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.subtract = function(other) {
return new Point(this.x - other.x, this.y - other.y);
};
Point.prototype.add = function(other) {
return new Point(this.x + other.x, this.y + other.y);
};
function resetZIndex(className) {
var els = document.getElementsByClassName(className);
for (var i = 0; i < els.length; i++) {
els[i].style["z-index"] = "0";
}
}
//
// Helper functions
//
function _intFromStyle(style) {
// remove 'px' and parse as int
var num = parseInt(style.substring(0, style.length - 2));
if (isNaN(num)) { return 0; }
return num;
}
function _moveElementsBelow(el) {
if (el.dataset.moved === "true") { return; }
// find all draggable elements below that haven't moved yet
var next = el;
for(;;) {
next = next.nextElementSibling;
if (next === null) { break; }
// determine if element is supposed to move
var draggable = next.getAttribute('draggable') === "true"
var hasMoved = next.dataset.moved === "true";
if (!draggable || hasMoved) { continue; }
// calculate delta
var styles = window.getComputedStyle(el);
var delta = el.offsetHeight + _intFromStyle(styles["marginBottom"]);
// move element up
next.style.top = (_intFromStyle(next.style.top) - delta) + 'px';
}
}
function _moveToTop(el) {
resetZIndex(dragClass);
var closest = el.closest('.' + dragClass);
closest.style['z-index'] = '1000';
}
//
// Event handlers
//
// onFileDrag is the event handler for the dragstart event in .file elements
function onFileDrag(ev) {
var data = ev.target.id + "," + ev.clientX + "," + ev.clientY;
ev.dataTransfer.setData("text/plain", data);
}
// onFileDrop is the event handler for the drop event in the drop zone
function onFileDrop(ev) {
ev.preventDefault();
// get event data
var data = ev.dataTransfer.getData("text/plain").split(",");
if (data.length != 3) {
return;
}
// find target element
var id = data[0];
var target = document.getElementById(id);
if (!target) {
return;
}
// get cursor positions
var cursorStart = new Point(parseInt(data[1]), parseInt(data[2]));
var cursorEnd = new Point(ev.clientX, ev.clientY);
// calculate change in coordinates
var delta = cursorEnd.subtract(cursorStart);
// get element's initial position
var left = _intFromStyle(target.style.left);
var top = _intFromStyle(target.style.top);
var rect = target.getBoundingClientRect();
var targetStart = new Point(left, top);
// calculate new position
var targetEnd = targetStart.add(delta);
// set new position
target.style.position = 'absolute';
target.style.left = targetEnd.x + 'px';
target.style.top = targetEnd.y + 'px';
/*if (window.getComputedStyle(target).position === 'relative') {
target.style.left = (rect.x) + 'px';
target.style.top = (rect.y) + 'px';
}*/
//_moveElementsBelow(target);
// set element as moved
target.setAttribute('data-moved', 'true');
}
function init() {
// set files as draggable and set dragstart event
var files = document.getElementsByClassName(dragClass);
for (var i = 0; i < files.length; i++) {
files[i].setAttribute("draggable", true);
files[i].addEventListener('click', (ev) => {
_moveToTop(ev.target);
});
files[i].addEventListener("dragstart", (ev) => {
_moveToTop(ev.target);
onFileDrag(ev);
});
files[i].style.background = "#FFF";
}
// setup dropzone
var dropzone = document.getElementById(dropZoneId);
dropzone.addEventListener("drop", onFileDrop);
dropzone.addEventListener("dragover", ev => {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
});
}
// Initialize event listeners
window.addEventListener("DOMContentLoaded", init);
init();
})("file", "js-repo-pjax-container");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment