捕获表中的多个td元素

时间:2018-11-12 10:42:49

标签: javascript jquery html angularjs

我正在研究选择表格中的单元格的方法。

我在这里找到了很好的解决方案:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.ids = [];
});

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 rectangleSelect(selector, x1,x2, y1, y2) {
    var elements = [];
    jQuery(selector).each(function() {
        var $this = jQuery(this);
        var offset = $this.offset();
        var x = offset.left;
        var y = offset.top;
        var w = $this.width();
        var h = $this.height();

        if (x >= x1 && x<=x2 && y>=y1 && y<=y2) {
            // this element fits inside the selection rectangle
            elements.push($this.get(0));
        }
    });
    return elements;
}
      
      function cellsBetween(start, end) {
        
        var bounds = {minX:0,minY:0,maxX:0,maxY:0};
        bounds.minX = $window.Math.min($(start).offset().left,$(end).offset().left);
        bounds.minY = $window.Math.min($(start).offset().top,$(end).offset().top);
        bounds.maxX = $window.Math.max($(end).offset().left+$(end).width(),$(start).offset().left+$(start).width());
        bounds.maxY = $window.Math.max($(end).offset().top+$(end).height(),$(start).offset().top+$(start).height());

        var initiallySelectedTds = rectangleSelect("td",bounds.minX,bounds.maxX,bounds.minY,bounds.maxY);
        
        for(var i=0;i<initiallySelectedTds.length;i++){
          if($(initiallySelectedTds[i]).offset().left<bounds.minX)
            bounds.minX = $(initiallySelectedTds[i]).offset().left;
          if($(initiallySelectedTds[i]).offset().left+$(initiallySelectedTds[i]).width()>bounds.maxX)
            bounds.maxX = $(initiallySelectedTds[i]).offset().left+$(initiallySelectedTds[i]).width();
          if($(initiallySelectedTds[i]).offset().top<bounds.minY)
            bounds.minY = $(initiallySelectedTds[i]).offset().top;
          if($(initiallySelectedTds[i]).offset().top+$(initiallySelectedTds[i]).height()>bounds.maxY)
            bounds.maxY = $(initiallySelectedTds[i]).offset().top+$(initiallySelectedTds[i]).height();
        }
        return rectangleSelect("td",bounds.minX,bounds.maxX,bounds.minY,bounds.maxY);
        
      }
      
    
      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));
    }
  }
});
[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;
}

[drag-select] .eng-selected-item {
  background: blue;
  color: white;
}

td {
  padding: 10px;
  border: 1px solid gray;
}
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="jquery" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <table drag-select drag-select-ids="ids">
      <tr>
        <td id="td-1-1">1-1</td>
        <td id="td-1-2">1-2</td>
        <td id="td-1-3">1-3</td>
        <td id="td-1-4">1-4</td>
        <td id="td-1-5">1-5</td>
        <td id="td-1-6">1-6</td>
        <td id="td-1-7">1-7</td>
        <td id="td-1-8">1-8</td>
        <td id="td-1-9">1-9</td>
        <td id="td-1-10">1-10</td>
      </tr>
      <tr>
        <td id="td-2-1">2-1</td>
        <td id="td-2-2">2-2</td>
        <td id="td-2-3">2-3</td>
        <td id="td-2-4">2-4</td>
        <td id="td-2-5">2-5</td>
        <td id="td-2-6">2-6</td>
        <td id="td-2-7">2-7</td>
        <td id="td-2-8">2-8</td>
        <td id="td-2-9">2-9</td>
        <td id="td-2-10">2-10</td>
      </tr>
      <tr>
        <td id="td-3-1">3-1</td>
        <td id="td-3-2">3-2</td>
        <td id="td-3-3">3-3</td>
        <td id="td-3-4">3-4</td>
        <td id="td-3-5">3-5</td>
        <td id="td-3-6">3-6</td>
        <td id="td-3-7">3-7</td>
        <td id="td-3-8">3-8</td>
        <td id="td-3-9">3-9</td>
        <td id="td-3-10">3-10</td>
      </tr>
      <tr>
        <td id="td-4-1">4-1</td>
        <td id="td-4-2">4-2</td>
        <td id="td-4-3">4-3</td>
        <td id="td-4-4">4-4</td>
        <td id="td-4-5">4-5</td>
        <td id="td-4-6">4-6</td>
        <td id="td-4-7">4-7</td>
        <td id="td-4-8">4-8</td>
        <td id="td-4-9">4-9</td>
        <td id="td-4-10">4-10</td>
      </tr>
      <tr>
        <td id="td-5-1">5-1</td>
        <td id="td-5-2">5-2</td>
        <td id="td-5-3">5-3</td>
        <td id="td-5-4">5-4</td>
        <td id="td-5-5">5-5</td>
        <td id="td-5-6">5-6</td>
        <td id="td-5-7">5-7</td>
        <td id="td-5-8">5-8</td>
        <td id="td-5-9">5-9</td>
        <td id="td-5-10">5-10</td>
      </tr>
    </table>
    <p>Selected IDs: {{ids | json}}</p>
  </body>

