|
52 | 52 | * @ngdoc object
|
53 | 53 | * @name isSelected
|
54 | 54 | * @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(). |
56 | 56 | * <br/>Defaults to false
|
57 | 57 | */
|
58 | 58 |
|
| 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 | + */ |
59 | 66 |
|
60 | 67 | /**
|
61 | 68 | * @ngdoc function
|
62 | 69 | * @name setSelected
|
63 | 70 | * @methodOf ui.grid.selection.api:GridRow
|
64 | 71 | * @description Sets the isSelected property and updates the selectedCount
|
65 | 72 | * 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 |
67 | 74 | */
|
68 | 75 | $delegate.prototype.setSelected = function (selected) {
|
69 | 76 | if (selected !== this.isSelected) {
|
|
72 | 79 | }
|
73 | 80 | };
|
74 | 81 |
|
| 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 | + |
75 | 98 | return $delegate;
|
76 | 99 | }]);
|
77 | 100 | }]);
|
|
84 | 107 | */
|
85 | 108 | module.service('uiGridSelectionService', ['$q', '$templateCache', 'uiGridSelectionConstants', 'gridUtil',
|
86 | 109 | function ($q, $templateCache, uiGridSelectionConstants, gridUtil) {
|
87 |
| - |
88 | 110 | var service = {
|
89 | 111 |
|
90 | 112 | initializeGrid: function (grid) {
|
|
96 | 118 | *
|
97 | 119 | * @description Grid properties and functions added for selection
|
98 | 120 | */
|
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 | + }; |
102 | 132 |
|
103 | 133 |
|
104 | 134 | /**
|
|
122 | 152 | var publicApi = {
|
123 | 153 | events: {
|
124 | 154 | 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) {}, |
125 | 165 | /**
|
126 | 166 | * @ngdoc event
|
127 | 167 | * @name rowSelectionChanged
|
|
414 | 454 | * @name enableFullRowSelection
|
415 | 455 | * @propertyOf ui.grid.selection.api:GridOptions
|
416 | 456 | * @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. |
418 | 458 | */
|
419 | 459 | if (typeof (gridOptions.enableFullRowSelection) === 'undefined') {
|
420 | 460 | gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
|
421 | 461 | }
|
| 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); |
422 | 478 | /**
|
423 | 479 | * @ngdoc object
|
424 | 480 | * @name enableSelectAll
|
|
446 | 502 | * <br/>Defaults to 30px
|
447 | 503 | */
|
448 | 504 | gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
|
449 |
| - |
450 | 505 | /**
|
451 | 506 | * @ngdoc object
|
452 | 507 | * @name enableFooterTotalSelected
|
|
456 | 511 | * <br/>GridOptions.showGridFooter must also be set to true.
|
457 | 512 | */
|
458 | 513 | gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
|
459 |
| - |
460 | 514 | /**
|
461 | 515 | * @ngdoc object
|
462 | 516 | * @name isRowSelectable
|
463 | 517 | * @propertyOf ui.grid.selection.api:GridOptions
|
464 | 518 | * @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
|
465 | 519 | */
|
466 |
| - |
467 | 520 | gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
|
468 | 521 | },
|
469 |
| - |
| 522 | + |
470 | 523 | /**
|
471 | 524 | * @ngdoc function
|
472 | 525 | * @name toggleRowSelection
|
|
479 | 532 | * @param {bool} noUnselect if true then rows cannot be unselected
|
480 | 533 | */
|
481 | 534 | 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 ){ |
486 | 536 | return;
|
487 | 537 | }
|
488 | 538 |
|
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) { |
495 | 544 | 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 | + } |
496 | 551 | }
|
497 | 552 | }
|
498 | 553 |
|
|
726 | 781 | $scope.selectButtonKeyDown = selectButtonKeyDown;
|
727 | 782 |
|
728 | 783 | // 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 |
730 | 785 | if (gridUtil.detectBrowser() === 'ie') {
|
731 | 786 | $elm.on('mousedown', selectButtonMouseDown);
|
732 | 787 | }
|
|
745 | 800 | uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
|
746 | 801 | }
|
747 | 802 | 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); |
749 | 805 | }
|
750 | 806 | else if (row.groupHeader) {
|
751 | 807 | uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
|
|
754 | 810 | }
|
755 | 811 | }
|
756 | 812 | 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); |
758 | 815 | }
|
| 816 | + self.options.enableFocusRowOnRowHeaderClick && row.setFocused(!row.isFocused) && self.api.selection.raise.rowFocusChanged(row, evt); |
759 | 817 | }
|
760 | 818 |
|
761 | 819 | function selectButtonMouseDown(evt) {
|
|
820 | 878 | priority: -200, // run after default directive
|
821 | 879 | scope: false,
|
822 | 880 | 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'); |
824 | 884 |
|
825 |
| - var existingNgClass = rowRepeatDiv.attr("ng-class"); |
826 |
| - var newNgClass = ''; |
827 | 885 | if (existingNgClass) {
|
828 |
| - newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-row-selected': row.isSelected}"; |
| 886 | + newNgClass = existingNgClass.slice(0, -1) + ',' + newNgClass; |
829 | 887 | } else {
|
830 |
| - newNgClass = "{'ui-grid-row-selected': row.isSelected}"; |
| 888 | + newNgClass = '{' + newNgClass; |
831 | 889 | }
|
832 |
| - rowRepeatDiv.attr("ng-class", newNgClass); |
| 890 | + rowRepeatDiv.attr('ng-class', newNgClass); |
833 | 891 |
|
834 | 892 | 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) {} |
840 | 895 | };
|
841 | 896 | }
|
842 | 897 | };
|
|
859 | 914 | require: '?^uiGrid',
|
860 | 915 | scope: false,
|
861 | 916 | link: function ($scope, $elm, $attrs, uiGridCtrl) {
|
862 |
| - |
863 |
| - var touchStartTime = 0; |
864 |
| - var touchTimeout = 300; |
| 917 | + var touchStartTime = 0, |
| 918 | + touchTimeout = 300; |
865 | 919 |
|
866 | 920 | // Bind to keydown events in the render container
|
867 | 921 | if (uiGridCtrl.grid.api.cellNav) {
|
868 |
| - |
869 | 922 | uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
|
870 | 923 | if (rowCol === null ||
|
871 | 924 | rowCol.row !== $scope.row ||
|
872 | 925 | rowCol.col !== $scope.col) {
|
873 | 926 | return;
|
874 | 927 | }
|
875 | 928 |
|
876 |
| - if (evt.keyCode === 32 && $scope.col.colDef.name === "selectionRowHeaderCol") { |
| 929 | + if (evt.keyCode === uiGridConstants.keymap.SPACE && $scope.col.colDef.name === 'selectionRowHeaderCol') { |
877 | 930 | 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); |
879 | 934 | $scope.$apply();
|
880 | 935 | }
|
881 | 936 |
|
|
903 | 958 | uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
|
904 | 959 | }
|
905 | 960 | 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); |
907 | 963 | }
|
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); |
910 | 967 | }
|
| 968 | + $scope.row.setFocused(!$scope.row.isFocused); |
| 969 | + $scope.grid.api.selection.raise.rowFocusChanged($scope.row, evt); |
911 | 970 | $scope.$apply();
|
912 | 971 |
|
913 | 972 | // don't re-enable the touchend handler for a little while - some devices generate both, and it will
|
914 | 973 | // 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 () { |
916 | 975 | $elm.on('touchend', touchEnd);
|
917 | 976 | }, touchTimeout);
|
918 | 977 | };
|
919 | 978 |
|
920 |
| - var touchStart = function (evt) { |
| 979 | + var touchStart = function () { |
921 | 980 | touchStartTime = (new Date()).getTime();
|
922 | 981 |
|
923 | 982 | // if we get a touch event, then stop listening for click
|
|
935 | 994 |
|
936 | 995 | // don't re-enable the click handler for a little while - some devices generate both, and it will
|
937 | 996 | // 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 () { |
939 | 998 | $elm.on('click', selectCells);
|
940 | 999 | }, touchTimeout);
|
941 | 1000 | };
|
|
951 | 1010 | }
|
952 | 1011 | }
|
953 | 1012 |
|
954 |
| - function deregisterRowSelectionEvents() { |
| 1013 | + function unregisterRowSelectionEvents() { |
955 | 1014 | if ($scope.registered) {
|
956 | 1015 | $elm.removeClass('ui-grid-disable-selection');
|
957 |
| - |
958 | 1016 | $elm.off('touchstart', touchStart);
|
959 | 1017 | $elm.off('touchend', touchEnd);
|
960 | 1018 | $elm.off('click', selectCells);
|
|
964 | 1022 | }
|
965 | 1023 |
|
966 | 1024 | registerRowSelectionEvents();
|
| 1025 | + |
967 | 1026 | // register a dataChange callback so that we can change the selection configuration dynamically
|
968 | 1027 | // if the user changes the options
|
969 |
| - var dataChangeDereg = $scope.grid.registerDataChangeCallback(function () { |
| 1028 | + var dataChangeUnreg = $scope.grid.registerDataChangeCallback(function () { |
970 | 1029 | if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
|
971 | 1030 | !$scope.registered) {
|
972 | 1031 | registerRowSelectionEvents();
|
973 | 1032 | } else if ((!$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection) &&
|
974 | 1033 | $scope.registered) {
|
975 |
| - deregisterRowSelectionEvents(); |
| 1034 | + unregisterRowSelectionEvents(); |
976 | 1035 | }
|
977 | 1036 | }, [uiGridConstants.dataChange.OPTIONS]);
|
978 | 1037 |
|
979 |
| - $elm.on('$destroy', dataChangeDereg); |
| 1038 | + $elm.on('$destroy', dataChangeUnreg); |
980 | 1039 | }
|
981 | 1040 | };
|
982 | 1041 | }]);
|
|
1014 | 1073 | }
|
1015 | 1074 | };
|
1016 | 1075 | }]);
|
1017 |
| - |
1018 | 1076 | })();
|
0 commit comments