【发布时间】:2018-11-12 10:42:48
【问题描述】:
我正在努力实现在表格中选择单元格。
我在这里找到了非常好的解决方案:
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 rectangleSelect(selector, x1,x2, y1, y2) {
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.width();
var h = $this.height();
if (x >= x1 && x<=x2 && y>=y1 && y<=y2) {
// this element fits inside the selection rectangle
elements.push($this.get(0));
}
});
return elements;
}
function cellsBetween(start, end) {
var bounds = {minX:0,minY:0,maxX:0,maxY:0};
bounds.minX = $window.Math.min($(start).offset().left,$(end).offset().left);
bounds.minY = $window.Math.min($(start).offset().top,$(end).offset().top);
bounds.maxX = $window.Math.max($(end).offset().left+$(end).width(),$(start).offset().left+$(start).width());
bounds.maxY = $window.Math.max($(end).offset().top+$(end).height(),$(start).offset().top+$(start).height());
var initiallySelectedTds = rectangleSelect("td",bounds.minX,bounds.maxX,bounds.minY,bounds.maxY);
for(var i=0;i<initiallySelectedTds.length;i++){
if($(initiallySelectedTds[i]).offset().left<bounds.minX)
bounds.minX = $(initiallySelectedTds[i]).offset().left;
if($(initiallySelectedTds[i]).offset().left+$(initiallySelectedTds[i]).width()>bounds.maxX)
bounds.maxX = $(initiallySelectedTds[i]).offset().left+$(initiallySelectedTds[i]).width();
if($(initiallySelectedTds[i]).offset().top<bounds.minY)
bounds.minY = $(initiallySelectedTds[i]).offset().top;
if($(initiallySelectedTds[i]).offset().top+$(initiallySelectedTds[i]).height()>bounds.maxY)
bounds.maxY = $(initiallySelectedTds[i]).offset().top+$(initiallySelectedTds[i]).height();
}
return rectangleSelect("td",bounds.minX,bounds.maxX,bounds.minY,bounds.maxY);
}
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>
<td id="td-1-5">1-5</td>
<td id="td-1-6">1-6</td>
<td id="td-1-7">1-7</td>
<td id="td-1-8">1-8</td>
<td id="td-1-9">1-9</td>
<td id="td-1-10">1-10</td>
</tr>
<tr>
<td id="td-2-1">2-1</td>
<td id="td-2-2">2-2</td>
<td id="td-2-3">2-3</td>
<td id="td-2-4">2-4</td>
<td id="td-2-5">2-5</td>
<td id="td-2-6">2-6</td>
<td id="td-2-7">2-7</td>
<td id="td-2-8">2-8</td>
<td id="td-2-9">2-9</td>
<td id="td-2-10">2-10</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>
<td id="td-3-5">3-5</td>
<td id="td-3-6">3-6</td>
<td id="td-3-7">3-7</td>
<td id="td-3-8">3-8</td>
<td id="td-3-9">3-9</td>
<td id="td-3-10">3-10</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>
<td id="td-4-5">4-5</td>
<td id="td-4-6">4-6</td>
<td id="td-4-7">4-7</td>
<td id="td-4-8">4-8</td>
<td id="td-4-9">4-9</td>
<td id="td-4-10">4-10</td>
</tr>
<tr>
<td id="td-5-1">5-1</td>
<td id="td-5-2">5-2</td>
<td id="td-5-3">5-3</td>
<td id="td-5-4">5-4</td>
<td id="td-5-5">5-5</td>
<td id="td-5-6">5-6</td>
<td id="td-5-7">5-7</td>
<td id="td-5-8">5-8</td>
<td id="td-5-9">5-9</td>
<td id="td-5-10">5-10</td>
</tr>
</table>
<p>Selected IDs: {{ids | json}}</p>
</body>
</html>
单元格选择效果很好。选择后,我希望能够选择更多的单元格,而不会使之前的单元格消失,并且还能够取消选择已经选择的单元格。
现在基本上每次我点击表格时,以前的选择都会消失,新的选择就会开始。
有谁知道,我该如何实现这个?
【问题讨论】:
-
到目前为止你有什么尝试?
-
你可以检测到
ctrl-click -
我试图将输出存储在变量中,而不是每次单击鼠标时将其传递给函数,但没有成功。我是 JavaScript 新手,无法真正理解它..
-
选择适用于矩形。你可以做什么:在
mouseDown上:如果ctrl关闭:创建一个新矩形,否则:清除所有矩形。您需要一个数组来存储所有矩形。 -
提供到目前为止您尝试过的代码。 Stackoverflow 在这里帮助您,而不是解决您的问题。表明你花了一些时间来处理它......
标签: javascript jquery html angularjs