]> git.ipfire.org Git - thirdparty/foundation/foundation-sites.git/commitdiff
refactor: make the magic mouseleave utility a simple event filter
authorNicolas Coden <nicolas@ncoden.fr>
Tue, 24 Jul 2018 21:57:34 +0000 (23:57 +0200)
committerNicolas Coden <nicolas@ncoden.fr>
Tue, 24 Jul 2018 21:57:34 +0000 (23:57 +0200)
js/foundation.core.utils.js
js/foundation.dropdownMenu.js

index 3cef14d9196f339c55f540f5715572e786a3101a..2fffbe3b19e36f23f960d28a61f984236e41620f 100644 (file)
@@ -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};
index 96f66fb13c2fb157457a3f5bd970a28e37146eda..aa25271b7d7cdd991b9d7cab92ee87caef51a3de 100644 (file)
@@ -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';
@@ -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) {
@@ -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"]'),