I wrote this code to make any element with class draggable draggable.
const d = document.getElementsByClassName("draggable");
for (let i = 0; i < d.length; i++) {
d[i].style.position = "relative";
}
function filter(e) {
let target = e.target;
if (!target.classList.contains("draggable")) {
return;
}
target.moving = true;
e.clientX ?
(target.oldX = e.clientX,
target.oldY = e.clientY) :
(target.oldX = e.touches[0].clientX,
target.oldY = e.touches[0].clientY)
target.oldLeft = window.getComputedStyle(target).getPropertyValue('left').split('px')[0] * 1;
target.oldTop = window.getComputedStyle(target).getPropertyValue('top').split('px')[0] * 1;
document.onmousemove = dr;
document.addEventListener('touchmove', dr, {passive: false})
function dr(event) {
event.preventDefault();
if (!target.moving) {
return;
}
event.clientX ?
(target.distX = event.clientX - target.oldX,
target.distY = event.clientY - target.oldY) :
(target.distX = event.touches[0].clientX - target.oldX,
target.distY = event.touches[0].clientY - target.oldY)
target.style.left = target.oldLeft + target.distX + "px";
target.style.top = target.oldTop + target.distY + "px";
}
function endDrag() {
target.moving = false;
}
target.onmouseup = endDrag;
target.ontouchend = endDrag;
}
document.onmousedown = filter;
document.ontouchstart = filter;
div {
width: 100px;
height: 100px;
background: red;
}
<div class="draggable"></div>
tl;dr- I want to make a Windows taskbar thing where elements can be moved and the other elements move to the right or left based on where the dragged element is approaching it.
I want the draggable elements to snap to the grid similar to what happens when you drag an icon on the Windows taskbar or a tab on another tab in your browser.
Following is my attempt. I removed movement along the verticle axis and touch support to make the code more readable. The snapping is working fine but the element being hovered is not moving to the other space.
const d = document.getElementsByClassName("draggable");
let grid = 50;
for (let i = 0; i < d.length; i++) {
d[i].style.position = "relative";
d[i].onmousedown = filter;
}
function filter(e) {
let target = e.target;
target.moving = true;
target.oldX = e.clientX;
target.oldLeft = window.getComputedStyle(target).getPropertyValue('left').split('px')[0] * 1;
document.onmousemove = dr;
function dr(event) {
event.preventDefault();
if (!target.moving) {
return;
}
target.distX = event.clientX - target.oldX;
target.style.left = target.oldLeft + Math.round(target.distX / grid) * grid + 'px'
}
function endDrag() {
target.moving = false;
}
document.onmouseup = endDrag;
}
.parent {
width: 100%;
height: 100%;
background: lime;
display: flex;
align-items: center;
}
.child {
width: 50px;
height: 50px;
position: relative;
}
.one {
background: red;
}
.two {
background: blue;
}
<div class="parent">
<div class="child one draggable"></div>
<div class="child two draggable"></div>
</div>
Further, I think checking for when the mouse has crossed half of the width of a div, while an element is being dragged, the div should move either one unit left or right depending whether the element is left or right to the element being dragged. The checking part is no trouble. We can just compare the magnitudes of the elements' offsetLeft. But how do I make the element move?
Please try to answer in vanilla javascript.
Edits: 1. Updated code 2. Updated title 3. Updated tl;dr and changed title 3.Added more tags