Last active
April 8, 2020 15:40
-
-
Save lgfa29/6f1a5806647fee19765bdcc8a49f1733 to your computer and use it in GitHub Desktop.
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
(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