From: Nicolas Coden Date: Wed, 12 Sep 2018 20:25:53 +0000 (+0200) Subject: Use pull request #11418 from ncoden/refactor/mouseleave-special-case for v6.5.0 X-Git-Tag: v6.5.0-rc.3^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=55e60ee86;p=thirdparty%2Ffoundation%2Ffoundation-sites.git Use pull request #11418 from ncoden/refactor/mouseleave-special-case for v6.5.0 9bd7f933c refactor: move dropdownMenu mouseleave special case to its own utility function 8f2470c28 docs: add doc for core utility onLeaveElement 90de67a17 refactor: make the magic mouseleave utility a simple event filter adeee972d docs: add some doc in the magic mouseleave utility "ignoreMousedisappear" f46e78bd1 fix: prevent Dropdown and Tooltip to hide when moving mouse to browser UI elements 5bdec3a3c tests: add visual test for the Dropdown magic mousleave bug f0168bb9f style: fix incorrectly named variable in ignoreMousedisappear utility 1847f6c9b fix: make the "ignoreMousedisappear()" handler called before mouseenter 3ec791559 docs: improve doc in "ignoreMousedisappear()" Signed-off-by: Nicolas Coden --- diff --git a/js/foundation.core.utils.js b/js/foundation.core.utils.js index 46b2f0ed4..5bc46b9a5 100644 --- a/js/foundation.core.utils.js +++ b/js/foundation.core.utils.js @@ -90,4 +90,32 @@ function onLoad($elem, handler) { return eventType; } -export { rtl, GetYoDigits, RegExpEscape, transitionend, onLoad }; +function onLeaveElement($elem, handler, { leaveWindow = true } = {}) { + const eventType = 'mouseleave.zf.util.onLeaveElement'; + + if ($elem && handler) { + + $elem.on(eventType, function leaveHandler(e, ...rest) { + const _this = this; + setTimeout(function leaveEventDebouncer() { + + if (e.relatedTarget === null && leaveWindow && document.hasFocus && document.hasFocus()) { + + $(document).one('mouseenter', function reenterHandler(reeenterE) { + if ($elem.has(reeenterE.target).length) { return false }; + e.relatedTarget = reeenterE.target; + handler.call(_this, e, ...rest); + }); + + return false; + } + + handler.call(_this, e, ...rest); + }); + }); + } + + return eventType; +} + +export { rtl, GetYoDigits, RegExpEscape, transitionend, onLoad, onLeaveElement }; diff --git a/js/foundation.dropdownMenu.js b/js/foundation.dropdownMenu.js index dc9fb57ba..2b1d6b776 100644 --- a/js/foundation.dropdownMenu.js +++ b/js/foundation.dropdownMenu.js @@ -1,12 +1,11 @@ 'use strict'; import $ from 'jquery'; +import { Plugin } from './foundation.core.plugin'; +import { rtl as Rtl, onLeaveElement } from './foundation.core.utils'; import { Keyboard } from './foundation.util.keyboard'; import { Nest } from './foundation.util.nest'; import { Box } from './foundation.util.box'; -import { rtl as Rtl } from './foundation.core.utils'; -import { Plugin } from './foundation.core.plugin'; - /** * DropdownMenu module. @@ -135,17 +134,19 @@ class DropdownMenu extends Plugin { } if (!this.options.disableHover) { - this.$menuItems.on('mouseenter.zf.dropdownmenu', function(e) { + this.$menuItems.on('mouseenter.zf.dropdownmenu', function (e) { var $elem = $(this), - hasSub = $elem.hasClass(parClass); + hasSub = $elem.hasClass(parClass); if (hasSub) { clearTimeout($elem.data('_delay')); - $elem.data('_delay', setTimeout(function() { + $elem.data('_delay', setTimeout(function () { _this._show($elem.children('.is-dropdown-submenu')); }, _this.options.hoverDelay)); } - }).on('mouseleave.zf.dropdownmenu', function(e) { + }); + + onLeaveElement(this.$menuItems, function (e) { var $elem = $(this), hasSub = $elem.hasClass(parClass); if (hasSub && _this.options.autoclose) { @@ -153,19 +154,8 @@ class DropdownMenu extends Plugin { clearTimeout($elem.data('_delay')); $elem.data('_delay', setTimeout(function () { - - // Ignore "magic mouseleave": when the mouse simply disapear from the document - // (like when entering in browser input suggestions See https://git.io/zf-11410), - // unless we actually left the window (and document lost focus). - // - // In firefox, document will not focus at the time the event is triggered, so we have - // to make this test after the delay. - if (e.relatedTarget === null && document.hasFocus && document.hasFocus()) { return false; } - _this._hide($elem); - }, _this.options.closingTime)); - } }); }