Skip to content

Commit

Permalink
Merge pull request #5068 from dlgski/menuAlly
Browse files Browse the repository at this point in the history
Removed the X and Close on menu, and implemented-ESC and cyclical tabs
  • Loading branch information
swalters committed Feb 8, 2016
2 parents 83af4a2 + d10464e commit c28c448
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 43 deletions.
19 changes: 5 additions & 14 deletions src/js/core/directives/ui-grid-column-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function ( i18nService, uiGridConstants, gridUtil ) {
*
*/
setColMenuItemWatch: function ( $scope ){
var deregFunction = $scope.$watch('col.menuItems', function (n, o) {
var deregFunction = $scope.$watch('col.menuItems', function (n) {
if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {
n.forEach(function (item) {
if (typeof(item.context) === 'undefined' || !item.context) {
Expand Down Expand Up @@ -213,16 +213,6 @@ function ( i18nService, uiGridConstants, gridUtil ) {
$event.stopPropagation();
$scope.hideColumn();
}
},
{
title: i18nService.getSafeText('columnMenu.close'),
screenReaderOnly: true,
shown: function(){
return true;
},
action: function($event){
$event.stopPropagation();
}
}
];
},
Expand Down Expand Up @@ -275,8 +265,6 @@ function ( i18nService, uiGridConstants, gridUtil ) {
*/
repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {
var menu = $elm[0].querySelectorAll('.ui-grid-menu');
var containerId = column.renderContainer ? column.renderContainer : 'body';
var renderContainer = column.grid.renderContainers[containerId];

// It's possible that the render container of the column we're attaching to is
// offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft
Expand Down Expand Up @@ -379,6 +367,7 @@ function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $documen
$scope.colElement = $columnElement;
$scope.colElementPosition = colElementPosition;
$scope.$broadcast('show-menu', { originalEvent: event });

}
};

Expand Down Expand Up @@ -421,6 +410,8 @@ function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $documen
$scope.$on('menu-shown', function() {
$timeout( function() {
uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
//Focus on the first item
gridUtil.focus.bySelector($document, '.ui-grid-menu-items .ui-grid-menu-item', true);
delete $scope.colElementPosition;
delete $scope.columnElement;
}, 200);
Expand Down Expand Up @@ -516,7 +507,7 @@ function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $documen
controller: ['$scope', function ($scope) {
var self = this;

$scope.$watch('menuItems', function (n, o) {
$scope.$watch('menuItems', function (n) {
self.menuItems = n;
});
}]
Expand Down
58 changes: 41 additions & 17 deletions src/js/core/directives/ui-grid-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18
templateUrl: 'ui-grid/uiGridMenu',
replace: false,
link: function ($scope, $elm, $attrs, uiGridCtrl) {
var menuMid;
var $animate;
var gridMenuMaxHeight;

$scope.dynamicStyles = '';
Expand Down Expand Up @@ -99,17 +97,22 @@ 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);

});
//automatically set the focus to the first button element in the now open menu.
gridUtil.focus.bySelector($elm, 'button[type=button]', true);
};


$scope.hideMenu = function(event, args) {
$scope.hideMenu = function(event) {
if ( $scope.shown ){
/*
* In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to
Expand All @@ -129,6 +132,8 @@ 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) {
Expand All @@ -149,6 +154,34 @@ 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) {
var setFocus = function(elm) {
elm.focus();
event.preventDefault();
return false;
};
if (event.keyCode === 9) {
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) {
setFocus(firstMenuItem);
} else if (event.target === firstMenuItem && event.shiftKey) {
setFocus(lastMenuItem);
}
}
}
};

if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
$scope.autoHide = true;
}
Expand All @@ -171,12 +204,7 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18
}

$scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));
},


controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
var self = this;
}]
}
};

return uiGridMenu;
Expand All @@ -196,15 +224,12 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18
leaveOpen: '=',
screenReaderOnly: '='
},
require: ['?^uiGrid', '^uiGridMenu'],
require: ['?^uiGrid'],
templateUrl: 'ui-grid/uiGridMenuItem',
replace: false,
compile: function($elm, $attrs) {
compile: function() {
return {
pre: function ($scope, $elm, $attrs, controllers) {
var uiGridCtrl = controllers[0],
uiGridMenuCtrl = controllers[1];

pre: function ($scope, $elm) {
if ($scope.templateUrl) {
gridUtil.getTemplate($scope.templateUrl)
.then(function (contents) {
Expand All @@ -216,8 +241,7 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18
}
},
post: function ($scope, $elm, $attrs, controllers) {
var uiGridCtrl = controllers[0],
uiGridMenuCtrl = controllers[1];
var uiGridCtrl = controllers[0];

// TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
// if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
Expand Down
11 changes: 0 additions & 11 deletions src/templates/ui-grid/uiGridMenu.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,6 @@
ng-show="shownMid">
<div
class="ui-grid-menu-inner">
<button
type="button"
ng-focus="focus=true"
ng-blur="focus=false"
class="ui-grid-menu-close-button"
ng-class="{'ui-grid-sr-only': (!focus)}">
<i
class="ui-grid-icon-cancel"
ui-grid-one-bind-aria-label="i18n.close">
</i>
</button>
<ul
role="menu"
class="ui-grid-menu-items">
Expand Down
33 changes: 32 additions & 1 deletion test/unit/core/directives/ui-grid-menu.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,35 @@ describe('ui-grid-menu', function() {
expect(item.hasClass('ng-hide')).toBe(false);
});
});
});


describe('keyUp and keyDown actions', function() {
var timeout, menuItemButtons;
beforeEach( function() {
inject(function ($timeout) {
timeout = $timeout;
});
$scope.$broadcast('show-menu');
$scope.$digest();
timeout.flush();
});

it('should focus on the first menu item after tabbing from the last menu item', function() {
menuItemButtons = menu.find('button');
var e = $.Event("keydown");
e.keyCode = 9;
spyOn(menuItemButtons[0],'focus');
//mock has 4 items, last one his hidden
$(menuItemButtons[2]).trigger(e);
expect(menuItemButtons[0].focus).toHaveBeenCalled();
});

it('should call hideMenu if ESC is pressed', function() {
spyOn(isolateScope, 'hideMenu');
var e = $.Event("keyup");
e.keyCode = 27;
$(menu).trigger(e);
expect(isolateScope.hideMenu).toHaveBeenCalled();
});
});
});

0 comments on commit c28c448

Please sign in to comment.