console
class Sortable {
constructor(el) {
this.element = el;
this.draggingEl = null;
this.draggingIn = 0;
this.lastIn = 0;
this.children = this.element.querySelectorAll("li");
this.childHeight = this.children[0].offsetHeight;
this.boundingOffset = this.element.getBoundingClientRect();
this.maxRange = this.childHeight * (this.children.length - 1);
this.indexInit();
this.positionInit();
this.eventInit();
window.onselectstart = function () {
return false;
}
}
indexInit() {
this.children.forEach(function (item, index) {
item.setAttribute("index", index);
})
}
positionInit() {
let itemHeight = this.childHeight;
this.children.forEach(function (item) {
let index = item.getAttribute("index");
item.style.top = `${index * itemHeight}px`;
})
}
eventInit() {
let that = this;
for (let i = 0; i < this.children.length; i++) {
this.children[i].addEventListener("mousedown", function (e) {
let startY = e.offsetY;
this.classList.add("aboveAll");
that.boundingOffset = that.element.getBoundingClientRect();
that.draggingEl = this;
that.draggingIn = this.getAttribute("index");
that.lastIn = this.getAttribute("index");
(function (thisEl) {
document.onmousemove = function (e) {
let y = e.clientY - that.boundingOffset.top - startY;
if (y <= 0) y = 0;
if (y >= that.maxRange) y = that.maxRange;
that.getPosition(y);
thisEl.style.top = `${y}px`;
}
})(this);
});
}
document.onmouseup = function () {
that.draggingEl.classList.remove("aboveAll");
that.draggingEl.setAttribute("index", that.draggingIn);
that.positionInit();
this.onmousemove = null;
}
}
getPosition(y) {
let index = Math.round(y / this.childHeight);
this.draggingIn = index;
if (index != this.lastIn) {
this.find(index).setAttribute("index", this.lastIn);
this.draggingEl.setAttribute("index", index);
this.lastIn = index;
this.positionInit();
}
}
find(index) {
for (let i = 0; i < this.children.length; i++) {
if (this.children[i].getAttribute("index") == index) return this.children[i];
}
}
}
let Sorter = new Sortable(document.querySelector(".sortable"));
<ul class="sortable">
<li>Content 1</li>
<li>Content 2</li>
<li>Content 3</li>
<li>Content 4</li>
<li>Content 5</li>
<li>Content 6</li>
<li>Content 7</li>
<li>Content 8</li>
<li>Content 9</li>
</ul>
* {
margin: 0;
padding: 0;
}
.sortable {
position: absolute;
left: 50%;
top: 50px;
transform: translate(-50%,0);
width: 200px;
list-style: none;
}
.sortable li {
position: absolute;
top: 0;
background: #50dd92;
width: 100%;
height: 40px;
border-radius: 18px;
box-sizing: border-box;
border: 1px solid #fff;
text-align: center;
line-height: 40px;
cursor: pointer;
transition: top 0.3s;
}
.aboveAll {
z-index: 1;
transition: none!important;
}