Skip to content

Commit b257282

Browse files
author
Mykhailo Miroshnikov
committed
MAGETWO-34476: Backend Menu JS improvements
- Fix aria-expanded toggling - Fix menu keyboard navigation - Refactor globalNavigation widget
1 parent ea19ec2 commit b257282

File tree

3 files changed

+66
-78
lines changed
  • app

3 files changed

+66
-78
lines changed

app/code/Magento/Backend/Block/Menu.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ protected function _addSubMenu($menuItem, $level, $limit)
410410
if ($level == 0 && $limit) {
411411
$colStops = $this->_columnBrake($menuItem->getChildren(), $limit);
412412
$output .= '<strong class="submenu-title">' . $this->_getAnchorLabel($menuItem) . '</strong>';
413-
$output .= '<button class="submenu-close _close"></button>';
413+
$output .= '<a href="#" class="submenu-close _close" data-role="close-submenu"></a>';
414414
}
415415

416416
$output .= $this->renderNavigation($menuItem->getChildren(), $level + 1, $limit, $colStops);

app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@
280280
.transition(color);
281281
}
282282
&:hover {
283+
cursor: pointer;
284+
text-decoration: none;
283285
&:before {
284286
color: @color-white;
285287
}

app/design/adminhtml/Magento/backend/web/js/theme.js

Lines changed: 63 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,134 +5,120 @@
55

66
define('globalNavigation', [
77
'jquery',
8-
'jquery/ui',
9-
'jquery/hover-intent'
8+
'jquery/ui'
109
], function ($) {
1110
'use strict';
1211

1312
$.widget('mage.globalNavigation', {
1413
options: {
15-
menuCategory: '.level-0',
16-
menuLinks: 'a',
17-
itemsConfig: null,
18-
hoverIntentConfig: {
19-
interval: 100,
20-
timeout: 500 // number = milliseconds delay before onMouseOut
14+
selectors: {
15+
topLevelItem: '.level-0',
16+
topLevelHref: '> a',
17+
subMenu: '> .submenu',
18+
closeSubmenuBtn: '[data-role="close-submenu"]'
2119
},
22-
overlayClass: 'admin__menu-overlay',
23-
categoriesConfig: {
24-
'li': {
25-
open: 'click'
26-
}
27-
}
20+
overlayTmpl: '<div class="admin__menu-overlay"></div>'
2821
},
2922

3023
_create: function () {
31-
this.menu = this.element;
32-
this.menuCategory = $(this.options.menuCategory, this.menu);
33-
this.menuLinks = $(this.options.menuLinks, this.menuCategory);
24+
var selectors = this.options.selectors;
3425

35-
this._addOverlay();
26+
this.menu = this.element;
27+
this.menuLinks = $(selectors.topLevelHref, selectors.topLevelItem);
3628

37-
this._bind();
29+
this._initOverlay()
30+
._bind();
3831
},
3932

40-
_addOverlay: function () {
33+
_initOverlay: function () {
4134
var wrapper = $('<div />').addClass('admin__scope');
4235

43-
this.overlay = $('<div />')
44-
.addClass(this.options.overlayClass)
45-
.appendTo('body')
46-
.hide(0);
36+
this.overlay = $(this.options.overlayTmpl).appendTo('body').hide(0);
4737

4838
/**
4939
* @todo fix LESS and remove next line and wrapper definition
5040
*/
5141
this.overlay.wrap(wrapper);
42+
43+
return this;
5244
},
5345

54-
_menuCategoryBind: function (category, config) {
55-
var open = this._open.bind(this);
46+
_bind: function () {
47+
var lighten = this._lighten.bind(this),
48+
open = this._open.bind(this),
49+
darken = this._darken.bind(this);
5650

57-
if (config.open) {
58-
$('> a', category).on(config.open, open);
59-
}
51+
this.menuLinks
52+
.on('focus', lighten)
53+
.on('click', open)
54+
.on('blur', darken);
6055
},
6156

62-
_menuCategoryEvents: function () {
63-
this.menuCategory.each($.proxy(function (i, category) {
64-
var itemConfig = {};
65-
66-
if (this.options.categoriesConfig) {
67-
$.each(this.options.categoriesConfig, $.proxy(function (selector, conf) {
68-
if ($(category).is(selector)) {
69-
itemConfig = conf;
70-
}
71-
}, this));
72-
}
73-
this._menuCategoryBind($(category), itemConfig);
74-
}, this));
57+
_lighten: function (e) {
58+
var selectors = this.options.selectors,
59+
menuItem = $(e.target).closest(selectors.topLevelItem);
60+
61+
menuItem
62+
.addClass('_active')
63+
.siblings(selectors.topLevelItem)
64+
.removeClass('_active');
7565
},
7666

77-
_bind: function () {
78-
this._menuCategoryEvents();
79-
this.menuLinks
80-
.on('focus.tabFocus', function (e) {
81-
$(e.target).trigger('mouseenter');
82-
})
83-
.on('blur.tabFocus', function (e) {
84-
$(e.target).trigger('mouseleave');
85-
});
67+
_darken: function (e) {
68+
var selectors = this.options.selectors,
69+
menuItem = $(e.target).closest(selectors.topLevelItem);
8670

87-
this.menuCategory.on('focus', 'a', this._open.bind(this));
71+
menuItem.removeClass('_active');
72+
},
73+
74+
_closeSubmenu: function (e) {
75+
var selectors = this.options.selectors,
76+
menuItem = $(e.target).closest(selectors.topLevelItem);
77+
78+
this._close(e);
79+
80+
$(selectors.topLevelHref, menuItem).focus();
8881
},
8982

9083
_open: function (e) {
91-
var menuItem = $(e.target).closest('.level-0'),
92-
subMenu = $('> .submenu', menuItem);
84+
var selectors = this.options.selectors,
85+
menuItemSelector = selectors.topLevelItem,
86+
menuItem = $(e.target).closest(menuItemSelector),
87+
subMenu = $(selectors.subMenu, menuItem),
88+
close = this._closeSubmenu.bind(this),
89+
closeBtn = subMenu.find(selectors.closeSubmenuBtn);
9390

9491
if (subMenu.length) {
9592
e.preventDefault();
9693
}
9794

9895
menuItem
9996
.addClass('_hover _recent')
100-
.siblings('._active')
101-
.addClass('_current')
102-
.removeClass('_active');
103-
104-
menuItem
105-
.siblings('.level-0')
97+
.siblings(menuItemSelector)
10698
.removeClass('_hover _recent');
10799

108-
subMenu
109-
.attr('aria-expanded', 'true');
100+
subMenu.attr('aria-expanded', 'true');
110101

111-
subMenu.find('button._close').on('click', this._close.bind(this));
102+
closeBtn.on('click', close);
112103

113-
this.overlay
114-
.on('click', this._close.bind(this))
115-
.show(0);
104+
this.overlay.show(0).on('click', close);
116105
},
117106

118107
_close: function (e) {
119-
var navigation = this.element,
120-
menuItem = $('.level-0._hover', navigation),
121-
subMenu = $('> submenu', menuItem);
108+
var selectors = this.options.selectors,
109+
menuItem = this.menu.find(selectors.topLevelItem + '._hover._recent'),
110+
subMenu = $(selectors.subMenu, menuItem),
111+
closeBtn = subMenu.find(selectors.closeSubmenuBtn);
122112

123113
e.preventDefault();
124114

125-
this.overlay.off('click').hide(0);
126-
127-
subMenu.find('button._close').off('click');
115+
this.overlay.hide(0).off('click');
128116

129-
menuItem.addClass('_active').removeClass('_current');
117+
closeBtn.off('click');
130118

131-
subMenu
132-
.removeClass('_show')
133-
.attr('aria-expanded', 'false');
119+
subMenu.attr('aria-expanded', 'false');
134120

135-
menuItem.removeClass('_hover _active');
121+
menuItem.removeClass('_hover _recent');
136122
}
137123
});
138124

0 commit comments

Comments
 (0)