From 58f638e99daf9e5f4cfb2b6c34c82b84230170b6 Mon Sep 17 00:00:00 2001 From: Grzegorz Blaszczyk Date: Fri, 2 Nov 2018 21:51:42 +0100 Subject: [PATCH] fix: vjs-lock-showing class gets removed from menu when no longer hovering on menu-button. (#5465) Fixes #1690 --- src/js/menu/menu-button.js | 18 +++++++----------- src/js/menu/menu.js | 27 ++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/js/menu/menu-button.js b/src/js/menu/menu-button.js index 2ba832ed0..6c6b2e06a 100644 --- a/src/js/menu/menu-button.js +++ b/src/js/menu/menu-button.js @@ -51,7 +51,9 @@ class MenuButton extends Component { this.on(this.menuButton_, 'click', this.handleClick); this.on(this.menuButton_, 'focus', this.handleFocus); this.on(this.menuButton_, 'blur', this.handleBlur); - + this.on(this.menuButton_, 'mouseenter', () => { + this.menu.show(); + }); this.on('keydown', this.handleSubmenuKeyPress); } @@ -221,14 +223,6 @@ class MenuButton extends Component { * @listens click */ handleClick(event) { - // When you click the button it adds focus, which will show the menu. - // So we'll remove focus when the mouse leaves the button. Focus is needed - // for tab navigation. - - this.one(this.menu.contentEl(), 'mouseleave', Fn.bind(this, function(e) { - this.unpressButton(); - this.el_.blur(); - })); if (this.buttonPressed_) { this.unpressButton(); } else { @@ -299,8 +293,8 @@ class MenuButton extends Component { // Set focus back to the menu button's button this.menuButton_.el_.focus(); } - // Up (38) key or Down (40) key press the 'button' - } else if (event.which === 38 || event.which === 40) { + // Enter (13) or Up (38) key or Down (40) key press the 'button' + } else if (event.which === 13 || event.which === 38 || event.which === 40) { if (!this.buttonPressed_) { this.pressButton(); event.preventDefault(); @@ -339,6 +333,7 @@ class MenuButton extends Component { pressButton() { if (this.enabled_) { this.buttonPressed_ = true; + this.menu.show(); this.menu.lockShowing(); this.menuButton_.el_.setAttribute('aria-expanded', 'true'); @@ -360,6 +355,7 @@ class MenuButton extends Component { if (this.enabled_) { this.buttonPressed_ = false; this.menu.unlockShowing(); + this.menu.hide(); this.menuButton_.el_.setAttribute('aria-expanded', 'false'); } } diff --git a/src/js/menu/menu.js b/src/js/menu/menu.js index 248426c45..df086f98c 100644 --- a/src/js/menu/menu.js +++ b/src/js/menu/menu.js @@ -2,6 +2,7 @@ * @file menu.js */ import Component from '../component.js'; +import document from 'global/document'; import * as Dom from '../utils/dom.js'; import * as Fn from '../utils/fn.js'; import * as Events from '../utils/events.js'; @@ -45,7 +46,8 @@ class Menu extends Component { */ addItem(component) { this.addChild(component); - component.on('click', Fn.bind(this, function(event) { + component.on('blur', Fn.bind(this, this.handleBlur)); + component.on(['tap', 'click'], Fn.bind(this, function(event) { // Unpress the associated MenuButton, and move focus back to it if (this.menuButton_) { this.menuButton_.unpressButton(); @@ -97,6 +99,29 @@ class Menu extends Component { super.dispose(); } + /** + * Called when a `MenuItem` loses focus. + * + * @param {EventTarget~Event} event + * The `blur` event that caused this function to be called. + * + * @listens blur + */ + handleBlur(event) { + const relatedTarget = event.relatedTarget || document.activeElement; + + // Close menu popup when a user clicks outside the menu + if (!this.children().some((element) => { + return element.el() === relatedTarget; + })) { + const btn = this.menuButton_; + + if (btn && btn.buttonPressed_ && relatedTarget !== btn.el().firstChild) { + btn.unpressButton(); + } + } + } + /** * Handle a `keydown` event on this menu. This listener is added in the constructor. *