3

I have a couple nested & hidden sub-nav lists

<ul class="nav">
<li><a href="index.html">Home</a></li>
<li><a class="profile" href="#">Profile</a>
    <ul id="profile">
        <li><a href="company.html">Company</a></li>
        <li><a href="structure.html">Structure</a></li>
        <li><a href="team.html">Team</a></li>
    </ul>
</li>

<li><a class="projects" href="#">Projects</a>
    <ul id="projects">
        <li><a href="chapter.html">Chapter</a></li>
        <li><a href="pblc-trde.html">Pblc Trde</a></li>
        <li><a href="globe.html">Globe</a></li>
        <li><a href="komforte.html">Komforte</a></li>
    </ul>
</li>    

I am currently using some jQuery i found online to show/hide the sub-nav upon click. What I am trying to accomplish is:

  1. Hopefully clean up the show/hide click function of the sub-nab menus.

  2. When clicking on the sub-nav menu items, the corresponding page that opens, needs to have the sub-nav expanded and give the corresponding menu item active class, so as to let the user know which page they are on.

  3. I am hoping to do this purely in JS/jQuery. The installation of the site will be in WordPress.

    $(document).ready(function () {
    
    $(".profile").click(function () {
        var X = $(this).attr('id');
        if (X == 1) {
            $("#profile").hide();
            $(this).attr('id', '0');
        } else {
            $("#profile").show();
            $(this).attr('id', '1');
        }
    
    });
    
    //Mouse click on nav
    $("#profile").mouseup(function () {});
    
    
    //Document Click
    $(document).mouseup(function () {
        $("#profile").hide();
        $(".profile").attr('id', '');
    });
    
    
    $(".projects").click(function () {
        var X = $(this).attr('id');
        if (X == 1) {
            $("#projects").hide();
            $(this).attr('id', '0');
        } else {
            $("#projects").show();
            $(this).attr('id', '1');
        }
    
    });
    
    //Mouse click on nav
    $("#projects").mouseup(function () {});
    
    //Document Click
    $(document).mouseup(function () {
        $("#projects").hide();
        $(".projects").attr('id', '');
    });
    });
    
    window.onload = function () {
     $("ul#profile li:first").addClass("active");
    };
    
     $(document).ready(function () {
      $("ul#profile").show()
    });
    
Brandon Leung
  • 50
  • 2
  • 10
  • You can use a combination of `document.location.href` (you'll need to do some manipulation of it) and `$('a[href=something]')` to find the link which points to the current page. – Dave Mar 18 '13 at 23:36
  • I added comments to the code in my answer, and made some tweaks to improve handling of more than one level of sub-menus. – Whistletoe Mar 19 '13 at 02:04

2 Answers2

1
$(document).ready(function()
{
    // Get the name of the page. Split the URL at the '/':s and get the last part
    // with pop():
    var pageName = (location.pathname).split('/').pop();

    // If we couldn't get a page name, default to index.html:
    if( pageName == '' )
    {
        pageName = 'index.html';
    }

    // Hide ul:s that are children of the navigation:
    $('.nav ul').hide();

    // Event handler for clicks on navigation links:
    $('.nav a').on('click', function()
    {
        // Change visibility for the first ul-child of the current li.
        // $(this) refers to the clicked element.
        $(this).parent('li').find('ul').first().toggle();

        // Hide other sub-menus:
        $(this).parents('li').siblings('li').children('ul').hide();
    });

    // Search through all link elements in the nav menu:
    $('.nav').find('a').each(function(index, value)
    {   
        // Append a '$' to the pagename to make the match()-function search
        // from the end of the href value:
        pageName += '$';

        if( value.href.match(pageName))
        {
            // If the pagename matches the href-attribute, then add the 'active'
            // class to the parent li, and show parent ul:s:
            $(this).parent('li').addClass('active').parents('ul').show();    
        }
    });
});
Whistletoe
  • 573
  • 2
  • 10
  • Sir, you are amazing!! This works in exactly the fashion I was hoping for. I will take the time to review what you wrote and try to break it down and understand it. Thank you so much! – Brandon Leung Mar 19 '13 at 01:12
  • There is only one small issue I see. When you have either of the sub nav menus open, and you click to open the other sub nav, it does not hide the previous sub nav – Brandon Leung Mar 19 '13 at 01:14
  • Edited to hide other sub-navs on click. – Whistletoe Mar 19 '13 at 01:21
  • Perfect. Can't thank you enough, this has been bugging me for almost 2 weeks. I can move on finally. =) – Brandon Leung Mar 19 '13 at 01:23
0

You could use a Cookie to hold the value of the currently open menu. This will allow for the value to be saved/retrieved between page loads and browser sessions.

As you've already got jQuery setup you can use the jQuery Cookie plugin to simplify things.

The code for it is quite simple (more examples on plugin page).

$.cookie('open_menu', 'projects'); //Save 'projects' under 'open_menu'
$.cookie('open_menu') //Returns 'projects'

Just check the value on page load and save it when one of the menu's is clicked.

If you'd prefer not to add any extra plugins here's some documentation on JavaScript's inbuilt cookie API.

Edit: I've created a JSFiddle with an example for you. The Cookie code doesn't seem to work in there sandbox, but the code should work for you, let me know if you have any troubles.

$(window).load(function() {
if ($.cookie('show_menu') !== undefined) {
    $('#' + $.cookie('show_menu')).click();
}

$('.nav > li > ul').each(function () {
    //Hide the sub lists
    $(this).hide();
    //Get link with same ID as Class
    var id = $(this).attr('id');
    //When link is clicked
    $('.' + id).click(function () {
        //Get the sub list
        var list = $('#' + $(this).attr('class'));
        //Check if it's currently visible
        if (list.is(':visible')) {
            list.hide(); //Hide list     
            $.cookie('show_menu', ''); //Unset open menu
        } else {
            $('.nav > li > ul').hide(); //Hide all other lists
            list.show(); //Show list
            $.cookie('show_menu', list.attr('class')); //Set open menu
        }
    });
});
});
Dracs
  • 437
  • 4
  • 20
  • I am still pretty new to hand coding js so using this js Cookie is pretty difficult for me. I understand the concept of what needs to happen, but I dont know how to implement. I know this may be a difficult/lengthy question to answer, but frankly, I am completely stuck, any examples will be greatly appreciated. – Brandon Leung Mar 19 '13 at 00:58
  • @BrandonLeung I've added in an JSFiddle for you and some example code which should work for your HTML layout. – Dracs Mar 19 '13 at 01:24