欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-13 13:09:16
...

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

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

代码:

<!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>

 

相关标签: js脚本