Skip to content

Commit 2485652

Browse files
cybermerlinmportuga
authored andcommitted
feat(selection): Enhance the selection feature
- highlight on hover row - enableSelectRowOnFocus - enableFocusRowOnRowHeaderClick - rowFocusChanged - Ignore multiSelect flag on selectCells if no keys are pressed. - Replace $timeout with window.setTimeout
1 parent ec13255 commit 2485652

File tree

5 files changed

+273
-73
lines changed

5 files changed

+273
-73
lines changed

src/features/selection/js/selection.js

+111-53
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,25 @@
5252
* @ngdoc object
5353
* @name isSelected
5454
* @propertyOf ui.grid.selection.api:GridRow
55-
* @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
55+
* @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
5656
* <br/>Defaults to false
5757
*/
5858

59+
/**
60+
* @ngdoc object
61+
* @name isFocused
62+
* @propertyOf ui.grid.selection.api:GridRow
63+
* @description Focused state of row. Should be readonly. Make any changes to focused state using setFocused().
64+
* <br/>Defaults to false
65+
*/
5966

6067
/**
6168
* @ngdoc function
6269
* @name setSelected
6370
* @methodOf ui.grid.selection.api:GridRow
6471
* @description Sets the isSelected property and updates the selectedCount
6572
* Changes to isSelected state should only be made via this function
66-
* @param {bool} selected value to set
73+
* @param {Boolean} selected value to set
6774
*/
6875
$delegate.prototype.setSelected = function (selected) {
6976
if (selected !== this.isSelected) {
@@ -72,6 +79,22 @@
7279
}
7380
};
7481

