From f4d3e222965d91a7faf0f4886ad6d4906789df9e Mon Sep 17 00:00:00 2001 From: "Khoury, Marc" Date: Wed, 9 Jun 2021 10:01:53 -0400 Subject: [PATCH 1/5] fix(core): use allowFloatWidth property to allow float calculations for width --- packages/core/src/js/factories/GridColumn.js | 12 ++++++++++++ .../src/js/factories/GridRenderContainer.js | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/core/src/js/factories/GridColumn.js b/packages/core/src/js/factories/GridColumn.js index b6bcd15d7e..e8d88f14ed 100644 --- a/packages/core/src/js/factories/GridColumn.js +++ b/packages/core/src/js/factories/GridColumn.js @@ -258,6 +258,18 @@ angular.module('ui.grid') * */ + /** + * @ngdoc property + * @name allowFloatWidth + * @propertyOf ui.grid.class:GridOptions.columnDef + * @description Allows float number in column width calculation + * @example + *
  $scope.gridOptions.columnDefs = [ { field: 'field1', width: 50.5, allowFloatWidth: true},
+   *                                          { field: 'field2', width: '20%', allowFloatWidth: true},
+   *                                          { field: 'field3', width: '*', allowFloatWidth: true }]; 
+ * + */ + /** * @ngdoc property * @name minWidth diff --git a/packages/core/src/js/factories/GridRenderContainer.js b/packages/core/src/js/factories/GridRenderContainer.js index 8bfa75df56..0ef62561d1 100644 --- a/packages/core/src/js/factories/GridRenderContainer.js +++ b/packages/core/src/js/factories/GridRenderContainer.js @@ -606,7 +606,12 @@ angular.module('ui.grid') if (angular.isNumber(column.width)) { // pixel width, set to this value - width = parseInt(column.width, 10); + if(column.colDef.allowFloatWidth) { + width = parseFloat(column.width); + } else { + width = parseInt(column.width, 10); + } + usedWidthSum = usedWidthSum + width; column.drawnWidth = width; @@ -615,7 +620,12 @@ angular.module('ui.grid') // percentage width, set to percentage of the viewport // round down to int - some browsers don't play nice with float maxWidth var percentageIntegerValue = parseInt(column.width.replace(/%/g, ''), 10); - width = parseInt(percentageIntegerValue / 100 * availableWidth); + if(column.colDef.allowFloatWidth) { + width = parseFloat(percentageIntegerValue / 100 * availableWidth); + } else { + width = parseInt(percentageIntegerValue / 100 * availableWidth, 10); + } + if (width > column.maxWidth) { width = column.maxWidth; @@ -647,6 +657,11 @@ angular.module('ui.grid') asterisksArray.forEach(function (column) { var width = parseInt(column.width.length * asteriskVal, 10); + if(column.colDef.allowFloatWidth) { + width = parseFloat(column.width.length * asteriskVal); + } + + if (width > column.maxWidth) { width = column.maxWidth; } From bb28b2fb523f5e47aa61a80bf70e4aabc49ab1e7 Mon Sep 17 00:00:00 2001 From: "Khoury, Marc" Date: Wed, 9 Jun 2021 10:09:20 -0400 Subject: [PATCH 2/5] fix(core): use allowFloatWidth property to allow float calculations for width --- packages/core/src/js/factories/GridRenderContainer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/js/factories/GridRenderContainer.js b/packages/core/src/js/factories/GridRenderContainer.js index 0ef62561d1..8204dc591e 100644 --- a/packages/core/src/js/factories/GridRenderContainer.js +++ b/packages/core/src/js/factories/GridRenderContainer.js @@ -606,7 +606,7 @@ angular.module('ui.grid') if (angular.isNumber(column.width)) { // pixel width, set to this value - if(column.colDef.allowFloatWidth) { + if (column.colDef.allowFloatWidth) { width = parseFloat(column.width); } else { width = parseInt(column.width, 10); @@ -620,7 +620,7 @@ angular.module('ui.grid') // percentage width, set to percentage of the viewport // round down to int - some browsers don't play nice with float maxWidth var percentageIntegerValue = parseInt(column.width.replace(/%/g, ''), 10); - if(column.colDef.allowFloatWidth) { + if (column.colDef.allowFloatWidth) { width = parseFloat(percentageIntegerValue / 100 * availableWidth); } else { width = parseInt(percentageIntegerValue / 100 * availableWidth, 10); @@ -657,7 +657,7 @@ angular.module('ui.grid') asterisksArray.forEach(function (column) { var width = parseInt(column.width.length * asteriskVal, 10); - if(column.colDef.allowFloatWidth) { + if (column.colDef.allowFloatWidth) { width = parseFloat(column.width.length * asteriskVal); } From e5ae7c085f4ac314dfbd4fab15b24f20730ee5cd Mon Sep 17 00:00:00 2001 From: Marcelo Portugal Date: Fri, 11 Jun 2021 16:05:45 -0400 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=F0=9F=90=9B=20improve=20accessibili?= =?UTF-8?q?ty=20in=20the=20grid=20menus=20and=20selection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add more keyboard handling and better announcements for checkboxes and menus --- packages/cellnav/src/js/cellnav.js | 11 +++--- .../src/js/directives/ui-grid-column-menu.js | 9 +++++ .../src/js/directives/ui-grid-header-cell.js | 29 +++++----------- .../src/js/directives/ui-grid-menu-button.js | 10 ++++++ .../core/src/js/directives/ui-grid-menu.js | 26 ++++---------- packages/core/src/js/en.js | 6 +++- packages/core/src/js/factories/GridRow.js | 8 +++++ .../ui-grid/ui-grid-menu-button.html | 4 +++ .../templates/ui-grid/uiGridHeaderCell.html | 1 + .../src/templates/ui-grid/uiGridMenu.html | 1 + .../directives/ui-grid-column-menu.spec.js | 4 +++ .../directives/ui-grid-header-cell.spec.js | 11 ++---- .../directives/ui-grid-menu-button.spec.js | 34 +++++++++++++++++++ .../test/core/directives/ui-grid-menu.spec.js | 29 ++++++++++------ .../core/test/core/factories/GridRow.spec.js | 28 ++++++--------- packages/selection/src/js/selection.js | 6 ++-- .../templates/selectionRowHeaderButtons.html | 2 ++ .../test/uiGridSelectionDirective.spec.js | 10 ++++-- 18 files changed, 140 insertions(+), 89 deletions(-) diff --git a/packages/cellnav/src/js/cellnav.js b/packages/cellnav/src/js/cellnav.js index ae9fd2dc23..e728307e27 100644 --- a/packages/cellnav/src/js/cellnav.js +++ b/packages/cellnav/src/js/cellnav.js @@ -830,15 +830,16 @@ } function getCellDisplayValue(currentRowColumn) { + var prefix = ''; + if (currentRowColumn.col.field === 'selectionRowHeaderCol') { // This is the case when the 'selection' feature is used in the grid and the user has moved // to or inside of the left grid container which holds the checkboxes for selecting rows. // This is necessary for Accessibility. Without this a screen reader cannot determine if the row // is or is not currently selected. - return currentRowColumn.row.isSelected ? i18nService.getSafeText('search.aria.selected') : i18nService.getSafeText('search.aria.notSelected'); - } else { - return grid.getCellDisplayValue(currentRowColumn.row, currentRowColumn.col); + prefix = (currentRowColumn.row.isSelected ? i18nService.getSafeText('search.aria.selected') : i18nService.getSafeText('search.aria.notSelected')) + ', '; } + return prefix + grid.getCellDisplayValue(currentRowColumn.row, currentRowColumn.col); } var values = []; @@ -847,9 +848,7 @@ var cellDisplayValue = getCellDisplayValue(currentSelection[i]) + getAppendedColumnHeaderText(currentSelection[i].col); values.push(cellDisplayValue); } - var cellText = values.toString(); - setNotifyText(cellText); - + setNotifyText(values.toString()); }); } // Only add the ngAria stuff it will be used diff --git a/packages/core/src/js/directives/ui-grid-column-menu.js b/packages/core/src/js/directives/ui-grid-column-menu.js index adf72ba5a4..ee6eadc93a 100644 --- a/packages/core/src/js/directives/ui-grid-column-menu.js +++ b/packages/core/src/js/directives/ui-grid-column-menu.js @@ -310,6 +310,11 @@ function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $documen $scope.menuItems = $scope.defaultMenuItems; uiGridColumnMenuService.setColMenuItemWatch( $scope ); + function updateCurrentColStatus(menuShown) { + if ($scope.col) { + $scope.col.menuShown = menuShown; + } + } /** * @ngdoc method @@ -324,8 +329,11 @@ function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $documen * @param {element} $columnElement the column element we want to position below */ $scope.showMenu = function(column, $columnElement, event) { + // Update the menu status for the current column + updateCurrentColStatus(false); // Swap to this column $scope.col = column; + updateCurrentColStatus(true); // Get the position information for the column element var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement ); @@ -359,6 +367,7 @@ function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $documen */ $scope.hideMenu = function( broadcastTrigger ) { $scope.menuShown = false; + updateCurrentColStatus(false); if ( !broadcastTrigger ) { $scope.$broadcast('hide-menu'); } diff --git a/packages/core/src/js/directives/ui-grid-header-cell.js b/packages/core/src/js/directives/ui-grid-header-cell.js index d89c8f109e..b4add0f4b9 100644 --- a/packages/core/src/js/directives/ui-grid-header-cell.js +++ b/packages/core/src/js/directives/ui-grid-header-cell.js @@ -69,6 +69,7 @@ // Hide the menu by default $scope.menuShown = false; + $scope.col.menuShown = false; // Put asc and desc sort directions in scope $scope.asc = uiGridConstants.ASC; @@ -347,13 +348,8 @@ $scope.handleClick = function(event) { // If the shift key is being held down, add this column to the sort - var add = false; - if (event.shiftKey) { - add = true; - } - // Sort this column then rebuild the grid's rows - uiGridCtrl.grid.sortColumn($scope.col, add) + uiGridCtrl.grid.sortColumn($scope.col, event.shiftKey) .then(function () { if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); } uiGridCtrl.grid.refresh(); @@ -361,30 +357,21 @@ }; $scope.headerCellArrowKeyDown = function(event) { - if (event.keyCode === 32 || event.keyCode === 13) { + if (event.keyCode === uiGridConstants.keymap.SPACE || event.keyCode === uiGridConstants.keymap.ENTER) { event.preventDefault(); $scope.toggleMenu(event); } }; $scope.toggleMenu = function(event) { - event.stopPropagation(); - // If the menu is already showing... - if (uiGridCtrl.columnMenuScope.menuShown) { - // ... and we're the column the menu is on... - if (uiGridCtrl.columnMenuScope.col === $scope.col) { - // ... hide it - uiGridCtrl.columnMenuScope.hideMenu(); - } - // ... and we're NOT the column the menu is on - else { - // ... move the menu to our column - uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm); - } + // If the menu is already showing and we're the column the menu is on + if (uiGridCtrl.columnMenuScope.menuShown && uiGridCtrl.columnMenuScope.col === $scope.col) { + // ... hide it + uiGridCtrl.columnMenuScope.hideMenu(); } - // If the menu is NOT showing + // If the menu is NOT showing or is showing in a different column else { // ... show it on our column uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm); diff --git a/packages/core/src/js/directives/ui-grid-menu-button.js b/packages/core/src/js/directives/ui-grid-menu-button.js index f7369e6baa..25f38c9204 100644 --- a/packages/core/src/js/directives/ui-grid-menu-button.js +++ b/packages/core/src/js/directives/ui-grid-menu-button.js @@ -376,6 +376,16 @@ function (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) { $scope.shown = false; + $scope.toggleOnKeydown = function(event) { + if ( + event.keyCode === uiGridConstants.keymap.ENTER || + event.keyCode === uiGridConstants.keymap.SPACE || + (event.keyCode === uiGridConstants.keymap.ESC && $scope.shown) + ) { + $scope.toggleMenu(); + } + }; + $scope.toggleMenu = function () { if ( $scope.shown ) { $scope.$broadcast('hide-menu'); diff --git a/packages/core/src/js/directives/ui-grid-menu.js b/packages/core/src/js/directives/ui-grid-menu.js index d3bd328a77..382f90bde7 100644 --- a/packages/core/src/js/directives/ui-grid-menu.js +++ b/packages/core/src/js/directives/ui-grid-menu.js @@ -112,14 +112,10 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18 // Turn off an existing document click handler angular.element(document).off('click touchstart', applyHideMenu); - $elm.off('keyup', checkKeyUp); - $elm.off('keydown', checkKeyDown); // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one $timeout(function() { angular.element(document).on(docEventType, applyHideMenu); - $elm.on('keyup', checkKeyUp); - $elm.on('keydown', checkKeyDown); }); }; @@ -144,8 +140,6 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18 } angular.element(document).off('click touchstart', applyHideMenu); - $elm.off('keyup', checkKeyUp); - $elm.off('keydown', checkKeyDown); }; $scope.$on('hide-menu', function (event, args) { @@ -173,28 +167,22 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18 } }; - // close menu on ESC and keep tab cyclical - var checkKeyUp = function(event) { - if (event.keyCode === 27) { - $scope.hideMenu(); - } - }; - - var checkKeyDown = function(event) { + $scope.checkKeyDown = function(event) { var setFocus = function(elm) { elm.focus(); event.preventDefault(); - return false; }; - if (event.keyCode === 9) { + if (event.keyCode === uiGridConstants.keymap.ESC) { + $scope.hideMenu(); + } else if (event.keyCode === uiGridConstants.keymap.TAB) { var firstMenuItem, lastMenuItem; var menuItemButtons = $elm[0].querySelectorAll('button:not(.ng-hide)'); if (menuItemButtons.length > 0) { firstMenuItem = menuItemButtons[0]; lastMenuItem = menuItemButtons[menuItemButtons.length - 1]; - if (event.target === lastMenuItem && !event.shiftKey) { + if (event.target.parentElement.id === lastMenuItem.parentElement.id && !event.shiftKey) { setFocus(firstMenuItem); - } else if (event.target === firstMenuItem && event.shiftKey) { + } else if (event.target.parentElement.id === firstMenuItem.parentElement.id && event.shiftKey) { setFocus(lastMenuItem); } } @@ -212,8 +200,6 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18 $scope.$on('$destroy', function unbindEvents() { angular.element($window).off('resize', applyHideMenu); angular.element(document).off('click touchstart', applyHideMenu); - $elm.off('keyup', checkKeyUp); - $elm.off('keydown', checkKeyDown); }); if (uiGridCtrl) { diff --git a/packages/core/src/js/en.js b/packages/core/src/js/en.js index b2bdb8b9f9..c9442dd4fe 100644 --- a/packages/core/src/js/en.js +++ b/packages/core/src/js/en.js @@ -37,7 +37,11 @@ last: 'Last Page' }, selection: { - selectAll: 'Select All' + aria: { + row: 'Row' + }, + selectAll: 'Select All', + displayName: 'Row Selection Checkbox' }, menu: { text: 'Choose Columns:' diff --git a/packages/core/src/js/factories/GridRow.js b/packages/core/src/js/factories/GridRow.js index 4178001712..1ea86dbfe5 100644 --- a/packages/core/src/js/factories/GridRow.js +++ b/packages/core/src/js/factories/GridRow.js @@ -31,6 +31,14 @@ angular.module('ui.grid') */ this.entity = entity; + /** + * @ngdoc object + * @name index + * @propertyOf ui.grid.class:GridRow + * @description The current position of the row in the array + */ + this.index = index; + /** * @ngdoc object * @name uid diff --git a/packages/core/src/templates/ui-grid/ui-grid-menu-button.html b/packages/core/src/templates/ui-grid/ui-grid-menu-button.html index 2a548e3963..8d1cf28856 100644 --- a/packages/core/src/templates/ui-grid/ui-grid-menu-button.html +++ b/packages/core/src/templates/ui-grid/ui-grid-menu-button.html @@ -1,8 +1,12 @@
  diff --git a/packages/core/src/templates/ui-grid/uiGridHeaderCell.html b/packages/core/src/templates/ui-grid/uiGridHeaderCell.html index 7b44fb00d4..00067d46c6 100644 --- a/packages/core/src/templates/ui-grid/uiGridHeaderCell.html +++ b/packages/core/src/templates/ui-grid/uiGridHeaderCell.html @@ -38,6 +38,7 @@ ng-click="toggleMenu($event)" ng-keydown="headerCellArrowKeyDown($event)" ui-grid-one-bind-aria-label="i18n.headerCell.aria.columnMenuButtonLabel" + aria-expanded="{{col.menuShown}}" aria-haspopup="true">