Reputation: 5770
Using twitter bootstrap, and I need to initiate active class to the li portion of the main nav. Automagically. We use php not ruby.
Sample nav :
<ul class="nav">
<li><a href="/">Home</a></li>
<li><a href="/forums">Forums</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/faqs.php">FAQ's</a></li>
<li><a href="/item.php">Item</a></li>
<li><a href="/create.php">Create</a></li>
</ul>
Bootstrap code is as follows:
<li class="active"><a href="/">Home</a></li>
So just need to figure out how to append the class active to the current page. Have looked thru nearly every answer on Stack, with no real joy.
I had played with this:
/*menu handler*/
$(function(){
var url = window.location.pathname;
var activePage = url.substring(url.lastIndexOf('/')+1);
$('.nav li a').each(function(){
var currentPage = this.href.substring(this.href.lastIndexOf('/')+1);
if (activePage == currentPage) {
$(this).parent().addClass('active');
}
});
})
But no joy.
Upvotes: 58
Views: 151702
Reputation: 931
There is a hitch with the accepted answer in some rare cases for bootstrap 4: In order to use the solution for relative paths like:
<ul class="navbar-nav nav-t">
<li class="nav-item"><a href="index.php" class="nav-link">Home</a></li>
<li class="nav-item"><a href="about.php" class="nav-link">About</a></li>
<li class="nav-item"><a href="blog.php" class="nav-link">Blog</a></li>
<li class="nav-item"><a href="info.php" class="nav-link">Info</a></li>
</ul>
Then you will find out that the code for:
if (activePage == currentPage) {
$(this).parent().addClass('active');
}
active page returns the whole url and current location returns the current href DOM Element value which is filename.php. To solve this just tweak the code a little by adding a method to correct this:
//... other js/jquery code
var activeMenuItemChanges=function () {
function stripTrailingSlash(str) {
if(str.substr(-1)=='/'){
return str.substr(0, str.length -1);
}
return str;
}
// for cases where we do not use full url but relative file names in the href of ul>li>a tags:
function getRelativeFileName(str){
let page=str.substr(str.lastIndexOf('/')+1);
if(page.length > 0){
return page;
}
return 'index'|'index.php';
}
let url=window.location.pathname;
let activeLocation=stripTrailingSlash(url);
let activeFileName=getRelativeFileName(activeLocation);
$('.nav-item a').each(function() {
let currentLocation=stripTrailingSlash($(this).attr('href'));
if(activeFileName==currentLocation){
$(this).parent().addClass('active');
}
});
}
activeMenuItemChanges();
//... other js/jquery code
Upvotes: 1
Reputation: 2524
For Bootstrap 3:
var url = window.location;
// Will only work if string in href matches with location
$('ul.nav a[href="'+ url +'"]').parent().addClass('active');
// Will also work for relative and absolute hrefs
$('ul.nav a').filter(function() {
return this.href == url;
}).parent().addClass('active');
For Bootstrap 4:
var url = window.location;
// Will only work if string in href matches with location
$('ul.navbar-nav a[href="'+ url +'"]').parent().addClass('active');
// Will also work for relative and absolute hrefs
$('ul.navbar-nav a').filter(function() {
return this.href == url;
}).parent().addClass('active');
Upvotes: 130
Reputation: 283
$(function() {
// Highlight the active nav link.
var url = window.location.pathname;
var filename = url.substr(url.lastIndexOf('/') + 1);
$('.navbar a[href$="' + filename + '"]').parent().addClass("active");
});
For more details Click Here!
Upvotes: 0
Reputation: 1791
I had the same problem, and this is what I added in my app launch script, and it worked smoothly. Here is the javascript
$(document).ready(function($){
var navs = $('nav > ul.nav');
// Add class .active to current link
navs.find('a').each(function(){
var cUrl = String(window.location).split('?')[0];
if (cUrl.substr(cUrl.length - 1) === '#') {
cUrl = cUrl.slice(0,-1);
}
if ($($(this))[0].href===cUrl) {
$(this).addClass('active');
$(this).parents('ul').add(this).each(function(){
$(this).parent().addClass('open');
});
}
});
});
And the corresponding HTML is shown below. I'm using CoreUI, a phenomenal open source admin template and has support for many front end frameworks like Angular, plain bootstrap, Angular 4 etc.
<div class="sidebar">
<nav class="sidebar-nav open" >
<ul class="nav" id="navTab" role="tablist">
<li class="nav-item">
<a class="nav-link" href="/summary"><i class="icon-speedometer"></i> Dashboard </a>
</li>
<li class="nav-item">
<a class="nav-link" href="/balanceSheet"><i class="icon-chart"></i> Balance Sheet </a>
</li>
<li class="divider"></li>
<li class="nav-title border-bottom">
<p class="h5 mb-0">
<i class="icon-graph"></i> Assets
</p>
</li>
</ul>
</nav>
</div>
Upvotes: 1
Reputation: 1447
The solution is simple and there is no need for server side or ajax, you only need jQuery and Bootstrap. On every page add an id
to the body
tag. Use that id
to find a tag that contains the page name (value of a tag).
Example:
page1.html
<body id="page1">
<ul class="nav navbar-nav">
<li><a href="page1.html">Page1</a></li>
<li><a href="page2.html">Page2</a></li>
</ul>
<script src="script.js"></script>
</body>
page2.html
<body id="page2">
<ul class="nav navbar-nav">
<li><a href="page1.html">Page1</a></li>
<li><a href="page2.html">Page2</a></li>
</ul>
<script src="script.js"></script>
</body>
script.js
<script>
$(function () {
$("#page1 a:contains('Page1')").parent().addClass('active');
$("#page2 a:contains('Page2')").parent().addClass('active');
});
</script>
Big thanks to Ben! YouTube
Upvotes: 1
Reputation: 343
Try this.
// Remove active for all items.
$('.page-sidebar-menu li').removeClass('active');
// highlight submenu item
$('li a[href="' + this.location.pathname + '"]').parent().addClass('active');
// Highlight parent menu item.
$('ul a[href="' + this.location.pathname + '"]').parents('li').addClass('active');
Upvotes: 6
Reputation: 5887
This did the job for me including active main dropdowns and the active childrens (thanks to 422):
$(document).ready(function () {
var url = window.location;
// Will only work if string in href matches with location
$('ul.nav a[href="' + url + '"]').parent().addClass('active');
// Will also work for relative and absolute hrefs
$('ul.nav a').filter(function () {
return this.href == url;
}).parent().addClass('active').parent().parent().addClass('active');
});
Upvotes: 10
Reputation: 1076
To activate the menus and submenus, even with params in the URL, use the code bellow:
// Highlight the active menu
$(document).ready(function () {
var action = window.location.pathname.split('/')[1];
// If there's no action, highlight the first menu item
if (action == "") {
$('ul.nav li:first').addClass('active');
} else {
// Highlight current menu
$('ul.nav a[href="/' + action + '"]').parent().addClass('active');
// Highlight parent menu item
$('ul.nav a[href="/' + action + '"]').parents('li').addClass('active');
}
});
This accepts URLs like:
/posts
/posts/1
/posts/1/edit
Upvotes: 0
Reputation: 1952
This works fine for me. It marks both simple nav elements and dropdown nav elements as active.
$(document).ready(function () {
var url = window.location;
$('ul.nav a[href="' + this.location.pathname + '"]').parent().addClass('active');
$('ul.nav a').filter(function() {
return this.href == url;
}).parent().parent().parent().addClass('active');
});
Passing this.location.pathname
to $('ul.nav a[href="'...'"]')
marks also simple nav elements. Passing url
did'nt work for me.
Upvotes: 3
Reputation: 123
Just in case you are using Boostrap in Angulajs: this is a simple directive that works for me (because data-toggle cited by Kam is not included in Angular-ui). Hope can help.
app.directive("myDataToggle", function(){
function link(scope, element, attrs) {
var e = angular.element(element);
e.on('click', function(){
e.parent().parent().children().removeClass('active');
e.parent().addClass("active");
})
}
return {
restrict: 'A',
link: link
};
});
<ul class="nav nav-sidebar">
<li><a href="#/page1" my-data-toggle>Page1</a></li>
<li><a href="#/page2" my-data-toggle>Page2</a></li>
<li><a href="#/page3" my-data-toggle>Page3</a></li>
</ul>
Upvotes: 2
Reputation: 517
You don't really need any JavaScript with Bootstrap:
<ul class="nav">
<li><a data-target="#" data-toggle="pill" href="#accounts">Accounts</a></li>
<li><a data-target="#" data-toggle="pill" href="#users">Users</a></li>
</ul>
To do more tasks after the menu item is selected you need JS as explained by other posts here.
Hope this helps.
Upvotes: 30
Reputation: 36413
If you are using an MVC framework with routes and actions:
$(document).ready(function () {
$('a[href="' + this.location.pathname + '"]').parent().addClass('active');
});
As illustrated in this answer by Christian Landgren: https://stackoverflow.com/a/13375529/101662
Upvotes: 8
Reputation: 135
if you put
data-toggle="pill"
in the tag it should work automatically.
http://twitter.github.com/bootstrap/javascript.html#tabs
read under Markup
Upvotes: 13
Reputation: 155
None of these worked for me. My Bootstrap setup navigates to separate pages (so I can't do it on a click action, but the active class is removed on the navigation to a new page), and my urls don't match exactly. So here's what I did, based on my exception-based situation. Hope it helps others:
//Adding the active class to Twitter bootstrap navs, with a few alternate approaches
$(document).ready(function() {
var rawhref = window.location.href; //raw current url
var newpage = ((window.location.href.match(/([^\/]*)\/?$/)[1]).substring(1)); //take only the last part of the url, and chop off the first char (substring), since the contains method below is case-sensitive. Don't need to do this if they match exactly.
if (newpage == 'someNonMatchingURL') { //deal with an exception literally
newpage = 'matchingNavbarText'
}
if (rawhref.indexOf('somePartofURL') != -1) { //look for a consistent part of the path in the raw url to deal with variable urls, etc.
newpage = "moreMatchingNavbarText"
}
$(".nav li a:contains('" + newpage + "')").parent().addClass('active'); //add the active class. Note that the contains method requires the goofy quote syntax to insert a variable.
});
Upvotes: 0
Reputation: 5770
We managed to fix in the end:
/*menu handler*/
$(function(){
function stripTrailingSlash(str) {
if(str.substr(-1) == '/') {
return str.substr(0, str.length - 1);
}
return str;
}
var url = window.location.pathname;
var activePage = stripTrailingSlash(url);
$('.nav li a').each(function(){
var currentPage = stripTrailingSlash($(this).attr('href'));
if (activePage == currentPage) {
$(this).parent().addClass('active');
}
});
});
Upvotes: 37
Reputation: 9080
Here is complete Twitter bootstrap example and applied active class based on query string.
Few steps to follow to achieve correct solution:
1) Include latest jquery.js and bootstrap.js javascript file.
2) Include latest bootstrap.css file
3) Include querystring-0.9.0.js for getting query string variable value in js.
4) HTML:
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li class="active">
<a href="#?page=0">
Home
</a>
</li>
<li>
<a href="#?page=1">
Forums
</a>
</li>
<li>
<a href="#?page=2">
Blog
</a>
</li>
<li>
<a href="#?page=3">
FAQ's
</a>
</li>
<li>
<a href="#?page=4">
Item
</a>
</li>
<li>
<a href="#?page=5">
Create
</a>
</li>
</ul>
</div>
</div>
</div>
JQuery in Script Tag:
$(function() {
$(".nav li").click(function() {
$(".nav li").removeClass('active');
setTimeout(function() {
var page = $.QueryString("page");
$(".nav li:eq(" + page + ")").addClass("active");
}, 300);
});
});
I have done complete bin, so please click here http://codebins.com/bin/4ldqpaf
Upvotes: 0