JSFiddle - React, Tailwind, and code Playground

by dhaval dave

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.11.4/vue.js"></script>
<h3>DnD</h3>

<div id="list">
    <ul>
        <li v-repeat="listX" v-draggable="x: {index: $index, dragged: 'dragged'}" v-dropzone="x: sort(listX, $index, $droptag, $dropdata)">{{$value}}</li>
    </ul>
    <div>only ↓</div>
    <ul>
        <li v-repeat="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] {
    -moz-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    user-select: none;
    /* Required to make elements draggable in old WebKit */
    -khtml-user-drag: element;
    -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;
}

JavaScript

var _, app, dropTo;

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

_ = {
  on: function(el, name, cb) {
    return el.addEventListener(name, cb);
  },
  off: function(el, name, cb) {
    return el.removeEventListener(name, cb);
  }
};

dropTo = '';

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