Search code examples
jqueryeventsevent-handlingevent-bubblingmouseleave

Jquery mouseleave event: how to know towards what element the mouse is going?


I think this is very jquery/javascript ninja question.

Basically i have two different divs, and inside the first one i have other elements and at the end of tree i have an ul.

The example http: http://jsfiddle.net/thTpB/23/

I want that when i leave the li's in the unordered list the second div (div.to_show) will remain opened only if i go in it directly from that "li".

It's for a classic menu, but for some reason i can't rewrite the html and include the second div inside every li and show it as a child.

I tried reading from the EventObject e the following properties:

  • e.toElement: firefox doesn't set it
  • e.relatedTarget: it is usually the parent, not the second div

What i have to do to get that behaviour? Bubble the event until i have e.relatedTarget == second div?

edit: Please suppose that i CAN'T change the DOM hierarchy. It's hard because of that.

Obviously with the mouseenter on a certain li i will change the content of the div.to_show.


Solution

  • Here's an example you want.. It will only hide menu contents if you mouse out of the menu entirely. This means if you mouse into a menu item selection, then mouse into the menu content div, it will still show that menu content div, not just disappear. This is achieved by putting the content you want to hide and show AND the menu li items themselves inside one container, and put a mouseout handler to hide everything only on that container. So menu items li no longer have ANY mouseout handler, just the overall divs + li's container (when you had a mouseout handler on individual li items, thats why you got behavior you didn't want where content disappeared all the time).

    Also it will show the menu item you want when you mouse over it and then if you mouse to another li, it will hide all the others when you mouse from one to the other BUT SHOW THE ONE YOU WANT and it looks smooth. This is achieved by hiding all items when you mouse between items (by calling all the content divs with a certain class, e.g. "elem"). and hiding all those, but then SHOWING the current selected item by using the connection between the contents of the menu item name and the class name of the element to show. For instance, the menu content div item of class "elem foo" means that when I mouse over li item with html content of "foo", all the div menu contents of class ".elem" are hidden, but the div menu content of class "foo" is shown.

    Hope this helps!

    WORKING JSFIDDLE DEMO HERE

    JS

        $("div.another_container li").mouseenter(function(){ 
           $(".elem").hide();
           $("." + $(this).children("a").eq(0).html()).show();
        });
    
        $(".elem").hide();
    
        $(".wrapper").mouseleave(function(){
            $(".elem").hide();
        });
    

    HTML

    <div class="container head">
    some header
    </div>
    <div class="wrapper">
        <div class="container">
            <div class="sixteen columns">
                <div class="another_container">
                    <ul class="menu">
                        <li><a href="#">foo</a></li>
                        <li><a href="#">bar</a></li>
                    </ul>
    
                </div>
            </div>
        </div>
         <div class="elem bar">
            BAR blabla
        </div>
          <div class="elem foo">
        FOO blabla
        </div>
    
    </div>
    <div class="container footer">
     some footer
    </div>    
    

    CSS

    .container .sixteen.columns{
        width: 940px;
    }
    
    
    .container .column, .container .columns {
        float: left;
        display: inline;
        margin-left: 10px;
        margin-right: 10px;
    }
    
    
    .another_container ul {
    height: 25px;
    width: 100%;
    margin: 0;
    position: relative;
    padding-top: 0px;
    padding-left: 0;
    padding-right: 0;
    padding-bottom: 4px;
    }
    ol, ul {
    list-style: none;
    }
    
    .another_container li:first-child {
    margin-left: 0px !important;
    }
    .another_container li {
    position: relative;
    text-align: left !important;
    float: left;
    width: auto;
    margin-left: 27px;
    }
    
    .elem {
    display: none;
    position: relative;
    width: 100%;
    height: 200px;
    text-align: center;
    float: left;
    padding-bottom: 20px;
    padding-left: auto;
    padding-right: auto;
    background-color: #f2f2f2;
    border-style: solid;
    border-color: red;
    border-bottom-width: 2px;
    }