This is my updated and modified script, it works completely, except I would like to universalize it... observe the **** how can I make it so that I don\'t have to do f
Any solution that uses clientY
, clientX
, pageY
, or pageX
within the dragend
event will completely fail in Firefox. Source: Bugzilla: Bug #505521, Set screen coordinates during HTML5 drag event.
How do we get by this limitation? document
's drop
event also fires at the same exact time as the dragend
event of the dragged element. But, we can see things like clientY
and clientX
here in firefox. So, let's just use that.
Two working demos, 100% JavaScript-Only Solution: SO Code Snippet and JSBin.
var startx = 0;
var starty = 0;
dragStartHandler = function(e) {
startx = e.clientX;
starty = e.clientY;
}
dragOverHandler = function(e) {
e.preventDefault();
return false;
}
dragEndHandler = function(e) {
if(!startx || !starty) {
return false;
}
var diffx = e.clientX - startx;
var diffy = e.clientY - starty;
var rect = e.target.getBoundingClientRect();
var offset = {
top: rect.top + window.scrollY,
left: rect.left + window.scrollX,
};
var newleft = offset.left + diffx;
var newtop = offset.top + diffy;
e.target.style.position = 'absolute';
e.target.style.left = newleft + 'px';
e.target.style.top = newtop + 'px';
startx = 0;
starty = 0;
}
document.getElementsByClassName("draggable")[0].addEventListener('dragstart', dragStartHandler);
document.addEventListener('dragover', dragOverHandler);
document.addEventListener('drop', dragEndHandler);
.draggable {
border: 1px solid black;
cursor: move;
width:250px;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<BR><BR><BR>
<div id="draggable1" class="draggable" draggable="true">
Hey, try to drag this element!
</div>
</body>
</html>
Explanation:
dragStartHandler()
: This is bound to the draggable element. Here, all we do is record the current x/y coordinates at start.dragOverHandler()
: This is bound to the document, so that we can override the default dragover behavior. This is needed to do any type of drag & dropping.dragEndHandler()
: This is bound to the document
's drop
. Normally, we would want this to bind to the element
's dragend
, but since clientY
and clientX
are missing, we bind it to the document. This just does exactly what you'd want to happen when dragend is called, except you have x/y coordinates.The formula used is:
set style to: (current position) - (original position)
That is as complicated as it gets, but to calculate and apply the style, just for the x-dimension, the code is...
var diffx = e.clientX - startx;
var rect = e.target.getBoundingClientRect();
var offset = {
left: rect.left + window.scrollX,
};
var newleft = offset.left + diffx;
e.target.style.position = 'absolute';
e.target.style.left = newleft + 'px';