82+
/**
83+
* @ngdoc function
84+
* @name setFocused
85+
* @methodOf ui.grid.selection.api:GridRow
86+
* @description Sets the isFocused property
87+
* Changes to isFocused state should only be made via this function
88+
* @param {Boolean} val value to set
89+
*/
90+
$delegate.prototype.setFocused = function(val) {
91+
if (val !== this.isFocused) {
92+
this.grid.selection.focusedRow && (this.grid.selection.focusedRow.isFocused = false);
93+
this.grid.selection.focusedRow = val ? this : null;
94+
this.isFocused = val;
95+
}
96+
};
97+
7598
return $delegate;
7699
}]);
77100
}]);
@@ -84,7 +107,6 @@
84107
*/
85108
module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',
86109
function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {
87-
88110
var service = {
89111

90112
initializeGrid: function (grid) {
@@ -96,9 +118,17 @@
96118
*
97119
* @description Grid properties and functions added for selection
98120
*/
99-
grid.selection = {};
100-
grid.selection.lastSelectedRow = null;
101-
grid.selection.selectAll = false;
121+
grid.selection = {
122+
lastSelectedRow: null,
123+
/**
124+
* @ngdoc object
125+
* @name focusedRow
126+
* @propertyOf ui.grid.selection.grid:selection
127+
* @description Focused row.
128+
*/
129+
focusedRow: null,
130+
selectAll: false
131+
};
102132

103133

104134
/**
@@ -122,6 +152,16 @@
122152
var publicApi = {
123153
events: {
124154
selection: {
155+
/**
156+
* @ngdoc event
157+
* @name rowFocusChanged
158+
* @eventOf ui.grid.selection.api:PublicApi
159+
* @description is raised after the row.isFocused state is changed
160+
* @param {object} scope the scope associated with the grid
161+
* @param {GridRow} row the row that was focused/unfocused
162+
* @param {Event} evt object if raised from an event
163+
*/
164+
rowFocusChanged: function (scope, row, evt) {},
125165
/**
126166
* @ngdoc event
127167
* @name rowSelectionChanged
@@ -414,11 +454,27 @@
414454
* @name enableFullRowSelection
415455
* @propertyOf ui.grid.selection.api:GridOptions
416456
* @description Enable selection by clicking anywhere on the row. Defaults to
417-
* false if `enableRowHeaderSelection` is true, otherwise defaults to false.
457+
* false if `enableRowHeaderSelection` is true, otherwise defaults to true.
418458
*/
419459
if (typeof (gridOptions.enableFullRowSelection) === 'undefined') {
420460
gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
421461
}
462+
/**
463+
* @ngdoc object
464+
* @name enableFocusRowOnRowHeaderClick
465+
* @propertyOf ui.grid.selection.api:GridOptions
466+
* @description Enable focuse row by clicking on the row header. Defaults to
467+
* true if `enableRowHeaderSelection` is true, otherwise defaults to false.
468+
*/
469+
gridOptions.enableFocusRowOnRowHeaderClick = (gridOptions.enableFocusRowOnRowHeaderClick !== false)
470+
|| !gridOptions.enableRowHeaderSelection;
471+
/**
472+
* @ngdoc object
473+
* @name enableSelectRowOnFocus
474+
* @propertyOf ui.grid.selection.api:GridOptions
475+
* @description Enable focuse row by clicking on the row anywhere. Defaults true.
476+
*/
477+
gridOptions.enableSelectRowOnFocus = (gridOptions.enableSelectRowOnFocus !== false);
422478
/**
423479
* @ngdoc object
424480
* @name enableSelectAll
@@ -446,7 +502,6 @@
446502
* <br/>Defaults to 30px
447503
*/
448504
gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
449-
450505
/**
451506
* @ngdoc object
452507
* @name enableFooterTotalSelected
@@ -456,17 +511,15 @@
456511
* <br/>GridOptions.showGridFooter must also be set to true.
457512
*/
458513
gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
459-
460514
/**
461515
* @ngdoc object
462516
* @name isRowSelectable
463517
* @propertyOf ui.grid.selection.api:GridOptions
464518
* @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
465519
*/
466-
467520
gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
468521
},
469-
522+
470523
/**
471524
* @ngdoc function
472525
* @name toggleRowSelection
@@ -479,20 +532,22 @@
479532
* @param {bool} noUnselect if true then rows cannot be unselected
480533
*/
481534
toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {
482-
var selected = row.isSelected,
483-
selectedRows;
484-
485-
if (row.enableSelection === false) {
535+
if ( row.enableSelection === false ){
486536
return;
487537
}
488538

489-
if (!multiSelect && !selected) {
490-
service.clearSelectedRows(grid, evt);
491-
} else if (!multiSelect && selected) {
492-
selectedRows = service.getSelectedRows(grid);
493-
if (selectedRows.length > 1) {
494-
selected = false; // Enable reselect of the row
539+
var selected = row.isSelected,
540+
selectedRows;
541+
542+
if (!multiSelect) {
543+
if (!selected) {
495544
service.clearSelectedRows(grid, evt);
545+
} else {
546+
selectedRows = service.getSelectedRows(grid);
547+
if (selectedRows.length > 1) {
548+
selected = false; // Enable reselect of the row
549+
service.clearSelectedRows(grid, evt);
550+
}
496551
}
497552
}
498553

@@ -726,7 +781,7 @@
726781
$scope.selectButtonKeyDown = selectButtonKeyDown;
727782

728783
// On IE, prevent mousedowns on the select button from starting a selection.
729-
// If this is not done and you shift+click on another row, the browser will select a big chunk of text
784+
// If this is not done and you shift+click on another row, the browser will select a big chunk of text
730785
if (gridUtil.detectBrowser() === 'ie') {
731786
$elm.on('mousedown', selectButtonMouseDown);
732787
}
@@ -745,7 +800,8 @@
745800
uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
746801
}
747802
else if (evt.ctrlKey || evt.metaKey) {
748-
uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
803+
uiGridSelectionService.toggleRowSelection(self, row, evt,
804+
self.options.multiSelect, self.options.noUnselect);
749805
}
750806
else if (row.groupHeader) {
751807
uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
@@ -754,8 +810,10 @@
754810
}
755811
}
756812
else {
757-
uiGridSelectionService.toggleRowSelection(self, row, evt, (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
813+
uiGridSelectionService.toggleRowSelection(self, row, evt,
814+
(self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
758815
}
816+
self.options.enableFocusRowOnRowHeaderClick && row.setFocused(!row.isFocused) && self.api.selection.raise.rowFocusChanged(row, evt);
759817
}
760818

761819
function selectButtonMouseDown(evt) {
@@ -820,23 +878,20 @@
820878
priority: -200, // run after default directive
821879
scope: false,
822880
compile: function ($elm, $attrs) {
823-
var rowRepeatDiv = angular.element($elm[0].querySelector('.ui-grid-canvas:not(.ui-grid-empty-base-layer-container)').children[0]);
881+
var rowRepeatDiv = angular.element($elm[0].querySelector('.ui-grid-canvas:not(.ui-grid-empty-base-layer-container)').children[0]),
882+
newNgClass = "'ui-grid-row-selected': row.isSelected, 'ui-grid-row-focused': row.isFocused}",
883+
existingNgClass = rowRepeatDiv.attr('ng-class');
824884

825-
var existingNgClass = rowRepeatDiv.attr("ng-class");
826-
var newNgClass = '';
827885
if (existingNgClass) {
828-
newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-row-selected': row.isSelected}";
886+
newNgClass = existingNgClass.slice(0, -1) + ',' + newNgClass;
829887
} else {
830-
newNgClass = "{'ui-grid-row-selected': row.isSelected}";
888+
newNgClass = '{' + newNgClass;
831889
}
832-
rowRepeatDiv.attr("ng-class", newNgClass);
890+
rowRepeatDiv.attr('ng-class', newNgClass);
833891

834892
return {
835-
pre: function ($scope, $elm, $attrs, controllers) {
836-
837-
},
838-
post: function ($scope, $elm, $attrs, controllers) {
839-
}
893+
pre: function ($scope, $elm, $attrs, controllers) {},
894+
post: function ($scope, $elm, $attrs, controllers) {}
840895
};
841896
}
842897
};
@@ -859,23 +914,23 @@
859914
require: '?^uiGrid',
860915
scope: false,
861916
link: function ($scope, $elm, $attrs, uiGridCtrl) {
862-
863-
var touchStartTime = 0;
864-
var touchTimeout = 300;
917+
var touchStartTime = 0,
918+
touchTimeout = 300;
865919

866920
// Bind to keydown events in the render container
867921
if (uiGridCtrl.grid.api.cellNav) {
868-
869922
uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
870923
if (rowCol === null ||
871924
rowCol.row !== $scope.row ||
872925
rowCol.col !== $scope.col) {
873926
return;
874927
}
875928

876-
if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") {
929+
if (evt.keyCode === uiGridConstants.keymap.SPACE && $scope.col.colDef.name === 'selectionRowHeaderCol') {
877930
evt.preventDefault();
878-
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
931+
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
932+
($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect),
933+
$scope.grid.options.noUnselect);
879934
$scope.$apply();
880935
}
881936

@@ -903,21 +958,25 @@
903958
uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
904959
}
905960
else if (evt.ctrlKey || evt.metaKey) {
906-
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
961+
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
962+
$scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
907963
}
908-
else {
909-
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt, ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect), $scope.grid.options.noUnselect);
964+
else if ($scope.grid.options.enableSelectRowOnFocus) {
965+
uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
966+
false, $scope.grid.options.noUnselect);
910967
}
968+
$scope.row.setFocused(!$scope.row.isFocused);
969+
$scope.grid.api.selection.raise.rowFocusChanged($scope.row, evt);
911970
$scope.$apply();
912971

913972
// don't re-enable the touchend handler for a little while - some devices generate both, and it will
914973
// take a little while to move your hand from the mouse to the screen if you have both modes of input
915-
$timeout(function () {
974+
window.setTimeout(function () {
916975
$elm.on('touchend', touchEnd);
917976
}, touchTimeout);
918977
};
919978

920-
var touchStart = function (evt) {
979+
var touchStart = function () {
921980
touchStartTime = (new Date()).getTime();
922981

923982
// if we get a touch event, then stop listening for click
@@ -935,7 +994,7 @@
935994

936995
// don't re-enable the click handler for a little while - some devices generate both, and it will
937996
// take a little while to move your hand from the screen to the mouse if you have both modes of input
938-
$timeout(function () {
997+
window.setTimeout(function () {
939998
$elm.on('click', selectCells);
940999
}, touchTimeout);
9411000
};
@@ -951,10 +1010,9 @@
9511010
}
9521011
}
9531012

954-
function deregisterRowSelectionEvents() {
1013+
function unregisterRowSelectionEvents() {
9551014
if ($scope.registered) {
9561015
$elm.removeClass('ui-grid-disable-selection');
957-
9581016
$elm.off('touchstart', touchStart);
9591017
$elm.off('touchend', touchEnd);
9601018
$elm.off('click', selectCells);
@@ -964,19 +1022,20 @@
9641022
}
9651023

9661024
registerRowSelectionEvents();
1025+
9671026
// register a dataChange callback so that we can change the selection configuration dynamically
9681027
// if the user changes the options
969-
var dataChangeDereg = $scope.grid.registerDataChangeCallback(function () {
1028+
var dataChangeUnreg = $scope.grid.registerDataChangeCallback(function () {
9701029
if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
9711030
!$scope.registered) {
9721031
registerRowSelectionEvents();
9731032
} else if ((!$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection) &&
9741033
$scope.registered) {
975-
deregisterRowSelectionEvents();
1034+
unregisterRowSelectionEvents();
9761035
}
9771036
}, [uiGridConstants.dataChange.OPTIONS]);
9781037

979-
$elm.on('$destroy', dataChangeDereg);
1038+
$elm.on('$destroy', dataChangeUnreg);
9801039
}
9811040
};
9821041
}]);
@@ -1014,5 +1073,4 @@
10141073
}
10151074
};
10161075
}]);
1017-
10181076
})();

src/features/selection/less/selection.less

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@import '../../../less/variables';
22

3-
.ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {
3+
.ui-grid-render-container-left .ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell,
4+
.ui-grid-row.ui-grid-row-focused > [ui-grid-row] > .ui-grid-cell {
45
background-color: @rowSelected;
56
}
67

0 commit comments

Comments
 (0)