Vanilla JavaScript draggable Mr Potato Head 🥔
Tags: javascript, html, css
Published: 2020-10-03 04:46:33

Who doesn't like Mr. and Mrs. Potato Head!

Today we will be recreating the iconic Mr. Potato Head in `JavaScript`.
Meaning we will have all his parts, which we can drag on his body.

![Mr. Potato Head](https://media.giphy.com/media/9GimADqtnpAPe/giphy.gif)

The result of today's article is this amazing Codepen.

{% codepen https://codepen.io/rebelchris/pen/XWdGZqq %}

## HTML Structure

As for out `HTML`, we have a fairly simple setup.

```html
<div class="container">
  <div class="parts">
    <img src="https://i.imgur.com/GONNbHf.png" class="draggable" />
    <img src="https://i.imgur.com/optSzq4.png" class="draggable" />
    <img src="https://i.imgur.com/qJDxc4o.png" class="draggable" />
    <img src="https://i.imgur.com/tIZGoeR.png" class="draggable" />
    <img src="https://i.imgur.com/bKlbeXU.png" class="draggable" />
    <img src="https://i.imgur.com/eUPbX3H.png" class="draggable" />
    <img src="https://i.imgur.com/voJPsR5.png" class="draggable" />
    <img src="https://i.imgur.com/dt2gqit.png" class="draggable" />
    <img src="https://i.imgur.com/2POeyJZ.png" class="draggable" />
  </div>
  <div class="body">
    <img src="https://i.imgur.com/kXbr8Tb.png" />
  </div>
</div>
```

So we use the container to wrap everything, then we have our parts div, which contains each of the body-parts with a class of `draggable`. 
And we have our body, which is Mr Potato's body.

## CSS Styling

We use [flexbox to center](https://daily-dev-tips.com/posts/css-flexbox-most-easy-center-vertical-and-horizontal/) our two divs.

```css
.container {
  display: flex;
  align-items: center;
  justify-content: space-around;
  min-height: 100vh;
  background: #efefef;
}
```

The Parts container is then `relative`, and we add a small border to make it look nicer.

```css
.container .parts {
  position: relative;
  border: 3px dashed black;
  width: 250px;
  height: 100vh;
}
```

Each image will be `absolute` so we can place it anywhere in the page.

```css
.container .parts img {
  position: absolute;
}
```

## Vanilla JavaScript draggable Mr. Potato Head parts

To make an actual Mr. Potato Head, we need to make sure all the parts are draggable!

> I did not use [the `draggable` element](https://daily-dev-tips.com/posts/vanilla-javascript-drag-n-drop/) since that requires a dropzone, and it doesn't serve this article.

Let's start by getting our elements with the class `draggable`.

```js
const draggableElements = document.querySelectorAll(".draggable");
```

Then we need to define four basic variables we will use to store our position in.
We also add a whichDown to see which element is dragging.

```js
let initX, initY, firstX, firstY, whichDown;
```

Next on our list is to loop over each element.

```js
draggableElements.forEach((element) => {
	// Code here
});
```

Then we need to attach a `mousedown` eventListener. This will be our starting point. We will define the current x and y position by using `offsetLeft` and `offsetTop`.
Then we get the mouse position x and y.

And we attach a eventListener too `mousemove` since that will be us, dragging a part. Once we move our mouse we call the `draggable` function which we will make in a second.

```js
draggableElements.forEach((element) => {
  element.addEventListener("mousedown", function (e) {
    e.preventDefault();
    whichDown = this;
    initX = this.offsetLeft;
    initY = this.offsetTop;
    firstX = e.pageX;
    firstY = e.pageY;
  });
});

window.addEventListener("mousemove", draggable, false);
``` 

Let's get started with our `draggable` function.

All this function does is change the `left` and `top` position of our part. And Set the `z-index` higher so it's on top.

```js
function draggable(e) {
  e.preventDefault();
  if (!whichDown) return;
  whichDown.style.zIndex = 9;
  whichDown.style.left = initX + e.pageX - firstX + "px";
  whichDown.style.top = initY + e.pageY - firstY + "px";
}
```

We calculate the original position + the dragged amount - the initial mouse x.
And the same goes for the y position.

That's cool, but we have no way of stopping it dragging now.
So let's add a `mouseup` listener.

```js
window.addEventListener(
  "mouseup",
  function () {
    if (whichDown) {      
      whichDown.style.zIndex = 0;
    }
    whichDown = null;
  },
  false
);
```

In this section, we add a `mouseup` event to our window, and once that happens, we remove the `z-index` from our dragging element and remove the draggable whichDown element.

That is it. We can now drag Mr. Potato Head's parts on his body!

### Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on [Facebook](https://www.facebook.com/DailyDevTipsBlog) or [Twitter](https://twitter.com/DailyDevTips1)