2017-06-12 18 views
1

私はテーブル内のセルを選択するためにTHISの実装を行っていますが、セルは列スパンまたは列スパンを持つことができます四角形/四角形の選択(「1-3」と「2-3」を選択してください。自動的に「1-4」を選択する必要があります)。それはTHIS質問に似ていますが、私は何かを得ることができませんでした。これがどのように実装されるか知っていますか?HTMLテーブルの選択をドラッグする(colspan/rowspanを使用した四角形/四角形)

リンク:Working Code

HTML

<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> 
     </tr> 
     <tr> 
     <td id="td-2-1">2-1</td> 
     <td id="td-2-2">2-2</td> 
     <td id="td-2-3" colspan="2">2-3</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> 
     </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> 
     </tr> 
    </table> 

はJavaScript

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

CSS

[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; 
} 
+0

は右常に下のように左上と2-3と1-1を選択するべきでも1-4を選択しますか?どのようにして1-1,1-2,1-3,2-1,2-2,2-3を選択しますか? これは、あなたが探している機能に適しているかもしれません。http://nightlycoding.com/index.php/2014/02/click-and-drag-multi-selection-rectangle-with-javascript/ – phil

+0

はい。基本的にExcelの機能を模倣しているはずです。選択は常に正方形/長方形でなければなりません。 –

答えて

1

私は、開始と終了のセルのx、y座標を使用対応する矩形の内側にある(すべて部分的にも)すべてのセルを計算します。次に、これらのセルの境界矩形を取得し、選択がもう展開されなくなるまでプロセスを繰り返します。

編集:Get DOM elements inside a rectangle area of a page

EDIT 2:機能rectangleSelectから(ほぼ完全に)であるenter image description here

http://plnkr.co/edit/8wZvcU1SgmieStsqg3lD?p=preview

:[3-2,2-3]を選択するような今支持ROWSPANおよび他edgecases

HTML:

<!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="[email protected]" 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> 
     </tr> 
     <tr> 
     <td id="td-2-1" colspan=2>2-1</td> 
     <td id="td-2-3" rowspan="2">2-3</td 
     ><td id="td-2-4">2-2</td> 
     </tr> 
     <tr> 
     <td id="td-3-1">3-1</td> 
     <td id="td-3-2">3-2</td> 
     <td id="td-3-4">3-4</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> 
     </tr> 
    </table> 
    <p>Selected IDs: {{ids | json}}</p> 
    </body> 

</html> 

CSS:

変わらずの

JS:

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 isPointBetween(point,x1,x2){ 
     return (point >=x1 && point <=x2) ||(point <=x1 && point>=x2); 
     } 
     function rectangleSelect(selector, bounds) { 
    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.outerWidth(); 
     var h = $this.outerHeight(); 
     if ((isPointBetween(x,bounds.minX,bounds.maxX) && isPointBetween(y,bounds.minY,bounds.maxY))|| 
      (isPointBetween(x+w,bounds.minX,bounds.maxX) && isPointBetween(y+h,bounds.minY,bounds.maxY)) 
      ) { 
      elements.push($this.get(0)); 
     } 
    }); 
    return elements; 
} 
     function getBoundsForElements(elements){ 
     var x1= elements.reduce(function(currMinX,element){ 
      var elementLeft = $(element).offset().left; 
      return currMinX && currMinX<elementLeft ? currMinX : elementLeft; 
     },undefined); 
     var x2= elements.reduce(function(currMaxX,element){ 
      var elementRight = $(element).offset().left+$(element).outerWidth(); 
      return currMaxX && currMaxX>elementRight ? currMaxX : elementRight; 
     },undefined); 
     var y1= elements.reduce(function(currMinY,element){ 
      var elementTop = $(element).offset().top; 
      return currMinY && currMinY<elementTop ? currMinY : elementTop; 
     },undefined); 
     var y2= elements.reduce(function(currMaxY,element){ 
      var elementBottom = $(element).offset().top+$(element).outerHeight(); 
      return currMaxY && currMaxY>elementBottom ? currMaxY : elementBottom; 
     },undefined); 
     return { 
      minX: x1, 
      maxX: x2, 
      minY: y1, 
      maxY: y2 
     }; 

     } 


     function cellsBetween(start, end) { 
     var bounds,elementsInside; 
     elementsInside = [start,end]; 
     do{ 
      bounds = getBoundsForElements(elementsInside); 
      var elementsInsideAfterExpansion = rectangleSelect("td",bounds); 
      if(elementsInside.length==elementsInsideAfterExpansion.length) 
      return elementsInside; 
      else 
      elementsInside=elementsInsideAfterExpansion; 
     }while(true) 

     } 


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

ありがとう!行間がある場合はどうでしょうか? http://plnkr.co/edit/RIlCH4G1EHQPFDBD2xSV?p=preview(3-2から3-4にドラッグしてみてください) –

+0

行スパンでも機能します – phil

関連する問題