How to add class to current pages navigation link

I have a nab bar where the background and nav links change to show which page your on by using class=“active”. I want to be able to create a static header that is the same for each page so that when I change a link they all get changed.

I’m currently using this to insert a static header and footer


<script>
    $(function(){
      // $("#insert_header").load("header.html");
      $("#insert_footer").load("footer.html");
    });
</script>

<div id="insert_header"></div>

Here is the header.


<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav navbar-right">
        <li>
            <a href="#">Home</a>

        </li>

        <li class="active">
            <a href="about.html">Get to Know us</a>

        </li>

        <li>
            <a href="new-patients.html">New Patients</a>

        </li>

        <li>
            <a href="contact.html">Contact Us</a>

        </li>
    </ul>
</div>

I was thinking maybe each page can have a variable that says which page it is, but how can I dynamically add that class to the corresponding nab links <li>?

Hi,

I’m not really sure I understand your question.

You could create a static header and using PHP include it on every page:

<?php include_once("header.php"); ?>

Depends where / how you store the variable.
One possibility would be the url as a query string.
Another would be as a data-attribute on an element.
Yet another would be in some kind of client-side storage.

Sorry, let me try again. I already know how to insert a static header. The problem is that whichever page your on needs to have a class added to the nav structure so that it changes the color of that link in the menu.

here is the nab structure


<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav navbar-right">
        <li>
            <a href="#">Home</a>
            
        </li>
        
        <li class="active">
            <a href="about.html">Get to Know us</a>
            
        </li>

        <li>
            <a href="new-patients.html">New Patients</a>
            
        </li>
        
        <li>
            <a href="contact.html">Contact Us</a>
            
        </li>
    </ul>
</div>

notice how the about link has class=“active”.

So what I want to do is maybe have a variable at the top of the page


<script> 
  var= "about.html"
</script>

and then have a function that somehow finds this


<li class="active">
      <a href="about.html">Get to Know us</a>
 </li>

and ads

class="active"

to the li.

Any help with this would be greatly appreciated.

Hi,

That shouldn’t be too difficult to do, but just so that I understand correctly, what speaks against hard-coding the class into your navigation on a per page basis?

Is the code for the navigation in a PHP file wich is included via an include statement (as above)?

I don’t want to have the navigation hardcoded because there are 30 plus pages (including subpages) and they occasionally change.

Right now though the navigation is hardcoded on each page. I would like to have this nav structure stored in an html file (header.html)

<div id=“insert_header”></div>


<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav navbar-right">
        <li>
            <a href="#">Home</a>
            
        </li>
        
        <li>
            <a href="about.html">Get to Know us</a>
            
        </li>

        <li>
            <a href="new-patients.html">New Patients</a>
            
        </li>
        
        <li>
            <a href="contact.html">Contact Us</a>
            
        </li>
    </ul>
</div>

then use something like this to insert it.


<script> 
    $(function(){
      $("#insert_header").load("header.html");     
    });

 // then something here to find the page variable at the top of the page (var page = "about.html";)

// then something to look through the navigation and find the li that matches the variable (ex. "about.html ") 

// and then add class="active" to the corresponding li 

</script>

I hope that makes sense?

Ok, so you want the navigation in a seperate file and you want to pull that into each page using AJAX.

In that case, would it be a possibility to use a callback to set the current menu item?

$("#insert_header").load("header.html", function(){
  $('a[href="about.html"]').addClass("current");
});

Thanks!!! How can we do it so that the class=“active” gets added to the li rather than the a tag?


<li class="active" >
    <a href="contact.html">Contact Us</a>
</li>

Hi,

I’m back at my PC now. I was answering earlier on an iPad (which sucks).

So, on reflection it’s better to use the attribute ends with selector, so that you can select the anchor tags based on the file they link to and not have to worry about if you got the full path correct.

Then you can do:

$("#insert_header").load("header.html", function(){
  $('ul.nav a[href$="about.html"]').parent().addClass("current");
}); 

This will not only add a class of “current” to the anchor tag’s parent (the <li>), but will match:

<a href="about.html">About</a>
<a href="./about.html">About</a>
<a href="/path/to/about.html">About</a>
<a href="http://www.mysite.com/path/to/about.html">About</a>

By limiting the scope of the selector to anything contained in the <ul> tag, you avoid matching things like:

<a href="http://www.sitepoint.com/about.html">About SitePoint</a>

HTH

Thanks Pullo, that got it working. However, I think because it I’m using query to insert the menu after the page loads it is causing problems. The drop down menu no-longer opens on hover, but rather requires you to click on it now. Any ideas? here is the site: http://aaronhaas.com/hooper/

Yeah, the script inclusion order is the problem.
How are you initializing the dropdown hover functionality?
Is it just enough to include the plugin?
Do you have an unminified version of it?

I think the bootstrap js for the drop down takes care of initializing it. I could be wrong though. I know it works as is if I just paste the menu back in and don’t use the insert script.

What plugin should I include? Is that the js mentioned below?

I just uploaded and linked to the unminified version

Ok, try moving the plugin code to within a callback:

Remove this:

<script type="text/javascript" src="assets/hover-dropdown/bootstrap-hover-dropdown.min.js"></script>

Change this:

$("#insert_header").load("header.html");

To this:

$("#insert_header").load("header.html", function(){
  // Start Bootstrap Hover Dropdown
(function(e,t,n){if("ontouchstart"in document)return;var r=e();e.fn.dropdownHover=function(n){r=r.add(this.parent());return this.each(function(){var i=e(this),s=i.parent(),o={delay:500,instantlyCloseOthers:!0},u={delay:e(this).data("delay"),instantlyCloseOthers:e(this).data("close-others")},a=e.extend(!0,{},o,n,u),f;s.hover(function(n){if(!s.hasClass("open")&&!i.is(n.target))return!0;a.instantlyCloseOthers===!0&&r.removeClass("open");t.clearTimeout(f);s.addClass("open");s.trigger(e.Event("show.bs.dropdown"))},function(){f=t.setTimeout(function(){s.removeClass("open");s.trigger("hide.bs.dropdown")},a.delay)});i.hover(function(){a.instantlyCloseOthers===!0&&r.removeClass("open");t.clearTimeout(f);s.addClass("open");s.trigger(e.Event("show.bs.dropdown"))});s.find(".dropdown-submenu").each(function(){var n=e(this),r;n.hover(function(){t.clearTimeout(r);n.children(".dropdown-menu").show();n.siblings().children(".dropdown-menu").hide()},function(){var e=n.children(".dropdown-menu");r=t.setTimeout(function(){e.hide()},a.delay)})})})};e(document).ready(function(){e('[data-hover="dropdown"]').dropdownHover()})})(jQuery,this);
  // End Bootstrap Hover Dropdown
});

Does that help?

Thanks pull. I tried those changes on several different pages and still no luck. I also tried moving both the query script and your new script up to the head section, but then the menu didn’t show up at all. Any more ideas?

Well, as it goes … :slight_smile:

If you look at your page in the console, you see the following error:

Bad masonry element: null masonry.js:1776

So, I removed the masonry plugin:

<!--<script type="text/javascript" src="assets/masonry/masonry.js"></script>-->

and then in jquery.wp.custom.js, I commented out the following:

// Masonry
// var container = document.querySelector('#masonryWr');
// var msnry = new Masonry( container, {
//   itemSelector: '.item'
// });

And the menu worked fine (I returned the plugin to its original position):

 $("#insert_header").load("header.html");

<!-- Plugins -->
<script type="text/javascript" src="assets/hover-dropdown/bootstrap-hover-dropdown.min.js"></script>

HTH