Skip to content

Commit

Permalink
fix(cellNav): Don't lose focus with wrapping nav
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
c0bra committed Nov 13, 2014
1 parent a335b92 commit 0e27c18
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
33 changes: 22 additions & 11 deletions src/features/cellnav/js/cellnav.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,13 @@
// gridUtil.logDebug('uiGridEdit preLink');
uiGridCtrl.cellNav.broadcastCellNav = function (newRowCol) {
$scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol);
uiGridCtrl.cellNav.broadcastFocus(newRowCol.row, newRowCol.col);
uiGridCtrl.cellNav.broadcastFocus(newRowCol);
};

uiGridCtrl.cellNav.broadcastFocus = function (row, col) {
uiGridCtrl.cellNav.broadcastFocus = function (rowCol) {
var row = rowCol.row,
col = rowCol.col;

if (grid.cellNav.lastRowCol === null || (grid.cellNav.lastRowCol.row !== row || grid.cellNav.lastRowCol.col !== col)) {
var newRowCol = new RowCol(row, col);
grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol);
Expand Down Expand Up @@ -688,8 +691,8 @@
};
}]);

module.directive('uiGridRenderContainer', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',
function ($timeout, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {
module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',
function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {
return {
replace: true,
priority: -99999, //this needs to run very last
Expand All @@ -706,9 +709,13 @@
var containerId = renderContainerCtrl.containerId;

var grid = uiGridCtrl.grid;
//needs to run last after all renderContainers are built

// Needs to run last after all renderContainers are built
uiGridCellNavService.decorateRenderContainers(grid);

// Let the render container be focus-able
$elm.attr("tabindex", -1);

// Bind to keydown events in the render container
$elm.on('keydown', function (evt) {
evt.uiGridTargetRenderContainerId = containerId;
Expand All @@ -717,6 +724,7 @@

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

// If the body element becomes active, re-focus on the render container so we can capture cellNav events again.
// NOTE: this happens when we navigate LET from the left-most cell (RIGHT from the right-most) and have to re-render a new
// set of cells. The cell element we are navigating to doesn't exist and focus gets lost. This will re-capture it, imperfectly...
if ($document.activeElement === $document.body) {
$elm[0].focus();
}

// Re-broadcast a cellNav event so we re-focus the right cell
uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
});
Expand Down Expand Up @@ -772,12 +787,8 @@
rowCol.col === $scope.col) {
setFocused();

if (
// This cellNav event came from a keydown event so we can safely refocus
(rowCol.hasOwnProperty('eventType') && rowCol.eventType === uiGridCellNavConstants.EVENT_TYPE.KEYDOWN)
// The focus has gone to the body element, because we've probably wrapped around
// ($document.activeElement === $document.body)
) {
// This cellNav event came from a keydown event so we can safely refocus
if (rowCol.hasOwnProperty('eventType') && rowCol.eventType === uiGridCellNavConstants.EVENT_TYPE.KEYDOWN) {
$elm.find('div')[0].focus();
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/less/body.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
// overflow: hidden;

.border-radius(0, @gridBorderRadius, @gridBorderRadius, 0);

// Prevent an outline from showing if we focus the render container element
&:focus {
outline: none;
}
}

.ui-grid-viewport {
Expand Down

0 comments on commit 0e27c18

Please sign in to comment.