JSFiddle - React, Tailwind, and code Playground

by Slava Slava

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.17/vue.js "></script>
<div id="list">
    <ul>
        <li v-for="item in listX" v-draggable="x: {index: $index, dragged: 'dragged'}" v-dropzone="x: sort(listX, $index, $droptag, $dropdata)">
        {{ item }}
        </li>
    </ul>
    <div>only ↓</div>
    <ul>
        <li v-for="value in listY" v-draggable="y: {index: $index, dragged: 'dragged'}" v-dropzone="
            y: sort(listY, $index, $droptag, $dropdata),
            x: move(listX, listY, $index, $droptag, $dropdata)
        ">{{ value }}</li>
    </ul>
    <hr />
    <div class="trash" v-dropzone="x: remove(listX, $droptag, $dropdata)">trash X</div>
    <div class="trash" v-dropzone="y: remove(listY, $droptag, $dropdata)">trash Y</div>
</div>

CSS

[draggable] {
    -webkit-user-select: none;
    user-select: none;
    /* Required to make elements draggable in old WebKit */
    -webkit-user-drag: element;
}
ul {
    list-style: none;
    padding: 0 0 0 5px;
    margin: 0;
    background: #666;
    width: 200px;
}
li {
    box-sizing: border-box;
    border-left: 4px solid transparent;
    padding: 0 0 0 5px;
    color: white;
}
li:hover:after {
    color: #c00;
    font-size: x-small;
    content:" (drag me)";
}
li.dragged {
    opacity: 0.4;
    color: black;
}
li.x {
    border-left: 4px dotted #00c;
}
li.y {
    border-left: 4px dotted #0c0;
}
li.over-no {
    text-decoration: line-through;
}
.trash {
    width: 300px;
    height: 30px;
    background: #666;
    color: white;
}
.trash.x {
    background: #00c;
}
.trash.y {
    background: #0c0;
}

CoffeeScript

app =
    el: '#list'
    data:
        listX: ['a', 'b', 'c', 'd']
        listY: ['A', 'B', 'C', 'D']
    methods:
        sort: (list, id, tag, data)->
            console.log 'sort', list, id, tag, data
            tmp = list[data.index]
            list.splice data.index, 1
            list.splice id, 0, tmp
        move: (from, to, id, tag, data)->
            console.log 'move', from, to, id, tag, data
            tmp = from[data.index]
            from.splice data.index, 1
            to.splice id, 0, tmp
        remove: (from, tag, data)->
            console.log 'remove', from, tag, data
            from.splice data.index, 1

_ =
    on: (el, name, cb)->
        el.addEventListener name, cb
    off: (el, name, cb)->
        el.removeEventListener name, cb

dropTo = ''
app.directives = 
    draggable:
            bind: ->
                @data = {}
                @dragstart = (e)=>
                    e.target.classList.add @data.dragged
                    e.dataTransfer.effectAllowed = 'all'
                    e.dataTransfer.dropEffect = 'copy'
                    e.dataTransfer.setData 'data', JSON.stringify(@data)
                    e.dataTransfer.setData 'tag', @arg
                    dropTo = @arg
                    console.log 'start', @arg, @data
                    false
                @dragend = (e)=>
                    e.target.classList.remove @data.dragged
                    console.log 'end', @arg
                    dropTo = ''
                    false
                @el.setAttribute 'draggable', true
                _.on @el, 'dragstart', @dragstart
                _.on @el, 'dragend', @dragend
            unbind: ->
                @el.setAttribute 'draggable', false
                _.off @el, 'dragstart', @dragstart
                _.off @el, 'dragend', @dragend
            update: (value, old)->
                @data = value

    dropzone:
            acceptStatement: true
            bind: ->
                #console.log '+...