Draggable elements between two lists
Tags: webdev, javascript, beginners, gsap
Published: 2022-07-15 15:40:53

This is for a basic dragging and dropping capability in between two set spots. 

## Helpful resources

This is the [documentation](https://greensock.com/docs/v3/Plugins/Draggable) for GSAP draggable, which is what I used. I also watched this [Youtube tutorial](https://www.youtube.com/watch?v=WXHW_iGu8pc&t=225s) by Wael Yasmina that was helpful in getting an idea for what you're able to do with this function.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pzd5hi17wqk0r191wzd1.png)
I found this [CodePen](https://codepen.io/stevewojcik/pen/LeOVRK) by Steve Wojcik and worked from there. I wanted to get familiar with the basics so I removed a lot of extra features that was in it like dropShadow, dragGroup, and highlight. I tested each section to see if it would effect the main drag and drop function, and if it didn't, I just removed it. This also helped get an idea for what different parts do.

## Imports
I used these scripts:
`//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/utils/Draggable.min.js`
`//cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js`
`//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js`

## HTML

```
<div id="container" class="container">
  <h1 id="list1">List 1</h1>
  <h1 id="list2">List 2</h1>
  
  <div id="dropArea"></div>
  <div id="dropArea2"></div>
  <div id="dropArea3"></div>
  
  <div class="first">
    <h3>1</h3>
  </div>
  <div class="second">
    <h3>2</h3>
  </div>
  <div class="third">
    <h3>3</h3>
  </div>
</div>
```

- container: the boundary

- lists: just the titles and will not be used

- drop areas: where the boxes will drop under list 2

- first/second/third: the draggable boxes

## CSS

```
.container
{
  position: absolute;
  margin: auto;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 400px;
  height: 330px;
  border-radius: 3px;
  border-style: solid;
  border-color: #fed3c1;
  border-width: 2px;
}

#list1 {
  margin-left: 100px;
  position: relative;
  margin-top: 35px;
}

#list2 {
  margin-left: 230px;
  position: absolute;
  margin-top: -58px;
}

.first
{
  position: absolute;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: pink;
  top: 100px;
  left: 106px;
  text-align: center;
}

#dropArea
{
  position: absolute;
  top: 100px;
  left: 242px;
  width: 50px;
  height: 50px;
}

.second
{
  position: absolute;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: pink;
  top: 175px;
  left: 105px;
  text-align: center;
}

#dropArea2
{
  position: absolute;
  top: 175px;
  left: 242px;
  width: 50px;
  height: 50px;
}

.third
{
  position: absolute;
  top: 0px;
  left: 0px;
  width: 50px;
  height: 50px;
  background-color: pink;
  top: 250px;
  left: 105px;
  text-align: center;
}

#dropArea3
{
  position: absolute;
  top: 250px;
  left: 242px;
  width: 50px;
  height: 50px;
}
```

I added background colors to everything while I was working with it so I could see exactly where everything was. I pretty much kept everything in the same place except when adding a new box, I made the start and finish lower. 

## Javascript

```
var dropArea = "#dropArea";
var overlapThreshold = "60%";

Draggable.create(".first", 
{
  bounds: "#container",
  onDrag: function(e) 
  {
      TweenLite.to(".first", 0.2, 
      {
        scaleX:1.10,
        scaleY:1.10
      });
  },
  onDragEnd: function(e) 
  {
    if (this.hitTest(dropArea, overlapThreshold)) 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 136,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    } 
    else 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 0,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    }
  }
});


var dropArea2 = "#dropArea2";
var overlapThreshold = "60%";

Draggable.create(".second", 
{
  bounds: "#container",
  onDrag: function(e) 
  {
      TweenLite.to(".second", 0.2, 
      {
        scaleX:1.10,
        scaleY:1.10
      });
  },
  onDragEnd: function(e) 
  {
    if (this.hitTest(dropArea2, overlapThreshold)) 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 136,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    } 
    else 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 0,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    }
  }
});


var dropArea3 = "#dropArea3";
var overlapThreshold = "60%";

Draggable.create(".third", 
{
  bounds: "#container",
  onDrag: function(e) 
  {
      TweenLite.to(".third", 0.2, 
      {
        scaleX:1.10,
        scaleY:1.10
      });
  },
  onDragEnd: function(e) 
  {
    if (this.hitTest(dropArea3, overlapThreshold)) 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 136,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    } 
    else 
    {
      TweenLite.to(this.target, 0.2, 
      {
        x: 0,
        y: 0,
        scaleX:1,
        scaleY:1
      });
    }
  }
});
```

This has the same code base three times, one for each box. I just changed the variable names to reflect where the box should land. 

- bound: this is where you put the container you want to keep your draggable item in
- onDrag: when the box is being dragged, it will look slightly bigger
- onDragEnd: If the box is placed in the dropArea, it will stay there, else, it will go back to its original position under List 1