In a menu of 3 levels, how to set a time when the event is mouseout on the second level to the third level?

Asked

Viewed 419 times

5

I have a menu with 3 levels vertically (similar to the globe.com), my problem is when I I am in the last item of the 2nd level(for example) and move the mouse to the 1st item of the 3rd level, Hover event in the 2nd level is activated and I miss the navigation not being able to reach the 3rd level level.

I need a solution similar to that of the globe, when I’m in the second level and I go to the 3rd, I need to set a time to reach the 3rd level.

My current script looks like this:

//manipula primeiro e segundo nivel
    $("#main-menu ul > li.mn-item-li").mouseenter(function (e) {
        var currentMenu = $(this);

        if (currentMenu.hasClass('sub-menu')) {
            currentMenu.find('.mn-item-a').addClass('active');
        }

        currentMenu.children('div').stop().show();

        //seta item do menu mais-visto aberto como padrão            
        currentMenu.find('.second-nivel').find('li').eq(0).find('a').addClass('active');
        $(".mn-maisvistos").css({ "visibility": "visible", "opacity": "1" });

        //seta altura do subnivel
        var heightSubnivel = currentMenu.find('.second-nivel').height();
        var widthtSubnivel = currentMenu.find('.second-nivel').width();
        currentMenu.find('.second-nivel').css({ 'height': heightSubnivel + 'px' });
        currentMenu.find('.third-nivel').css({ 'height': heightSubnivel + 'px' });

        //manipula segundo e terceiro nivel
        var timer;
        var teste = function () {

            currentMenu.find('.second-nivel > li a').mouseenter(function () {
                var dataSubNivel = $(this).data("menu-id");
                var indexSubNivel = $(this).parent().index();

                $('.second-nivel > li a').removeClass('active');

                if ($(this).parent().hasClass("subnivel")) {

                    //console.info(indexSubNivel)

                    $('.third-nivel > li').css('visibility', 'hidden');
                    $(this).parents('.second-nivel').next().find("." + dataSubNivel).css({ 'visibility': 'visible', 'opacity': '1' });
                    $(this).addClass('active');

                } else {

                    $('.third-nivel > li').css('visibility', 'hidden');
                    $(this).css("background-image", "none");
                }
                clearTimeout(timer);
            })
        }

        currentMenu.find('.second-nivel > li a').mouseleave(function () {
            $(this).off('mouseenter');
            timer = setTimeout(function () { teste() }, 500);
        });

        currentMenu.find('.second-nivel > li a').mousemove(function (event) {
            var pageCoords = "( " + event.pageX + ", " + event.pageY + " )";
            var clientCoords = "( " + event.clientX + ", " + event.clientY + " )";
            console.info("( event.pageX, event.pageY ) : " + pageCoords);               
        });

    }).mouseleave(function () {
        $(this).find('.third-nivel > li').css({ 'visibility': 'hidden', 'opacity': '0' });
        $(this).find('.second-nivel li a').removeClass('active');
        $(this).children("div").stop().hide();
        $(this).find('.mn-item-a').removeClass('active');
    });
  • Welcome! It’s possible to merge HTML so we can test with your code? ideally by making a jsFiddle (http://jsfiddle.net)

  • 1

    Welcome to Stackoverflow, please use jsfiddle.net and put your html and javascript code in it so we can use it to solve your problem, if you don’t know how to use jsFiddle, just edit your question and post your HTML code in it.

3 answers

1

Instead of creating a menu of your own - and because you’re already using jQuery - prefer to use a plugin that already does it for you:

Plugins are usually tested, have mechanisms to avoid problems like this and include features such as mobile device support.

There is the plugin Bootstrap 2, who uses his idea of a time, and the jQuery-menu-Aim who uses another strategy to avoid this problem.

1

Instead of using the .css() you could use the .animate(), so you could control how long the animation would take to happen.

currentMenu.find('.second-nivel').animate({ height: heightSubnivel }, 500);
currentMenu.find('.third-nivel').animate({ height: heightSubnivel }, 500);

In addition to being able to control the animation that each item will do to open and close, you can still control how long it will take. Any doubt see the documentation.

0

It would be nice to see HTML relevant to your problem to understand why, for example, you thought it necessary to "set the height of the sub-level". But, in a very general way, the type of menu you want to do does not require jQuery.

Using only the pseudo-class hover from CSS, it is possible to create a three-level menu similar to Globo.com. I made a very simple example, I didn’t bother to make it look good, but I hope the idea is clear: http://jsfiddle.net/AGzUL/

The trick was to use position: absolute to let one DIV appear on top of the other "naturally". The use of the class ativo allows one of the Divs to already open along with the second level of the menu. It is not ideal and does not work in all cases, but I left so in the name of simplicity.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.