I am doing a project where images in a 3×3 grid are re-arranged by drag and drop.
When an image is dragged and dropped over another, they swap positions and I have got that part working, but I also need a line of text at the bottom showing how the images have been re-ordered. So if I swap the items 1 and 5 the text would no longer read: 1,2,3,4,5,6,7,8,9 but instead it should look like: 5,2,3,4,1,6,7,8,9.
I am really struggling with how to print the new numbers order after the items swap. Here is how it looks (the colors of the boxes were chosen randomly and have no importance):
This is my code:
//IMAGE ORDER
let order = [1, 2, 3, 4, 5, 6, 7, 8, 9]
function showOrder(order) {
document.getElementById('order').textContent = "Order: " + order.toString();
}
showOrder(order);
//DRAG AND DROP SWAP
var draggedImage = null;
var items;
function dragStart(e) {
draggedImage = this;
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("item", this.innerHTML);
}
function dragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = "move";
return false;
}
function dragEnter(e) {
this.classList.add("dragover");
}
function dragLeave(e) {
this.classList.remove("dragover");
}
function drop(e) {
e.stopPropagation();
if (draggedImage != this) {
draggedImage.innerHTML = this.innerHTML;
draggedImage.setAttribute("data-item", this.innerHTML);
let replacedImage = e.dataTransfer.getData("item");
this.innerHTML = replacedImage;
this.setAttribute("data-item", replacedImage);
}
return false;
}
function dragEnd(e) {
items.forEach(function(item) {
item.classList.remove("dragover");
});
}
document.addEventListener("DOMContentLoaded", event => {
items = document.querySelectorAll(".container .image");
items.forEach(function(item) {
item.addEventListener("dragstart", dragStart);
item.addEventListener("dragenter", dragEnter);
item.addEventListener("dragover", dragOver);
item.addEventListener("dragleave", dragLeave);
item.addEventListener("drop", drop);
item.addEventListener("dragend", dragEnd);
});
});
.container {
width: 330px;
height: 330px;
background-color: lightgrey;
display: flex;
flex-wrap: wrap;
}
.image {
width: 100px;
height: 100px;
background-color: #fff5d7;
text-align: center;
line-height: 100px;
margin: 5px;
cursor: move;
}
.order {
width: 330px;
height: 50px;
background-color: lightgrey;
margin-top: 10px;
text-align: center;
line-height: 50px;
font-size: x-large;
font-family: Helvetica;
}
<div class="container">
<div draggable="true" class="image" id="1"><img src="Dummy billeder/nummer 1.png" width="100px"></div>
<div draggable="true" class="image" id="2"><img src="Dummy billeder/nummer 2.png" width="100px"></div>
<div draggable="true" class="image" id="3"><img src="Dummy billeder/nummer 3.png" width="100px"></div>
<div draggable="true" class="image" id="4"><img src="Dummy billeder/nummer 4.png" width="100px"></div>
<div draggable="true" class="image" id="5"><img src="Dummy billeder/nummer 5.png" width="100px"></div>
<div draggable="true" class="image" id="6"><img src="Dummy billeder/nummer 6.png" width="100px"></div>
<div draggable="true" class="image" id="7"><img src="Dummy billeder/nummer 7.png" width="100px"></div>
<div draggable="true" class="image" id="8"><img src="Dummy billeder/nummer 8.png" width="100px"></div>
<div draggable="true" class="image" id="9"><img src="Dummy billeder/nummer 9.png" width="100px"></div>
</div>
<div id="order"></div>
I have tried finding a way to indentify the position of the two images in the grid and then swapping those numbers in an array, when an image is dropped but I could not get it to work.
2
Answers
Copy the IDs to your draggable content () and update the order box on the drop.
But a better approach would be to move the whole boxes:
If you want to go really cool, here’s a reactive approach without manipulating DOM manually:
Here’s a simpler and cleaner example/suggestion in where:
data
atrribute.grid
element)