Angularjs 如何使用mousedown.dragselect事件捕获表td元素?

Angularjs 如何使用mousedown.dragselect事件捕获表td元素?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我有一个指令,它呈现一个HTML表,其中每个td元素都有一个id 我要完成的是使用mousedown.dragselect/mouseup.dragselect确定已选择哪些元素,然后突出显示这些选定的元素。到目前为止,我得到的是这样的东西: var $ele = $(this); scope.bindMultipleSelection = function() { element.bind('mousedown.dragselect', function() { $document

我有一个指令,它呈现一个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
};

我怎样才能让
td
元素被
mousedown.dragselect
选中,并能够获取它们的ID,然后突出显示它们?

我怀疑使用任何与拖动相关的操作都无法满足您的需要。拖动实际上是在移动元素时使用的(例如,在“我的电脑/查找器”中拖动文件),而您要做的是多选

因此,该指令需要做很多事情:

  • 收听
    mousedown
    mouseenter
    mouseup
    ,事件

    • mousedown
      应监听表格的单元格,并设置“拖动”模式
    • mouseenter
      也应监听单元格,如果指令处于拖动模式,请选择“适当的单元格”
    • mouseup
      应禁用拖动模式,并实际位于整个身体上,以防在光标不在桌子上时提起鼠标
  • 在这里很有用,因为它可以很好地将上述事件委托给表,因此代码对初始化此指令后添加的单元格更加友好。(除非您有这样明确的理由,否则我不会在Angular项目中包含或使用jQuery)

  • 虽然您没有提到“适当的单元格”,但我怀疑单击鼠标的位置与当前矩形中选定的单元格之间的所有单元格,而不仅仅是按住鼠标时输入的单元格。找到这些,并可与表中的所有单元格一起使用

  • 所有侦听器都应该被包装
    $scope.$apply
    ,以确保Angular在启动后运行摘要循环

  • 对于将所选元素的ID传递给周围作用域的指令,该指令可以使用
    作用域
    属性和
    =
    符号进行双向绑定,如中所述

将所有这些结合起来,可以得出:

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));
    }
  }
});

您也可以在本

中看到这一点,您好,Michal Charemza,谢谢您的回复,您的解决方案对我很有用。我做了一些修改,以供其他指令使用。我使用了$rootScope.$broadcast('DRAG_SELECTED_UPDATE',$scope.dragSelectIds);从长远来看,使用
$rootScope.$broadcast
可能会受到限制,因为这将使同一应用程序中很难同时有多个这样的表。您建议如何替代使用$rootScope.$broadcast?好的。我使用而不是使用$rootScope.$broadcast
[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;
}