0

I'm learning JavaScript and jQuery and while doing the following exercise I had a problem. I have a div on the right side of the page which contains another smaller div, which contains an unordered list with some imgs, that I want to appear only when the mouse pointer enters the first div.

The problem is that when the mouse pointer enters the first div, the smaller one starts moving up and down uncontrollably.

I've tried using the .is(:hover) method on the bigger div, as suggested by another question on SO but it didn't help.

Here's my code:

stato = "out";

$("#control").mouseover(

  function() {

    if (stato == "out")
      $("#socialBox").animate({
        top: 300
      });
    //$("#socialBox").show();
    stato = "in";



  }

);


$("#control").mouseleave(

  function() {
    $("#socialBox").animate({
      top: -500
    });
    //$("#socialBox").hide();
    stato = "out";

  }

);
body {
  background: lightblue;
}

img {
  height: 50px;
  width: 50px;
}

ul {
  list-style-type: none;
}

#control {
  position: fixed;
  right: 0px;
  top: 0px;
  height: 100%;
  width: 100px;
  background: yellow;
}

#socialBox {
  position: fixed;
  top: -500px;
  right: 0px;
  width: 75px;
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control"></div>
<div id="socialBox">
  <ul>
    <li><img id="cane" src="img/cane.jpg" /></li>
    <li><img id="gatto" src="img/gatto.jpg" /></li>
    <li><img id="koala" src="img/koala.jpg" /></li>
    <li><img id="mucca" src="img/mucca.jpg" /></li>
    <li><img id="panda" src="img/panda.jpg" /></li>
    <li id="nascondi"> X </li>
  </ul>
</div>

I've also tried using other mouse events such as mouseenter and mouseout but I get the same issue.

Thanks in advance.

kiswa
  • 14,737
  • 1
  • 21
  • 29
Slowww
  • 29
  • 6
  • @Alex thanks for your editing: can you explane to me which changes did you apply to my code? I can't see any.. :-S Thank you. – Slowww Jul 09 '18 at 12:22

4 Answers4

0

the behaviour is triggered because the "#socialBox" enters the view, then blocks the "path" between mousepointer and "#control" and so the script triggers a mouseleave-event.

First of all, get rid of the mousemove... use mouseenter and you can delete the stato variable.

Next wrap the "#control" div around the "#socialbox" like so:

<div id="control">
  <div id="socialBox">
    <ul>
      <li><img id="cane" src="img/cane.jpg" /></li>
      <li><img id="gatto" src="img/gatto.jpg" /></li>
      <li><img id="koala" src="img/koala.jpg" /></li>
      <li><img id="mucca" src="img/mucca.jpg" /></li>
      <li><img id="panda" src="img/panda.jpg" /></li>
      <li id="nascondi"> X </li>
    </ul>
  </div>
</div>
Thieri
  • 203
  • 1
  • 10
0

As Thieri mentioned, you need to wrap your socialBox inside of the control div.

The socialBox is not bound to the parent div.


stato = "out";

$("#control").mouseover(
  function() {
    if (stato == "out")
      $("#socialBox").animate({
        top: 0
      });
    //$("#socialBox").show();
    stato = "in";
  }
);


$("#control").mouseleave(
  function() {
    $("#socialBox").animate({
      top: -500
    });
    //$("#socialBox").hide();
    stato = "out";
  }
);
body {
  background: lightblue;
}

img {
  height: 50px;
  width: 50px;
}

ul {
  list-style-type: none;
}

#control {
  position: fixed;
  right: 0px;
  top: 0px;
  height: 100%;
  width: 100px;
  background: yellow;
}

#socialBox {
  position: fixed;
  top: -500px;
  right: 0px;
  width: 75px;
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control">
  <div id="socialBox">
    <ul>
      <li><img id="cane" src="img/cane.jpg" /></li>
      <li><img id="gatto" src="img/gatto.jpg" /></li>
      <li><img id="koala" src="img/koala.jpg" /></li>
      <li><img id="mucca" src="img/mucca.jpg" /></li>
      <li><img id="panda" src="img/panda.jpg" /></li>
      <li id="nascondi"> X </li>
    </ul>
  </div>
