0

I'm trying to make a 3x3 grid with the grid items being each a part of 1 image. These items I want to be able to drag and drop them inside another 3x3 grid.(In any order I want).

I've encountered a roadblock and been trying to solve it for a while now.

Directory tree:

.
├── Project/
│   └── Res/
│       ├── Media/
│       │   └── Images/
│       │       └── image.jpg
│       ├── Scripts/
│       │   └── anim3.js
│       ├── Styles/
│       │   └── anim3.css
│       └── Pages/
│           └── animPage3.html
└── index.html(not relevant)

animPage3.html:

<body>
<head>
<link 
rel="stylesheet" href="Res/Styles/anim3.css">
</head>

<div class="draggable-grid">
  <div class="box" draggable="true"></div>
  ...There's a total of 9 these...
</div>

<div class="droppable-grid">

<div class="droppable-box"></div> 
<!--There's a total of 9 of these "droppable-box" divs-->

</div>
<script src="Res/Scripts/anim3.js">
</body>

anim3.css:

.grid-cont {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
.draggable-grid, .droppable-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 10px;
}
.box {
  width: 100px; 
  height: 100px; 
  background-image: url('../Media/Images/image.jpg');
  background-size: 300% 300%;
}
.droppable-box {
  border: 2px dashed #ccc;
  height: 100px; 
}

anim3.js:

const draggableBoxes = document.querySelectorAll('.draggable-grid .box');
const droppableBoxes = document.querySelectorAll('.droppable-grid .droppable-box');
draggableBoxes.forEach(box => {
  box.addEventListener('dragstart', dragStart);
});
droppableBoxes.forEach(droppableBox => {
  droppableBox.addEventListener('dragover', dragOver);
  droppableBox.addEventListener('dragenter', dragEnter);
  droppableBox.addEventListener('dragleave', dragLeave);
  droppableBox.addEventListener('drop', drop);
});
let draggedItem = null;
function dragStart() {
  draggedItem = this;
  setTimeout(() => this.style.display = 'none', 0);
}
function dragOver(e) {
  e.preventDefault();
}
function dragEnter(e) {
  e.preventDefault();
  this.classList.add('hovered');
}
function dragLeave() {
  this.classList.remove('hovered');
}
function drop() {
  this.classList.remove('hovered');
  this.append(draggedItem);
  draggedItem.style.display = 'block';
  draggedItem = null;
}

I tried to comment out //setTimeout(() => this.style.display = 'none', 0); Which didn't make the drag work.

What I want the code to do: Make two 3×3 grids. 1st grid has draggable items and the items background is each a part of "1 image*. "2nd grid* is were I want to be able to drop the items, at any of the 9 boxes.

0

1 Answer 1

0

Using this is a bit confusing. Use the e.target instead. And then create event listeners for the parent elements, and test if e.target is the right element.

const draggableGrid = document.querySelector('.draggable-grid');
const droppableGrid = document.querySelector('.droppable-grid');

draggableGrid.addEventListener('dragstart', dragStart);

droppableGrid.addEventListener('dragover', dragOver);
droppableGrid.addEventListener('dragenter', dragEnter);
droppableGrid.addEventListener('dragleave', dragLeave);
droppableGrid.addEventListener('drop', drop);

let draggedItem = null;

function dragStart(e) {
  draggedItem = e.target;
  setTimeout(() => draggedItem.style.display = 'none', 0);
}

function dragOver(e) {
  e.preventDefault();
}

function dragEnter(e) {
  e.preventDefault();
  if (e.target.classList.contains('droppable-box')) {
    e.target.classList.add('hovered');
  }
}

function dragLeave(e) {
  e.target.classList.remove('hovered');
}

function drop(e) {
  if (e.target.classList.contains('droppable-box')) {
    e.target.classList.remove('hovered');
    e.target.append(draggedItem);
    draggedItem.style.display = 'block';
    draggedItem = null;
  }
}
.grid-cont {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.draggable-grid,
.droppable-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 10px;
}

.box {
  width: 100px;
  height: 100px;
  background-color: orange;
}

.droppable-box {
  border: 2px dashed #ccc;
  height: 100px;
}

.hovered {
  border-style: solid;
}
<div class="draggable-grid">
  <div class="box" draggable="true">1</div>
  <div class="box" draggable="true">2</div>
  <div class="box" draggable="true">3</div>
  <div class="box" draggable="true">4</div>
  <div class="box" draggable="true">5</div>
  <div class="box" draggable="true">6</div>
  <div class="box" draggable="true">7</div>
  <div class="box" draggable="true">8</div>
  <div class="box" draggable="true">9</div>
</div>

<div class="droppable-grid">
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
  <div class="droppable-box"></div>
</div>

Not the answer you're looking for? Browse other questions tagged or ask your own question.