Skip to content

Commit

Permalink
refactor: make the magic mouseleave utility a simple event filter
Browse files Browse the repository at this point in the history
  • Loading branch information
ncoden committed Jul 24, 2018
1 parent 8f2470c commit 90de67a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 39 deletions.
70 changes: 36 additions & 34 deletions js/foundation.core.utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,46 +91,48 @@ function onLoad($elem, handler) {
}

/**
* Watch for the mouse leaving the jQuery element `$elem` and triggers the given `handler` it so.
* When the mouse desapear from the document (like when going on a browser UI element, See https://git.io/zf-11410),
* nothing is triggered. If the mouse reapear later on the document outside of `$elem`, the given handler is triggered.
* Retuns an handler for the `mouseleave` that ignore disappeared mouses.
*
* If the `leaveWindow` option is `true` (by default), the given handler is triggered when the mouse desapeared because
* the window lost focus (like with [Alt]+[Tab]).
* If the mouse "disappeared" from the document (like when going on a browser UI element, See https://git.io/zf-11410),
* the event is ignored.
* - If the `ignoreLeaveWindow` is `true`, the event is ignored when the user actually left the window
* (like by switching to an other window with [Alt]+[Tab]).
* - If the `ignoreReappear` is `true`, the event will be ignored when the mouse will reappear later on the document
* outside of the element it left.
*
* @function
*
* @param {Object} [] $elem - jQuery element to watch.
* @param {Function} [] handler - function to trigger when the mouse left the element.
* @param {Object} [{leaveWindow = true}] object - options
* @returns {String} - event type attached to the given element.
* @param {Function} [] handler - handler for the filtered `mouseleave` event to watch.
* @param {Object} [] options - object of options:
* - {Boolean} [false] ignoreLeaveWindow - also ignore when the user switched windows.
* - {Boolean} [false] ignoreReappear - also ignore when the mouse reappeared outside of the element it left.
* @returns {Function} - filtered handler to use to listen on the `mouseleave` event.
*/
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);
});
function ignoreMousedisappear(handler, { ignoreLeaveWindow = false, ignoreReappear = false } = {}) {
return function leaveEventHandler(eEnter, ...rest) {
const callback = handler.bind(this, eEnter, ...rest);
setTimeout(function leaveEventDebouncer() {

if (eEnter.relatedTarget !== null
// - if the user switched to an other window (and we don't ignore it)
|| !ignoreLeaveWindow && document.hasFocus && !document.hasFocus()) {
callback();
}

else if (!ignoreReappear) {
$(document).one('mouseenter', function reenterEventHandler(eReenter) {
if (!$(eEnter.currentTarget).has(eReenter.target).length) {

eEnter.relatedTarget = eReenter.target;
callback();

}
});
}
});
}

return eventType;
};
}

export {rtl, GetYoDigits, RegExpEscape, transitionend, onLoad, onLeaveElement};

export {rtl, GetYoDigits, RegExpEscape, transitionend, onLoad, ignoreMousedisappear};
8 changes: 3 additions & 5 deletions js/foundation.dropdownMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import $ from 'jquery';
import { Plugin } from './foundation.core.plugin';
import { rtl as Rtl, onLeaveElement } from './foundation.core.utils';
import { rtl as Rtl, ignoreMousedisappear } from './foundation.core.utils';
import { Keyboard } from './foundation.util.keyboard';
import { Nest } from './foundation.util.nest';
import { Box } from './foundation.util.box';
Expand Down Expand Up @@ -149,9 +149,7 @@ class DropdownMenu extends Plugin {
_this._show($elem.children('.is-dropdown-submenu'));
}, _this.options.hoverDelay));
}
});

onLeaveElement(this.$menuItems, function (e) {
}).on('mouseleave.zf.dropdownMenu', ignoreMousedisappear(function (e) {
var $elem = $(this),
hasSub = $elem.hasClass(parClass);
if (hasSub && _this.options.autoclose) {
Expand All @@ -162,7 +160,7 @@ class DropdownMenu extends Plugin {
_this._hide($elem);
}, _this.options.closingTime));
}
});
}));
}
this.$menuItems.on('keydown.zf.dropdownMenu', function(e) {
var $element = $(e.target).parentsUntil('ul', '[role="menuitem"]'),
Expand Down

0 comments on commit 90de67a

Please # to comment.