AngularJS表中的键盘导航

Hof*_*ffZ 1 javascript angularjs

我正在尝试将Windows(Delphi VCL)中的特殊表/网格表格移植到Angular应用程序.

可以在此处测试角度应用程序的简化版本:jsFiddle演示.

用户可以根据需要添加任意数量的行,如jsFiddle中所示.

问题是:是否可以使用Angular指令或其他一些Angular魔法解决以下问题?

  1. 按下回车键时跳转到下一个单元格(右侧单元格或新行)
  2. 直接跳到箭头下方的单元格.
  3. 在箭头上方直接跳到上方的单元格.

HTML:

<tbody>
<tr ng-repeat="p in persons">
    <td>
        <input ng-model="p.name">
    </td>
    <td>
        <input ng-model="p.age">
    </td>
    <td>
        <button ng-click="add($index)">Add new person</button>
    </td>
</tr>
</tbody>
Run Code Online (Sandbox Code Playgroud)

JS:

function TestingCtrl($scope) {

  $scope.persons = [{
      name: 'Alice',
      age: 20
    }, {
      name: 'Bob',
      age: 30
    }];

  $scope.add = function(index) {
    var newPerson = function() {
      return {
        name: '',
        age: ''
      };
    };
    $scope.persons.splice(index + 1, 0, new newPerson());
  }

}
Run Code Online (Sandbox Code Playgroud)

Hof*_*ffZ 7

我想通了.此Plunk将在输入键和所有箭头键(向上,向下,向左,向右)上导航.谢谢@Armen指出我正确的方向.

<div ng-app="myApp">
<div ng-controller="TestingCtrl">
    <table navigatable>
        <thead>
            <tr>
                <th>Name</th>
                <th>Age</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="p in persons">
                <td>
                    <input type="text" ng-model="p.name">
                </td>
                <td>
                    <input type="text" ng-model="p.age">
                </td>
                <td>
                    <button ng-click="add($index)">Add new person</button>
                </td>
            </tr>
        </tbody>
    </table>
</div>
Run Code Online (Sandbox Code Playgroud)

angular.module("myApp", [])
.controller("TestingCtrl", ["$scope",
  function TestingCtrl($scope) {
    $scope.persons = [{
        name: 'Alice',
        age: 20
      }, {
        name: 'Bob',
        age: 30
      }];

    $scope.add = function(index) {
      var newPerson = function() {
        return {
          name: '',
          age: ''
        };
      };
      $scope.persons.splice(index + 1, 0, new newPerson());
    }

  }
])
.directive('navigatable', function() {
  return function(scope, element, attr) {

    element.on('keypress.mynavigation', 'input[type="text"]', handleNavigation);


    function handleNavigation(e) {

      var arrow = {left: 37, up: 38, right: 39, down: 40};

      // select all on focus
      element.find('input').keydown(function(e) {

        // shortcut for key other than arrow keys
        if ($.inArray(e.which, [arrow.left, arrow.up, arrow.right, arrow.down]) < 0) {
          return;
        }

        var input = e.target;
        var td = $(e.target).closest('td');
        var moveTo = null;

        switch (e.which) {

          case arrow.left:
            {
              if (input.selectionStart == 0) {
                moveTo = td.prev('td:has(input,textarea)');
              }
              break;
            }
          case arrow.right:
            {
              if (input.selectionEnd == input.value.length) {
                moveTo = td.next('td:has(input,textarea)');
              }
              break;
            }

          case arrow.up:
          case arrow.down:
            {

              var tr = td.closest('tr');
              var pos = td[0].cellIndex;

              var moveToRow = null;
              if (e.which == arrow.down) {
                moveToRow = tr.next('tr');
              }
              else if (e.which == arrow.up) {
                moveToRow = tr.prev('tr');
              }

              if (moveToRow.length) {
                moveTo = $(moveToRow[0].cells[pos]);
              }

              break;
            }

        }

        if (moveTo && moveTo.length) {

          e.preventDefault();

          moveTo.find('input,textarea').each(function(i, input) {
            input.focus();
            input.select();
          });

        }

      });


      var key = e.keyCode ? e.keyCode : e.which;
      if (key === 13) {
        var focusedElement = $(e.target);
        var nextElement = focusedElement.parent().next();
        if (nextElement.find('input').length > 0) {
          nextElement.find('input').focus();
        } else {
          nextElement = nextElement.parent().next().find('input').first();
          nextElement.focus();
        }
      }
    }
  };
})
Run Code Online (Sandbox Code Playgroud)

我从不同的来源做了som复制/粘贴.需要重构.