From b9315cb150ac4555890d5dee5b4c3a9c8f90c089 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Mon, 16 May 2016 13:20:05 +0200 Subject: [PATCH] feat(menu): add support for md-autofocus attribute * Currently, the most common components are supporting `md-autofocus`, except the `$mdMenu` component. `md-menu` did only support `md-menu-focus-target`, which was a unclear and undocumented attribute. * This commit adds support for the `md-autofocus` directive, to be consistent with the whole API. It also adds a documentation for the focus behavior in `md-menu`. Closes #7868. --- src/components/menu/js/menuController.js | 2 +- src/components/menu/js/menuDirective.js | 17 +++++++- src/components/menu/js/menuServiceProvider.js | 2 +- src/components/menu/menu.spec.js | 42 +++++++++++++++++++ src/core/util/autofocus.js | 2 +- 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/components/menu/js/menuController.js b/src/components/menu/js/menuController.js index fa821e421e..057c6e8e92 100644 --- a/src/components/menu/js/menuController.js +++ b/src/components/menu/js/menuController.js @@ -153,7 +153,7 @@ function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $r }; this.focusMenuContainer = function focusMenuContainer() { - var focusTarget = menuContainer[0].querySelector('[md-menu-focus-target]'); + var focusTarget = menuContainer[0].querySelector('[md-menu-focus-target], [md-autofocus]'); if (!focusTarget) focusTarget = menuContainer[0].querySelector('.md-button'); focusTarget.focus(); }; diff --git a/src/components/menu/js/menuDirective.js b/src/components/menu/js/menuDirective.js index 4474abb10d..bd9a33ffaa 100644 --- a/src/components/menu/js/menuDirective.js +++ b/src/components/menu/js/menuDirective.js @@ -102,7 +102,22 @@ * * * - + * + * ### Auto Focus + * By default, when a menu opens, `md-menu` focuses the first button in the menu content. + * + * But sometimes you would like to focus another specific menu item instead of the first.
+ * This can be done by applying the `md-autofocus` directive on the given element. + * + * + * + * + * Auto Focus + * + * + * + * + * * ### Preventing close * * Sometimes you would like to be able to click on a menu item without having the menu diff --git a/src/components/menu/js/menuServiceProvider.js b/src/components/menu/js/menuServiceProvider.js index a33dd39de4..73fbf2aecb 100644 --- a/src/components/menu/js/menuServiceProvider.js +++ b/src/components/menu/js/menuServiceProvider.js @@ -210,7 +210,7 @@ function MenuProvider($$interimElementProvider) { opts.menuContentEl[0].addEventListener('click', captureClickListener, true); // kick off initial focus in the menu on the first element - var focusTarget = opts.menuContentEl[0].querySelector('[md-menu-focus-target]'); + var focusTarget = opts.menuContentEl[0].querySelector('[md-menu-focus-target], [md-autofocus]'); if ( !focusTarget ) { var firstChild = opts.menuContentEl[0].firstElementChild; diff --git a/src/components/menu/menu.spec.js b/src/components/menu/menu.spec.js index 0bd72dc559..2f61f835b8 100644 --- a/src/components/menu/menu.spec.js +++ b/src/components/menu/menu.spec.js @@ -141,6 +141,48 @@ describe('material.components.menu', function() { expect(getOpenMenuContainer(menu).length).toBe(0); })); + describe('autofocus', function() { + + it('should focus a button with md-menu-focus-target', inject(function($compile, $rootScope, $document) { + var menu = $compile( + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + )($rootScope); + + openMenu(menu); + + var menuTarget = $document[0].querySelector('#menuFocus'); + + expect(document.activeElement).toBe(menuTarget); + })); + + it('should focus a button with md-autofocus', inject(function($compile, $rootScope, $document) { + var menu = $compile( + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + )($rootScope); + + openMenu(menu); + + var menuTarget = $document[0].querySelector('#menuFocus'); + + expect(document.activeElement).toBe(menuTarget); + })); + + }); + describe('closes with -', function() { it('closes on normal option click', function() { diff --git a/src/core/util/autofocus.js b/src/core/util/autofocus.js index d87484c5b8..784cbdd5cf 100644 --- a/src/core/util/autofocus.js +++ b/src/core/util/autofocus.js @@ -13,7 +13,7 @@ angular.module('material.core') * @description * * `[md-autofocus]` provides an optional way to identify the focused element when a `$mdDialog`, - * `$mdBottomSheet`, or `$mdSidenav` opens or upon page load for input-like elements. + * `$mdBottomSheet`, `$mdMenu` or `$mdSidenav` opens or upon page load for input-like elements. * * When one of these opens, it will find the first nested element with the `[md-autofocus]` * attribute directive and optional expression. An expression may be specified as the directive