web-dev-qa-db-ja.com

Angularjsでキー押下の組み合わせを監視する方法は?

コントローラーにキーの組み合わせを監視させようとしています。議論のために、次のようにしましょう。上下左右左右右ba。ユーザーが現在ページのどこにいるかに関係なく、これらを探すためにangularを取得するにはどうすればよいですか?

9
Korra

ng-keydown を使用してこれを行うことができるようです。

これが 作業プランカー です。

このサンプルでは、​​ng-keydown<body>にバインドしました。すべてのキーボードイベントをグローバルにキャッチするのに非常にうまく機能します。

@charlietflが指摘しているように、ng-keydownは多くのキーボードイベントを登録するため、これを使用可能にするのは大変な作業になります。たとえば、組み合わせ(ctrl + rなど)をリッスンしようとした場合、ctrlキーは何度も登録されます。

JS:

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

myApp.controller('Ctrl', function($scope) {


    $scope.keyBuffer = [];

    function arrays_equal(a,b) { return !(a<b || b<a); }

    $scope.down = function(e) {

      $scope.keyBuffer.Push(e.keyCode);

      var upUp = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
      if (arrays_equal(upUp, $scope.keyBuffer)) {

        alert('thats it!');
      }
    };

  });

HTML:

<body ng-controller="Ctrl" ng-keydown="down($event)">
11
Davin Tryon

私はそれを行うために別の方法を使用しています。

$scope.keyboard = {
  buffer: [],
  detectCombination: function() {
    var codes = {};

    this.buffer.forEach(function(code) {
      codes['key_' + code] = 1;
    });

    if ((codes.key_91 || codes.key_93) && codes.key_8) {
      // I'm looking for 'command + delete'
    }
  },
  keydown: function($event) {
    this.buffer.Push($event.keyCode);
    this.detectCombination();
  },
  keyup: function($event, week) {
    this.buffer = [];
  }
};
4
Chris Fan

バックスペースキー(Mac)とデルキー(PC)の検出:

<body ng-controller="Ctrl" ng-keydown="keyDown($event)">..<body>

$scope.keyDown = function(value){
    if(value.keyCode == 46 || value.keyCode == 8) {
        //alert('Delete Key Pressed');
    }
};
2
Peter Kreinz

これはすべてテストされていませんが、 ng-keypress を使用できます

<body ng-keypress="logKeys($rootScope,$event)">...</body>

次のような関数を呼び出すには:

appCtrl.$scope.logKeys = function($rootScope,$event){
    $rootScope.keyLog.shift(); // Remove First Item of Array
    $rootScope.keyLog.Push($event.keyCode); // Adds new key press to end of Array
    if($scope.$rootScope.keyLog[0] !== 38) { return false; } // 38 == up key
    if($scope.$rootScope.keyLog[1] !== 38) { return false; }
    if($scope.$rootScope.keyLog[2] !== 40) { return false; } // 40 = down key
    if($scope.$rootScope.keyLog[3] !== 40) { return false; }
    if($scope.$rootScope.keyLog[4] !== 27) { return false; } // 37 = left key
    if($scope.$rootScope.keyLog[5] !== 39) { return false; } // 39 = right key
    if($scope.$rootScope.keyLog[6] !== 37) { return false; }
    if($scope.$rootScope.keyLog[7] !== 39) { return false; }
    if($scope.$rootScope.keyLog[8] !== 65) { return false; } // 65 = a
    if($scope.$rootScope.keyLog[9] !== 66) { return false; } // 66 = b

    $rootScope.doThisWhenAllKeysPressed(); // Got this far, must all match!
    return true;
}

入力フィールドの外では、ng-keypressは機能しないと思いますが、 angular-ui からのキープレスは機能する可能性があります。

配列差分関数もあるはずですが、特定の呼び出しは今のところ私を回避します。

1
OddEssay

これが私の見解です:

var app = angular.module('contra', []);
app.directive('code', function () {
    function codeState() {
        this.currentState = 0;
        this.keys = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
        this.keyPressed = function (key) {
            if (this.keys[this.currentState] == key) {
                this.currentState++;
                if (this.currentState == this.keys.length) {
                    this.currentState = 0;
                    return true;
                }
            } else {
                this.currentState = 0;
            }
            return false;
        };
    };
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var cs = new codeState();
            scope.isValid = "NO";
            element.bind("keydown", function (event) {
                scope.$apply(function () {
                    if (cs.keyPressed(event.which)) {
                        scope.isValid = "YES";
                        console.log("CODE ENTERED");
                    } else {
                        scope.isValid = "NO";
                    }
                });
            });
        }
    }
});

これとの違いは、ディレクティブであるため、これを本文に添付すると、ページ全体に適用されます。これにより、コードを複数回入力することもできます。

プランカー:

http://plnkr.co/edit/tISvsjYKYDrSvA8pu2St

0
Manny D

チェックアウト このプランカー 。単純な「2つのUPキーストロークを連続して」シナリオを実装しました。

プレーンなjQueryでそれを実行し、$rootScope.$broadcastでイベントを伝達できます。

JQueryコードをに登録してAngular runコールバック(angularがすでにブートストラップされていることを保証):

app.run(function($rootScope) {
  var upHitOnce = false;
  $(document).keyup(function(event) {
    if (event.which == 38) {
      if (upHitOnce) {
        $rootScope.$broadcast('DoubleUpFired');
        $rootScope.$apply();
        upHitOnce = false;
      } else {
        upHitOnce = true;
      }
    } else {
      upHitOnce = false;
    }
  });
});

そして、どのコントローラーも次のようにこのイベントをリッスンできます。

$scope.$on('DoubleUpFired', function() {
    $scope.fired = true;
});

ng-keydownアクションコールバックをbodyにバインドすることは問題ありませんが、小さな欠点があります。キーストロークごとに$digestを起動します。本当に必要なのは、何らかの方法でUIを更新する必要があるときにシーケンスが入力された場合にのみ、$digestです。

編集

実際のjQuery依存関係を削除する方法についてのコメントを参照してください。

0
Kos Prov

'ctrl + s'または 'commond + s'(commondKeyを変更)で保存しようとしている場合は、次のように使用できます。

指令:

(function () {

  'use strict';
  var lastKey = 0;
  //var commondKey = 17;
  var commondKey = 91;
  angular
    .module('xinshu')
    .directive('saveEnter', function () {
      return function (scope, element, attrs) {
        element.bind("keydown", function (event) {
          if (event.which != commondKey && event.which != 83) {
            lastKey = 0;
          }
          if (lastKey == commondKey && event.which == 83) {
            scope.$apply(function () {
              scope.$eval(attrs.saveEnter);
            });
            event.preventDefault();
          }
          lastKey = event.which;
        });
      };
    });
})();

要素:

<input id="title" save-enter="vm.saveTitle()"/>

Htmlのsave-enterを変更して、saveEnterinディレクティブの名前を変更できます。

'vm.saveTitle()'はあなたがやりたいことです。

0
isdot