Skip to content

Instantly share code, notes, and snippets.

@fauxparse
Created January 13, 2015 01:49
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save fauxparse/cb287d17a1b246932715 to your computer and use it in GitHub Desktop.
Sortable lists in < 100 LoC
class SortableList
constructor: (el) ->
@el = $(el)
down: (e) =>
e.preventDefault()
top = @el.offset().top
@el.find(".sortable").each (i, el) ->
$el = $(el)
offset = $el.offset().top
h = $el.outerHeight(true)
y = offset - top
$el.data height: h, offset: y, y: y
@drag =
offset: top
item: $(e.target).closest(".sortable").addClass("sorting")
items: ($(item) for item in @el.find(".sortable").get())
origin: @eventPosition(e)
$(document).
on("mousemove touchmove", @move).
on("mouseup touchend", @up)
@move(e)
move: (e) =>
# TODO: auto-scroll parent region
y = @eventPosition(e) - @drag.origin
@drag.item.
css(transform: "translateY(#{y}px)").
data(y: @drag.item.data("offset") + y)
@sortItems()
up: (e) =>
e.preventDefault()
@el.find(".sortable").removeClass("sorting").css(transform: "translateY(0)")
for item in @drag.items
item.appendTo(@el)
$(document).
off("mousemove touchmove", @move).
off("mouseup touchend", @up)
@el.trigger("sorted")
eventPosition: (e) ->
if e.originalEvent.targetTouches?.length
e.originalEvent.targetTouches[0].pageY
else
e.pageY
sortItems: ->
@drag.items.sort (a, b) =>
a.data("y") - b.data("y")
y = 0
for item in @drag.items
dy = y - item.data("offset")
unless item.hasClass("sorting")
item.
data(y: y).
css(transform: "translateY(#{dy}px)")
y += item.data("height")
$(document)
.on "mousedown touchstart", ".sortable-list [rel=reorder]", (e) ->
list = $(e.target).closest(".sortable-list")
unless manager = list.data("sortable")
manager = new SortableList(list)
list.data "sortable", manager
manager.down e
.on "click tap", ".sortable-list [rel=reorder]", (e) ->
e.preventDefault()
<ul class="sortable-list">
<li class="sortable"><span rel="reorder"></span> Stark</li>
<li class="sortable"><span rel="reorder"></span> Lannister</li>
<li class="sortable"><span rel="reorder"></span> Baratheon</li>
<li class="sortable"><span rel="reorder"></span> Greyjoy</li>
</ul>
.sortable-list {
.sorting {
position: relative;
z-index: 1;
opacity: 0.85;
}
.sortable:not(.sorting) {
transition: transform 0.5s ease-out;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment