我懷疑使用任何有關拖動不會給你你想要的。在移動元素(例如,在我的電腦/ Finder中拖動文件)時,實際上會使用拖動,而您之後的操作是多重選擇。
所以有一些事情指令需要:
聽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, 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));
}
}
});
另一件事,這將使體驗更好一點,是將光標設置爲指針,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
嗨米哈爾Charemza看到這個動作,謝謝您的回覆,您的解決方案爲我工作。 – user1489941
我修改了一點點以供其他指令使用。我使用了$ rootScope。$ broadcast('DRAG_SELECTED_UPDATE',$ scope.dragSelectIds); – user1489941
從長遠來看,使用'$ rootScope。$ broadcast'可能最終會受到限制,因爲這會使同一應用程序中同時存在多個此類表格變得困難。 –