</html>

单元格选择效果很好。选择之后,我希望能够选择更多的单元,而不会丢失之前的单元,并且还能够取消选择已经选择的单元。

现在基本上,每次我单击表时,先前的选择都会消失,而新的选择将开始。

有人有什么想法,我怎么实现呢?

对此有任何想法。

1 个答案:

答案 0 :(得分:2)

只需像setEndCell function那样修改您,

function mouseEnter(el) {
    if (!dragging) return;
    setEndCell(el);
  }


  function setEndCell(el) {
    if (el.hasClass(cls)) { // if added then remove on click
      el.removeClass(cls);
      var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
      elIndex !==-1 && $scope.dragSelectIds.splice(elIndex, 1)
      return false;
    }
    if (!$scope.dragSelectIds) {
      $scope.dragSelectIds = [];
    }
    //$element.find('td').removeClass(cls);
    $(cellsBetween(startCell, el)).each(function() {
      var el = angular.element(this);
      el.addClass(cls);
      // change if added, then not to add twice.
      var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
      elIndex ===-1 && $scope.dragSelectIds.push(el.attr('id'));
    });
  }

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.ids = [];
});

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) {
        if (el.hasClass(cls)) {
          el.removeClass(cls);
          var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
          elIndex !==-1 && $scope.dragSelectIds.splice(elIndex, 1)
          return false;
        }
        if (!$scope.dragSelectIds) {
          $scope.dragSelectIds = [];
        }
        //$element.find('td').removeClass(cls);
        $(cellsBetween(startCell, el)).each(function() {
          var el = angular.element(this);
          el.addClass(cls);
          var elIndex = $scope.dragSelectIds.indexOf(el[0].id);
          elIndex ===-1 && $scope.dragSelectIds.push(el.attr('id'));
        });
      }

      function rectangleSelect(selector, x1, x2, y1, y2) {
        var elements = [];
        jQuery(selector).each(function() {
          var $this = jQuery(this);
          var offset = $this.offset();
          var x = offset.left;
          var y = offset.top;
          var w = $this.width();
          var h = $this.height();

          if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
            // this element fits inside the selection rectangle
            elements.push($this.get(0));
          }
        });
        return elements;
      }

      function cellsBetween(start, end) {

        var bounds = {
          minX: 0,
          minY: 0,
          maxX: 0,
          maxY: 0
        };
        bounds.minX = $window.Math.min($(start).offset().left, $(end).offset().left);
        bounds.minY = $window.Math.min($(start).offset().top, $(end).offset().top);
        bounds.maxX = $window.Math.max($(end).offset().left + $(end).width(), $(start).offset().left + $(start).width());
        bounds.maxY = $window.Math.max($(end).offset().top + $(end).height(), $(start).offset().top + $(start).height());

        var initiallySelectedTds = rectangleSelect("td", bounds.minX, bounds.maxX, bounds.minY, bounds.maxY);

        for (var i = 0; i < initiallySelectedTds.length; i++) {
          if ($(initiallySelectedTds[i]).offset().left < bounds.minX)
            bounds.minX = $(initiallySelectedTds[i]).offset().left;
          if ($(initiallySelectedTds[i]).offset().left + $(initiallySelectedTds[i]).width() > bounds.maxX)
            bounds.maxX = $(initiallySelectedTds[i]).offset().left + $(initiallySelectedTds[i]).width();
          if ($(initiallySelectedTds[i]).offset().top < bounds.minY)
            bounds.minY = $(initiallySelectedTds[i]).offset().top;
          if ($(initiallySelectedTds[i]).offset().top + $(initiallySelectedTds[i]).height() > bounds.maxY)
            bounds.maxY = $(initiallySelectedTds[i]).offset().top + $(initiallySelectedTds[i]).height();
        }
        return rectangleSelect("td", bounds.minX, bounds.maxX, bounds.minY, bounds.maxY);

      }


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

