How To Highlight Show Active Tab In A Navbar-Fixed-Top - javascript

I am current changing a website to use Bootstrap and I have been advised that they want to use the navbar-inverse navbar-fixed-top main menu.
The thing is I can't figure out how to highlight the selected page and keep it highlighted.
I have tried the follow Jquery but I cant get none of them working
$(function() {
$('#nav li a').click(function() {
$('#nav li').removeClass();
$($(this).attr('href')).addClass('active');
});
});
My HTML for my menu is:
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" runat="server" href="~/">Logo Here</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a runat="server" href="~/"><span class="glyphicon glyphicon-home"></span></a></li>
<li style="border-left: 1px solid lightgray"><a runat="server" href="~/About">About</a></li>
<li style="border-left: 1px solid lightgray"><a runat="server" href="~/Session/pg1">Session</a></li>
<li style="border-left: 1px solid lightgray"><a runat="server" href="~/EmailPg">Email</a></li>
</ul>
<asp:LoginView runat="server" ViewStateMode="Disabled">
<AnonymousTemplate>
<ul class="nav navbar-nav navbar-right">
<li><a runat="server" href="~/Contact">Contact us</a></li>
</ul>
</AnonymousTemplate>
</asp:LoginView>
</div>
</div>
</div>
I would prefer if its possible to do it with CSS or Jquery but I was also a little confused as, do I add the Jquery to every page OR can I add one lot to my Site.Master file

You were not selecting the active li tag correctly.
Instead I suggest you use something like this:
$(function() {
$('#nav li a').click(function() {
$(this).closest('li') // select the parent <li> tag
.addClass('active')// add the active class
.siblings() // select the siblings of the active tag
.removeClass('active'); // remove the active class from the other <li>
});
});

Fixed by adding the below JQuery to my Site.Master file
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.navbar-nav a').filter(function () {
return this.href == url;
}).parent().addClass('active');

Related

How do I access these id's with javaScript

