2014-04-18 9 views
7

mam dyrektywę, która renderuje tabeli HTML, gdzie każdy element td ma identyfikatorJak przechwytywać elementy tabeli td za pomocą zdarzenia mousedown.dragselect?

Co chcę osiągnąć jest użycie mousedown.dragselect/mouseup.dragselect określić, które elementy zostały zaznaczone, a następnie zaznacz te wybrane elementy. To, co mam tak daleko jest coś takiego:

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

Jak mogę uzyskać każdy td pierwiastek wybrany przez mousedown.dragselect, i być w stanie uzyskać ich identyfikatory, a następnie zaznaczyć je?

Odpowiedz

12

Podejrzewam, że użycie czegoś związanego z przeciąganiem nie da ci tego, czego chcesz. Przeciąganie jest aktualnie używane podczas przesuwania elementów (np. Przeciągania plików w Moim komputerze/Finderze), kiedy to, co masz na myśli, to wielokrotny wybór.

Więc istnieje wiele rzeczy, dyrektywa wymaga:

  • Słuchaj mousedown, mouseenter i mouseup, wydarzenia.

    • mousedown powinien nasłuchiwać na komórkach tabeli i ustawić tryb "przeciągania".
    • mouseenter powinien słuchać na komórki, jak również, a jeśli dyrektywa jest w trybie przeciągania, wybierz „odpowiednich komórek”
    • mouseup należy wyłączyć tryb przeciągania i faktycznie na całym ciele, w przypadku, gdy mysz jest podnoszony w górę, gdy kursor nie znajduje się nad stołem.
  • jQuery delegation jest tu przydatny, ponieważ może on ładnie przekazać powyższe zdarzenia do tabeli, więc kod jest znacznie bardziej przyjazny dla komórek, które zostały dodane po tej dyrektywy jest inicjowany. (Nie uwzględniam ani nie użyję jQuery w projekcie Angular, chyba że masz na to wyraźny powód).

  • Mimo, że nie byli to, „odpowiednie komórki” Podejrzewam wszystkie komórki „pomiędzy”, gdzie mysz kliknięciu i aktualną komórkę, wybrany w prostokąt i nie tylko wspomnieć, że komórki zostały wprowadzone, gdy mysz była przytrzymywana. Aby je znaleźć, razem z filtering można używać wszystkich komórek z tabeli.

  • Wszyscy słuchacze powinni być owinięci $scope.$apply, aby upewnić się, że Angular uruchamia cykl trawienia po wystrzeleniu.

  • aby dyrektywa komunikacji identyfikatory wybranych elementów otaczającej zakresie dyrektywa można użyć dwukierunkowego wiązania za pomocą właściwości scope i = symbolu, jak wyjaśniono w Angular docs

Wyrażając to wszystko razem daje:

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

Inną rzeczą, która sprawi, że doświadczenie nieco ładniejszy, jest ustawienie kursora do wskaźnika, a 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; 
} 

Można również zobaczyć w akcji w tym working demo

+0

Cześć Michał Charemza, dziękuję za odpowiedź, swoją pracę rozwiązanie dla mnie. – user1489941

+0

Zmodyfikowałem trochę, aby mogły być używane przez inne dyrektywy. Użyłem $ rootScope. $ Broadcast ('DRAG_SELECTED_UPDATE', $ scope.dragSelectIds); – user1489941

+0

Użycie '$ rootScope. $ Broadcast' może na dłuższą metę zostać ograniczone, ponieważ utrudni to posiadanie więcej niż jednej takiej tabeli w tej samej aplikacji w tym samym czasie. –

Powiązane problemy