jq 表格行、列拖动排序

这个需求出来本可以使用很多插件,但由于后面的需求无法满足在固定插件下继续开发,所以参考了layuitable插件制作了这样一个简单的行列拖拽排序。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>无标题文档</title>
		<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
		<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" rel="stylesheet">
		<style>
			.Reports {
				width: calc(100% - 20%);
				margin: 20px 10% !important;
				text-align: center;
				position: relative;
			}

			body,
			#sortable tbody {
				position: relative;
			}

			#sortable thead th p {
				margin: 0;
			}

			#sortable thead th {
				vertical-align: middle;
				height: 50px;
				border: 1px solid #dee2e6
			}

			#sortable tbody tr td:first-child {
				cursor: move;
				background-color: #555555;
				width: 150px;
			}

			#sortable th:first-child {
				width: 150px;
				background-color: #555555;
				border-right: 1px solid #555;
				border-top: 1px solid #555;
				border-bottom: 1px solid #555;
				position: relative;
			}

			#sortable tbody td {
				vertical-align: middle;
				position: relative;
			}

			#sortable tbody tr {
				position: inherit;
				border: 1px solid black;
			}

			#sortable .vis_hide {
				visibility: hidden;
				/* left: -2px; */
				border: none;
				border-bottom: 1px solid #e4e4e4;
			}

			.createDivBg {
				position: fixed;
				top: 0;
				bottom: 0;
				left: 0;
				right: 0;
				z-index: 10000;
				cursor: move;
				-moz-user-select: none;
				-webkit-user-select: none;
				-o-user-select: none;
				-ms-user-select: none
			}

			.createDiv {
				border: 1px dotted #ccc;
				height: 34px;
				line-height: 34px;
				background: #eee;
				position: fixed;
				z-index: 100000
			}

			body {

				-webkit-touch-callout: none;
				/* iOS Safari */

				-webkit-user-select: none;
				/* Chrome/Safari/Opera */

				-khtml-user-select: none;
				/* Konqueror */

				-moz-user-select: none;
				/* Firefox */

				-ms-user-select: none;
				/* Internet Explorer/Edge */

				user-select: none;
				/* Non-prefixed version, currently */

			}
		</style>
	</head>

	<body>
		<div style="">
			<div class="Reports">
				<table id="sortable" class="table table-bordered">
					<thead id="sorthead">
						<tr>
							<th class="Thead">
								<p>全不选</p>
								<p>全选</p>
							</th>
							<th data-key="1">样式一</th>
							<th data-key="2">样式二</th>
							<th data-key="3">样式三</th>
							<th class="Thead">总价</th>
						</tr>
					</thead>
					<tbody>
						<tr id="div1" data-index="0">
							<td class="RowSort Thead">小海豚</td>
							<td data-key="1">
								<div>
									<p>产品一</p>
									<p>¥500</p>
								</div>
							</td>
							<td data-key="2">
								<div>
									<p>产品二</p>
									<p>¥500</p>
								</div>
							</td>
							<td data-key="3">
								<div>
									<p>产品三</p>
									<p>¥560</p>
								</div>
							</td>
							<td>¥400</td>
						</tr>
						<tr id="div2" data-index="1">
							<td class="RowSort Thead">美的</td>
							<td data-key="1">
								<div>
									<p>产品一</p>
									<p>¥200</p>
								</div>
							</td>
							<td data-key="2">
								<div>
									<p>产品二</p>
									<p>¥500</p>
								</div>
							</td>
							<td data-key="3">
								<div>
									<p>产品三</p>
									<p>¥500</p>
								</div>
							</td>
							<td>¥400</td>
						</tr>
						<tr id="div3" data-index="2">
							<td class="RowSort Thead">志高</td>
							<td data-key="1">
								<div>
									<p>产品一</p>
									<p>¥500</p>
								</div>
							</td>
							<td data-key="2">
								<div>
									<p>产品二</p>
									<p>¥5900</p>
								</div>
							</td>
							<td data-key="3">
								<div>
									<p>产品三</p>
									<p>¥500</p>
								</div>
							</td>

							<td>¥400</td>
					</tbody>
				</table>
			</div>
		</div>
		<script>
			var _this = this,
				tableId = $("#sortable"),
				isDragging = false;
			window.onload = function() {
				$("table tbody tr").each(function() {
					let $sel = $(this).children("td:first");
					rowDrag($sel)
				})
				coldrag()
			}
			//列拖动
			function coldrag() {
				// 绑定鼠标按下事件
				$("table thead").find('th:not(:first)').css('cursor', 'move')
					.on('mousedown', function(e) {
						// 非鼠标左键都不执行
						if (e.button !== 0) {
							return;
						}
						e.preventDefault();
						var $this = $(this),
							field = $this.text(),
							key = $this.data('key'),
							headWidth = this.offsetWidth,
							thLeft = this.offsetLeft,
							trwidth = $this.parent().width(),
							headHight = this.offsetHeight;
						if (!key) {
							return;
						}
						var $cloneHead = $this.clone().addClass("vis_hide").css({
								'width': headWidth,
								'border': 'none',
								'border-bottom': '1px solid #e4e4e4'
							}).attr("isclone", ''),
							originLeft = $this.position().left,
							originTop = $this.offset().top,
							disX = e.clientX - originLeft, // 鼠标距离被移动元素左侧的距离
							color = $this.parents('tr:eq(0)').css("background-color"),
							width = $this.width(),
							moveDistince = 0,
							$that = $(this),
							firstmove = true,
							isStart = true;
						// 移动事件
						$('body').on('mousemove', function(e) {
							if (isStart && $cloneHead) {
								if (!isDragging) {
									$this.after($cloneHead);
									$this.css({
										'position': 'absolute',
										'z-index': 1,
										'border': '1px solid #e4e4e4',
										'background-color': '#e4e4e4',
										'width': headWidth,
										'height': headHight,
										'top': 0
									});
								}
							}
							if (firstmove) {
								$("table tbody").find('td[data-key="' + key + '"]').each(function() {
									$(this).after($(this).clone().addClass("vis_hide").css({
										'border': '1px solid #e4e4e4',
										'border-left': 'none'
									}).attr('data-clone', ''));
									$(this).css({
										'position': 'absolute',
										'z-index': 1,
										'background-color': '#e4e4e4',
										'width': headWidth,
										'top': '-2px'
									});
								})
							}
							firstmove = false
							isDragging = true;
							var left = e.clientX - disX, // 计算当前被移动列左侧位置应该哪里
								$leftTh = $cloneHead.prev().prev(),
								hasLeftTh = $leftTh.length > 0,
								leftKey = hasLeftTh ? $leftTh.data('key') : [],
								$rightTh = $cloneHead.next(),
								hasRightTh = $rightTh.length > 0,
								rightKey = hasRightTh ? $rightTh.data('key') : [],
								leftMove = hasLeftTh && ($cloneHead.position().left - left > $leftTh.width() / 2.0), //左移超过要进过的元素的一半就返回true
								rightMove = hasRightTh && (left - $cloneHead.position().left > $rightTh.width() / 2.0),
								moveDistince = Math.abs($cloneHead.position().left - left); //记录移动距离

							$this.css('left', left + 2); //要移动的元素
							// Thead 是要固定不能超过的类,
							if (leftMove) {
								if (!$leftTh.hasClass("Thead")) $cloneHead.after($leftTh);
							} else if (rightMove) {
								if (!$rightTh.hasClass("Thead")) $cloneHead.prev().before($rightTh);
							}
							//这里是td的交换
							$("table tbody").find('td[data-key="' + key + '"][data-clone]').each(function() {
								$(this).prev().css('left', left);
								if (leftMove) {
									if (!$leftTh.hasClass("Thead")) {
										if ($(this).prev().prev().length !== 0) {
											$(this).after($(this).prev().prev());
										}
									}
								} else if (rightMove) {
									if (!$rightTh.hasClass("Thead")) {
										if ($(this).next().length !== 0) {
											$(this).prev().before($(this).next());
										}
									}
								}
							})
						}).on('mouseup', function() {
							$('body').off('mousemove').off('mouseup')
							if (isStart && $cloneHead) {
								isStart = false;
								if (isDragging) {
									isDragging = false;
									$this.css({
										'position': 'relative',
										'z-index': 'inherit',
										'width': headWidth,
										'height': 'auto',
										'left': 'inherit',
										'background-color': 'transparent'
									});
									// 样式回滚到不影响
									$this.parent().find('th[data-key="' + key + '"][isclone]').remove(); //移除克隆项
									var prefKey = $this.prev().data('key');
									$('table tbody').find('td[data-key="' + key + '"][data-clone]').each(function() {
										$(this).prev().removeClass('vis_hide').css({
											'position': 'relative',
											'z-index': 'inherit',
											'left': 'inherit',
											'width': headWidth,
											'top': 0,
											'background-color': 'transparent'
										});
										$(this).remove();
									});
									$cloneHead = null;
								} else {
									$that.unbind('click');
								}
							}
						})
					})
			}

			//行拖动
			function rowDrag($sel) {
				// 被暂停 或者 不是鼠标左键 则取消拖拽效果
				$sel.on("mousedown", function(e) {
					// if (_this.suspendConfig[tableId].rowDrag || e.button !== 0) {
					// 	return;
					// }
					var $this = $(this),
						index = parseInt($this.parent().data('index')),
						$bodyTr = $("table").children('tbody').children('tr[data-index=' + index + ']'),
						$cloneTr = $bodyTr.clone().css('visibility', 'hidden'),
						bodyScrollTop = $("table").children('tbody').scrollTop(), // 记录当前滚动条位置
						originTop = $this.parent().position().top,
						disY = e.clientY - originTop, // 鼠标距离被移动元素上侧的距离(点的位置不同,数值不同)
						disW = this.parentNode.offsetWidth;
					$('body').on("mousemove", function(e) {
						if (!isDragging) {
							isDragging = true;
							// $(this).css({
							// 	cursor:'move'
							// })
							$bodyTr.after($cloneTr);
							$bodyTr.css({
								'position': 'absolute',
								'z-index': 1,
								'width': disW,
								'background-color': '#e4e4e4'
							})
							$bodyTr.children("td").css({
								"display": 'inline-block',
								'width': 100 / $bodyTr.children("td").length - 1 + '%',
								'white-space': 'nowrap',
								'border': 'none',
								'text-algin': 'center'
							})
						}
						var top = e.clientY - disY + ($("table").children('tbody').scrollTop() - bodyScrollTop), // 计算当前被移动行top位置应该哪里
							trTop = $cloneTr.position().top, //当前行所在位置
							$UpTr = $bodyTr.prev(),
							hasUpTr = $UpTr.length > 0,
							$downTr = $cloneTr.next(),
							hasDownTr = $downTr.length > 0,
							upMove = hasUpTr && (trTop - top > $UpTr.height() / 2.0),
							downMove = hasDownTr && (top - trTop > $downTr.height() / 2.0);

						if (trTop - top > 0 ? !hasUpTr : !hasDownTr) {
							$bodyTr.css('top', trTop);
							return;
						}
						$bodyTr.css('top', top);
						if (upMove) {
							updateDataIndex($bodyTr, -1)
							$cloneTr.after(updateDataIndex($UpTr, 1));
						} else if (downMove) {
							updateDataIndex($bodyTr, 1).before(updateDataIndex($downTr, -1))
						}
						// 同步 data-index
						function updateDataIndex($el, diff) {
							var tempIndex = parseInt($el.data('index')) + diff;
							$el.data('index', tempIndex);
							$el.attr('data-index', tempIndex);
							return $el
						}
					}).on('mouseup', function(e) {
						$('body').off('mousemove').off('mouseup');
						if (isDragging) {
							isDragging = false;
							$bodyTr.css({
								'position': 'inherit',
								'z-index': 'inherit',
								'top': 0,
								'width': 'auto',
								'background-color': 'transparent'
							});
							$bodyTr.children("td").css({
								"display": 'table-cell',
								'width': 'auto',
								border: '1px solid #dee2e6',
								'text-algin': 'center'
							})
							$bodyTr.next().remove();
						}
					})
				})
			}
		</script>
	</body>
</html>

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值