Last active
September 3, 2020 02:33
-
-
Save pradeep1991singh/61094a290befa181bba52519a28b61cc to your computer and use it in GitHub Desktop.
SortableList support drag-drop feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Sortable</title> | |
</head> | |
<body> | |
<div id="list"></div> | |
<script type="text/javascript"> | |
/** | |
* SortableList library code here | |
*/ | |
"use strict"; | |
let SortableList = (function (document) { | |
// 1: list constructor | |
function CustomSortableList(parentElement, data) { | |
// Set selectedItem initial value to null | |
this.selectedItem = null; | |
// Item default styles | |
this.itemStyle = `font-family: sans-serif; height: 25px; /*padding: 1px 5px; margin: 5px*/; border: 1px solid transparent; /*background: #ccc*/; line-height: 25px; /*border-radius: 3px*/;`; | |
try { | |
// Build & render list | |
let parentHtml = parentElement.innerHTML; | |
data.forEach((item, index) => { | |
parentHtml += `<li class="item" draggable="true" data-order="${index}" style="${this.itemStyle}">${item}</li>`; | |
}) | |
parentElement.innerHTML = `<ul>${parentHtml}</ul>`; | |
// add drag-drop event listeners | |
document.querySelectorAll(`#${parentElement.id} .item`).forEach(item => { | |
// This event is fired when the user starts dragging an element or text selection. | |
item.addEventListener('dragstart', this.dragStartHandler.bind(this)); | |
// This event is fired continuously when an element or text selection is being dragged and the mouse pointer | |
// is over a valid drop target (every 50 ms WHEN mouse is not moving ELSE much faster between 5 ms | |
// (slow movement) and 1ms (fast movement) approximately. This firing pattern is different than mouseover ). | |
item.addEventListener('dragover', this.dragOverHandler.bind(this)); | |
// This event is fired when a dragged element or text selection enters a valid drop target. | |
item.addEventListener('dragenter', this.dragEnterHandler.bind(this)); | |
// This event is fired when a dragged element or text selection leaves a valid drop target. | |
item.addEventListener('dragleave', this.dragLeaveHandler.bind(this)); | |
// This event is fired when an element or text selection is dropped on a valid drop target. | |
item.addEventListener('drop', this.dropHandler.bind(this)); | |
// The dragend event is fired when a drag operation is being ended | |
// (by releasing a mouse button or hitting the escape key). | |
item.addEventListener('dragend', this.dragEndHandler.bind(this)); | |
}); | |
} | |
catch (e) { | |
throw new Error(e); | |
} | |
} | |
// 2: drag and drop apis | |
CustomSortableList.prototype = { | |
dragStartHandler: function (e) { | |
// Add drag tracking class | |
e.target.classList.add('drag-start'); | |
// Handle styles | |
this.handleStyle(e.target) | |
// Move effect | |
e.dataTransfer.effectAllowed = 'move'; | |
// Add the target node's innerHTML to the data transfer object | |
e.dataTransfer.setData('text/html', e.target.innerHTML); | |
this.selectedItem = e.target; | |
}, | |
dragOverHandler: function (e) { | |
e.preventDefault(); | |
// Set the dropEffect to move | |
e.dataTransfer.dropEffect = 'move'; | |
if (this.selectedItem != e.target) { | |
// Sort items | |
this.getItemIndex(this.selectedItem) < this.getItemIndex(e.target) | |
? e.target.parentElement.insertBefore(this.selectedItem, e.target.nextSibling) | |
: e.target.parentElement.insertBefore(this.selectedItem, e.target); | |
} | |
}, | |
dragEnterHandler: function (e) { | |
e.target.classList.add('drag-enter'); | |
}, | |
dragLeaveHandler: function (e) { | |
e.target.classList.remove('drag-enter'); | |
}, | |
dropHandler: function (e) { | |
e.stopPropagation(); | |
// Handle drop here | |
}, | |
dragEndHandler: function (e) { | |
// Clear element classes | |
e.target.classList.remove('drag-start', 'drag-enter'); | |
// remove drag-start styles | |
this.handleStyle(e.target); | |
}, | |
handleStyle: function (targetElement) { | |
// Add drag-start styles | |
targetElement.className.indexOf('drag-start') > -1 | |
? targetElement.setAttribute('style', `${this.itemStyle}border:1px solid #000;`) | |
: targetElement.setAttribute('style', `${this.itemStyle}`); | |
}, | |
getItemIndex: function (item) { | |
const children = item.parentNode.children; | |
let i = children.length - 1 | |
for (; i >= 0; i--) { | |
if (item == children[i]) { | |
break; | |
} | |
} | |
return i; | |
} | |
} | |
return CustomSortableList; | |
})(document); | |
let data = [ | |
'A List Item', | |
'Another List Item', | |
'Yet Another List Item' | |
]; | |
let parentElement = document.getElementById('list'); | |
let list = new SortableList(parentElement, data); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment