Skip to content

Commit 94a3114

Browse files
committed
fix(cellNav): Minor fixes and speed improvement
1 parent ac4b0bd commit 94a3114

File tree

3 files changed

+188
-27
lines changed

3 files changed

+188
-27
lines changed

src/features/cellnav/js/cellnav.js

Lines changed: 181 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@
213213
scrollTo: function (grid, $scope, rowEntity, colDef) {
214214
service.scrollTo(grid, $scope, rowEntity, colDef);
215215
},
216+
216217
/**
217218
* @ngdoc function
218219
* @name getFocusedCell
@@ -389,6 +390,84 @@
389390
}
390391
},
391392

393+
/**
394+
* @ngdoc method
395+
* @methodOf ui.grid.cellNav.service:uiGridCellNavService
396+
* @name scrollToIfNecessary
397+
* @description Scrolls the grid to make a certain row and column combo visible,
398+
* in the case that it is not completely visible on the screen already.
399+
* @param {Grid} grid the grid you'd like to act upon, usually available
400+
* from gridApi.grid
401+
* @param {object} $scope a scope we can broadcast events from
402+
* @param {GridRow} gridRow row to make visible
403+
* @param {GridCol} gridCol column to make visible
404+
*/
405+
scrollToIfNecessary: function (grid, $scope, gridRow, gridCol) {
406+
var args = {};
407+
408+
// Alias the visible row and column caches
409+
var visRowCache = grid.renderContainers.body.visibleRowCache;
410+
var visColCache = grid.renderContainers.body.visibleColumnCache;
411+
412+
// Get the top, left, right, and bottom "scrolled" edges of the grid
413+
var topBound = grid.renderContainers.body.prevScrollTop + grid.headerHeight;
414+
topBound = (topBound < 0) ? 0 : topBound;
415+
416+
var leftBound = grid.renderContainers.body.prevScrollLeft;
417+
418+
var bottomBound = grid.renderContainers.body.prevScrollTop + grid.gridHeight - grid.headerHeight;
419+
420+
if (grid.horizontalScrollbarHeight) {
421+
bottomBound = bottomBound - grid.horizontalScrollbarHeight;
422+
}
423+
424+
var rightBound = leftBound + grid.gridWidth;
425+
if (grid.verticalScrollbarWidth) {
426+
rightBound = rightBound - grid.verticalScrollbarWidth;
427+
}
428+
429+
if (gridRow !== null) {
430+
var seekRowIndex = visRowCache.indexOf(gridRow);
431+
var totalRows = visRowCache.length;
432+
// var percentage = ( seekRowIndex + ( seekRowIndex / ( totalRows - 1 ) ) ) / totalRows;
433+
// args.y = { percentage: percentage };
434+
var scrollLength = (grid.renderContainers.body.getCanvasHeight() - grid.renderContainers.body.getViewportHeight());
435+
436+
// Add the height of the native horizontal scrollbar, if it's there. Otherwise it will mask over the final row
437+
if (grid.horizontalScrollbarHeight && grid.horizontalScrollbarHeight > 0) {
438+
scrollLength = scrollLength + grid.horizontalScrollbarHeight;
439+
}
440+
441+
// var pixelsToSeeRow = (scrollLength * percentage) + grid.options.rowHeight;
442+
var pixelsToSeeRow = ((seekRowIndex + 1) * grid.options.rowHeight);
443+
pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;
444+
445+
var scrollPixels, percentage;
446+
if (pixelsToSeeRow < topBound) {
447+
scrollPixels = grid.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);
448+
percentage = scrollPixels / scrollLength;
449+
args.y = { percentage: percentage };
450+
}
451+
else if (pixelsToSeeRow > bottomBound) {
452+
scrollPixels = pixelsToSeeRow - bottomBound + grid.renderContainers.body.prevScrollTop;
453+
percentage = scrollPixels / scrollLength;
454+
args.y = { percentage: percentage };
455+
}
456+
}
457+
458+
if (gridCol !== null) {
459+
var pixelsToSeeColumn = this.getLeftWidth(grid, gridCol) + gridCol.drawnWidth;
460+
461+
if (pixelsToSeeColumn < leftBound || pixelsToSeeColumn > rightBound) {
462+
args.x = { percentage: this.getLeftWidth(grid, gridCol) / this.getLeftWidth(grid, visColCache[visColCache.length - 1] ) };
463+
}
464+
}
465+
466+
if (args.y || args.x) {
467+
$scope.$broadcast(uiGridConstants.events.GRID_SCROLL, args);
468+
}
469+
},
470+
392471
/**
393472
* @ngdoc method
394473
* @methodOf ui.grid.cellNav.service:uiGridCellNavService
@@ -462,8 +541,8 @@
462541
</file>
463542
</example>
464543
*/
465-
module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants',
466-
function (gridUtil, uiGridCellNavService, uiGridCellNavConstants) {
544+
module.directive('uiGridCellnav', ['$log', 'gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants',
545+
function ($log, gridUtil, uiGridCellNavService, uiGridCellNavConstants) {
467546
return {
468547
replace: true,
469548
priority: -150,
@@ -500,21 +579,57 @@
500579
};
501580
}]);
502581

503-
module.directive('uiGridRenderContainer', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants',
504-
function (gridUtil, uiGridCellNavService, uiGridCellNavConstants) {
582+
module.directive('uiGridRenderContainer', ['$log', '$timeout', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', 'uiGridCellNavConstants',
583+
function ($log, $timeout, gridUtil, uiGridConstants, uiGridCellNavService, uiGridCellNavConstants) {
505584
return {
506585
replace: true,
507586
priority: -99999, //this needs to run very last
508-
require: '^uiGrid',
587+
require: ['^uiGrid', 'uiGridRenderContainer'],
509588
scope: false,
510589
compile: function () {
511590
return {
512591
pre: function ($scope, $elm, $attrs, uiGridCtrl) {
513592
},
514-
post: function ($scope, $elm, $attrs, uiGridCtrl) {
593+
post: function ($scope, $elm, $attrs, controllers) {
594+
var uiGridCtrl = controllers[0],
595+
renderContainerCtrl = controllers[1];
596+
597+
var containerId = renderContainerCtrl.containerId;
598+
515599
var grid = uiGridCtrl.grid;
516600
//needs to run last after all renderContainers are built
517601
uiGridCellNavService.decorateRenderContainers(grid);
602+
603+
$elm.on('keydown', function (evt) {
604+
var direction = uiGridCellNavService.getDirection(evt);
605+
if (direction === null) {
606+
return true;
607+
}
608+
609+
var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
610+
var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);
611+
// $log.debug('next id', rowCol.row.entity.id);
612+
613+
uiGridCtrl.cellNav.broadcastCellNav(rowCol);
614+
uiGridCellNavService.scrollToIfNecessary(grid, $scope, rowCol.row, rowCol.col);
615+
// setTabEnabled();
616+
617+
evt.stopPropagation();
618+
evt.preventDefault();
619+
620+
return false;
621+
});
622+
623+
// When there's a scroll event we need to make sure to re-focus the right row, because the cell contents may have changed
624+
$scope.$on(uiGridConstants.events.GRID_SCROLL, function (evt, args) {
625+
// We have to wrap in TWO timeouts so that we run AFTER the scroll event is resolved.
626+
$timeout(function () {
627+
$timeout(function () {
628+
var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
629+
uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
630+
});
631+
});
632+
});
518633
}
519634
};
520635
}
@@ -528,8 +643,8 @@
528643
* @restrict A
529644
* @description Stacks on top of ui.grid.uiGridCell to provide cell navigation
530645
*/
531-
module.directive('uiGridCell', ['uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants',
532-
function (uiGridCellNavService, gridUtil, uiGridCellNavConstants) {
646+
module.directive('uiGridCell', ['$log', '$timeout', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants',
647+
function ($log, $timeout, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants) {
533648
return {
534649
priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell
535650
restrict: 'A',
@@ -542,25 +657,28 @@
542657

543658
setTabEnabled();
544659

545-
$elm.on('keydown', function (evt) {
546-
var direction = uiGridCellNavService.getDirection(evt);
547-
if (direction === null) {
548-
return true;
549-
}
660+
// $elm.on('keydown', function (evt) {
661+
// var direction = uiGridCellNavService.getDirection(evt);
662+
// if (direction === null) {
663+
// return true;
664+
// }
550665

551-
var rowCol = $scope.colContainer.cellNav.getNextRowCol(direction, $scope.row, $scope.col);
666+
// var rowCol = $scope.colContainer.cellNav.getNextRowCol(direction, $scope.row, $scope.col);
667+
// $log.debug('next id', rowCol.row.entity.id);
552668

553-
uiGridCtrl.cellNav.broadcastCellNav(rowCol);
554-
setTabEnabled();
669+
// uiGridCtrl.cellNav.broadcastCellNav(rowCol);
670+
// setTabEnabled();
555671

556-
evt.stopPropagation();
557-
evt.preventDefault();
672+
// evt.stopPropagation();
673+
// evt.preventDefault();
558674

559-
return false;
560-
});
675+
// return false;
676+
// });
561677

562-
$elm.find('div').on('focus', function (evt) {
563-
uiGridCtrl.cellNav.broadcastFocus($scope.row, $scope.col);
678+
$elm.find('div').on('click', function (evt) {
679+
uiGridCtrl.cellNav.broadcastCellNav(new RowCol($scope.row, $scope.col));
680+
681+
evt.stopPropagation();
564682
});
565683

566684
//this event is fired for all cells. If the cell matches, then focus is set
@@ -569,20 +687,58 @@
569687
rowCol.col === $scope.col) {
570688
setFocused();
571689
}
690+
else {
691+
clearFocus();
692+
}
693+
694+
// $scope.grid.queueRefresh();
572695
});
573696

697+
// $scope.$on(uiGridConstants.events.GRID_SCROLL, function (evt, args) {
698+
// clearFocus();
699+
700+
// $log.debug('scrollIndex 1', uiGridCtrl.grid.renderContainers.body.prevRowScrollIndex);
701+
702+
// $timeout(function () {
703+
// $log.debug('scrollIndex 2', uiGridCtrl.grid.renderContainers.body.prevRowScrollIndex);
704+
705+
// var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
706+
707+
// if (lastRowCol === null) {
708+
// return;
709+
// }
710+
711+
// if (lastRowCol.hasOwnProperty('row') && lastRowCol.row === $scope.row && lastRowCol.hasOwnProperty('col') && lastRowCol.col === $scope.col) {
712+
// setFocused();
713+
// }
714+
// });
715+
// });
716+
574717
function setTabEnabled() {
575718
$elm.find('div').attr("tabindex", -1);
576719
}
577720

578721
function setFocused() {
579722
var div = $elm.find('div');
580723
// gridUtil.logDebug('setFocused: ' + div[0].parentElement.className);
581-
div[0].focus();
582-
div.attr("tabindex", 0);
583-
$scope.grid.queueRefresh();
724+
// div[0].focus();
725+
// div.attr("tabindex", 0);
726+
div.addClass('ui-grid-cell-focus');
727+
// $scope.grid.queueRefresh();
584728
}
585729

730+
function clearFocus() {
731+
var div = $elm.find('div');
732+
// gridUtil.logDebug('setFocused: ' + div[0].parentElement.className);
733+
// div[0].focus();
734+
// div.attr("tabindex", 0);
735+
div.removeClass('ui-grid-cell-focus');
736+
// $scope.grid.queueRefresh();
737+
}
738+
739+
$scope.$on('$destroy', function () {
740+
$elm.find('div').off('click');
741+
});
586742
}
587743
};
588744
}]);
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
@import '../../../less/variables';
22

3-
.ui-grid-cell-contents:focus {
3+
// .ui-grid-cell-contents:focus {
4+
// outline: 0;
5+
// background-color: @focusedCell;
6+
// }
7+
8+
.ui-grid-cell-focus {
49
outline: 0;
510
background-color: @focusedCell;
611
}

src/templates/ui-grid/uiGridViewport.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="ui-grid-viewport">
22
<div class="ui-grid-canvas">
3-
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by row.uid" class="ui-grid-row" ng-style="containerCtrl.rowStyle(rowRenderIndex)">
3+
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row" ng-style="containerCtrl.rowStyle(rowRenderIndex)">
44
<div ui-grid-row="row" row-render-index="rowRenderIndex"></div>
55
</div>
66
</div>

0 commit comments

Comments
 (0)