Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
fix(menuBar): Fix hovering consecutive nested menus.
Browse files Browse the repository at this point in the history
Fix issue where hovering two consecutive nested menus would not
properly open the second nested menu.

Also adds a test and fixes an issue where the focusMenu() method
of the menu bar controller would not focus the first menu if none
was already selected.

Fixes #6685.

  Closes #7361
  • Loading branch information
topherfangio authored and ThomasBurleson committed Mar 2, 2016
1 parent 035626b commit 4bdda21
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/components/menu/js/menuController.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r
if (self.currentlyOpenMenu && self.currentlyOpenMenu != nestedMenu) {
var closeTo = self.nestLevel + 1;
self.currentlyOpenMenu.close(true, { closeTo: closeTo });
self.isAlreadyOpening = true;
nestedMenu.open();
} else if (nestedMenu && !nestedMenu.isOpen && nestedMenu.open) {
self.isAlreadyOpening = true;
nestedMenu.open();
Expand Down
2 changes: 1 addition & 1 deletion src/components/menuBar/js/menuBarController.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ MenuBarController.prototype.focusMenu = function(direction) {

var changed = false;

if (focusedIndex == -1) { focusedIndex = 0; }
if (focusedIndex == -1) { focusedIndex = 0; changed = true; }
else if (
direction < 0 && focusedIndex > 0 ||
direction > 0 && focusedIndex < menus.length - direction
Expand Down
113 changes: 111 additions & 2 deletions src/components/menuBar/menu-bar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('material.components.menuBar', function() {
it('sets md-position-mode to "bottom left" on nested menus', function() {
var menuBar = setup();
var nestedMenu = menuBar[0].querySelector('md-menu');

expect(nestedMenu.getAttribute('md-position-mode')).toBe('left bottom');
});

Expand All @@ -25,6 +26,92 @@ describe('material.components.menuBar', function() {
expect(ariaRole).toBe('menubar');
});
});

describe('nested menus', function() {
var menuBar, menus, subMenuOpen, ctrl;

it('opens consecutive nested menus', function() {
menuBar = setup();
ctrl = menuBar.controller('mdMenuBar');
menus = menuBar[0].querySelectorAll('md-menu md-menu');

angular.element(document.body).append(menuBar);

// Open the menu-bar menu
ctrl.focusMenu(1);
ctrl.openFocusedMenu();
waitForMenuOpen();

// Open the first nested menu
openSubMenu(0);
waitForMenuOpen();
expect(getOpenSubMenu().text().trim()).toBe('Sub 1 - Content');

// Open the second nested menu, the first menu should close
openSubMenu(1);
waitForMenuClose();

// Then the second menu should become visible
waitForMenuOpen();
expect(getOpenSubMenu().text().trim()).toBe('Sub 2 - Content');

menuBar.remove();
});

function openSubMenu(index) {
// If a menu is already open, trigger the mouse leave to close it
if (subMenuOpen) {
subMenuOpen.triggerHandler({
type: 'mouseleave',
target: subMenuOpen[0],
currentTarget: subMenuOpen[0]
});
}

// Set the currently open sub-menu and trigger the mouse enter
subMenuOpen = angular.element(menus[index]);
subMenuOpen.triggerHandler({
type: 'mouseenter',
target: subMenuOpen[0],
currentTarget: subMenuOpen[0]
});
}

function getOpenSubMenu() {
debugger;
var containers = document.body.querySelectorAll('._md-open-menu-container._md-active');
var lastContainer = containers.item(containers.length - 1);

return angular.element(lastContainer.querySelector('md-menu-content'));
}

function setup(){
var el;
inject(function($compile, $rootScope) {
el = $compile([
'<md-menu-bar>',
' <md-menu>',
' <md-menu-item>',
' <button ng-click="clicked=true">Button {{i}}</button>',
' </md-menu-item>',
' <md-menu-content class="test-submenu">',
' <md-menu ng-repeat="i in [1, 2]">',
' <md-menu-item>',
' <button ng-click="subclicked=true">Sub Button{{i}}</button>',
' </md-menu-item>',
' <md-menu-content>Sub {{i}} - Content</md-menu-content>',
' </md-menu>',
' </md-menu-content>',
' </md-menu>',
'</md-menu-bar>'
].join(''))($rootScope);
$rootScope.$digest();
});
attachedMenuElements.push(el);

return el;
}
});
});

describe('MenuBarCtrl', function() {
Expand Down Expand Up @@ -64,6 +151,13 @@ describe('material.components.menuBar', function() {
describe('#focusMenu', function() {
var focused;
beforeEach(function() { focused = false; });
it('focuses the first menu if none is focused', function() {
var menus = mockButtonAtIndex(0);
spyOn(ctrl, 'getFocusedMenuIndex').and.returnValue(-1);
spyOn(ctrl, 'getMenus').and.returnValue(menus);
ctrl.focusMenu(1);
expect(focused).toBe(true);
});
it('focuses the next menu', function() {
var menus = mockButtonAtIndex(1);
spyOn(ctrl, 'getFocusedMenuIndex').and.returnValue(0);
Expand Down Expand Up @@ -100,13 +194,16 @@ describe('material.components.menuBar', function() {
var mockButton = {
querySelector: function() { return {
focus: function() { focused = true; }
}; }
}; },

// TODO: This may need to become more complex if more of the tests use it
classList: { contains: function() { return false; } }
};
for (var i = 0; i < 3; ++i) {
if (i == index) {
result.push(mockButton);
} else {
result.push({});
result.push({ classList: mockButton.classList });
}
}
return result;
Expand Down Expand Up @@ -307,5 +404,17 @@ describe('material.components.menuBar', function() {
}
});
});

function waitForMenuOpen() {
inject(function($material) {
$material.flushInterimElement();
});
}

function waitForMenuClose() {
inject(function($material) {
$material.flushInterimElement();
});
}
});

0 comments on commit 4bdda21

Please sign in to comment.