Using Bootstrap 4 v6, I have the following navigation:
I'm trying to set the active class on the selected menu item, but nothing I've done has worked.
The closest that I've come is with this code:
$(document).ready(function() {
$('.navbar ul li').click(function(e) {
$('.navbar ul li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
e.preventDefault();
});
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse fixed-top">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">DCH</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="index.php">Home</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Feline Diabetes</a>
<div class="dropdown-menu bg-inverse navbar-inverse">
<a class="dropdown-item" href="treatment.php">Treatment</a>
<a class="dropdown-item" href="insulin.php">Insulin and Testing</a>
<a class="dropdown-item" href="relatedconditions.php">Related Conditions</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="nutrition.php">Nutrition</a>
</li>
<li class="nav-item">
<a class="nav-link" href="protocol.php">Protocol</a>
</li>
<li class="nav-item">
<a class="nav-link" href="links.php">Links</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://diabeticcathelp.com/forum" target="_blank">Forum</a>
</li>
<li class="nav-item">
<a class="nav-link" href="contact.php">Contact Us</a>
</li>
</ul>
</div>
</nav>
It does change the active class to the clicked menu item, but it does not change the pages. It also doesn't work on the submenu items, though I think that I would need different code to see if those particular items were clicked and I haven't gotten that far. First, I'd like to get past the page switching issue. If I remove the e.preventDefault()
call, then the pages shift, but the menu items are not changed to active.
Any ideas on how I might make this work?
Update. I have this working for everything except for the submenus. I'm using the following code, which is adapted from one of the answers in this thread:
$(document).ready(function () {
var listItems = $('.navbar ul li');
$.each(listItems, function (key, litem) {
var aElement = $(this).children(litem)[0];
if(aElement == document.URL) {
$(litem).addClass('active');
}
});
});
The only thing that I'm missing is the adding active to the submenu items. This code is taking the first child item of .navbar ul li items and doing the comparison to see if I need to add the active class. I know that when I have an li with a class of .nav-item .dropdown that I need to step through the children of the .dropdown-menu, and check there. I'm just struggling to figure out how. I really need to take a JQuery course.
Further edit:
After playing with this for a few hours, I have a solution that works for what I'm trying to do:
var setSubItemParent = false;
$(document).ready(function () {
var listItems = $('.navbar ul li');
$.each(listItems, function(key, litem) {
iterateLinks(litem);
})
});
function iterateLinks(liItem) {
var divchildren = $(liItem).children('div');
setSubItemParent = false;
/* If there are div children, iterate them */
if (divchildren.length > 0) {
iterateLinks(divchildren[0]);
/* If an item was set and we're in a div, add active to
this element as well. */
if(setSubItemParent) {
$(liItem).addClass('active');
}
}
else {
var achildren = $(liItem).children('a');
/* Run through all a tags and see if they should be active */
if (achildren.length > 0 ) {
$.each(achildren, function(key, achild) {
if (achild.href == document.URL) {
$(achild).addClass('active');
setSubItemParent = true;
}
});
}
}
}
The code runs through all of the li elements in the menu and digs further if it finds a div. This probably isn't the most robust solution to the problem, but it does work. I am open to a better solution, however.