Making a simple drag and drop with JS!
Tags: webdev, javascript, tutorial, beginners
Published: 2023-08-09 00:00:00

This week I decided to practice using JS drag events by making a simple drag and drop. I'd like to share how I made it using a couple of event listeners! First, I'll explain what drag events are, but I won't go to deep on the CSS since this is mostly focused on the Javascript. Here's the final result:

{% codepen https://codepen.io/lensco825/pen/OJadOaw %}

## How Drag Events Work 
There are 4 main Javascript events that people use, `mouse` events (most known for `onclick`), `keyboard` events, `load` events, and `drag` events. They do what they're named after, so drag events simply help make certain events happen when the user is dragging. You basically need to drag items and drop items in your HTML, because even if you can drag an element, it'll also need to be dropped somewhere. Luckily you can also make `drop` events when a dragging item goes to a drop zone. There are many fun ways web developers use drag-and-drop events, and they're commonly seen, from online quizzes to game puzzles that use Javascript. 
<hr>

# Making Ehe Draggable Element
To understand this Codepen, there is 1 draggable element and 3 drop elements, or drop zones. To make an element draggable, we have to give it the `draggable` attribute and set it to `true`. Now when we click, hold, and move around with it we're dragging it! 

```html
<html>
  <body>
<!--draggable element-->
    <div class="dragElement" draggable="true">
      <h3>Drag and Drop!</h3>
    </div>
<!--drop zones-->
     <div class="dropZone One"></div>
     <div class="dropZone Two"></div>
     <div class="dropZone Three"></div>
  </body>
</html>
```
<hr>
# Making Drop Zones Droppable
Drag elements would be useless without a place to drop them, which is why with JS we'll add drop zones! First, we store the drag element in a variable and the drop elements in an array.

```js
var dragItem = document.querySelector('.dragElement');
var dropZoneSet = Array.from(document.querySelectorAll('.dropZone'));
```
Now we use the `forEach()` method on the drop zones to give them a `dragover` event, where when the drag element drags overs them, they'll catch the element using the `appendChild()` method. `AppendChild()` helps an element take another element and make it its child, putting the element inside it. So we're basically telling the drop element to put the drag element inside it. 

```js
dropZoneSet.forEach(dropzone => {
  dropzone.addEventListener('dragover', (e) => {
    e.preventDefault();
    dropzone.appendChild(dragItem);
});
});

```
### `e.preventDefault`
Whenever we drag something, you'll notice that the mouse will show a stop sign. That means, by default, the computer is stopping us from making an element draggable. Notice that we needed to set the `draggable` attribute to `true`, which means by default it was set to false. In order to stop this, we use the method `e.preventDefault()` which helps us stop the default reaction of the computer. Just make sure when using this in an event listener, you add the event object parameter `e`.
<hr>

# Dragging over the drop zone
I made it so that whenever the drag hovers over or away from the drop zones their green borders will appear then disappear. To do this I once again used the `forEach()` method and gave them a `dragover` and `dragleave` event. The `dragover` event listener makes an event when a drag element is hovering over a drop zone while the `dragleave` event listener makes an event when a draggable item stops hovering over a drop zone. In the event listeners, I made it so that when the drag element is hovering over the drop zone a class with a green border gets added, however when no longer hovering over that class gets removed. This is all done with `classList.add` and `classList.remove`.

```js
dropZoneSet.forEach((dropZone) => {
//hovering over
  dropZone.addEventListener('dragover', () => {
    dropZone.classList.add('hoverOver');
  });
  //no longer hovering over
   dropZone.addEventListener('dragleave', () => {
    dropZone.classList.remove('hoverOver');
  });
 
});
```
<hr>
# Events when being dragged and dropped
Lastly, I gave the drag element two event listeners. One with `drag` where when being dragged a class with a black background and white color gets added, and the other using the `dragend` event listener, the class gets removed after the element stops getting dragged.

```js
dragItem.addEventListener('drag', () => {
  dragItem.classList.add('beingDragged');
} )


dragItem.addEventListener('dragend', () => {
  dragItem.classList.remove('beingDragged');
} )

```
<hr>
# Conclusion
That's how you make a simple drag-and-drop! However, if you drag and drop long or fast enough you can see that there's a bug where the border still stays to the drop zones that no longer have the dragging element hovering over them. I don't know how to fix this, but if this happens again in another project, I'll definitely make sure to see what's causing it. There are lots of other ways of making drag and drops, this is just the simplest one I could think of. If you have any questions or would like to comment on something, just email me or comment it down! I'll make sure to keep on posting for the last bit of the summer, have a nice day/night👋!