0

I have two divs: the red over the blue. I want that when the user hover the red this fadeOut and when hover the background (when he gets out of the blue) the red fadeIn. (What is more surprising to me is that the red fadeIn not when I hover the background but when I mouseleave it? I don't understand)

The example here life:http://jsfiddle.net/DpD8S/

HTML:

<div id="background">
    <div id="red"></div>
    <div id="blue"></div>
</div>​

CSS:

#red{
    position:absolute;
    top: 20px;
    left: 20px;
    width: 60px;
    height: 30px;
    background-color:red;
    cursor: pointer;
    z-index: 1; 
    }

#blue{
    position:absolute;
    top: 20px;
    left: 20px;
    width: 60px;
    height: 30px;
    background-color:blue;
    cursor: pointer; 
    }

#background{
    position: relative;
    margin: 0 auto;
    width:300px;
    height: 300px;
    border: 1px solid;
    border-color:#CCC;
    text-align: center;
    cursor: pointer;  }

JQUERY:

$(function(){      
    $("#red").hover(function() {
        $("#red").fadeOut();
    });

    $("#background").hover(function() {
        $("#red").fadeIn("normal");
    });   
})​
Nrc
  • 9,577
  • 17
  • 67
  • 114
  • 1
    If I understand correctly, the jsfiddle works just as you described – dualed Dec 18 '12 at 14:52
  • "I want that when the user hover the red, this fadeOut and when hover the background, the red fadeIn" Now when I hover the background, red DOES NOT fadeIn. I don't understand why? – Nrc Dec 18 '12 at 14:56

5 Answers5

2

Your problem is probably the definition of hover.

hover( handlerIn(eventObject) , handlerOut(eventObject)  )
hover( handlerInOut(eventObject)  )

That means when you pass only one function it is called for mouseenter as well as mouseleave. You should either use these events or pass two functions to hover

Also this is pretty much "backwards". Hiding something when you enter it will always be a problem. So this is why I now rename your divs. You should show #active when you enter #inactive, and hide #active when you leave #active.

Here's a fiddle http://jsfiddle.net/MwQaf/1/

dualed
  • 10,262
  • 1
  • 26
  • 29
  • @Nrc this is because when you hide red you "enter" blue. If you attach that second handler to the `mouseenter` handler of `#background`, it should work – dualed Dec 18 '12 at 15:09
  • Do you mean this?: http://jsfiddle.net/DpD8S/13/ You can try directly in the Fiddle. I think it does not work – Nrc Dec 18 '12 at 15:21
  • @Nrc I was a bit hasty there. I updated my answer, use that. ;) – dualed Dec 18 '12 at 15:23
  • @Nrc just curious why you dismiss this answer, does the fiddle not work on your system? – dualed Dec 18 '12 at 16:32
  • Perhaps this is similar but less complicated : http://jsfiddle.net/DpD8S/21/ Anyway your option works and is good. Thank you. – Nrc Dec 19 '12 at 09:26
  • @Nrc The fiddle you linked is, as I said in my answer backwards. It is bound to give you headaches some day if not already (try moving the mouse quickly over the element, it will sometimes get stuck in blue). I tried to explain to you what you actually did wrong, maybe this is why it looks more complex but it is still only two very tiny event handlers on two elements, I don't see why it is *complicated*. The accepted answer is of course fine, though it requires more CSS and HTML code. – dualed Dec 19 '12 at 12:34
2

Make a transparent stable zone, which would catch your event.

<div id="background">
    <div id="blue"></div>
    <div id="red"></div>
    <div id="transparent"></div>
</div>​

CSS:

#red{
    position:absolute;
    top: 20px;
    left: 20px;
    width: 60px;
    height: 30px;
    background-color:red;
    cursor: pointer;
    z-index: 1; 
    }

#blue{
    position:absolute;
    top: 20px;
    left: 20px;
    width: 60px;
    height: 30px;
    background-color:blue;
    cursor: pointer; 
    }

#transparent {
    position:absolute;
    top: 20px;
    left: 20px;
    width: 60px;
    height: 30px;
    background-color:none;
    cursor: pointer; 
    z-index: 2; 
    }

