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 '';
}
}
})