</div>
Alex
  • 2,164
  • 1
  • 9
  • 27
0

The problem is that your animated #socialBox is not nested into #control. Whichever mouse event you're using, whenever the animating box gets under the cursor, the cursor "leaves" #control, triggering the hide animation.

If you want to keep your markup as it is, you can delay the animation with a timer. In my solution below, the timer makes sure that the animation will not be executed if both #control mouseleave and #socialBox mouseenter (or vice versa) trigger at almost the same time.

I also called .stop() before the animation to avoid queueing multiple animations by moving the mouse too quickly.

var shown = false;
var timer;

function triggerAnimation(show) {
    clearTimeout(timer);
    timer = setTimeout(function() {
        // If we're already on the same state, no need to animate
        if (show === shown) return;

        // Animate socialBox
        $("#socialBox").stop().animate({ top: show ? 300 : -500 });

        // Toggle state
        shown = !shown;
    }, 10);
}

$("#control, #socialBox")
    .mouseenter(function() { triggerAnimation(true); })
    .mouseleave(function() { triggerAnimation(false); });
body { background: lightblue; }
img { height: 50px; width: 50px; }
ul { list-style-type: none; }
#control { position: fixed; right: 0px; top: 0px; height: 100%; width: 100px; background: yellow; }
#socialBox { position: fixed;  top: -500px; right: 0px; width: 75px; background:red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control"></div>
<div id="socialBox">
    <ul>
        <li><img id="cane" src="img/cane.jpg"/></li>
        <li><img id="gatto" src="img/gatto.jpg"/></li>
        <li><img id="koala" src="img/koala.jpg"/></li>
        <li><img id="mucca" src="img/mucca.jpg"/></li>
        <li><img id="panda" src="img/panda.jpg"/></li>
        <li id="nascondi"> X </li>
    </ul>
</div>
DarthJDG
  • 16,511
  • 11
  • 49
  • 56
0

TL;DR: Move your socuialBox div into the content div.

Complete explanation: The problem is all because of event bubbling.

First, your html need to be changed as the socialBox div is outside of the control div the event fires repeatedly even while using mouseenter and mouseleave. So the socialBox is moved into the control div and used mouseenter and mouseleave events.

Second, the event bubbling. The problem still comes after the first step because of event bubbling.

mouseover - triggered when a mouse pointer is moved into an element. While moving over the child element, events of child elements gets fired and the event bubbles that causes the mouseover of the parent getting fired.

mouseout - same as mouseover but triggered when leaving the element.

mouseenter - triggered only when the mouse pointer gets into the element to which the event is bounded. Event will no bubble.

mouseleave - same as mouseenter but triggered when leaving the element the event bounded to.

To understand more clearly, refer these docs. jQuery mouseover, jQuery mouseout.

@gilly3 has a nice working fiddle to demonstrate the events in his answer

stato = "out";

$("#control").mouseenter(function() {
    $("#socialBox").animate({
      top: 100
    });
    stato = "in";
});


$("#control").mouseleave(function() {
    $("#socialBox").animate({
      top: -500
    });
    stato = "out";
});
body {
  background: lightblue;
}

img {
  height: 50px;
  width: 50px;
}

ul {
  list-style-type: none;
}

#control {
  position: fixed;
  right: 0px;
  top: 0px;
  height: 100%;
  width: 100px;
  background: yellow;
}

#socialBox {
  position: fixed;
  top: -500px;
  right: 0px;
  width: 75px;
  background: red;
  pointer:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control">
    <div id="socialBox">
      <ul>
        <li><img id="cane" src="img/cane.jpg" /></li>
        <li><img id="gatto" src="img/gatto.jpg" /></li>
        <li><img id="koala" src="img/koala.jpg" /></li>
        <li><img id="mucca" src="img/mucca.jpg" /></li>
        <li><img id="panda" src="img/panda.jpg" /></li>
        <li id="nascondi"> X </li>
      </ul>
    </div>
</div>
Vignesh Raja
  • 7,927
  • 1
  • 33
  • 42