I have a CSS Grid and I'm trying to implement a drag and drop (or drag and swap) feature. It's getting close to working as desired but as the title says, the dragged cell will not drop properly into a cell to the left of its original position. The feature only works when the cell being dragged is moved to the right. Can anyone see what the problem is?
var dragSrcEl = null;
function handleDragStart(e) {
this.style.opacity = "0.4";
dragSrcEl = this;
e.dataTransfer.effectAllowed = "move";
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = "move";
return false;
}
function handleDragEnter(e) {
this.classList.add("over");
}
function handleDragLeave(e) {
this.classList.remove("over");
}
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSrcEl != this) {
this.replaceWith(this, dragSrcEl);
}
return false;
}
function handleDragEnd(e) {
this.style.opacity = "1";
items.forEach(function (item) {
item.classList.remove("over");
});
}
let items = document.querySelectorAll(".grid-container .grid-item");
items.forEach(function (item) {
item.addEventListener("dragstart", handleDragStart, false);
item.addEventListener("dragenter", handleDragEnter, false);
item.addEventListener("dragover", handleDragOver, false);
item.addEventListener("dragleave", handleDragLeave, false);
item.addEventListener("drop", handleDrop, false);
item.addEventListener("dragend", handleDragEnd, false);
});
.grid-container {
display: grid;
grid-template-columns: repeat(3, 40px);
grid-template-rows: repeat(4, 30px);
margin: auto;
}
.grid-item {
border: 1px solid #666;
background-color: #ddd;
cursor: move;
}
.grid-item.over {
border: 3px dotted #666;
}
[draggable] {
user-select: none;
}
<!DOCTYPE html>
<head>
<body>
<div class="grid-container" id="grid">
<div draggable="true" class="grid-item" id="box1">1</div>
<div draggable="true" class="grid-item" id="box2">2</div>
<div draggable="true" class="grid-item" id="box3">3</div>
</div>