0

I have a dropdownmenu which I hide/show with JS based on mouseleave and mouseenter event. I am using JS to hide the menu with a timeout, so a user with a shaky mouse does not accidentally close the menu.

I am also using the KeePassXC-Browser plugin. This creates a key-icon inside the password input field.

When I hover over the key-icon inside my dropdown menu, the mouseleave event is triggered.

enter image description here

Here is an example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
  <div style="padding:20px;background-color:grey" id="wrapper">
        <input type="password">
  <div>
  
  <script>
  const wrapper = document.getElementById('wrapper');
  wrapper.addEventListener("mouseleave", function(event){
    console.log('LEAVING');
  });
  </script>
  </body>
</html>

How can I catch on mouse leave, that the plugin icon is hovered? Is there a general approach that also covers possible other plugins that add icons to input elements?

EDIT: Hint from Cbroe, the mouseleave is caused because the key icon is outside the wrapper and positioned absolute to appear on the input box: enter image description here

Adam
  • 25,960
  • 22
  • 158
  • 247
  • 2
    Have you tried to check using the DOM inspector, _where_ this icon element actually gets inserted? I am guessing it probably did not actually get inserted as a descendant of your wrapper, but somewhere outside (and only gets positioned absolute to appear in the right place) - and in that case it would of course not be a browser bug, but "works as designed." Mouseenter/-leave events fire based on DOM structure, not visual display. – CBroe Sep 29 '22 at 06:32
  • Also note that the plug-in creates the div element in the shadowRoot (closed), which complicates possible solutions. – Yogi Sep 29 '22 at 08:46
  • After trying possible solutions, checking for the .kpxc class on the event.relatedTarget seems the best way to skip false mouse-leave events. Yet, would need to experiment to see what object is passed in relatedTarget when the element is in the shadow. – Yogi Sep 29 '22 at 11:35
  • @Yogi but .kpxc class is not on event.relatedTarget. It would be on a child of it, but you cannot access the child, because its shadowRoot (closed) – Adam Sep 29 '22 at 14:22

1 Answers1

0

As said in comments from Cbroe, the mouseleave is caused because the key icon is outside the wrapper and positioned absolute to appear on the input box.

Also autocomplete from the input would trigger mouseleave as well.

To fix it, one could check in the mouseleave event if the mouse coordinates are still in the wrapper:

<script>
  const wrapper = document.getElementById('wrapper');
  wrapper.addEventListener("mouseleave", function(event){
      const wrapperBounding = wrapper.getBoundingClientRect();
        if (event.clientX >= wrapper.left && event.clientX <= wrapper.right &&
            event.clientY >= wrapper.top && event.clientY <= wrapper.bottom) {
            return
        }
        console.log('LEAVING');
  });
</script>
Adam
  • 25,960
  • 22
  • 158
  • 247