2

I am currently switching the menu of my site from pure JavaScript to jQuery. My menu has a rollout / rollin effect.

The menu has an outer wrapper which has an onmouseout event set. If this fires, the relatedTarget is checked whether it's a child of the outer wrapper. If not, the rollin shall happen.

What happens right now is, that if the mouse is moved from the menu's inner wrapper (this is to center the actual menu) to the menu's outer wrapper, the onmouseout fires. There seems to be a tiny part which doesn't belong to the menuOuterWrapper.

The site isn't online right now, so I've prepared a Fiddle here. You will see the problem if you move your mouse from the gray area above the handle to the left or right dark area. The menu will roll in and then immediately out again. The rollin shall only occur when the mouse is moved out of the outer wrapper, i.e. under the dark gray area (or the light gray handle area). To see the dark gray areas, you might have to increase the width of the result block. [EDIT: I reduced the width of inner to 600px, so the dark side areas should be visible by default now.]

SO tells me that I shall include code when linking to JSFiddle. I don't want to break the rules but I'll be honest: I'm clueless where the problem comes from. My best idea is that I made a mistake in my isChildOf implementation, so I'll give you this:

jQuery.fn.isChildOf = function (parentId) {
    if ($(this).parents("#" + parentId).length > 0) {
      return true;
    } else {
      return false;
    }
};

$('#outer').on('mouseout', function(event) {
    if (!$(event.relatedTarget).isChildOf("outer")) {
        mouseIsOverMenu = false;
        menu_rollin();
    }
});

Although this is a minimal example, I did nearly the same with pure JS, where it worked fine. So I guess it's something in the jQuery part. Since these are my first steps with jQuery, it is even more likely.

Every help you can provide is highly appreciated :)

[UPDATE]

I got it working now. The problem was that I didn't check for the relatedTarget to be "outer" itself. So when the mouse leaves the content div and enters the outer div, mouseout fires and of course, outer is no child of itself. So I amended it to

$('#outer').on('mouseout', function(event) {
    if (!(event.relatedTarget.id == "outer") &&    
        !$(event.relatedTarget).isChildOf("outer")) {
        mouseIsOverMenu = false;
        menu_rollin();
    }
});

and that fixed the problem.

Dennis
  • 125
  • 7
  • 2
    I cannot see any problem with fiddle, works fine for me (chromium) – igor Dec 19 '13 at 13:30
  • its working fine mate....check for any `addon` or `plugin` in your browser which might be hindering something! – NoobEditor Dec 19 '13 at 13:32
  • I've just checked it with chromium and firefox nightly on linux (Debian Wheezy) and with Chrome, Firefox, Opera, and IE on Windows 7. Chrome and Firefox behave like described on both OS: moving from the gray area to the dark gray area rolls in the menu and immediately out again. Opera and IE don't start the rollout at all. But on the actual site (here locally), they do the exactly same. – Dennis Dec 19 '13 at 13:49
  • actually it works also for me. It collapses only after getting out of the gray areas. – nowhere Dec 19 '13 at 13:50
  • I've forgotten to mention: you will have to increase the width of the result panel until its width is wider then 960px, sorry. Did you do this? – Dennis Dec 19 '13 at 13:56
  • Increased width to almost 2 full screens and tested with FF 26.0 on Win7. Seems fine. – Dan Iveson Dec 19 '13 at 13:58
  • Ok, this is weird. How can it be that I can reproduce the behavior on different machines with different OS and different browsers, while it seems to work for all others? Good news is, my general idea still seems to work ;) Hopefully someone will get this behavior too. Meanwhile, thanks for checking to you. – Dennis Dec 19 '13 at 14:08

2 Answers2

0

if i understood your question right.

This might help

$('#inner').on('mouseover', function() {
        mouseIsOverMenu = true;
        setTimeout(menu_rollout, 500);
    });

    $('#inner').on('mouseout', function(event) {
        if (!$(event.relatedTarget).isChildOf("outer")) {
            mouseIsOverMenu = false;
            menu_rollin();
        }
    });

What i did is i have changed the id of #outer to #inner.

  • Thanks for your input but if I used this, the menu wouldn't open when you hover somewhere over the outer wrapper expect the handle. The menu shall also close when you leave the outer wrapper. Your change wouldn't close it if one leaves outer wrapper left or right of the centered inner wrapper. – Dennis Dec 19 '13 at 14:17
0

This is a dirty hack, but your problem seems to be with the mouseout function applying too frequently, and what functionality you really want is capturing the mouse leaving the bottom of the menu/content.

Here's some code that will do just that.

$('#outer').on('mouseout', function(event) {
    if(event.clientY >= document.getElementById('outer').offsetHeight){
        mouseIsOverMenu = false;
        menu_rollin();
    }
});

here's the associated jsFiddle

Mike
  • 874
  • 1
  • 8
  • 15