3

I am currently trying to make a navigation-menu where an active-class is applied to the anchors whose href attributes that match the current URL, so I can style that anchor in a way that makes it stand out from the rest of the menu.

This is my mark-up:

<div id="sidebar">

  <h2>Navigation menu</h2>
  <h2 class="subnav"><a href="menu1/menu_item1">Menu item 1</a></h2>
  <h2 class="subnav"><a href="menu1/menu_item2">Menu item 2</a></h2>
  <h2 class="subnav"><a href="menu1/menu_item3">Menu item 3</a></h2>
  <h2 class="subnav"><a href="menu1/menu_item4">Menu item 4</a></h2>
  <h2 class="subnav"><a href="menu1/menu_item5">Menu item 5</a></h2>

</div> 

This is the jQuery:

   jQuery(function($) {

      // get the current url
      var path = location.pathname.substring(1); 

      // defining the top subnav anchor
      var $top_item = $('#sidebar h2:nth-child(2) a'); 

      // defining all subnav anchors
      var $all_items = $('#sidebar h2.subnav a'); 

      // defining the anchors with a href that matches the current url
      var $selected_item = $('#sidebar h2 a[@href$="' + path + '"]'); 

      // setting the selected menu item'class as active
      $selected_item.addClass('active'); 

      // THIS IS WHERE I THINK THE ERROR IS
      // if none of the h2.subnav's has a url that matches 
      // the current location then assume that it's the top one that's active:
      if ($all_items("href") !== path) $top_item.addClass('active');

  });

I am applying the active-class with jQuery, it works fine as long as there is a match between an anchors href and the location url. If the url don't match any of the anchors I want the active-class to be applied to the $top_item. That part of my jQuery doesn't work.

I can't see what the error is, but then again I'm somewhat of a Javascript/jQuery n00b. Any help would be appreciated.

John C
  • 3,052
  • 3
  • 34
  • 47
timkl
  • 3,299
  • 12
  • 57
  • 71
  • $all_items is a jQuery object with a bunch of matched links in it - if you want to check the href of each one, you would need to use something like .each() to cycle through. For example: $all_items.each(function(){alert($(this).attr("href"));}); – Nathan Long Nov 19 '08 at 20:27

4 Answers4

6

This should do want you want: mark the matching link, and failing that, mark your default one.

function markActiveLink() {

    //Look through all the links in the sidebar
   $("div#sidebar a").filter(function() {

      //Take the current URL and split it into chunks at each slash
      var currentURL = window.location.toString().split("/");

      //return true if the bit after the last slash is the current page name
      return $(this).attr("href") == currentURL[currentURL.length-1];

    //when the filter function is done, you're left with the links that match.
    }).addClass("active");

   //Afterwards, look back through the links. If none of them were marked,
   //mark your default one.
   if($("div#sidebar a").hasClass("active") == false) {
      $("div#sidebar h2:nth-child(2) a").addClass("active");
    }
 }

markActiveLink();

Also, I found an official tutorial on this on the jQuery Docs site - scroll to the bottom to see the jQuery code. It's tighter than mine, although it's not tailored to your situation.

Nathan Long
  • 122,748
  • 97
  • 336
  • 451
  • The first part worked great, just had to adjust it a bit to fit my url-scheme. I can't get the last snippet to work, however. I inspect the source with Firebug it shows that none of the anchors has the "active" class. – timkl Nov 19 '08 at 22:29
  • I think my selector syntax on the last line was the problem. I have edited it. Does this work? – Nathan Long Nov 19 '08 at 23:54
1

great read.. but, I have to make a suggestion.. even if the JS works perfectly, you really should keep all menu list items within an Unordered List (or Ordered List),.. as a best practice.. :)

1

Give this code a shot, its something I put together for the company that I work for.

// highlight tab function
var path = location.pathname;
var home = "/";
$("a[href='" + [path || home] + "']").parents("li").each(function() {   
    $(this).addClass("selected");
});
jrutter
  • 3,173
  • 9
  • 42
  • 51
0

I think you can simplify this a bit:

function highlightSelected()
{
  $("h2.subnav a").each(
    function()
    {
      if (location.pathname.indexOf(this.href) > -1)
      {
        $(this).addClass("selected");
      }
    }
  );
}
Tom
  • 22,301
  • 5
  • 63
  • 96