Навигация по пользовательскому интерфейсу с помощью клавиатуры
Рассмотрим следующую разметку -
<ul id="list">
<li class="list-item" tabindex="0">test 1</li>
<li class="list-item" tabindex="1">test 2</li>
<li class="list-item" tabindex="2">test 3</li>
<li class="list-item" tabindex="3">test 4</li>
<li class="list-item" tabindex="4">test 5</li>
<li class="list-item" tabindex="5">test 6</li>
<li class="list-item" tabindex="6">test 7</li>
</ul>
и этот кусок кода jQuery -
$(".list-item").bind({
keydown: function(e) {
var key = e.keyCode;
var target = $(e.currentTarget);
switch(key) {
case 38: // arrow up
target.prev().focus();
break;
case 40: // arrow down
target.next().focus();
break;
}
},
focusin: function(e) {
$(e.currentTarget).addClass("selected");
},
focusout: function(e) {
$(e.currentTarget).removeClass("selected");
}
});
$("li").first().focus();
Как переносить этот код в angular? У меня это до сих пор -
<li class="list-item" ng-repeat="item in items" tabindex="{{item.tabIndex}}">
{{item.name}}
</li>
Как сделать привязку в angular?
Ответы
Ответ 1
Лучше всего использовать tabindex
для поиска элементов для фокуса. Попробуйте что-то вроде этого:
<li class="list-item" ng-repeat="item in items"
tabindex="{{item.tabIndex}}"
ng-class="item.selected"
ng-keydown="onKeydown(item, $event)" ng-focus="onFocus(item)">{{item.name}}
</li>
Затем в вашем контроллере вы хотите обработчик Keydown;
var KeyCodes = {
BACKSPACE : 8,
TABKEY : 9,
RETURNKEY : 13,
ESCAPE : 27,
SPACEBAR : 32,
LEFTARROW : 37,
UPARROW : 38,
RIGHTARROW : 39,
DOWNARROW : 40,
};
$scope.onKeydown = function(item, $event) {
var e = $event;
var $target = $(e.target);
var nextTab;
switch (e.keyCode) {
case KeyCodes.ESCAPE:
$target.blur();
break;
case KeyCodes.UPARROW:
nextTab = - 1;
break;
case KeyCodes.RETURNKEY: e.preventDefault();
case KeyCodes.DOWNARROW:
nextTab = 1;
break;
}
if (nextTab != undefined) {
// do this outside the current $digest cycle
// focus the next element by tabindex
$timeout(() => $('[tabindex=' + (parseInt($target.attr("tabindex")) + nextTab) + ']').focus());
}
};
И простой обработчик фокуса;
$scope.onFocus = function(item, $event) {
// clear all other items
angular.forEach(items, function(item) {
item.selected = undefined;
});
// select this one
item.selected = "selected";
};
Это с моей головы, если это поможет любому, кто попадает в эту нить, как я.
Ответ 2
Вы также можете создать директиву angular, как показано ниже:
claimApp.directive('keyNavigation', function ($timeout) {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if (event.which === 38) {
var target = $(event.target).prev();
$(target).trigger('focus');
}
if (event.which === 40) {
var target = $(event.target).next();
$(target).trigger('focus');
}
});
};
});
И затем используйте его в своем HTML, как это:
<li class="list-item" ng-repeat="item in items" key-navigation>
{{item.name}}
</li>
Ответ 3
На этот вопрос был дан ответ за несколько месяцев до того, как он был задан, и у него есть живой рабочий пример в Plunker.
var app = angular.module('test', []);
app.controller('testCtrl',function ($scope, $window) {
$scope.console = $window.console;
$scope.records = [];
for (var i = 1; i <= 9; i++) {
$scope.records.push({ id: i, navIndex: i, name: 'record ' + i});
}
$scope.focusIndex = 3;
$scope.open = function ( index ) {
var record = $scope.shownRecords[ index ]
console.log('opening : ', record );
};
$scope.keys = [];
$scope.keys.push({ code: 13, action: function() { $scope.open( $scope.focusIndex ); }});
$scope.keys.push({ code: 38, action: function() { $scope.focusIndex--; }});
$scope.keys.push({ code: 40, action: function() { $scope.focusIndex++; }});
И ссылка на подобный вопрос задавалась за несколько недель до того, как этот поток fooobar.com/questions/444974/...
Ответ 4
Директива без jQuery
.directive('arrow', function ($timeout) {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if (event.which === 38) {
var prevNode = element[0].previousElementSibling;
var prev = angular.element(prevNode);
prev[0].focus();
}
if (event.which === 40) {
var target = element.next();
target[0].focus();
}
});
};
});
Использование в html
<tr arrow>
<td>test 1</td>
</tr>
<tr arrow>
<td>test 2</td>
</tr>