按住鼠标左键拖动选取单元格。选中的单元格背景变红色

效果如下图所示:碰到合并单元格,会自动做大选取范围。

代码:

<!DOCTYPE html>
<html>
 <HEAD>
  <TITLE>0003按住鼠标拖选单元格</TITLE>
  <script src="/static/jquery/jquery-3.3.1.min.js"></script>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <style type="text/css">
table,table tr th, table tr td { border:1px solid #0094ff;}
table { width: 750px; min-height: 25px; line-height: 25px; text-align: center; border-collapse: collapse;}

  </style>
  <SCRIPT LANGUAGE="JavaScript">
  var mouseDownFlag = false;
  var startTd,endTd;
  $(function(){
	  var tdsPos = getPos($("#tableId").children().eq(0));
	  getRealPos(tdsPos);
	  $("td").mousedown(function(){
		  mouseDownFlag = true;
		  startTd = this;
	  });
	  $("td").mouseup(function(){
		  mouseDownFlag = false;
		  endTd = this;
		  var obj = selectTd(tdsPos,startTd,endTd);
		  fillBackColor(obj);
	  });
	  $("td").mouseenter(function(){
		  if(mouseDownFlag){
			  endTd = this;
			  var obj = selectTd(tdsPos,startTd,endTd);
			  fillBackColor(obj);
		  }
	  });
	//填充背景颜色
	  function fillBackColor(obj){
		  $("td").css("background-color","");
		  var containTds = obj.containTds;
		  for(var i=0;i<containTds.length ;i++){
			  $(containTds[i].ele).css("background-color","red");
		  }
	  }

	//根据开始和结束单元格,获取选中的单元格
	  function selectTd(tdsPos, startTd,endTd){
		var obj = {startTd:startTd,endTd:endTd};
		var table = $(startTd).parent().parent();
		obj.startRowIdx = $(startTd).parent().prevAll().length;
		obj.startColIdx = $(startTd).prevAll().length;
		obj.endRowIdx = $(endTd).parent().prevAll().length;
		obj.endColIdx = $(endTd).prevAll().length;
		var containTds = [tdsPos[obj.startRowIdx][obj.startColIdx],tdsPos[obj.endRowIdx][obj.endColIdx]];
		obj.area = getMinArea(tdsPos,containTds);
		obj.containTds = containTds;
		return obj;
	  }
	//根据包含的tds,获取最小区域坐标
	function getAreaByTds(tdsPos,containTds){
		var area = {xMin:99999,yMin:99999,xMax:-1,yMax:-1};
		for(var i=0;i<containTds.length;i++){
			var xMin = Number(containTds[i].pos.x);
			var yMin = Number(containTds[i].pos.y);
			var xMax = Number(containTds[i].pos.x + containTds[i].colspan - 1);
			var yMax = Number(containTds[i].pos.y + containTds[i].rowspan - 1);
			area.xMin = Math.min(area.xMin,xMin);
			area.yMin = Math.min(area.yMin,yMin);
			area.xMax = Math.max(area.xMax,xMax);
			area.yMax = Math.max(area.yMax,yMax);
		}
		return area;
	}
	//根据包含的单元格确定最小区域
	function getMinArea(tdsPos,containTds){
		var newTds = [];
		var targetArea = getAreaByTds(tdsPos,containTds);
		for(var i=0;i<tdsPos.length;i++){
			var tds = tdsPos[i];
			for(var j=0;j<tds.length;j++){
				var td = tds[j];
				var f = function(item){
					return item.pos.x == td.pos.x && item.pos.y == td.pos.y;
				};
  				//只检查containTds还未包含的
				if(!containTds.find(f)){
					var tdArea = {};
					tdArea.xMin = td.pos.x;
					tdArea.yMin = td.pos.y;
					tdArea.xMax = td.pos.x + td.colspan - 1;
					tdArea.yMax = td.pos.y + td.rowspan - 1;
					var relation = getRelation(tdArea, targetArea);
					if(relation != "不相交"){
						newTds.push(td);
					}
				}
			}
		}
		if(newTds.length == 0){
			return targetArea;
		}
		for(var i=0;i<newTds.length;i++){
			containTds.push(newTds[i]);
		}
		return getMinArea(tdsPos,containTds);
	}
	  //获取单元格与指定区域内的关系,1.targetArea完全包含tdArea,2. targetArea与tdArea 部分重合 3. targetArea与tdArea不相交
	  function getRelation(tdArea, targetArea){
		//矩形各由两点(左上/右下)决定,使用屏幕坐标系
		//矩形   A (x1,y1),(x2,y2);
		 var x1 = tdArea.xMin;
		 var y1 = tdArea.yMin;
		 var x2 = tdArea.xMax;
		 var y2 = tdArea.yMax;
		//矩形   B   (x3,y3),(x4,y4);
		 var x3 = targetArea.xMin;
		 var y3 = targetArea.yMin;
		 var x4 = targetArea.xMax;
		 var y4 = targetArea.yMax;
		 var m= (x1 > x4)|(x2 < x3);
	     var n= (y2 < y3)|(y1 > y4);
	     if(m|n){
	     //不相交
	     	return "不相交";
	     }else{
	     //相交
	     	if(x3<=x1 && y3<=y1 && x4>=x2 && y4 >= y2){
	     		//targetArea完全包含tdArea
	     		return "包含";
	     	}else{
	     		//targetArea与tdArea 部分重合
	     		return "部分重合";
	     	}
	     }
		return "未定义关系";
	  }
	  /**获取单元格修正前的坐标位置 */
		function getPos(trParent) {
			var tdsPos = [];
			var trs = trParent.children();
			for(var i=0;i<trs.length;i++){
				var tr = trs.eq(i);
				var tds = tr.children();
				tdsPos[i] = [];
				for(var j=0;j<tds.length;j++){
					var td = tds.eq(j);
					var curRowIdx = $(td).parent().prevAll().length;
					var curColIdx = $(td).prevAll().length;
					var rowSpan = td.attr("rowSpan") ? Number(td.attr("rowSpan")) : 1;
					var colSpan = td.attr("colSpan") ? Number(td.attr("colSpan")) : 1;
					tdsPos[i][j] = {title:td.html(), pos:{x:curColIdx,y:curRowIdx}
						,rowspan : rowSpan, colspan :colSpan, ele:td };
				}
			}
			return tdsPos;
	    }
		/**获取单元格真实的X坐标位置 */
	 	function getRealPos(headRows) {
	            var findFieldRows = void 0;
	            //计算同一行x的位置
	            headRows.forEach(function (rowCols, y) {
	                var nextPosx = 0;
	                rowCols.forEach(function (col, x) {
	                    col.pos = {};
	                    col.pos.x = nextPosx;
	                    col.pos.y = y;
	                    col.colspan = col.colspan || 1;
	                    nextPosx = nextPosx + col.colspan;
	                });
	            });
	            //计算 rowspan对后边行的影响
	            for (var rowIndex = headRows.length - 1; rowIndex >= 0; rowIndex--) {
	                var curRow = headRows[rowIndex];
	                for (var cellIndex = 0; cellIndex < curRow.length; cellIndex++) {
	                    var curCell = curRow[cellIndex];
	                    //console.log("正在处理的行:=》", curCell);
	                    curCell.rowspan = curCell.rowspan || 1;
	                    if (curCell.rowspan > 1) {
	                        //将后边行中所有与当前cell相同位置的单元格依次后移当前单元格x相等的单元格后移当前单元格clospan个单位
	                        //当前行影响以后(被rowspan包含)所有的行
	                        for (var nextRowindex = rowIndex + 1; nextRowindex < headRows.length && curCell.rowspan > nextRowindex - rowIndex; nextRowindex++) {
	                            //判断是否存在合并信息
	                            var nextRow = headRows[nextRowindex];
	                            for (var nextCellIndex = 0; nextCellIndex < nextRow.length; nextCellIndex++) {
	                                var nextCell = nextRow[nextCellIndex];
	                                if (nextCell.pos.x >= curCell.pos.x) {
	                                    nextCell.pos.x += curCell.colspan;
	                                    //console.log("需要移动的列:=》", nextCell);
	                                }
	                            }
	                        }
	                    }
	                }
	        }
	    }
});
  </SCRIPT>
 </HEAD>
<body>
<a href="index.html">返回</a>
<h1>0003按住鼠标左键拖动选取单元格。选中的单元格背景变红色</h1>
<table id="tableId">
		<tr>
			<td colspan="3">A</td>
			<td rowspan="3">B</td>
			<td rowspan="2" colspan="2">C</td>
			<td>D</td>
		</tr>
		<tr>
			<td colspan="2">E</td>
			<td rowspan="2">F</td>
			<td>G</td>
		</tr>
		<tr>
			<td>H</td>
			<td>I</td>
			<td>J</td>
			<td>K</td>
			<td>L</td>
		</tr>
		<tr>
			<td>M</td>
			<td>N</td>
			<td>O</td>
			<td>P</td>
			<td>Q</td>
			<td>R</td>
			<td>S</td>
		</tr>
	</table>
</body>
</html>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值