Javascript 在HTML表格上拖动所选内容(带colspan/rowspan的方形/矩形部分)
我正在研究如何在表中选择单元格,但在我的例子中,单元格可以有一个colspan或rowspan,这样选择就不会局限于正方形/矩形选择(尝试选择“1-3”和“2-3”,这两个选项也会自动选择“1-4”)。这和问题类似,但我一直没能找到任何有效的方法。你知道这将如何实施吗 链接: HTMLJavascript 在HTML表格上拖动所选内容(带colspan/rowspan的方形/矩形部分),javascript,jquery,css,angularjs,html-table,Javascript,Jquery,Css,Angularjs,Html Table,我正在研究如何在表中选择单元格,但在我的例子中,单元格可以有一个colspan或rowspan,这样选择就不会局限于正方形/矩形选择(尝试选择“1-3”和“2-3”,这两个选项也会自动选择“1-4”)。这和问题类似,但我一直没能找到任何有效的方法。你知道这将如何实施吗 链接: HTML 我使用了起始单元格和结束单元格的x和y坐标,然后计算对应矩形内的每个单元格(甚至部分)。然后获取这些单元格的边框,并重复此过程,直到选择不再扩展 编辑:功能rectangleSelect是(几乎完全)来自: 编辑
我使用了起始单元格和结束单元格的x和y坐标,然后计算对应矩形内的每个单元格(甚至部分)。然后获取这些单元格的边框,并重复此过程,直到选择不再扩展 编辑:功能
rectangleSelect
是(几乎完全)来自:
编辑2:现在支持rowspan和其他边缘,如选择[3-2,2-3]:
HTML:
安古拉斯普朗克
文件。写(“”);
1-1
1-2
1-3
1-4
2-1
2-32-2
3-1
3-2
3-4
4-1
4-2
4-3
4-4
所选ID:{IDs | json}
CSS:未更改
JS:
var-app=angular.module('plunker',[]);
应用程序控制器('MainCtrl',函数($scope){
$scope.ids=[];
});
应用程序指令('dragSelect',函数($window,$document){
返回{
范围:{
DragSelectId:“=”
},
控制器:函数($scope$element){
var cls=‘工程选定项目’;
var startCell=null;
var=false;
功能鼠标(el){
拖动=假;
}
功能鼠标向下(el){
拖动=真;
电池(el);
setEndCell(el);
}
功能鼠标器(el){
如果(!拖动)返回;
setEndCell(el);
}
函数setStartCell(el){
startCell=el;
}
函数setEndCell(el){
$scope.dragSelectIds=[];
$element.find('td').removeClass(cls);
$(cellsBetween(startCell,el))。每个(函数(){
var el=角度元素(本);
el.addClass(cls);
$scope.dragSelectIds.push(el.attr('id'));
});
}
函数isPointBetween(点,x1,x2){
返回(点>=x1&&point应该选择1-1作为左上角,2-3作为右下角,也应该选择1-4?然后如何选择1-1,1-2,1-3,2-1,2-2,2-3?可能类似的东西更适合您所寻找的功能:是的。它应该基本上模仿excel的功能。因此选择应该始终是正方形的/矩形。谢谢!但是如果有行跨度(尝试从3-2拖动到3-4),有人可以添加对多个选择的支持吗?每次我做一个新的选择时,旧的选择都会显示出来?当一行的所有单元格合并,并尝试选择垂直的一列,横穿整行时会出现错误。(如十字架)
<table drag-select drag-select-ids="ids">
<tr>
<td id="td-1-1">1-1</td>
<td id="td-1-2">1-2</td>
<td id="td-1-3">1-3</td>
<td id="td-1-4">1-4</td>
</tr>
<tr>
<td id="td-2-1">2-1</td>
<td id="td-2-2">2-2</td>
<td id="td-2-3" colspan="2">2-3</td>
</tr>
<tr>
<td id="td-3-1">3-1</td>
<td id="td-3-2">3-2</td>
<td id="td-3-3">3-3</td>
<td id="td-3-4">3-4</td>
</tr>
<tr>
<td id="td-4-1">4-1</td>
<td id="td-4-2">4-2</td>
<td id="td-4-3">4-3</td>
<td id="td-4-4">4-4</td>
</tr>
</table>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.ids = [];
});
app.directive('dragSelect', function($window, $document) {
return {
scope: {
dragSelectIds: '='
},
controller: function($scope, $element) {
var cls = 'eng-selected-item';
var startCell = null;
var dragging = false;
function mouseUp(el) {
dragging = false;
}
function mouseDown(el) {
dragging = true;
setStartCell(el);
setEndCell(el);
}
function mouseEnter(el) {
if (!dragging) return;
setEndCell(el);
}
function setStartCell(el) {
startCell = el;
}
function setEndCell(el) {
$scope.dragSelectIds = [];
$element.find('td').removeClass(cls);
cellsBetween(startCell, el).each(function() {
var el = angular.element(this);
el.addClass(cls);
$scope.dragSelectIds.push(el.attr('id'));
});
}
function cellsBetween(start, end) {
var coordsStart = getCoords(start);
var coordsEnd = getCoords(end);
var topLeft = {
column: $window.Math.min(coordsStart.column, coordsEnd.column),
row: $window.Math.min(coordsStart.row, coordsEnd.row),
};
var bottomRight = {
column: $window.Math.max(coordsStart.column, coordsEnd.column),
row: $window.Math.max(coordsStart.row, coordsEnd.row),
};
return $element.find('td').filter(function() {
var el = angular.element(this);
var coords = getCoords(el);
return coords.column >= topLeft.column
&& coords.column <= bottomRight.column
&& coords.row >= topLeft.row
&& coords.row <= bottomRight.row;
});
}
function getCoords(cell) {
var row = cell.parents('row');
return {
column: cell[0].cellIndex,
row: cell.parent()[0].rowIndex
};
}
function wrap(fn) {
return function() {
var el = angular.element(this);
$scope.$apply(function() {
fn(el);
});
}
}
$element.delegate('td', 'mousedown', wrap(mouseDown));
$element.delegate('td', 'mouseenter', wrap(mouseEnter));
$document.delegate('body', 'mouseup', wrap(mouseUp));
}
}
});
[drag-select] {
cursor: pointer;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
[drag-select] .eng-selected-item {
background: blue;
color: white;
}
td {
padding: 10px;
border: 1px solid gray;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="jquery" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<table drag-select drag-select-ids="ids">
<tr>
<td id="td-1-1">1-1</td>
<td id="td-1-2">1-2</td>
<td id="td-1-3">1-3</td>
<td id="td-1-4">1-4</td>
</tr>
<tr>
<td id="td-2-1" colspan=2>2-1</td>
<td id="td-2-3" rowspan="2">2-3</td
><td id="td-2-4">2-2</td>
</tr>
<tr>
<td id="td-3-1">3-1</td>
<td id="td-3-2">3-2</td>
<td id="td-3-4">3-4</td>
</tr>
<tr>
<td id="td-4-1">4-1</td>
<td id="td-4-2">4-2</td>
<td id="td-4-3">4-3</td>
<td id="td-4-4">4-4</td>
</tr>
</table>
<p>Selected IDs: {{ids | json}}</p>
</body>
</html>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.ids = [];
});
app.directive('dragSelect', function($window, $document) {
return {
scope: {
dragSelectIds: '='
},
controller: function($scope, $element) {
var cls = 'eng-selected-item';
var startCell = null;
var dragging = false;
function mouseUp(el) {
dragging = false;
}
function mouseDown(el) {
dragging = true;
setStartCell(el);
setEndCell(el);
}
function mouseEnter(el) {
if (!dragging) return;
setEndCell(el);
}
function setStartCell(el) {
startCell = el;
}
function setEndCell(el) {
$scope.dragSelectIds = [];
$element.find('td').removeClass(cls);
$(cellsBetween(startCell, el)).each(function() {
var el = angular.element(this);
el.addClass(cls);
$scope.dragSelectIds.push(el.attr('id'));
});
}
function isPointBetween(point,x1,x2){
return (point >=x1 && point <=x2) ||(point <=x1 && point>=x2);
}
function rectangleSelect(selector, bounds) {
var elements = [];
jQuery(selector).each(function() {
var $this = jQuery(this);
var offset = $this.offset();
var x = offset.left;
var y = offset.top;
var w = $this.outerWidth();
var h = $this.outerHeight();
if ((isPointBetween(x,bounds.minX,bounds.maxX) && isPointBetween(y,bounds.minY,bounds.maxY))||
(isPointBetween(x+w,bounds.minX,bounds.maxX) && isPointBetween(y+h,bounds.minY,bounds.maxY))
) {
elements.push($this.get(0));
}
});
return elements;
}
function getBoundsForElements(elements){
var x1= elements.reduce(function(currMinX,element){
var elementLeft = $(element).offset().left;
return currMinX && currMinX<elementLeft ? currMinX : elementLeft;
},undefined);
var x2= elements.reduce(function(currMaxX,element){
var elementRight = $(element).offset().left+$(element).outerWidth();
return currMaxX && currMaxX>elementRight ? currMaxX : elementRight;
},undefined);
var y1= elements.reduce(function(currMinY,element){
var elementTop = $(element).offset().top;
return currMinY && currMinY<elementTop ? currMinY : elementTop;
},undefined);
var y2= elements.reduce(function(currMaxY,element){
var elementBottom = $(element).offset().top+$(element).outerHeight();
return currMaxY && currMaxY>elementBottom ? currMaxY : elementBottom;
},undefined);
return {
minX: x1,
maxX: x2,
minY: y1,
maxY: y2
};
}
function cellsBetween(start, end) {
var bounds,elementsInside;
elementsInside = [start,end];
do{
bounds = getBoundsForElements(elementsInside);
var elementsInsideAfterExpansion = rectangleSelect("td",bounds);
if(elementsInside.length==elementsInsideAfterExpansion.length)
return elementsInside;
else
elementsInside=elementsInsideAfterExpansion;
}while(true)
}
function wrap(fn) {
return function() {
var el = angular.element(this);
$scope.$apply(function() {
fn(el);
});
}
}
$element.delegate('td', 'mousedown', wrap(mouseDown));
$element.delegate('td', 'mouseenter', wrap(mouseEnter));
$document.delegate('body', 'mouseup', wrap(mouseUp));
}
}
});