Question

Im working on a multilevel accordeon menu using Jquery. Everything works fine when toggle the first submenu but when i have one more level of submenus they don't show up / don't do anything. Im pretty sure it's because of something im not doing quit well with the css treatment on the jquery but i just can't figure it out.

Here's the online test:

Example

You can check the problem clicking on the first option ("Actualitat dia a dia") and then on the last item of the submenu ("Actualidad") that have also a submenu but it doesn't show up or toggle.

Here's the jquery

$(document).ready (function(){
    $(".menu-desplegable > ul > li:has(ul)").addClass("has-sub");

    $('.menu-desplegable > ul > li > a').click(function() {
    var checkElement = $(this).next();
    $('.menu-desplegable li').removeClass('active');            
    $(this).closest('li').addClass('active');

        if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
        $(this).closest('li').removeClass('active');
        checkElement.slideUp('normal');
    }

        if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
        $('.menu-desplegable ul ul:visible').slideUp('normal');
        checkElement.slideDown('normal');
        }

        if (checkElement.is('ul')) {
        return false;
    } else {
    return true;    
     }
       });
    });     

Was it helpful?

Solution

You have set the click element to be .menu-desplegable > ul > li > a so only the direct child a is bound to that listener.

You need to change your click element to .menu-desplegable > ul li a so that a nested ul li a can be clicked. Then you need to change the block that handles sliding the ul up.

Change:

if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
    $('.menu-desplegable ul ul:visible').slideUp('normal');
    checkElement.slideDown('normal');
}

To:

if (checkElement.is('ul') && !checkElement.is(':visible')) {
    checkElement.slideDown('normal');
}

Live example.

OTHER TIPS

I have the working solution in this fiddle. http://jsfiddle.net/QQBbe/6/

Basically just change the javascript as follows:

$(".menu-desplegable ul li:has(ul)").addClass("has-sub");

// this will prevent the nested menu items from triggering 
// the .has-sub click event as it applies to itself and all of it's children
$('.menu-desplegable').on("click", "li", function (e) {

    e.preventDefault();
    e.stopPropagation();
});

// I would delegate the on click event like this, 
// in case you decide to dynamically add more menu options
$('.menu-desplegable').on("click", ".has-sub", function (e) {

    e.preventDefault();
    e.stopPropagation();

    // if the targets nested ul is not visible, display it
    if (!$(this).hasClass("active")) {

        $(this).addClass("active");
        $(this).children("ul").slideDown('normal');
    } else {

        $(this).removeClass("active");
        $(this).children("ul").slideUp('normal');
    }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top