A Tale of Backgrounds, Absolutes, mouseleave, and mouseenter

Thursday, August 18, 2011

mouseleave is simple to understand:

Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element.

How hard could it be? http://jsfiddle.net/JP6aV/

$(function () {
    var output = $("#output");
    $("#content")
      .mouseenter(function (e) {
          output.text("I'm in!");
    }).mouseout(function (e) {
          output.text("I'm out!");
    });
});

Like many simple things there are some traps under different circumstances. For example, when you put absolutely positioned elements into a page, you might think mouseenter and mouseleave are misbehaving. Watch what happens on http://jsfiddle.net/uUsEM/1/ when the mouse goes into the grey box.

If you've worked with nearly any UI framework before, you'll realize this isn't a misbehavior, but a feature.  But, what if your goal is to use mouseleave and mouseenter to know when the mouse is over the content area, regardless of what might be positioned on top? One solution is to create an element whose sole purpose is to provide mouseenter and mouseleave events for the content area. If the element overlays the content area exactly, has a higher z-index than any other element, and is invisible, then you just might have something that works (see http://jsfiddle.net/5psgc/1/).

$(function() {
    var output = $("#output");
    var content = $("#content");
    var eventSource = $("<div></div>");
    $("body").append(eventSource);

    eventSource.css({
        position: "absolute",
        left: content.offset().left,
        top: content.offset().top,
        width: content.width(),
        height: content.height(),
        opacity: 0,
        "z-index": 999
    }).mouseenter(function(e){
        output.text("I'm in!");
    }).mouseout(function(e) {
        output.text("I'm out!"); 
    });
});

If you try http://jsfiddle.net/5psgc/1/ in Chrome, you'll see the "in" and "out" messages only appear when the mouse is going into, or out of, the content area – no matter where the grey div appears. In IE9 the "in" and "out" messages appear at the wrong places. It's as if Internet Explorer has no empathy for an empty, faceless, soulless div.

The solution?

Set the background-color on the event source. Even though the color doesn't appear, because the opacity is at 0, the events start working as expected.

eventSource.css({
    position: "absolute",
    left: content.offset().left,
    top: content.offset().top,
    width: content.width(),
    height: content.height(),
    opacity: 0,
    "background-color": "#000", // <-- crazy
    "z-index": 999
})

See: http://jsfiddle.net/5psgc/2/


Comments
Ken Tong Thursday, August 18, 2011
But I can no longer select text in #content
gravatar Dan G. Switzer, II Friday, August 19, 2011
I've seen these type of issues crop up with IE and mouseover events before as well:

blog.pengoworks.com/...
scott Friday, August 19, 2011
Yes. That is an unfortunate side effect. This plays a role in a larger sample to come.
gravatar Vladimir Bychkov Thursday, September 1, 2011
Or you can use jQuery .hover event - http://api.jquery.com/hover/
The one with two handlers:
.hover( handlerIn(eventObject),handlerOut(eventObject) )
gravatar Yanay Tuesday, September 13, 2011
Brilliant! I was going crazy trying to understand (yet again) the wonders of IE. Thanks a lot!
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!