dnd

by Trina Lu

HTML

<div id="app">
  <h2>Todos:</h2>
  <ol>
    <li v-for="(todo, i) in todos"
    :key="todo.text"
    draggable 
    @dragstart="onDragStart(i)"
    @dragend="onDragEnd(i)"
    @dragover="onDragOver(i)"
    @dragleave="onDragLeave(i)"
    :style="{ ...getTranslateY(i), opacity: i === draggingTarget ? 0 : 1 }"
   >
     {{draggingTarget === i}} / 
     {{ todo.text }}
    </li>
  </ol>
</div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  padding: 8px 4px;
  border: 1px solid gold;
  transition: all 0.2s;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

del {
  color: rgba(0, 0, 0, 0.3);
}

Vue

new Vue({
  el: "#app",
  data: {
  	draggingTarget: null,
    dragOverTarget: null,
    isDragging: false,
    todos: [
      { text: "#1", done: false },
      { text: "#2", done: false },
      { text: "#3", done: true },
      { text: "#4", done: true }
    ]
  },
  methods: {
  	log: function(...everything){
    	console.log(everything)
    },
    onDragStart(i) {
    	this.draggingTarget = i;
    },
    onDragEnd(i) {
      const temp = [...this.todos];      
      temp.splice(this.draggingTarget, 1);
      temp.splice(this.dragOverTarget, 0, this.todos[this.draggingTarget]);
      
      this.todos = [...temp];
      this.draggingTarget = null
      this.dragOverTarget = null
    },
    onDragOver(i) {
    	this.dragOverTarget = i;
    },
    onDragLeave(i) {
    	/* this.dragOverTarget = null */;
    },
    getTranslateY(i) {
    	if (this.draggingTarget !== null 
      	&& this.dragOverTarget !== null 
        && this.draggingTarget !== i
      ) {
      	const min = Math.min(this.draggingTarget, this.dragOverTarget);
      	const max = Math.max(this.draggingTarget, this.dragOverTarget);
        if (i <= max && i >= min) {
          const direction = i < this.draggingTarget ? 1 : -1;
        	return { transform: `translateY(${36 * direction}px)`};
        }
        
      }
    	return '';
    }
  }
})