2

I have a nested ul "tree" that, for the sake of this question, is only a couple levels at the top and a couple children, but if you could assume that from the top ul (targeted with id="group" here) that there could be several nested elements, but they will always follow this structure. At the moment I only have the top elements collapsing their children ul elements on collapse. I want to achieve this nature throughout all of the ul elements. Furthermore, I want to also collapse open elements "at the same level" of another clicked so that only one ul with another is open. I hope I've explained the feature I'm trying to accomplish. I feel like I should be using slideToggle() but every attempt with it has ended poorly... I should also say that this is my first hand at actually using delegate() but I understand the propagation ("event bubbling") and is part of the reason I feel like it's the way to go for such a task. The other being that I may need to append new elements into the ul. So here's what I have currently:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('ul#group').delegate('a', 'click', function(event) {
            if($(event.target).next().is(':visible')) {
                if($(event.target).next()) {
                    $(event.target).next().find('ul').slideUp(250, function() {
                        $(event.target).next().slideUp(250);
                    });
                }
            } else {
                $(event.target).next().slideDown(250);
            }
        });
    });
</script>
<ul id="group">
    <li>
        <a href="#" onclick="return false;">Foo Bar 1</a>
        <ul>
            <li>
                <a href="#" onclick="return false;">Foo 1</a>
                <ul>
                    <li>
                        <a href="#" onclick="return false;">Bar 1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#" onclick="return false;">Foo 2</a>
                <ul>
                    <li>
                        <a href="#" onclick="return false;">Bar 2</a>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
    <li>
        <a href="#" onclick="return false;">Bar Foo 2</a>
        <ul>
            <li>
                <a href="#" onclick="return false;">Bar 1</a>
                <ul>
                    <li>
                        <a href="#" onclick="return false;">Foo 1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#" onclick="return false;">Bar 2</a>
                <ul>
                    <li>
                        <a href="#" onclick="return false;">Foo 2</a>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

And here's a jsfiddle link to the test case. All input is welcome to the best way this can be accomplished.

edward.louis
  • 357
  • 2
  • 5
  • 14

3 Answers3

1

Is something like this what you're after: http://jsfiddle.net/GSEDy/3/

I made some edits.

$('ul#group').delegate('a', 'click', function(event) {
    if ($(event.target).next().is(':visible')) {
        $(event.target).next().find('ul').slideUp(250, function() {
            $(event.target).next().slideUp(250);
        });
    } else {
        $(event.target).parent().siblings().find("ul").slideUp(250);
        $(event.target).next().slideDown(250);
    }
});​
ahren
  • 16,803
  • 5
  • 50
  • 70
1

Simpler one:

$('ul#group').delegate('a', 'click', function(event) {
  $(this).parent().children('ul').slideToggle(250);  
});
// At beginning hide elements preferably with css
$('ul#group').find('ul').hide();​​​​​​​

Without collapsing elements at the same level.

Here it is.

Alexander
  • 23,432
  • 11
  • 63
  • 73
0

While I would prefer the other solutions, I will provide an alternate route for sake of example. I made a jQuery plugin that creates a clickOut pseudo-event a while back in which I utilized the minified version for. The advantage of this is that the user can click outside of the menu and menus will collapse. http://jsfiddle.net/GSEDy/7/

$('#group li').click(function (event) {
    'use strict';
    $(this).children('ul').slideToggle(250, function () {
        $(this).find('ul').hide();
    });
    $(this).siblings().children('ul').each(function () {
        $(this).slideUp(250, function () {
            $(this).find('ul').hide();
        });
    });
    event.stopPropagation();
}).clickOut(function () {
    'use strict';
    $(this).children('ul').slideUp(250, function () {
        $(this).find('ul').hide();
    });
});​
Tyler Crompton
  • 12,284
  • 14
  • 65
  • 94