按住鼠标左键拖动选取单元格。选中的单元格背景变红色
程序员文章站
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>
下一篇: ibatis 批量添加数据