I have website with a javaScript function that should scroll to section on page when user clicks a navigation item. This script worked before I made changes to my nav menu. I can not figure out how to reference the ID's in the javaScript correctly.
Here is HTML nav menu:
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle Navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Data Detective</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a id="home" href="#homeSect">HOME</a></li>
<li><a id="about" href="#aboutSect">ABOUT</a></li>
<li><a id="portfolio" href="#portfolioSect">PORTFOLIO</a></li>
<li><a id="contact" href="#contactSect">CONTACT</a></li>
</ul>
</div>
</div>
</div>
Here is the javaScript:
$(document).ready(function() {
setBindings();
});
//Allow screen to Scroll to selected section
function setBindings() {
$("nav ul li a").click(function (tip) {
tip.preventDefault();
var sectionID = "#" + tip.currentTarget.id + "Sect";
alert('button id ' + sectionID);
$("html body").animate({
scrollTop: $(sectionID).offset().top
}, 1000);
});
}
You should use .navbar class.
Please change:
$("nav ul li a").click(function (tip) {
TO
$(".navbar ul li a").click(function (tip) {
Further more, I recommend you to use var sectionID = $(this).attr('href'); instead var sectionID = "#" + tip.currentTarget.id + "Sect"; because it's more simply.
Your jQuery selector:
$("nav ul li a")
will search for the element <nav> (which doesn't exist).
Instead, you can use the selector:
$(".nav a")
I would do a more useful global function I guess. I would check for any href with an anchor reference, check if there is a div with that id, and then scroll to that one.
That way you're not limited to the menu but can use the same code everywhere. Also I made the event caputurer the top level document, so you can insert and remove elements at hearts content and it will always work without having to be rebound.
$(document).on('click','a[href^="#"]',function(e) {
var target = $(e.currentTarget).attr('href');
var $target = $(target);
if($target.length > 0) {
$("html body").animate({
scrollTop: $target.offset().top
}, 1000);
}
});
div.sect {
margin:50px;
height:400px;
width:100%;
background-color:gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li><a id="blah" href="www.google.nl">Excluded</a></li>
<li><a id="home" href="#homeSect">HOME</a></li>
<li><a id="about" href="#aboutSect">ABOUT</a></li>
<li><a id="portfolio" href="#portfolioSect">PORTFOLIO</a></li>
<li><a id="contact" href="#contactSect">CONTACT</a></li>
<li><a id="blah" href="www.google.nl">Excluded</a></li>
<div class="sect" id="portfolioSect">
portfolioSect
</div>
<div class="sect" id="homeSect">
homeSect
</div>
<div class="sect" id="aboutSect">
aboutSect
</div>
<div class="sect" id="contactSect">
contactSect
</div>

How to Ensure Elements have Loaded Before Adding Class on PageLoad

I have the following bit of code, which first loads a navbar to the website on page load (this is so that I don't have to create a new navbar for each page):
<div id="nav"></div>
<script>$( "#nav" ).load( "nav.html" );</script>
And to show the "active" tab for that page, I have the following script:
<script>
window.onload = function() {
document.getElementById('lindex').className = 'active';
};
</script>
However, when the page loads, I am seeing this error in the console (for the document.getElementById line):
index.html:70 Uncaught TypeError: Cannot set property 'className' of null
And the "active" tab does not update when I navigate to the page. Strangely, it does seem to add the class when I reload the page, but intermittently. Does anyone know why this might be happening?
Here is the code for the navbar (nav.html):
<nav class="navbar navbar-inverse ">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<img src="/img/logo.png">
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li id="lindex" class="listitem">Home</li>
<li id="lpandp" class="listitem">Products & Purchasing</li>
<li>Freight & Distribution</li>
<li>Blog</li>
<li>Contact Us</li>
<li class="dropdown">
</li>
</ul>
</div>
</div>
</nav>
I have also tried:
$(function() {
$('#about').addClass('expand');
});
But this doesn't seem to work either, unless I refresh the page after navigating to it.
Try the following
<script>$( "#nav" ).load( "nav.html",function(){
$('#lindex').addClass('active');// add the class after the nav is loaded
});</script>
$( document ).ready(function() {
console.log( "ready!" );
$( "#nav" ).load( "nav.html");
console.log( "after load nav.html!" );
//add the class here
$('#lindex').addClass('active');
});
$("#lindex").addClass("Your Class Name");

Create a menu file with dynamic tabs

I am trying to make my website's menu in one file only and just include it in the rest of the .html pages. I am copy and pasting the menu each time I make a new page because I want the tab that is active to be highlighted for each different page. This is the reason why I can't make one file only for every page, and I have no idea how can I make it work to set the tab active in each different page.
This is the code I am copy-pasting in each page.
<!-- BEGIN MENU -->
<section id="menu-area">
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div id="navbar" class="navbar-collapse collapse">
<ul id="top-menu" class="nav navbar-nav navbar-right main-nav">
<li>Home</li>
<li>Downloads</li>
<li>Media</li>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown">Research <span
class="fa fa-angle-down"></span></a>
<ul class="dropdown-menu" role="menu">
<li>D3</li>
</ul></li>
<li>Team</li>
<li class="active">Contact</li>
</ul>
</div>
<!--/.nav-collapse -->
<a href="#" id="search-icon"> <i class="fa fa-search"> </i>
</a>
</div>
</nav>
</section>
<!-- END MENU -->
In this case the contact tab is highlighted:
<li class="active">Contact</li>
If the case is that the home page is active, then I would need to do this:
<li class="active">Home</li>
I hope I made myself clear, my English is terrible. I appreciate any idea, I am really new at web development.
One thing you can do is to read the URL and on base of that you add the active class to that link in your menu.
$(function() {
var pgurl = window.location.href.substr(window.location.href
.lastIndexOf("/")+1);
$("#nav ul li a").each(function(){
if($(this).attr("href") == pgurl || $(this).attr("href") == '' )
$(this).addClass("active");
})
});
Using D3
<script>
var pgUrl = window.location.href.substr(window.location.href.lastIndexOf('/') + 1);
d3.select("#navbar").selectAll("a").each(function(d){
if(d.tecode here == pgUrl )
d.attr("class","active");
});
</script>
I think this way more useful:
$(function(){
var pgUrl = window.location.href.substr(window.location.href.lastIndexOf('/') + 1);
$("#nav ul li a[href='"+ pgUrl +"']").addClass('active');
});

Getting navigation to display the selected page

I'm struggling with getting my navigation menu to show the selected page. I'm using the Bootstrap framework to build my site. This is my navigation menu:
<nav class="navbar">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/index.html">Digital Transformation</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav pull-right">
<li class="active">Transformation deck</li>
<li>Background information</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
As far as I can tell, Bootstrap uses the following JS to make the selected menu item active, which I have in my header:
<script>
$('label').click(function() {
$(this).parent('li').toggleClass('active');
});
</script>
However with this code my primary nav item is active on page load, but when I select the second item it keeps 'Tranformation deck' as active instead of 'Background information'.
Am I missing a trick here? Any help would be greatly appreciated.
If you want to hook up click listeners to your nav items, your script should be something like this:
<script>
$('#navbar nav li a').click(function() {
$(this).parent('li').toggleClass('active');
});
</script>
You don't have any 'label' tags in your code, so there isn't anything to attach click event handlers to.
$(function() {
// this will get the full URL at the address bar
var url = window.location.href;
// passes on every "a" tag
$("#navbar a").each(function() {
// checks if its the same on the address bar
if (url == (this.href)) {
$(this).closest("li").addClass("active");
}
});
});

More efficient way of listening for jQuery hasClass method?

I'm trying to listen if an element with the id of dropdown has the class open. If #dropdown has .open, add class badge-border to class badge. If #dropdown doesn't have .open, remove class badge-border from class badge. Here is my code:
HTML:
<!doctype html>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>Language (EN)
</li>
<li>Currency ($)
</li>
<li><i class="fa fa-user"></i> My Account
</li>
<li class="dropdown" id="dropdown"> <i class="fa fa-shopping-cart"><span class="badge">36</span></i> My Cart
<ul class="dropdown-menu" id="dropdown-menu">
<li>Action
</li>
<li>Another action
</li>
<li>Something else here
</li>
<li role="separator" class="divider"></li>
<li>Separated link
</li>
</ul>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/vendor/jquery-1.11.3.min.js"><\/script>')
</script>
</body>
JS:
$(document).ready(function () {
var interval = setInterval(changeBadge, 1);
function changeBadge() {
if ($('#dropdown').hasClass('open')) {
console.log('add class border');
// clearInterval(interval);
$(".badge").addClass("badge-border");
} else {
console.log('remove class border');
$(".badge").removeClass("badge-border");
}
};
});
The above way works to accomplish my goals, but I have a feeling that listening to an event every 1 millisecond isn't the best way to do it.
To make more sense of all this, you can view the demo here: http://jsfiddle.net/obliviga/qt7o3u6e/2/
You will need to maximize the viewport until the navbar is not in mobile mode, then click the shopping cart dropdown to see the badge's border added.
EDIT:
The reason why I implemented the way I did is because when the user clicks out of the cart dropdown, it should close, and the styles should revert to how they were before.
Consider using Mutation Observers intended exactly to track DOM changes, including changes of attribute values.
Note that IE supports Mutation Observers since version 11. For IE 10 and older, a fallback is needed.
EDIT: The reason why I implemented the way I did is because when the
user clicks out of the cart dropdown, it should close, and the styles
should revert to how they were before.
Updated , Added click event attached to document which removes .open class from #dropdown if present , calls handler of #dropdown a click event with this set to #dropdown a , with handler remove .badge-border class from .badge element which should revert styles of .badge to properties initially set at css.
Try attaching click event to selector $("#dropdown a") , calling .delay(1) on $(this).parents("#dropdown") within handler , .queue() function to check for open class , .toggleClass() to set $(this).parents("#dropdown") class on $(this).parents("#dropdown") with second argument Boolean $(this).parents("#dropdown")
$(document).ready(function () {
function changeBadge(e) {
$(this).parents("#dropdown")
.delay(1, "check")
.queue("check", function () {
$(".badge").toggleClass("badge-border", $(this).hasClass("open"));
}).dequeue("check")
}
$("#dropdown a").click(changeBadge);
$(document).on("click", function (e) {
var elem = $("#dropdown");
if ($(e.target).is("#dropdown *")) {
return false
} else {
if (elem.is(".open") || $(".badge").hasClass("badge-border")) {
elem.removeClass("open");
changeBadge.call(elem.find("a.dropdown-toggle")[0])
}
}
})
});
jsfiddle http://jsfiddle.net/qt7o3u6e/6/

Categories