#background{
    position: relative;
    margin: 0 auto;
    width:300px;
    height: 300px;
    border: 1px solid;
    border-color:#CCC;
    text-align: center;
    cursor: pointer; 
}
​

Then use hover(function(),function()). Don't forget to stop executing event functions there:

$(function(){      
    $("#transparent").hover(function() {
        $("#red").stop().fadeOut();
    }, function() {
       $("#red").fadeIn("normal");
    });

})​

http://jsfiddle.net/DpD8S/14/

user666
  • 226
  • 1
  • 8
  • This issue can be resolved without adding useless elements to the `DOM`. – Rémi Breton Dec 18 '12 at 15:23
  • This is a clever solution and it works in the fiddle. As this is a very simplified example of a much more complex problem I have with a lot of divs. I am not sure if I will be able to apply it there. Anyway it gives me a new line of possibilities. Thank you!! – Nrc Dec 18 '12 at 15:59
  • This is my favorite option because it works in any situation, it doesn't matter if the divs have or not the same size or position. I have tried a variant with mouseenter and mouseleave too: http://jsfiddle.net/DpD8S/22/ – Nrc Dec 19 '12 at 10:10
1

Perhaps you would prefer to change: $("#background").hover(...) to $("#blue").mouseleave(...)

http://jsfiddle.net/DpD8S/18/

IsisCode
  • 2,490
  • 18
  • 20
  • What you say is a very good solution. But be careful your fiddle does not work. I think you mean this?: http://jsfiddle.net/DpD8S/18/ – Nrc Dec 18 '12 at 16:08
  • This is a very good solution because is clear and simple. But I think it will work only it the 2 divs have the same exact size and position. – Nrc Dec 19 '12 at 10:12
1

The #background div is wrapping the other two. Your $('#background').hover() function is called whenever a hover event occurs on #background, even its children.

I believe you can achieve what you want by doing this:

$("#red").mouseenter(function() {
    $(this).fadeOut();
});

$("#red, #blue").mouseleave(function() {
    $("#red").fadeIn("normal");
}); 

This, however, produces a weird behaviour as the two "fade" animations are queued. If the user hovers in and out quickly, the div seems unresponsive and animates in a weird manner.

If installing plugins is an option, you can try this plugin to animate colors. This will allow you to even reduce the number of elements to just the div itself. You will also be able to cut back on CSS and use cleaner JavaScript. Check out the fiddle.

Rémi Breton
  • 4,209
  • 2
  • 22
  • 34
  • What you say makes sense, but your example makes some weird movement on mouseleave. I tried to add event.stopPropagation() but it does no work either: http://jsfiddle.net/DpD8S/16/ – Nrc Dec 18 '12 at 15:51
  • I just thought of this; is there any reason why CSS3 can't be used your situation? – Rémi Breton Dec 18 '12 at 19:15
  • The weird behaviour is caused by the `#red` element finishing its `fadeOut()` animation before the `fadeIn()` may begin. – Rémi Breton Dec 18 '12 at 19:29
  • What can be improved with css3 ? – Nrc Dec 19 '12 at 09:02
  • You could use CSS3 transitions to animate the background-color. Like so: http://jsfiddle.net/DpD8S/23/. Check out this other answer talking about CSS transitions: http://stackoverflow.com/questions/9670075/css-transition-shorthand-with-multiple-properties/9670311#9670311 – Rémi Breton Dec 19 '12 at 14:12
0

The hover function is typically defined like this -

$('#red').hover(function() {
    $(this).fadeOut();
}, function() {
    $(this).fadeIn();
});

The first function is the mouseenter portion of .hover(). The second function is the mouseleave portion of the hover. In your case the background div appears to be inconsequential to the problem.

Jay Blanchard
  • 34,243
  • 16
  • 77
  • 119
  • Weird. I'd go with @Remi Breton's answer, where he separates the functions properly. I didn't think about the hover reacting this way. – Jay Blanchard Dec 18 '12 at 15:46