JavaScript创建的可编辑表格
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>JS可拖拽表格</title>
<style>
:root {
--pre-color: lavender;
--end-color: #ffccff;
}
table {
width: 70%; margin: 20px auto; border-collapse: collapse; font-size: 14px;
}
th {
height: 32px; font-weight: bold; background-color: #ccc;
}
td {
width: 25%; height: 32px; border: 1px solid #000; text-align: center;
user-select: none; cursor: move;
}
.dragging { background-color: lavender; }
.hover-target { background-color: #ffccff; }
#drag-helper {
position: absolute; display: none; border: 1px solid #000;
background-color: #ffccff; pointer-events: none; z-index: 1000;
text-align: center; line-height: 32px; font-size: 14px;
}
</style>
</head>
<body>
<table id="draggableTable">
<thead><tr><th colspan="4">JS可拖拽表格</th></tr></thead>
<tbody>
<tr><td>Java</td><td>Java One</td><td>JBuilder</td><td>PB</td></tr>
<tr><td>C++</td><td>VS</td><td>Office</td><td>Windows</td></tr>
<tr><td>PS</td><td>Flash</td><td>.Net</td><td>PM</td></tr>
</tbody>
</table>
<div id="drag-helper"></div>
<script type="text/javascript">
/**
* created by yzh 2002.4.12
* 可以实现表格内容的内部拖动
* 确保中间过度层的存在,id为指定
* 请大家引用时保留这段作者声明,此代码为开源代码;使用不受限制,欢迎大家采用本人所写JS动态拖动表格实现代码。
*/
// ====== 模拟 class:使用构造函数 + prototype ======
function DraggableTable(tableId) {
this.table = document.getElementById(tableId);
this.helper = document.getElementById('drag-helper');
this.draggedCell = null;
this.originalContent = '';
this.offsetX = 0;
this.offsetY = 0;
// 保存 this 引用(避免回调中 this 指向 window)
var self = this;
// 使用 DOM事件绑定
this.table.onmousedown = function(e) {
self.onMouseDown(e || window.event);
};
document.onmousemove = function(e) {
self.onMouseMove(e || window.event);
};
document.onmouseup = function(e) {
self.onMouseUp(e || window.event);
};
// 禁止文本选中(IE)
this.table.onselectstart = function() { return false; };
}
// 手动实现 element.closest('td')
DraggableTable.prototype.findClosestTd = function(el) {
while (el && el.nodeName) {
if (el.nodeName.toLowerCase() === 'td') {
return el;
}
el = el.parentNode;
}
return null;
};
// 清除所有 hover-target 类
DraggableTable.prototype.clearHover = function() {
var tds = this.table.getElementsByTagName('td');
for (var i = 0; i < tds.length; i++) {
var cls = tds[i].className;
if (cls.indexOf('hover-target') !== -1) {
tds[i].className = cls.replace('hover-target', '').replace(/\s+/g, ' ');
}
}
};
// ====== 事件处理方法 ======
DraggableTable.prototype.onMouseDown = function(e) {
var target = e.target || e.srcElement;
var cell = this.findClosestTd(target);
if (!cell) return;
// 阻止默认行为
if (e.preventDefault) e.preventDefault();
else e.returnValue = false;
this.draggedCell = cell;
this.originalContent = cell.innerHTML;
// 添加 dragging 样式
cell.className += ' dragging';
// 初始化 helper
var rect = this.getOffset(cell);
this.helper.style.width = rect.width + 'px';
this.helper.style.height = rect.height + 'px';
this.helper.innerHTML = this.originalContent;
this.helper.style.display = 'block';
this.offsetX = e.clientX - rect.left;
this.offsetY = e.clientY - rect.top;
this.updateHelperPosition(e.clientX - this.offsetX, e.clientY - this.offsetY);
};
DraggableTable.prototype.onMouseMove = function(e) {
if (!this.draggedCell) return;
this.updateHelperPosition(e.clientX - this.offsetX, e.clientY - this.offsetY);
// 清除旧 hover
this.clearHover();
// 查找当前悬停的 td
var target = document.elementFromPoint ?
document.elementFromPoint(e.clientX, e.clientY) : null;
var hoverCell = target ? this.findClosestTd(target) : null;
if (hoverCell && hoverCell !== this.draggedCell &&
this.isInsideTable(hoverCell)) {
hoverCell.className += ' hover-target';
}
};
DraggableTable.prototype.onMouseUp = function(e) {
if (!this.draggedCell) return;
// 查找 drop 目标
var target = document.elementFromPoint ?
document.elementFromPoint(e.clientX, e.clientY) : null;
var dropCell = target ? this.findClosestTd(target) : null;
if (dropCell && dropCell !== this.draggedCell &&
this.isInsideTable(dropCell)) {
// 交换内容
var temp = dropCell.innerHTML;
dropCell.innerHTML = this.originalContent;
this.draggedCell.innerHTML = temp;
}
// 清理
this.draggedCell.className = this.draggedCell.className.replace('dragging', '').replace(/\s+/g, ' ');
this.helper.style.display = 'none';
this.clearHover();
this.draggedCell = null;
};
DraggableTable.prototype.updateHelperPosition = function(x, y) {
this.helper.style.left = x + 'px';
this.helper.style.top = y + 'px';
};
// 判断单元格是否在本表格内
DraggableTable.prototype.isInsideTable = function(cell) {
var parent = cell;
while (parent) {
if (parent === this.table) return true;
parent = parent.parentNode;
}
return false;
};
// 获取元素绝对位置(兼容 IE6+)
DraggableTable.prototype.getOffset = function(el) {
var left = 0, top = 0, width = el.offsetWidth, height = el.offsetHeight;
while (el) {
left += el.offsetLeft;
top += el.offsetTop;
el = el.offsetParent;
}
return { left: left, top: top, width: width, height: height };
};
// ====== 初始化 ======
function initApp() {
new DraggableTable('draggableTable');
}
// 使用 window.onload 确保 DOM 加载完成
if (window.addEventListener) {
window.addEventListener('load', initApp, false);
} else if (window.attachEvent) {
window.attachEvent('onload', initApp);
} else {
window.onload = initApp;
}
</script>
</body>
</html>
浙公网安备 33010602011771号