Skip to content

Instantly share code, notes, and snippets.

@solotimes
Created December 3, 2018 07:57
Show Gist options
  • Save solotimes/77235b8b7d3afeceb7a12d7594d2d975 to your computer and use it in GitHub Desktop.
Save solotimes/77235b8b7d3afeceb7a12d7594d2d975 to your computer and use it in GitHub Desktop.
Vue.js DnD
<div id="some-list" class="q" droppable="true" v-on="dragover:dragover, drop:drop">
<div v-repeat="items" draggable="true" v-on="dragstart:dragstart, dragend:dragend, dragover:dragover, dragenter:dragenter">{{text}}</div>
</div>
<div id="placeholder">placeholder</div>
</div>
new Vue {
el: '#some-list'
data: {
items: [1 to 5].map -> {text: "Item-#{it}", qqq:it}
_dragElem: null
_insertIndex: null
_placeholder: document.getElementById 'placeholder'
}
methods: {
reorder: !->
sty_elem = document.createElement('style');
document.head.appendChild sty_elem
sty_elem.appendChild (document.createTextNode '')
s = sty_elem.sheet
for i from 0 to this.items.length
e = i
if this._dragElem?
sourceIndex = this._dragElem.$index
--e if sourceIndex < e
#console.log i, e
rule = ".q div:nth-child(#{i+1}) {top:#{e*50}px }"
s.insertRule rule, s.cssRules.length
dragstart: (ev) !->
this._dragElem = ev.targetVM
this._dragNode = ev.target
this.reorder!
st = this._dragNode.style
Vue.nextTick !->
st.opacity = 0
st.height = 0
this.$el.insertBefore this._placeholder, ev.target
#ev.preventDefault! # <- should not do this
dragend: (ev) !->
#console.log \dragend
this.$el.removeChild this._placeholder
this._dragNode.style.opacity = 1
this._dragNode.style.height = '50px'
this._dragNode = null
this._dragElem = null
this.reorder!
ev.preventDefault!
drop: (ev) !->
#console.log \drop
insertIndex = this._insertIndex
sourceIndex = this._dragElem.$index
return if sourceIndex == insertIndex
removed = this.items.splice sourceIndex, 1
this.items.splice insertIndex, 0, removed[0]
this.dragend ev
dragover: (ev) !->
#console.log \over
ev.preventDefault!
return true
dragenter: (ev) !->
sourceIndex = this._dragElem.$index
insertIndex = ev.targetVM.$index
this._insertIndex = insertIndex
# FIXME
posElem = if sourceIndex < insertIndex then ev.target else ev.target.previousSibling
this.$el.insertBefore this._placeholder, posElem.nextSibling
ev.preventDefault!
return true
}
created: !->
this.reorder!
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.9.3/vue.min.js"></script>
body
background-color #eee
.q div
width 200px
height 50px
border solid 1px #ccc
box-shadow 0 1px 2px 0px #888
background-color #f8f8f8
margin 5px
display inline-block
position absolute
transition top 400ms
&#placeholder
opacity 0.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment