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

查看:49
本文介绍了如何使用 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).

虽然你没有提到它,适当的单元格"我怀疑所有的单元格介于"鼠标点击的地方,和当前单元格,在一个矩形中选择,不是 只是按住鼠标时输入的单元格.要找到这些,cellIndexrowIndex 可以与过滤表格中的所有单元格一起使用.

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 属性的双向绑定,以及 = 符号,如 Angular 文档

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天全站免登陆