[drag-select] .eng-selected-item {
  background: blue;
  color: white;
}

td {
  padding: 10px;
  border: 1px solid gray;
}
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="jquery" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
  <script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <table drag-select drag-select-ids="ids">
    <tr>
      <td id="td-1-1">1-1</td>
      <td id="td-1-2">1-2</td>
      <td id="td-1-3">1-3</td>
      <td id="td-1-4">1-4</td>
      <td id="td-1-5">1-5</td>
      <td id="td-1-6">1-6</td>
      <td id="td-1-7">1-7</td>
      <td id="td-1-8">1-8</td>
      <td id="td-1-9">1-9</td>
      <td id="td-1-10">1-10</td>
    </tr>
    <tr>
      <td id="td-2-1">2-1</td>
      <td id="td-2-2">2-2</td>
      <td id="td-2-3">2-3</td>
      <td id="td-2-4">2-4</td>
      <td id="td-2-5">2-5</td>
      <td id="td-2-6">2-6</td>
      <td id="td-2-7">2-7</td>
      <td id="td-2-8">2-8</td>
      <td id="td-2-9">2-9</td>
      <td id="td-2-10">2-10</td>
    </tr>
    <tr>
      <td id="td-3-1">3-1</td>
      <td id="td-3-2">3-2</td>
      <td id="td-3-3">3-3</td>
      <td id="td-3-4">3-4</td>
      <td id="td-3-5">3-5</td>
      <td id="td-3-6">3-6</td>
      <td id="td-3-7">3-7</td>
      <td id="td-3-8">3-8</td>
      <td id="td-3-9">3-9</td>
      <td id="td-3-10">3-10</td>
    </tr>
    <tr>
      <td id="td-4-1">4-1</td>
      <td id="td-4-2">4-2</td>
      <td id="td-4-3">4-3</td>
      <td id="td-4-4">4-4</td>
      <td id="td-4-5">4-5</td>
      <td id="td-4-6">4-6</td>
      <td id="td-4-7">4-7</td>
      <td id="td-4-8">4-8</td>
      <td id="td-4-9">4-9</td>
      <td id="td-4-10">4-10</td>
    </tr>
    <tr>
      <td id="td-5-1">5-1</td>
      <td id="td-5-2">5-2</td>
      <td id="td-5-3">5-3</td>
      <td id="td-5-4">5-4</td>
      <td id="td-5-5">5-5</td>
      <td id="td-5-6">5-6</td>
      <td id="td-5-7">5-7</td>
      <td id="td-5-8">5-8</td>
      <td id="td-5-9">5-9</td>
      <td id="td-5-10">5-10</td>
    </tr>
  </table>
  <p>Selected IDs: {{ids | json}}</p>
</body>

</html>