Skip to content

Commit 0e27c18

Browse files
committed
fix(cellNav): Don't lose focus with wrapping nav
When navigating beyond the left/right edges of grid around to the other side, the grid was losing focus which prevented further navigation because any keydown events were being sent to <body> (the new activeElement). This fix causes the renderContainer to be REFOCUSED after a GRID_SCROLL event in the case that the activeElement is document.body. We are assuming that when scrolling within the grid, an element within the grid should have focus.
1 parent a335b92 commit 0e27c18

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

src/features/cellnav/js/cellnav.js

+22-11
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,13 @@
638638
// gridUtil.logDebug('uiGridEdit preLink');
639639
uiGridCtrl.cellNav.broadcastCellNav = function (newRowCol) {
640640
$scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol);
641-
uiGridCtrl.cellNav.broadcastFocus(newRowCol.row, newRowCol.col);
641+
uiGridCtrl.cellNav.broadcastFocus(newRowCol);
642642
};
643643

644-
uiGridCtrl.cellNav.broadcastFocus = function (row, col) {
644+
uiGridCtrl.cellNav.broadcastFocus = function (rowCol) {
645+
var row = rowCol.row,
646+
col = rowCol.col;
647+
645648
if (grid.cellNav.lastRowCol === null || (grid.cellNav.lastRowCol.row !== row || grid.cellNav.lastRowCol.col !== col)) {
646649
var newRowCol = new RowCol(row, col);
647650
grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);
@@ -688,8 +691,8 @@
688691
};
689692
}]);
690693

691-
module.directive('uiGridRenderContainer', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',
692-
function ($timeout, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {
694+
module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',
695+
function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {
693696
return {
694697
replace: true,
695698
priority: -99999, //this needs to run very last
@@ -706,9 +709,13 @@
706709
var containerId = renderContainerCtrl.containerId;
707710

708711
var grid = uiGridCtrl.grid;
709-
//needs to run last after all renderContainers are built
712+
713+
// Needs to run last after all renderContainers are built
710714
uiGridCellNavService.decorateRenderContainers(grid);
711715

716+
// Let the render container be focus-able
717+
$elm.attr("tabindex", -1);
718+
712719
// Bind to keydown events in the render container
713720
$elm.on('keydown', function (evt) {
714721
evt.uiGridTargetRenderContainerId = containerId;
@@ -717,6 +724,7 @@
717724

718725
// When there's a scroll event we need to make sure to re-focus the right row, because the cell contents may have changed
719726
$scope.$on(uiGridConstants.events.GRID_SCROLL, function (evt, args) {
727+
// Skip if there's no currently-focused cell
720728
if (uiGridCtrl.grid.api.cellNav.getFocusedCell() == null) {
721729
return;
722730
}
@@ -727,6 +735,13 @@
727735
// Get the last row+col combo
728736
var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
729737

738+
// If the body element becomes active, re-focus on the render container so we can capture cellNav events again.
739+
// NOTE: this happens when we navigate LET from the left-most cell (RIGHT from the right-most) and have to re-render a new
740+
// set of cells. The cell element we are navigating to doesn't exist and focus gets lost. This will re-capture it, imperfectly...
741+
if ($document.activeElement === $document.body) {
742+
$elm[0].focus();
743+
}
744+
730745
// Re-broadcast a cellNav event so we re-focus the right cell
731746
uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
732747
});
@@ -772,12 +787,8 @@
772787
rowCol.col === $scope.col) {
773788
setFocused();
774789

775-
if (
776-
// This cellNav event came from a keydown event so we can safely refocus
777-
(rowCol.hasOwnProperty('eventType') && rowCol.eventType === uiGridCellNavConstants.EVENT_TYPE.KEYDOWN)
778-
// The focus has gone to the body element, because we've probably wrapped around
779-
// ($document.activeElement === $document.body)
780-
) {
790+
// This cellNav event came from a keydown event so we can safely refocus
791+
if (rowCol.hasOwnProperty('eventType') && rowCol.eventType === uiGridCellNavConstants.EVENT_TYPE.KEYDOWN) {
781792
$elm.find('div')[0].focus();
782793
}
783794
}

src/less/body.less

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
// overflow: hidden;
55

66
.border-radius(0, @gridBorderRadius, @gridBorderRadius, 0);
7+
8+
// Prevent an outline from showing if we focus the render container element
9+
&:focus {
10+
outline: none;
11+
}
712
}
813

914
.ui-grid-viewport {

0 commit comments

Comments
 (0)