Here's my solution for you, I've programmed video games before, and you run into this problem a lot.
You're checking if it'll go out, but not doing anything if it does! If it goes outside, you have to set it to the edge.
https://jsfiddle.net/7btv7oqy/3/
var lastElementX = 0; //last X position of element
var lastElementY = 0; //last Y position of element
var lastMouseX = 0; //last X position of mouse
var lastMouseY = 0;//last Y position of mouse
var mouseX = 0; //current mouse position X
var mouseY = 0; //current mouse position Y
var currentElement = null; //currently selected div
var elementWidth = 0;
var elementHeight = 0;
var container = null; //container div
var isMouseDown = 0; //if greater than zero, mouse is down
//limits of container div
var bottomLimit = 0;
var topLimit = 0;
var leftLimit = 0;
var rightLimit = 0;
function init() {
container = document.getElementsByClassName("container")[0];
topLimit = container.getBoundingClientRect().top;
bottomLimit = container.getBoundingClientRect().bottom;
leftLimit = container.getBoundingClientRect().left;
rightLimit = container.getBoundingClientRect().right;
document.addEventListener("mousedown", function mouseDown(e) {
e.preventDefault();
++isMouseDown;
document.addEventListener("mousemove", mouseMove);
setCurrentElement(getElementUnderMouse(e)); //set current element
currentElement.style.position = "absolute";
lastElementX = currentElement.getBoundingClientRect().left;
lastElementY = currentElement.getBoundingClientRect().top;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
});
document.addEventListener("mouseup", function mouseUp(e) {
e.preventDefault();
--isMouseDown;
setCurrentElement(null);
document.removeEventListener("mousemove", mouseMove);
});
}
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
// report(e);
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the right edge, set to right edge
if (diffX + lastElementX + elementWidth >= rightLimit) {
lastElementX = rightLimit - elementWidth;
}
//check if it would go off the left edge, set to left edge
if(diffX + lastElementX <= leftLimit) {
lastElementX = leftLimit;
}
}
//this will always happen:
lastMouseX = mouseX;
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the bottom edge, set to bottom edge
if(diffY + lastElementY + elementHeight >= bottomLimit) {
lastElementY = bottomLimit - elementHeight;
}
//check if it would go off the top edge, set to top edge
if(diffY + lastElementY <= topLimit) {
lastElementY = topLimit;
}
}
//this will always happen:
lastMouseY = mouseY;
setCurrentElementPosition(lastElementX, lastElementY);
}
}
function setCurrentElementPosition(left = null, top = null) {
if(currentElement) {
currentElement.style.top = top + 'px'
currentElement.style.left = left + 'px';
}
}
function setCurrentElement(element) {
currentElement = element;
if(element) {
elementWidth = currentElement.offsetWidth;
elementHeight = currentElement.offsetHeight;
} else {
elementWidth = 0;
elementHeight = 0;
}
}
function hasClass(element, cls) {
return ("" + element.className + "").indexOf("" + cls + "") > -1;
}
function getElementUnderMouse(e) {
var x = e.clientX;
var y = e.clientY;
return document.elementFromPoint(x, y);
}
function report(e) {
console.log("isMouseDown: " + isMouseDown);
console.log("mouseX: " + e.clientX);
console.log("mouseY: " + e.clientY);
console.log("currentElement: " + currentElement);
console.log("currentElement top: " + currentElement.getBoundingClientRect().top);
console.log("currentElement bottom: " + currentElement.getBoundingClientRect().bottom);
console.log("container top: " + container.getBoundingClientRect().top);
console.log("container bottom: " + container.getBoundingClientRect().bottom);
}
init();
EDIT: Not sure why it's missing by one pixel at the right and bottom, you'll have to do some investigation on that front. Seems like it's not taking into consideration the border, despite you using offsetWidth. Good luck!