2014-04-18 71 views
7

我有這使得每個td元素都有一個id如何使用mousedown.dragselect事件捕獲table td元素?

我想做到的是用mousedown.dragselect/mouseup.dragselect來確定哪個單元已經被選中,然後突出顯示那些選定的元素一個HTML表中的指令。我到目前爲止是這樣的:

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,然後突出顯示它們?

回答

12

我懷疑使用任何有關拖動不會給你你想要的。在移動元素(例如,在我的電腦/ Finder中拖動文件)時,實際上會使用拖動,而您之後的操作是多重選擇。

所以有一些事情指令需要:

  • mousedownmouseentermouseup,事件。

    • mousedown應監聽表格的單元格,並設置「拖動」模式。
    • mouseenter監聽的細胞,以及,如果該指令是在拖曳模式,選擇「合適的細胞」
    • mouseup應禁用拖動模式,實際上是對整個身體的情況下,鼠標擡起而光標不在桌子上。
  • jQuery delegation在這裏很有用,因爲它可以很好地委託上述事件表,因此代碼更加友好該指令被初始化之後添加細胞。 (除非你有明確的理由,否則我不會在Angular項目中包含或使用jQuery)。

  • 雖然你沒有提到它,「適當的細胞」我懷疑這裏單擊鼠標「之間」的所有單元格,和當前單元格,在矩形選擇,而不是只是的細胞在鼠標被按下時進入。要找到這些,可以使用cellIndexrowIndex,以及filtering表中的所有單元格。

  • 所有的聽衆都應該打包$scope.$apply以確保Angular在觸發後運行消化週期。

  • 對於選定元素的ID傳送到所述周圍範圍的指令,該指令可以使用雙向使用scope屬性綁定,並且=符號,如在Angular docs

解釋

把所有這些組合起來得到:

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

另一件事,這將使體驗更好一點,是將光標設置爲指針,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; 
} 

您也可以在此working demo

+0

嗨米哈爾Charemza看到這個動作,謝謝您的回覆,您的解決方案爲我工作。 – user1489941

+0

我修改了一點點以供其他指令使用。我使用了$ rootScope。$ broadcast('DRAG_SELECTED_UPDATE',$ scope.dragSelectIds); – user1489941

+0

從長遠來看,使用'$ rootScope。$ broadcast'可能最終會受到限制,因爲這會使同一應用程序中同時存在多個此類表格變得困難。 –

相關問題