我有一个指令,它呈现一个
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中看到此操作