admin管理员组

文章数量:1415467

I have an app in which I generate a set of spans using ng-repeat, and each span has a unique id (let's say span-{{$index}}). Now I want to perform the following:

  • If I click on a span, I want the id of the span to be copied. I managed to do this via the ng-click.
  • I want to extend this functionality further to detect multiple clicks, to get an array of the selected ids, but only if the CTRL key is held down during the clicks.

For eg. if I had the ctrl button clicked when I chose span with id 1,3,5,7, my array should have [1,3,5,7] , but if I didn't have the CTRL key pressed then I should only have [7], as it was the last span selected.

Also, can I bind relative events? E.g. if I select span with an id of 1, if I click CTRL+DOWN_ARROW, id 2 is also selected... and then id 3 and so on until I keep pressing DOWN_ARROW.

I guess the closest I've seen of this type of UX is with selecting contacts in Gmail while posing a new mail. I can select contacts using all sorts of keyboard and mouse binations. I'm looking for something very similar

I'm playing around with different UX techniques but I'm stuck on how exactly I could do this with angular.

I have an app in which I generate a set of spans using ng-repeat, and each span has a unique id (let's say span-{{$index}}). Now I want to perform the following:

  • If I click on a span, I want the id of the span to be copied. I managed to do this via the ng-click.
  • I want to extend this functionality further to detect multiple clicks, to get an array of the selected ids, but only if the CTRL key is held down during the clicks.

For eg. if I had the ctrl button clicked when I chose span with id 1,3,5,7, my array should have [1,3,5,7] , but if I didn't have the CTRL key pressed then I should only have [7], as it was the last span selected.

Also, can I bind relative events? E.g. if I select span with an id of 1, if I click CTRL+DOWN_ARROW, id 2 is also selected... and then id 3 and so on until I keep pressing DOWN_ARROW.

I guess the closest I've seen of this type of UX is with selecting contacts in Gmail while posing a new mail. I can select contacts using all sorts of keyboard and mouse binations. I'm looking for something very similar

I'm playing around with different UX techniques but I'm stuck on how exactly I could do this with angular.

Share Improve this question edited Apr 17, 2015 at 15:59 AncientSwordRage 7,68421 gold badges100 silver badges193 bronze badges asked Feb 3, 2015 at 9:38 navinpainavinpai 1,00515 silver badges36 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

For your first question see the plunkr below.

If you pass $event through to your ng-click function you can access the event in your controller. In my example I checked if altKey was true which is checking if the alt key was pressed at the same time as the click. You can also access ctrlKey, shiftKey and which mouse button was pressed. See MouseEvent object here - http://www.w3schools./jsref/dom_obj_event.asp

The controller:

angular.module('exampleApp', [])

.controller("ItemCtrl", function($scope){

    $scope.items = [
      {text: "Bob", id: 1},
      {text: "Alice", id: 2},
      {text: "Frank", id: 3},
      {text: "Lisa", id: 4}
    ];
    $scope.itemList = [];

    $scope.addItemIdToList = function(event, item){
        if(event.altKey){
          if(isItemInList(item)){
            removeItemIdFromList(item);
          } else {
            addItemIdToList(item);
          }
        } else {
          addItemIdAsSingleSelection(item);
        }
    };

    var isItemInList = function(item){
      var indexOfItem = $scope.itemList.indexOf(item.id);
      return indexOfItem > -1;
    }

    var removeItemIdFromList = function(item){
      var indexOfItem = $scope.itemList.indexOf(item.id);
      $scope.itemList.splice(indexOfItem, 1);
    };

    var addItemIdToList = function(item){
      $scope.itemList.push(item.id);
    };

    var addItemIdAsSingleSelection = function(item){
      $scope.itemList = [item.id];
    };
})

http://plnkr.co/edit/RAX5oxkTomXxryp0sNNc

When the logic starts to bee a bit more plicated it would probably be best to do this sort of thing in a directive.

For the second question the basic parts can be seen in the following example:

angular.module('exampleApp', [])

.directive('keypressEvents', function ($document, $rootScope) {
    return {
        restrict: 'E',
        link: function () {
            console.log('linked');
            $document.on('keypress', function(e) {
                if(e.altKey){
                    var s = 223;
                    var a = 229;
                    if(e.which == s){
                      $rootScope.$broadcast("add_next_id");
                    } else if(e.which == a){
                      $rootScope.$broadcast("remove_last_id");
                    }
                }
            })
        }
    }
})

.controller("ItemCtrl", function($scope, $rootScope){

      $scope.items = [
      {text: "Bob", id: 1},
      {text: "Alice", id: 2},
      {text: "Frank", id: 3},
      {text: "Lisa", id: 4}
    ];

    $scope.itemList = [1];

    $rootScope.$on('add_next_id', function (evt, obj, key) {
        $scope.$apply(function () {
            addNextId();
        });
    });

    $rootScope.$on('remove_last_id', function (evt, obj, key) {
        $scope.$apply(function () {
            removeLastId();
        });
    });

    var addNextId = function(){
        var lastId = $scope.itemList[$scope.itemList.length - 1];
        if(lastId < $scope.items.length){
          $scope.itemList.push(lastId+1); 
        }
    };

    var removeLastId = function(){
        if($scope.itemList.length > 1){
          $scope.itemList.pop();
        }
    };

     $scope.isItemInList = function(item){
      var indexOfItem = $scope.itemList.indexOf(item.id);
      return indexOfItem > -1;
    }
})

http://plnkr.co/edit/PyyjfRMovygeq9qNbzWo

We listen on the document for key presses and check again for altKey. Then if the keyCode is one of our hotkeys we send a message to $rootScope using $rootScope.$broadcast() which the controller is listening to with the $rootScope.$on() method.

In the above example alt+s will add more ids and alt+a will remove them down to the originally selected one.

Perhaps an Angular directive would be helpful. Here's an example of how you can capture meta key info using an angular directive and get access to the info inside an Angular Controller (Plnkr):

<!DOCTYPE html>
<html>

  <head>
    <script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  </head>

  <body ng-app="myapp" ng-controller="main">
    <h1>Hello {{person}}</h1>
    <p>Ctrl: |{{info.ctrl}}|</p>
    <keyboard info="info"></keyboard>
    <script>
      var app = angular.module('myapp', []);
      app.controller('main', function($scope){
        $scope.info = { ctrl: false };
        $scope.person = "Me";

      });

      app.directive('keyboard', function($timeout){
        return {
          scope: {
            info: '='
          },
          link: function(scope, element, attr){
            console.dir(scope.info);
            $(document).on('keydown', function(e){
              $timeout(function(){
                scope.info.ctrl = e.ctrlKey;
              });
            });
            $(document).on('keyup', function(e){
              $timeout(function(){
                scope.info.ctrl = e.ctrlKey;
              });
            });
          }
        }
      });
    </script>
  </body>

</html>

本文标签: javascriptDetect mousekeyboard events in Angular for ngrepeatStack Overflow