如何使用mousedown.dragselect事件捕获表td元素? [英] How do I capture table td elements using mousedown.dragselect event?

查看:103
本文介绍了如何使用mousedown.dragselect事件捕获表td元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个指令,该指令呈现一个HTML表,其中每个td元素都有一个ID

I have a directive which renders a HTML table where each td element has an id

我要完成的工作是使用mousedown.dragselect/mouseup.dragselect确定已选择了哪些元素,然后突出显示那些选定的元素.到目前为止,我的情况是这样的:

What I want to accomplish is to use the mousedown.dragselect/mouseup.dragselect to determine which elements have been selected, and then highlight those selected elements. What I have so far is something like this:

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.dragselect选择的每个td元素,并能够获取其ID并突出显示它们?

How can I get every td element selected by mousedown.dragselect, and be able to get their ids and then highlight them?

推荐答案

我怀疑使用任何与拖动有关的东西都无法满足您的需求.在移动元素时(例如,在我的电脑"/查找器"中拖动文件)时,如果您要进行的是多项选择,则实际上会使用拖动.

I suspect using anything relating to dragging won't give you what you want. Dragging is actually used when moving elements about (e.g. dragging files in My Computer / Finder), when what you're after is multiple selection.

因此,该指令需要满足以下条件:

So there a number of things the directive needs:

  • 收听mousedownmouseentermouseup事件.

  • mousedown应该侦听表的单元格,并设置拖动"模式.
  • mouseenter也应侦听单元格,如果指令处于拖动模式,请选择适当的单元格"
  • mouseup应该禁用拖动模式,并且实际上应该在整个身体上,以防在光标不在桌子上方时抬起鼠标.
  • mousedown should listen on the cells of the table, and set a "dragging" mode.
  • mouseenter should listen on the cells as well, and if the directive is in dragging mode, select the "appropriate cells"
  • mouseup should disable dragging mode, and actually be on the whole body, in case the mouse is lifted up while the cursor is not over the table.

jQuery委托在这里很有用,因为它可以很好地将上述事件委托给表,因此代码对初始化此指令后添加的单元格更加友好. (除非您有明确的理由,否则我不会在Angular项目中包含或使用jQuery.)

jQuery delegation is useful here, as it can nicely delegate the above events to the table, so the code is much more friendly to cells that are added after this directive is initialised. (I wouldn't include or use jQuery in an Angular project unless you have a clear reason like this).

尽管您还没有提到它,但是合适的单元格"我怀疑所有单击鼠标的单元格之间的所有单元格,以及当前单元格(在矩形中选择),而不是只是按住鼠标时已输入的单元格.要找到这些内容,请 cellIndex rowIndex

Although you've not mentioned it, the "appropriate cells" I suspect all the cells "between" where the mouse was clicked, and the current cell, chosen in a rectangle, and not just the cells that have been entered while the mouse was held down. To find these, cellIndex and rowIndex can be used, together with filtering all the cells from the table.

所有侦听器都应包装为$scope.$apply,以确保Angular在触发后运行摘要循环.

All the listeners should be wrapped $scope.$apply to make sure Angular runs a digest cycle after they fire.

要使指令将所选元素的id传递到周围的范围,该指令可以使用scope属性和=符号进行双向绑定,如角度文档

For the directive to communicate the ids of the selected elements to the surrounding scope, the directive can use bi-directional binding using the scope property, and the = symbol, as explained in the Angular docs

将所有这些放在一起可以得到:

Putting all this together gives:

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

使体验更好的另一件事是将光标设置为指针,并禁用文本选择

Another thing that will make the experience a bit nicer, is to set the cursor to a pointer, and 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;
}

您还可以在此工作演示

这篇关于如何使用mousedown.dragselect事件捕获表td元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