我有一个像这样的简单表格。
╔═════════════╦═════════╦═════════╗
║ Col1 ║ Col2 ║ Col3 ║
╠═════════════╬═════════╬═════════╣
║ Value 1 ║ Value 2 ║ Value 3 ║
║ Value 4 ║ Value 5 ║ Value 6 ║
║ Value 7 ║ Value 8 ║ Value 9 ║
╚═════════════╩═════════╩═════════╝
我需要它的值的行是可以拖动的,这样我就可以改变它们的顺序。类似的方式 .sortable()
在jquery中可以使用,但我需要在vanila JS中使用。我已经找到了许多使用不同库的解决方案,但在纯JS中没有。
有足够简单的解决方案吗?我不需要动画或任何库提供的东西,只需要功能。
提前感谢你的任何形式的帮助。
在codepen上找到了一个用vanila JS的工作方案。
https:/codepen.iochingypenExxvpjo?editors=1010。
JS
(function() {
"use strict";
const table = document.getElementById('table');
const tbody = table.querySelector('tbody');
var currRow = null,
dragElem = null,
mouseDownX = 0,
mouseDownY = 0,
mouseX = 0,
mouseY = 0,
mouseDrag = false;
function init() {
bindMouse();
}
function bindMouse() {
document.addEventListener('mousedown', (event) => {
if(event.button != 0) return true;
let target = getTargetRow(event.target);
if(target) {
currRow = target;
addDraggableRow(target);
currRow.classList.add('is-dragging');
let coords = getMouseCoords(event);
mouseDownX = coords.x;
mouseDownY = coords.y;
mouseDrag = true;
}
});
document.addEventListener('mousemove', (event) => {
if(!mouseDrag) return;
let coords = getMouseCoords(event);
mouseX = coords.x - mouseDownX;
mouseY = coords.y - mouseDownY;
moveRow(mouseX, mouseY);
});
document.addEventListener('mouseup', (event) => {
if(!mouseDrag) return;
currRow.classList.remove('is-dragging');
table.removeChild(dragElem);
dragElem = null;
mouseDrag = false;
});
}
function swapRow(row, index) {
let currIndex = Array.from(tbody.children).indexOf(currRow),
row1 = currIndex > index ? currRow : row,
row2 = currIndex > index ? row : currRow;
tbody.insertBefore(row1, row2);
}
function moveRow(x, y) {
dragElem.style.transform = "translate3d(" + x + "px, " + y + "px, 0)";
let dPos = dragElem.getBoundingClientRect(),
currStartY = dPos.y, currEndY = currStartY + dPos.height,
rows = getRows();
for(var i = 0; i < rows.length; i++) {
let rowElem = rows[i],
rowSize = rowElem.getBoundingClientRect(),
rowStartY = rowSize.y, rowEndY = rowStartY + rowSize.height;
if(currRow !== rowElem && isIntersecting(currStartY, currEndY, rowStartY, rowEndY)) {
if(Math.abs(currStartY - rowStartY) < rowSize.height / 2)
swapRow(rowElem, i);
}
}
}
function addDraggableRow(target) {
dragElem = target.cloneNode(true);
dragElem.classList.add('draggable-table__drag');
dragElem.style.height = getStyle(target, 'height');
dragElem.style.background = getStyle(target, 'backgroundColor');
for(var i = 0; i < target.children.length; i++) {
let oldTD = target.children[i],
newTD = dragElem.children[i];
newTD.style.width = getStyle(oldTD, 'width');
newTD.style.height = getStyle(oldTD, 'height');
newTD.style.padding = getStyle(oldTD, 'padding');
newTD.style.margin = getStyle(oldTD, 'margin');
}
table.appendChild(dragElem);
let tPos = target.getBoundingClientRect(),
dPos = dragElem.getBoundingClientRect();
dragElem.style.bottom = ((dPos.y - tPos.y) - tPos.height) + "px";
dragElem.style.left = "-1px";
document.dispatchEvent(new MouseEvent('mousemove',
{ view: window, cancelable: true, bubbles: true }
));
}
function getRows() {
return table.querySelectorAll('tbody tr');
}
function getTargetRow(target) {
let elemName = target.tagName.toLowerCase();
if(elemName == 'tr') return target;
if(elemName == 'td') return target.closest('tr');
}
function getMouseCoords(event) {
return {
x: event.clientX,
y: event.clientY
};
}
function getStyle(target, styleName) {
let compStyle = getComputedStyle(target),
style = compStyle[styleName];
return style ? style : null;
}
function isIntersecting(min0, max0, min1, max1) {
return Math.max(min0, max0) >= Math.min(min1, max1) &&
Math.min(min0, max0) <= Math.max(min1, max1);
}
init();
})();
CSS:
.draggable-table {
position: absolute;
top: 25%;
left: 20%;
width: 60%;
height: 50%;
border-collapse: collapse;
background: white;
-webkit-box-shadow: 0px 0px 10px 8px rgba(0, 0, 0, 0.1);
box-shadow: 0px 0px 10px 8px rgba(0, 0, 0, 0.1);
}
.draggable-table .draggable-table__drag {
font-size: 0.95em;
font-weight: lighter;
text-transform: capitalize;
position: absolute;
width: 100%;
text-indent: 50px;
border: 1px solid #f1f1f1;
z-index: 10;
cursor: grabbing;
-webkit-box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.05);
box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.05);
opacity: 1;
}
HTML
<table id="table" class="draggable-table">
<thead>
<th>Name</th>
<th>Occupation</th>
</thead>
<tbody>
<tr>
<td>April Douglas</td>
<td>Health Educator</td>
</tr>
<tr>
<td>Salma Mcbride</td>
<td>Mental Health Counselor</td>
</tr>
<tr>
<td>Kassandra Donovan</td>
<td>Makeup Artists</td>
</tr>
<tr>
<td>Yosef Hartman</td>
<td>Theatrical and Performance</td>
</tr>
<tr>
<td>Ronald Mayo</td>
<td>Plant Etiologist</td>
</tr>
<tr>
<td>Trey Woolley</td>
<td>Maxillofacial Surgeon</td>
</tr>
</tbody>
</table>