I’ve got drag and drop working, I use a fairly standard drag and drop.
You can see the GitHub here.
There are two things, one annoying, and one “nice to have”, that I’d like to fix.
On the annoying side, I cannot drag anything to the bottom row. I can drag the bottom row up, I just can’t drag anything to the bottom row.
On the “nice to have” side, I would like to move the rows aside as I move something down:
The pertinent snippets of the code relating to dragging below:
CSS:
ul.order { /* Set up a list with no indent and no first character to make sortable table appearance */
list-style-type: none;
margin-left: 0; padding-left: 0;
}
.grid-container {
display: table;
width: 100%;
border: none;
cursor: move;
font-size: 18px;
}
.grid-containerHdr {
display: table;
width: 100%;
margin-bottom: -16px;
border: none;
font-size: 18px;
}
The list that looks like a table table is generated with the following JS:
for (i = 0; i < Object.keys(customMenus).length; i++) {
const containerSpan = document.createElement('span');
containerSpan.classList.add("grid-container");
const menuIdSpan = document.createElement('span');
menuIdSpan.classList.add("baseSort", "menuIdBody");
const menuTitleSpan = document.createElement('span');
menuTitleSpan.classList.add("baseSort", "menuTitleBody");
const parentIdSpan = document.createElement('span');
parentIdSpan.classList.add("baseSort", "menuParentIdBody");
const menuArgSpan = document.createElement('span');
menuArgSpan.classList.add("baseSort", "menuArgBody");
var createLi = document.createElement("li");
createLi.setAttribute('id', customMenus[i].menuId);
createLi.setAttribute('draggable', true);
createLi.classList.add("listItem");
menuIdSpan.appendChild(document.createTextNode(customMenus[i].menuId));
menuTitleSpan.appendChild(document.createTextNode(customMenus[i].menuTitle));
parentIdSpan.appendChild(document.createTextNode(customMenus[i].parentId));
menuArgSpan.appendChild(document.createTextNode(customMenus[i].menuArg));
//console.log(menuIdSpan,menuTitleSpan);
containerSpan.appendChild(menuIdSpan);
containerSpan.appendChild(menuTitleSpan);
containerSpan.appendChild(parentIdSpan);
containerSpan.appendChild(menuArgSpan);
createLi.appendChild(containerSpan);
ulSort.appendChild(createLi);
}
The sort code is:
var listItems = document.querySelectorAll('.listItem');
var dragSrcEl = null;
function handleDragStart(e) {
this.className += " dragStartClass";
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
e.dataTransfer.setDragClass("dataTransferClass");
//just added
e.target.style.border = "5px solid #ffffff";
}
function handleDragOver(e) {
// if (e.preventDefault) { not needed according to my question and anwers on : http://stackoverflow.com/questions/36920665/why-if-statement-with-e-preventdefault-drag-and-drop-javascript
e.preventDefault();
// }
e.dataTransfer.dropEffect = 'move'; // sets cursor
return false;
}
function handleDragEnter(e) {
// this / e.target is the current hover target.
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over'); // this / e.target is previous target element.
}
function handleDrop(e) {
var listItems = document.querySelectorAll('.listItem');
e.stopPropagation(); // stops the browser from redirecting.
dragSrcOrderId = parseInt(dragSrcEl.getAttribute("order-id"));
dragTargetOrderId = parseInt(this.getAttribute("order-id"));
var tempThis = this;
// Don't do anything if dropping the same column we're dragging.
// and
// check if only one difference and then do not execute
// && ((Math.abs(dragSrcOrderId - dragTargetOrderId)) != 1)
if (dragSrcEl != this) {
// Set the source column's HTML to the HTML of the column we dropped on.
var tempThis = this;
function makeNewOrderIds(tempThis) {
// check if up or down movement
dragSrcEl.setAttribute("order-id", dragTargetOrderId);
tempThis.setAttribute("order-id", dragTargetOrderId);
// find divs between old and new location and set new ids - different in up or down movement (if else)
if (dragSrcOrderId < dragTargetOrderId) {
for (i = dragSrcOrderId + 1; i < dragTargetOrderId; i++) {
listItems[i].setAttribute("order-id", i - 1);
// set new id src
dragSrcEl.setAttribute("order-id", dragTargetOrderId - 1);
}
} else {
for (i = dragTargetOrderId; i < dragSrcOrderId; i++) {
listItems[i].setAttribute("order-id", i + 1);
// set new id src
dragSrcEl.setAttribute("order-id", dragTargetOrderId);
}
}
};
makeNewOrderIds(tempThis);
dragSrcEl.classList.remove("dragStartClass");
reOrder(listItems);
} else {
dragSrcEl.classList.remove("dragStartClass");
return false;
}
};
function handleDragEnd(e) {
for (i = 0; i < listItems.length; i++) {
listItem = listItems[i];
listItem.classList.remove('over');
}
dragSrcEl.classList.remove("dragStartClass");
e.target.style.border = "none";
}
for (i = 0; i < listItems.length; i++) {
listItem = listItems[i];
listItem.setAttribute("order-id", i);
listItem.addEventListener('dragstart', handleDragStart, false)
listItem.addEventListener('dragenter', handleDragEnter, false)
listItem.addEventListener('dragover', handleDragOver, false)
listItem.addEventListener('dragleave', handleDragLeave, false)
listItem.addEventListener('drop', handleDrop, false)
listItem.addEventListener('dragend', handleDragEnd, false)
}
function reOrder(listItems) {
var tempListItems = listItems;
tempListItems = Array.prototype.slice.call(tempListItems, 0);
tempListItems.sort(function(a, b) {
return a.getAttribute("order-id") - b.getAttribute("order-id");
});
var parent = document.getElementById('listOrder');
parent.innerHTML = "";
for (var i = 0, l = tempListItems.length; i < l; i++) {
parent.appendChild(tempListItems[i]);
}
};