Question

I'm trying to create a jQuery dropdow menu, so far it's working fine. Except that you can only open folders/trees, not close them again. I guess that i have to use EQ or Siblings in jQuery? But unfurtunately i don't know how to put them together - Could anyone show? :)

<ul class="nav">
    <li><a href="#">Test link</a></li>
    <ul class="nav">
        <li>Test under</li>
    </ul>
</ul>

jQuery(document).ready(function(){
    jQuery('.nav ul').css('display', 'none');

    jQuery('.nav li').click(function(){
        jQuery(this).find('ul:first').slideDown(); 
    })

})

//Simon

Was it helpful?

Solution

There is a syntax error with your markup - the only valid direct descendant of a <ul> element is <li>. If you want to nest your list, do it within the <li> itself:

<ul class="nav">
    <li>
        <a href="#">Test link</a>
        <ul class="nav">
            <li>Test under</li>
        </ul>
    </li>
</ul>

For toggling, we simply instruct to search for a sibling <ul> element and apply the .slideToggle() method to it when the link is clicked:

$(function() {
    // Hide submenus
    $(".nav ul").hide();

    // Toggle nested <ul> (siblings of the link)
    $(".nav > li > a").click(function(e) {
        $(this).siblings("ul").slideToggle();
        e.preventDefault();
    });
});

Here is a demo fiddle: http://jsfiddle.net/teddyrised/2y9fz/ (added more list items to demonstrate the effect)

OTHER TIPS

Use slideToggle(); instead of slideDown();, this will make it so it performs slideDown or slideUp depending on the current orientation.

this should help

Each part is labeled, so it's easy to understand. This is much more aware and thought through than just using slideToggle. Instead it creates situations where it should slide up or down distinctly, and reverts previous branches when another is selected.

$('.nav ul').each(function () {
    $(this).on('click', function(e) {
        e.stopPropagation();//ignore ul clicks
    }).parent().on('click', function () {//target only parents of a ul
        if($(this).hasClass('on')) {//if selected
            $(this).addClass('on').children('ul').slideUp();//slideup
        } else {//if not selected
            if($(this).parent('.nav')) {//if start of branch
                $(this).parent().find('.on').removeClass('on').find('ul').slideUp();//close other branches
            }
            $(this).addClass('on').children('ul').slideDown();//slideDown
        }
    });
});

It's recursive, and it only targets li that have a ul child. When you select a different branch it will also revert the previously opened branch. I removed the anchor tags, because the action was to be on click, and the links in the example didn't go anywhere. If it doesn't go anywhere, why does it need to have a link?

It also fixes the html formatting, to put the uls inside of the lis, instead of them being siblings. ie <li><ul><li></li></ul></li> instead of <li></li><ul><li></li></ul>.

made a fiddle: http://jsfiddle.net/filever10/gmL4x/

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