Question

I'm trying to create a drop-down menu acting as the sub-menu of a main menu. The sub-menu is simply a div element containing items/links. When a main menu item is clicked, the sub-menu drops down and stays there. That's all easy, but I want the sub-menu to slide back up if the cursor leaves the sub-menu. In other words, a simple 'mouseout' event. It seems, however, that when the cursor enters one of the items inside the sub-menu, the 'mouseout' event is triggered. That's what you would except, if you think about it, as the cursor does leave the sub-menu element even though it doesn't leave its boundries. However, this does pose a problem, because I only want the event to fire if the cursor is moved outside the boundries of the sub-menu element.

What it really boils down to, is having one div inside another div, like this:

----------------------------
|          DIV-1           |
|                          |
|      -------------       |
|      |           |       |
|      |   DIV-2   |       |   AREA OUTSIDE DIV-1
|      |           |       |
|      |           |       |
|      |           |       |
|      -------------       |
|                          |
|                          |
----------------------------

Now, 2 things may cause DIV-1 to fire a 'mouseout' event:

  1. The cursor moves from within the boundries of DIV-1 to the area outside those boundries
  2. The cursor moves from within the boundries of DIV-1 to the area of DIV-2

My goal is to be able to distinguish these two occurences from one another, yet I haven't been able to figure out how.

Does anyone have a good solution for this problem? It seems a common enough feature, so someone must have solved it.

Was it helpful?

Solution

Since mouseover events from child elements bubble/propagate to the parents, I would use a timer that is cancelled in the onmouseover event of the sub menu's div, if I was going the non-library route:

var hideMenuTimer;
subMenuDiv.onmouseover = function () {
    window.clearTimeout(hideMenuTimer);
}
subMenuDiv.onmouseout = function (evt) {
    evt = evt || window.event;
    if ((evt.target || evt.srcElement).id == "subMenuDiv")
        hideMenuTimer = window.setTimeout(function () {
            subMenuDiv.style.display = "none";
        }, 300);
}

A very simple example but it should work, providing all sub elements of the sub menu div correctly bubble the onmouseover event to the subMenuDiv element then the timer is cancelled before it polls. Also, I've put a 300ms timeout because I think it's best to have this sort of thing so that if you accidentally mouseout you have a short window to get the mouse back in before it hides. If you want it to hide instantly, setting it to 0ms should work fine too.

OTHER TIPS

http://users.tpg.com.au/j_birch/plugins/superfish/ <-- save yourself the time, he already pulled out his hair for you (maybe not literally, though, don't know)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top