I know there're example of doing this on the web but every example is different and so is my own implementation. I'm trying to figure what's wrong with my implementation since it doesn't work as expected.
code snippet:
var mousePressX = -1;
var mousePressY = -1;
document.getElementById("contextMenu").addEventListener("mousedown", function(event) {
mousePressX = event.clientX;
mousePressY = event.clientY;
}, false);
document.getElementById("contextMenu").addEventListener("mouseup", function(event) {
mousePressX = -1;
mousePressY = -1;
}, false);
document.getElementById("contextMenu").addEventListener("mousemove", function(event) {
if (mousePressX != -1 && mousePressY != -1) {
repositionElement(event.target, event.clientX, event.clientY);
}
}, false);
function repositionElement(element, currentMouseX, currentMouseY) {
element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
}
jsfiddle : /
can't really figure out what's wrong but I've noticed that if I change the following lines:
element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
to :
element.style.left = currentMouseX - mousePressX + 'px';
element.style.top = currentMouseY - mousePressY + 'px';
The element will be properly dragged only when it's being dragged towards the positive x-axis (to the right) and towards the positive y-axis (to the bottom) and when mouseup is triggered it'll be positioned in somewhere near the left-most top-most corner area (around 0,0)
I know there're example of doing this on the web but every example is different and so is my own implementation. I'm trying to figure what's wrong with my implementation since it doesn't work as expected.
code snippet:
var mousePressX = -1;
var mousePressY = -1;
document.getElementById("contextMenu").addEventListener("mousedown", function(event) {
mousePressX = event.clientX;
mousePressY = event.clientY;
}, false);
document.getElementById("contextMenu").addEventListener("mouseup", function(event) {
mousePressX = -1;
mousePressY = -1;
}, false);
document.getElementById("contextMenu").addEventListener("mousemove", function(event) {
if (mousePressX != -1 && mousePressY != -1) {
repositionElement(event.target, event.clientX, event.clientY);
}
}, false);
function repositionElement(element, currentMouseX, currentMouseY) {
element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
}
jsfiddle : http://jsfiddle.net/4rLctko8/
can't really figure out what's wrong but I've noticed that if I change the following lines:
element.style.left = element.offsetLeft + (currentMouseX - mousePressX) + 'px';
element.style.top = element.offsetTop + (currentMouseY - mousePressY) + 'px';
to :
element.style.left = currentMouseX - mousePressX + 'px';
element.style.top = currentMouseY - mousePressY + 'px';
The element will be properly dragged only when it's being dragged towards the positive x-axis (to the right) and towards the positive y-axis (to the bottom) and when mouseup is triggered it'll be positioned in somewhere near the left-most top-most corner area (around 0,0)
Share Improve this question asked Apr 17, 2015 at 15:30 dikson231dikson231 2015 silver badges10 bronze badges 02 Answers
Reset to default 19Quite interesting, had so far only done it with jQuery. Rewrote it a bit and made sure that every mousemove has it's event listener removed afterwards - that would be a memory leak that you might start to notice otherwise :
http://jsfiddle.net/8wtq17L8/
var contextmenu = document.getElementById('contextMenu');
var initX, initY, mousePressX, mousePressY;
contextmenu.addEventListener('mousedown', function(event) {
initX = this.offsetLeft;
initY = this.offsetTop;
mousePressX = event.clientX;
mousePressY = event.clientY;
this.addEventListener('mousemove', repositionElement, false);
window.addEventListener('mouseup', function() {
contextmenu.removeEventListener('mousemove', repositionElement, false);
}, false);
}, false);
function repositionElement(event) {
this.style.left = initX + event.clientX - mousePressX + 'px';
this.style.top = initY + event.clientY - mousePressY + 'px';
}
Seems to be working well. :-)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Edit - thought I'd add a version with touch support too (although newer devices seem to emulate mouse events). Not like Jquery where you can select multiple event listeners so it's mostly a repetition, just with touch events :
http://codepen.io/Shikkediel/pen/VLZKor?editors=011
var object = document.getElementById('element'),
initX, initY, firstX, firstY;
object.addEventListener('mousedown', function(e) {
e.preventDefault();
initX = this.offsetLeft;
initY = this.offsetTop;
firstX = e.pageX;
firstY = e.pageY;
this.addEventListener('mousemove', dragIt, false);
window.addEventListener('mouseup', function() {
object.removeEventListener('mousemove', dragIt, false);
}, false);
}, false);
object.addEventListener('touchstart', function(e) {
e.preventDefault();
initX = this.offsetLeft;
initY = this.offsetTop;
var touch = e.touches;
firstX = touch[0].pageX;
firstY = touch[0].pageY;
this.addEventListener('touchmove', swipeIt, false);
window.addEventListener('touchend', function(e) {
e.preventDefault();
object.removeEventListener('touchmove', swipeIt, false);
}, false);
}, false);
function dragIt(e) {
this.style.left = initX+e.pageX-firstX + 'px';
this.style.top = initY+e.pageY-firstY + 'px';
}
function swipeIt(e) {
var contact = e.touches;
this.style.left = initX+contact[0].pageX-firstX + 'px';
this.style.top = initY+contact[0].pageY-firstY + 'px';
}
Extending upon @Shikkediel answer, my version is here
Basically, I switched to an absolute positioned div and simply got the offset x, y and added them to the initial x - y of the dragged element. The absolute position also helps in case you have multiple divs inside a single container.
document.getElementById('dragHandle').addEventListener('mousedown',
function(e) {
e.preventDefault();
originalY = e.clientY;
originalX = e.clientX;
elementY = object2.offsetTop;
elementX = object2.offsetLeft;
window.addEventListener('mousemove', dragIt, false);
window.addEventListener('mouseup', function()
{
window.removeEventListener('mousemove', dragIt, false);
}, false);
}, false);
function dragIt(e)
{
let deltaY = e.clientY - originalY;
let deltaX = e.clientX - originalX;
originalY = e.clientY;
originalX = e.clientX;
elementY += deltaY;
elementX += deltaX;
object2.style.top = elementY + "px";
object2.style.left = Math.min(Math.max(container.getBoundingClientRect().left, elementX), container.getBoundingClientRect().right- object2.offsetWidth) + "px";
object2.style.top = Math.min(Math.max(container.getBoundingClientRect().top, elementY), container.getBoundingClientRect().bottom - object2.offsetHeight) + "px";
}
I also included a drag handle and constrained the dragging to the parent #container.