19

i wanna build a menu that is shown on mouseover and displays elements: category: - sub-category1 - sub-category2

I managed to accomplish that, but my problem is that when i hover over the menu and it shows the elements inside and i move the mouse away from the menu itself, the elements dont hide.

Here is my code:

<div x-data="{open: false}">
    <button @mouseover="open = true">Category</button>
    <div x-show="open" @mouseout="open = false" class="h-80 bg-red-900">
        <ul>
            <li>Sub-category 1</li>
            <li>Sub-category 2</li>
        </ul>
    </div>
</div>
RedZ
  • 857
  • 1
  • 13
  • 25

4 Answers4

21

use @mouseover.away = "open = false" on the outside div

15

Don't use mouseout event. Use mouseleave on the outside div instead.

Here is the solution that worked well for me.

<div x-data="{ open: false }" class="ml-4" @mouseleave="open = false">
        <button @mouseover="open = true" class="border border-primary-900">Category</button>
        <div x-show="open" class="h-80 bg-red-900">
            <ul>
                <li>Sub-category 1</li>
                <li>Sub-category 2</li>
            </ul>
        </div>
    </div>

Example :

The following example illustrates the difference between mouseout and mouseleave events. The mouseleave event is added to the <ul> to color the list purple whenever the mouse exits the <ul>. mouseout is added to the list to color the targeted element orange when the mouse exits it.

When you try this out, you'll find that mouseout is delivered to the individual list items, while mouseleave goes to the overall list, courtesy of the hierarchy of the items and the fact that list items obscure the underlying .

let test = document.getElementById("test");

// Briefly make the list purple when the mouse moves off the
// <ul> element
test.addEventListener("mouseleave", function( event ) {
  // highlight the mouseleave target
  event.target.style.color = "purple";

  // reset the color after a short delay
  setTimeout(function() {
    event.target.style.color = "";
  }, 1000);
}, false);

// Briefly make an <li> orange when the mouse moves off of it
test.addEventListener("mouseout", function( event ) {
  // highlight the mouseout target
  event.target.style.color = "orange";

  // reset the color after a short delay
  setTimeout(function() {
    event.target.style.color = "";
  }, 500);
}, false);
<ul id="test">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
</ul>

Source : You can see more details about the difference between mouseout and mouseleave

OLIVIERS
  • 334
  • 3
  • 13
0

The mouseout event triggers when the mouse pointer leaves any child elements as well the selected element.

The mouseleave event is only triggered when the mouse pointer leaves the selected element.

Test this:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
x = 0;
y = 0;
$(document).ready(function(){
  $("div.over").mouseout(function(){
    $(".over span").text(x += 1);
  });
  $("div.enter").mouseleave(function(){
    $(".enter span").text(y += 1);
  });
});
</script>
</head>
<body>

<p>The mouseout event triggers when the mouse pointer leaves any child elements as well the selected element.</p>
<p>The mouseleave event is only triggered when the mouse pointer leaves the selected element. </p>

<div class="over" style="background-color:lightgray;padding:20px;width:250px;float:left">
  <h3 style="background-color:white;">Mouseout event triggered: <span></span></h3>
</div>

<div class="enter" style="background-color:lightgray;padding:20px;width:250px;float:right">
  <h3 style="background-color:white;">Mouseleave event triggered: <span></span></h3>
</div>

</body>
</html>

So as suggested by OLIVIERS this is a good solution:

<div x-data="{ open: false }" class="ml-4" @mouseleave="open = false">
    <button @mouseover="open = true" class="border border-primary-900">Category</button>
    <div x-show="open" class="h-80 bg-red-900">
        <ul>
            <li>Sub-category 1</li>
            <li>Sub-category 2</li>
        </ul>
    </div>
</div>

The solution from Christopher is making use of the .away modifier from alpine:

When the .away modifier is present, the event handler will only be executed when the event originates from a source other than itself, or its children.

This is useful for hiding dropdowns and modals when a user clicks away from them.

combined with the mouseover event

Adam
  • 25,960
  • 22
  • 158
  • 247
0
           <div x-data="{ open: false }">
                <div @mouseover="open = true"  @mouseover.away = "open = false" >
                  hover over me 
                </div>
                <div x-show="open" >
                   data 
                </div>
          </div>
Judith lobo
  • 131
  • 4