我有一个指令,它呈现一个
HTML表,其中每个td元素都有一个id
我想要完成的是使用mousedown.dragselect / mouseup.dragselect来确定选择了哪些元素,然后突出显示那些选定的元素.到目前为止我所拥有的是这样的:
- var $ele = $(this);
- scope.bindMultipleSelection = function() {
- element.bind('mousedown.dragselect',function() {
- $document.bind('mousemove.dragselect',scope.mousemove);
- $document.bind('mouseup.dragselect',scope.mouseup);
- });
- };
- scope.bindMultipleSelection();
- scope.mousemove = function(e) {
- scope.selectElement($(this));
- };
- scope.mouseup = function(e) {
- };
- scope.selectElement = function($ele) {
- if (!$ele.hasClass('eng-selected-item'))
- $ele.addClass('eng-selected-item'); //apply selection or de-selection to current element
- };
我怀疑使用任何与拖动有关的东西都不会给你你想要的东西.拖动实际上是在移动元素时使用(例如,在“我的电脑/搜索器”中拖动文件),当你所追求的是多重选择时.
所以指令需要很多东西:
>听mousedown,mouseenter和mouseup,事件.
> mousedown应该监听表格的单元格,并设置“拖动”模式.
> mouseenter也应该监听单元格,如果指令处于拖动模式,请选择“适当的单元格”
> mouseup应该禁用拖动模式,实际上是在整个身体上,以防鼠标在光标不在桌面上时被抬起.
> jQuery delegation在这里很有用,因为它可以很好地将上述事件委托给表,因此代码对初始化此指令后添加的单元格更加友好. (除非你有明确的理由,否则我不会在Angular项目中包含或使用jQuery).
>虽然你没有提到它,但是“适当的细胞”我怀疑点击鼠标的所有单元格和在矩形中选择的当前单元格,而不仅仅是鼠标时输入的单元格被压制住了.为了找到这些,可以使用cellIndex
和rowIndex
,以及filtering表中的所有单元格.
>所有的监听器都应该包含$scope.$apply以确保Angular在它们触发后运行一个摘要周期.
>对于将所选元素的id传递给周围范围的指令,该指令可以使用scope属性和=符号进行双向绑定,如Angular docs中所述.
把所有这些放在一起给出了:
- 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,row: $window.Math.max(coordsStart.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));
- }
- }
- });
使体验更好的另一件事是将光标设置为指针,并且disable text selection
- [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;
- }
您还可以在此working demo中看到此操作