verism
verism

Reputation: 1164

Setting active states in nested elements

I have a menu with rudimentary nested lists as below:

<nav>
    <ul id="mainNav">

        <li><a href="expand-the-sub-menu">Option 1</a>
            <ul class="navChild">
                <li><a href="somewhere">Option 1 Link 1</a></li>
                <li><a href="somewhere">Option 1 Link 2</a></li>
                <li><a href="somewhere">Option 1 Link 3</a></li>
                <li><a href="somewhere">Option 1 Link 4</a></li>
                <li><a href="somewhere">Option 1 Link 5</a></li>
            </ul>
        </li>

        <li><a href="expand-the-sub-menu">Option 2</a>
            <ul class="navChild">
                <li><a href="somewhere">Option 2 Link 1</a></li>
                <li><a href="somewhere">Option 2 Link 2</a></li>
                <li><a href="somewhere">Option 2 Link 3</a></li>
                <li><a href="somewhere">Option 2 Link 4</a></li>
                <li><a href="somewhere">Option 2 Link 5</a></li>
            </ul>
        </li>

        <li><a href="somewhere">Option 3</a></li>
        <li><a href="somewhere">Option 4</a></li>
        <li><a href="somewhere">Option 5</a></li>
        <li><a href="somewhere">Option 6</a></li>
    </ul>
</nav>

And I've written some conditional script to produce the desired animated effect, depending on the current menu state:

$('#mainNav ul').hide();

$('#mainNav>li>a').click(function(){
    var elm = this;

    // If clicked element has a sibling ul with specified class
    if ($(elm).next().hasClass('navChild')){
        // ... & another child ul is already visible
        if ($('.navChild').is(':visible')){
            $('#mainNav ul').fadeOut(300, function() {
                $(elm).siblings('ul').fadeIn(300);
            });
        // ... & no child ul is visible
        } else {
            $('nav').animate({bottom:'60px'},300,function(){
               $(elm).next().fadeIn(300);
            });
        }

    // Else clicked element has no sibling ul with specified class
    } else {
        // ... & another child ul is already visible
        if ($('.navChild').is(':visible')){
            $('#mainNav ul').fadeOut(300, function(){
                $('nav').animate({bottom:'24px'});
            });
        // ... & no child ul is visible
        } else {
            // Follow link as usual
        }
    }
});

The code may be ugly and verbose, but it works.

What I'm trying to do now is highlight the current menu item. If it's a top-level <a> tag, then just that link should be highlighted. When in a child-level <a> tag, however, both that link and its parent link should be highlighted. Another caveat is that I'd like all child links to be in a non-active state when revealed by clicking on their parent link.

Here's a jsFiddle http://jsfiddle.net/pHwgk that almost works, If you show, hide, then re-show a child-level <ul>, you should hopefully see what I mean - i.e. I don't want it to remember the state it was previously in.

I'm hoping someone will have an elegant solution to save on my probably unnecessarily massive coding.

Upvotes: 0

Views: 580

Answers (2)

Madevil
Madevil

Reputation: 46

Tidy up some unnecessary code for better effects and result:

http://jsfiddle.net/Madevil/hBVqF/

You don't need .each() to .addClass() or manipulate in this case.

Upvotes: 0

Adam
Adam

Reputation: 44939

Take a look at this: http://jsfiddle.net/adamzr/ku6Yj/

I added:

$('.navChild>li>a').each(function(){
    $(this).addClass('off');
});

to be called whenever a main level link is clicked on. It will set all the lowerlevel links to the "off" state. This should eliminate the "memory effect" as well as ensure that sublevel links appear off before they are clicked on.

Upvotes: 1

Related Questions