我正在研究选择表格中的单元格的方法。
我在这里找到了很好的解决方案:
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>
单元格选择效果很好。选择之后,我希望能够选择更多的单元,而不会丢失之前的单元,并且还能够取消选择已经选择的单元。
现在基本上,每次我单击表时,先前的选择都会消失,而新的选择将开始。
有人有什么想法,我怎么实现呢?
对此有任何想法。
答案 0 :(得分:2)
只需像setEndCell function
那样修改您,
function mouseEnter(el) {
if (!dragging) return;
setEndCell(el);
}
function setEndCell(el) {
if (el.hasClass(cls)) { // if added then remove on click
el.removeClass(cls);
var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
elIndex !==-1 && $scope.dragSelectIds.splice(elIndex, 1)
return false;
}
if (!$scope.dragSelectIds) {
$scope.dragSelectIds = [];
}
//$element.find('td').removeClass(cls);
$(cellsBetween(startCell, el)).each(function() {
var el = angular.element(this);
el.addClass(cls);
// change if added, then not to add twice.
var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
elIndex ===-1 && $scope.dragSelectIds.push(el.attr('id'));
});
}
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) {
if (el.hasClass(cls)) {
el.removeClass(cls);
var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
elIndex !==-1 && $scope.dragSelectIds.splice(elIndex, 1)
return false;
}
if (!$scope.dragSelectIds) {
$scope.dragSelectIds = [];
}
//$element.find('td').removeClass(cls);
$(cellsBetween(startCell, el)).each(function() {
var el = angular.element(this);
el.addClass(cls);
var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
elIndex ===-1 && $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>