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

Commit

Permalink
fix(menu): fix menus inside toolbars and dialogs
Browse files Browse the repository at this point in the history
fixes #6131, fixes #6109, fixes #6049, fixes #6073, references #6080,
fixes #6089, fixes #6116
  • Loading branch information
rschmukler committed Dec 8, 2015
1 parent 22a81ff commit 378248a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 23 deletions.
5 changes: 2 additions & 3 deletions src/components/menu/js/menuController.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r
// Default element for ARIA attributes has the ngClick or ngMouseenter expression
triggerElement = $element[0].querySelector('[ng-click],[ng-mouseenter]');

this.isInMenuBar = opts.isInMenuBar;
this.nestedMenus = $mdUtil.nodesToArray(menuContainer[0].querySelectorAll('.md-nested-menu'));

menuContainer.on('$mdInterimElementRemove', function() {
Expand Down Expand Up @@ -117,7 +118,7 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r
element: menuContainer,
target: triggerElement,
preserveElement: true,
parent: $element
parent: 'body'
}).finally(function() {
self.disableHoverListener();
});
Expand All @@ -128,14 +129,12 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r

$scope.$watch(function() { return self.isOpen; }, function(isOpen) {
if (isOpen) {
triggerElement.setAttribute('aria-expanded', 'true');
menuContainer.attr('aria-hidden', 'false');
$element[0].classList.add('md-open');
angular.forEach(self.nestedMenus, function(el) {
el.classList.remove('md-open');
});
} else {
triggerElement && triggerElement.setAttribute('aria-expanded', 'false');
menuContainer.attr('aria-hidden', 'true');
$element[0].classList.remove('md-open');
}
Expand Down
4 changes: 4 additions & 0 deletions src/components/menu/js/menuDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ function MenuDirective($mdUtil) {
}
menuContainer.append(menuContents);

element.on('$destroy', function() {
menuContainer.remove();
});

element.append(menuContainer);
menuContainer[0].style.display = 'none';
mdMenuCtrl.init(menuContainer, { isInMenuBar: isInMenuBar });
Expand Down
9 changes: 3 additions & 6 deletions src/components/menu/js/menuServiceProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,8 @@ function MenuProvider($$interimElementProvider) {
* Place the menu into the DOM and call positioning related functions
*/
function showMenu() {
if (!opts.preserveElement) {
opts.parent.append(element);
} else {
element[0].style.display = '';
}
opts.parent.append(element);
element[0].style.display = '';

return $q(function(resolve) {
var position = calculateMenuPosition(element, opts);
Expand Down Expand Up @@ -294,7 +291,7 @@ function MenuProvider($$interimElementProvider) {
if ((hasAnyAttribute(target, ['ng-click', 'ng-href', 'ui-sref']) ||
target.nodeName == 'BUTTON' || target.nodeName == 'MD-BUTTON') && !hasAnyAttribute(target, ['md-prevent-menu-close'])) {
var closestMenu = $mdUtil.getClosest(target, 'MD-MENU');
if (!target.hasAttribute('disabled') && (closestMenu == opts.parent[0])) {
if (!target.hasAttribute('disabled') && (!closestMenu || closestMenu == opts.parent[0])) {
close();
}
break;
Expand Down
46 changes: 32 additions & 14 deletions src/components/menu/menu.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
describe('material.components.menu', function() {
ddescribe('material.components.menu', function() {
var attachedElements = [];
var $mdMenu, $timeout, menuActionPerformed, $mdUtil;

Expand All @@ -7,7 +7,7 @@ describe('material.components.menu', function() {
$mdUtil = _$mdUtil_;
$mdMenu = _$mdMenu_;
$timeout = _$timeout_;
var abandonedMenus = $document[0].querySelectorAll('.md-menu-container');
var abandonedMenus = $document[0].querySelectorAll('.md-open-menu-container');
angular.element(abandonedMenus).remove();
}));
afterEach(function() {
Expand Down Expand Up @@ -41,6 +41,23 @@ describe('material.components.menu', function() {
expect(getOpenMenuContainer(menu).length).toBe(0);
});

it('cleans up an open menu when the element leaves the DOM', function() {
var menu = setup();
openMenu(menu);
menu.remove();
expect(getOpenMenuContainer(menu).length).toBe(0);
});

it('sets up proper aria-owns and aria-haspopup relations between the button and the container', function() {
var menu = setup();
var button = menu[0].querySelector('button');
expect(button.hasAttribute('aria-haspopup')).toBe(true);
expect(button.hasAttribute('aria-owns')).toBe(true);
var ownsId = button.getAttribute('aria-owns');
openMenu(menu);
expect(getOpenMenuContainer(menu).attr('id')).toBe(ownsId);
});

it('opens on click without $event', function() {
var noEvent = true;
var menu = setup('ng-click', noEvent);
Expand Down Expand Up @@ -98,7 +115,7 @@ describe('material.components.menu', function() {
openMenu(menu);
expect(getOpenMenuContainer(menu).length).toBe(1);

var openMenuEl = menu[0].querySelector('md-menu-content');
var openMenuEl = $document[0].querySelector('md-menu-content');

pressKey(openMenuEl, $mdConstant.KEY_CODE.ESCAPE);
waitForMenuClose();
Expand Down Expand Up @@ -197,21 +214,22 @@ describe('material.components.menu', function() {
// ********************************************

function getOpenMenuContainer(el) {
var res;
el = (el instanceof angular.element) ? el[0] : el;
var container = el.querySelector('.md-open-menu-container');
if (container.style.display == 'none') {
return angular.element([]);
} else {
return angular.element(container);
}
inject(function($document) {
var container = $document[0].querySelector('.md-open-menu-container');
if (container && container.style.display == 'none') {
res = [];
} else {
res = angular.element(container);
}
});
return res;
}

function openMenu(el, triggerType) {
inject(function($document) {
el.children().eq(0).triggerHandler(triggerType || 'click');
$document[0].body.appendChild(el[0]);
waitForMenuOpen();
});
el.children().eq(0).triggerHandler(triggerType || 'click');
waitForMenuOpen();
}

function closeMenu() {
Expand Down

0 comments on commit 378248a

Please sign in to comment.