I have this one problem regarding the highlighted navbar menu which will only highlight when we clicked on it. For that to work, I'm using javascript. However, each pages has its own sub pages, for example, page Home has a link of local/home, but its content will lead to local/home/content. The sub link will not make the navbar to function The navbar was coded in different file, which I just extends in the home and other pages. I'm not very good at explaining but if I can elaborate more on any part I would do so. Below I attached my JS and my navbar:
Navbar :
<ul class="navbar-nav mr-auto" id="nav">
<li class="nav-item">
<a class="nav-link active" href="{{ url('/') }}">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('courses') }}">opportunities</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('events') }}">events</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('uqalc') }}">courses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('contact') }}">contact</a>
</li>
</ul>
Javascript :
const currloc = location.href;
const menuItem = document.querySelectorAll('a');
const menuLen = menuItem.length;
for (let i = 0; i < menuLen; i++) {
menuItem[i].classList.remove('active');
if (menuItem[i].href === currloc) {
menuItem[i].className = "nav-link active";
}
}
Here, I add active class to the anchor tag which is inside .navbar-nav If the window location is https://www.google.com/index.html
then this code find an anchor tag which one inside the .navbar-nav if anchor tag href should be index.html then this code add class active to the anchor tag
function removeQueryString(url) {
return url.split('?')[0]
}
[].forEach.call(document.querySelectorAll('.navbar-nav a'), function(elem) {
if (removeQueryString(elem.href) === removeQueryString(window.location.href))
elem.classList.add('active')
else
elem.classList.remove('active')
})
Related
This is how my code looks like:
<div class="header-nav navbar-collapse collapse ">
<ul id="navigation" class=" nav navbar-nav">
<li>
Home
</li>
<li>
About Us
</li>
</ul>
</div>
I've been trying to add the active class to each of them when the user is on that specific page but no succes so far
Tis is how my script looks like:
var i = 0;
[].forEach.call(document.querySelectorAll('li > a'), function(nav) {
console.log(nav.pathname,window.location.pathname);
if (nav.pathname === window.location.pathname){
i = 1;
console.log(i);
nav.classList.add('active')
}
else{
console.log(i)
nav.classList.removeClass('active')
}
})
The active class is set on the "a" not on "li" and i don't know how to fix this. Maybe someone can help me?
In looking at the classes, it looks like you may be using Bootstrap. I added in those libs to the snippet, and updated some of the classes. I also added in another nav item with the href equal to js since that is the pathname for the snippet window. Otherwise it won't add the active class as there would not be a pathname that would be equal.
I also changed the nav items to pills, so you can see the active link easier.
var i = 0;
document.querySelectorAll('ul.nav > li > a').forEach((nav) => {
console.log({
navPathname: nav.pathname,
windowLocationPathname: window.location.pathname,
areEqual: nav.pathname === window.location.pathname,
});
if (nav.pathname === window.location.pathname) {
nav.classList.add('active')
} else {
nav.classList.remove('active')
}
})
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<div class="navbar navbar-light bg-light">
<ul id="navigation" class="nav nav-pills">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="js">JS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="about-us.html">About Us</a>
</li>
</ul>
</div>
To target the parent element, you have a few options - my favorite is element.closest(selector) which takes a starting element and finds the closest containing parent that matches selector
let els = document.querySelectorAll('li > a');
els.forEach(el => {
el.addEventListener('click', e => {
els.forEach(a => a.closest('li').classList.remove('active'));
e.target.closest('li').classList.add('active');
})
})
li.active {
background-color: green;
}
<ul>
<li><a href='#'>link 1</a></li>
<li><a href='#'>link 1</a></li>
<li><a href='#'>link 1</a></li>
</ul>
Thanks for this, i merged the two responses and made it into one that works for me, this is the script that worked without even touching the classes into the nav-bar:
document.querySelectorAll('ul.nav > li > a').forEach((nav) => {
console.log({
navPathname: nav.pathname,
windowLocationPathname: window.location.pathname,
areEqual: nav.pathname === window.location.pathname,
});
if (nav.pathname === window.location.pathname) {
nav.closest('li').classList.add('active')
} else {
nav.closest('li').classList.remove('active')
}
})
I am developing a web page wherein I have header(containing the navigational menu) in separate html file say reusableheader.html and footer in separate file i.e. reusablefooter.html.
reusableheader.html:
<style>
.nav-menu a:hover, .nav-menu .active > a, .nav-menu li:hover > a {
color: #3fbbc0;
border-color: #3fbbc0;
}
</style>
<script>
$(function(){
var current_page_URL = location.href;
$( "a" ).each(function()
{
if ($(this).attr("href") !== "#")
{
var target_URL = $(this).prop("href");
if (target_URL == current_page_URL)
{
$("a").parent("li").removeClass("active");
$(this).parent("li").addClass("active");
return false;
}
}
});
});
</script>
<nav class="nav-menu d-none d-lg-block"> //set to fixed-top.
<ul>
<li class="active"><a class="nav-link" href="/hospital/">Home</a></li>
<li><a class="nav-link" href="/hospital/aboutus">About</a></li>
<li><a class="nav-link" href="/hospital/services">Services</a></li>
<li><a class="nav-link" href="/hospital/departments">Departments</a></li>
<li><a class="nav-link" href="/hospital/doctors">Doctors</a></li>
<li class="drop-down"><a class="nav-link" href="#">Reach Us</a>
<ul>
<li><a class="nav-link" href="/hospital/contact">Contact Us</a></li>
<li><a class="nav-link" href="#">Feedback</a></li>
<li><a class="nav-link" href="#">Blogs</a></li>
<li><a class="nav-link" href="#">Newsletters</a></li>
</ul>
</li>
</ul>
</nav><!-- .nav-menu -->
I am including the below javascript code in all my other web pages:
otherpages.jsp
<script>
$(function() {
$("#header").load("reusableheader.html");
});
</script>
The above code works fine i.e. on click of link on the menu item, its becomes the active link with the color assigned(in css) but when I scroll the page down, the activeness shifts from currently active link back to the "home" link.
What am I doing wrong here?
I think the problem is with removing the active class on the li element. How can you say $("a").parent("li").removeClass("active"); when you have got so many a elements with parent li element.
Instead, create a new for loop function which removes the element if the active class is found regardless of wherever it is in the list. And also add the logic on the click event of the li element, otherwise, it keeps looking for a URL match and changes it and would behave oddly if any path gets appended to the URL.
function removeClass() {
var listItems = $(".nav-menu > ul > li");
listItems.each(function (idx, li) {
$(li).removeClass("active");
});
}
I want to get the user url on my site. I want to show if the user url is the root domain, add active class to the id home-item-menu. If not, don't do nothing.
I was using window.location.href and window.location.host but didn't work.
For the rest of section's I was using indexof (and the string that the url has), but because the root domain don't have any string I don't know how to do it.
<nav class="cl-effect-5">
<li class="nav-item" id="home-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#home"><span data-hover="HOME">HOME</span></a>
</li>
</nav>
<nav class="cl-effect-5">
<li class="nav-item" id="rucab-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#rucab"><span data-hover="RUCAB">RUCAB</span></a>
</li>
</nav>
<nav class="cl-effect-5">
<li class="nav-item" id="inscripciones-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#inscripciones"><span data-hover="INSCRIPCIONES">INSCRIPCIONES</span></a>
</li>
</nav>
<nav class="cl-effect-5">
<li class="nav-item" id="habitaciones-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#habitaciones"><span data-hover="HABITACIONES">HABITACIONES</span></a>
</li>
</nav>
<nav class="cl-effect-5">
<li class="nav-item" id="staff-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#staff"><span data-hover="STAFF">STAFF</span></a>
</li>
</nav>
<nav class="cl-effect-5">
<li class="nav-item" id="blog-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#contact"><span data-hover="BLOG">BLOG</span></a>
</li>
</nav>
<nav class="cl-effect-5">
<li class="nav-item" id="contacto-item-menu">
<a class="nav-link menu-rucab js-scroll-trigger" href="#contacto"><span data-hover="CONTACTO">CONTACTO</span></a>
</li>
</nav>
JQuery/Javascript
$( document ).ready(
function() {
var url = window.location.href;
var host = window.location.host;
if(url.indexOf('http://' + host + '/') != -1) {
document.getElementById("home-item-menu").classList.add("active");
}
if (document.URL.indexOf("habitaciones") > -1)
{
document.getElementById("habitaciones-item-menu").classList.add("active");
} else if (document.URL.indexOf("contacto") > -1) {
document.getElementById("contacto-item-menu").classList.add("active");
} else if (document.URL.indexOf("rucab") > -1) {
document.getElementById("rucab-item-menu").classList.add("active");
} else if (document.URL.indexOf("inscripciones") > -1) {
document.getElementById("inscripciones-item-menu").classList.add("active");
} else if (document.URL.indexOf("staff") > -1) {
document.getElementById("staff-item-menu").classList.add("active");
} else if (document.URL.indexOf("blog") > -1) {
document.getElementById("blog-item-menu").classList.add("active");
}
});
You can use the condition window.location.pathname === '/':
if(window.location.pathname === '/') {
document.getElementById("home-item-menu").classList.add("active");
}
Hi #Pedro Corchero Murga you can use javascript sessions to achieve this set the text of the nav item to javascript session and get that session on load function and check the conditions if you don't familiar with javascript sessions you can see this link : https://www.w3schools.com/jsref/prop_win_sessionstorage.asp
First of all, define how you want to tell your application if this is my root URL, which one way to achieve this is as follows;
function isAtRoot () {
// Let's say you're currently at 'https://myhome.domain/',
// and this is your root.
var href = window.location.href,
urlWithoutQueryString = href.split('?')[0],
host = window.location.host,
regexp = new RegExp("^https?://" + host + "/?$", "i");
return !!urlWithoutQueryString.match(regexp);
}
Or you can also use window.location.pathname for this.
Then, run your javascript like above as follows,
if (isAtRoot()) {
document.getElementById("home-item-menu").classList.add("active");
}
However, I'd suggest that you have a list of paths for your site and give it an alias or name to it. Then, run something like isAtRoot against it instead, which will have more trust-able precision for future references.
This is my menu
<ul class="sidebar-menu" id="navigation-menu">
<li class="active"><a class="nav-link" href="/"><i class="fas fa-home"></i><span>Home Page</span></a></li>
<li class="nav-item dropdown">
<i class="fas fa-cog"></i><span>Configuration</span>
<ul class="dropdown-menu">
<li><a class="nav-link" href="/Configuration/AccountCodes">Account Codes</a></li>
<li><a class="nav-link" href="/Configuration/Branches">Branches</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<i class="fas fa-person-booth"></i><span>Directory</span>
<ul class="dropdown-menu">
<li><a class="nav-link" href="/Directory/Users?Role=Administrator">Administrators</a></li>
<li><a class="nav-link" href="/Directory/Users?Role=Manager">Managers</a></li>
<li><a class="nav-link" href="/Directory/Users?Role=Agent">Agents</a></li>
</ul>
</li>
</ul>
This is my Jquery, when I select AccountCodes which is under the Configuration dropdown, it should only set the parent list item active. However, the Directory parent is set to active as well. I'm not sure how to select it directly.
Also, due to the structure of my URL, I am unable to continue to use endWith. Is there an alternate method of setting an active class based on the url? Currently, if I select AccountCodes or Branches, it correctly sets the Configuration dropdown item as active. However, If I select agent, nothing is selected at all due to its url ending with a ?Agent instead of Users
<script>
$(document).ready(function () {
var current = location.pathname;
console.log(current);
$("#navigation-menu a").each(function () {
var $this = $(this);
console.log($this.attr('href'));
if ($this.attr('href').endsWith(current)) {
console.log($this.parent());
$this.parent().addClass('active');
console.log("matched");
}
});
if ($(".dropdown-menu li").hasClass("active")) {
console.log("Yes");
var $this = $(this);
$(".dropdown-menu li").prev().parent().parent().addClass('active');
console.log($(".dropdown-menu li").closest(".nav-item dropdown"));
}
});
</script>
There would be two ways to mark only the parent link as active.
1. With jQuery
The advantage of this is that it will be compatible with any back end platform.
<script>
$(document).ready(function () {
var current = location.pathname;
console.log(current);
$("#navigation-menu a").each(function () {
var $this = $(this);
var link = $this.attr('href');
console.log(link);
// Remove the query string parameters by finding their starting position
var indexOfQueryString = link.lastIndexOf("?");
link = link.substring(0, indexOfQueryString);
if (link.endsWith(current)) {
console.log("matched");
if ($this.parent().parent().hasClass('.dropdown-menu')) {
var parentLink = $this.closest('.dropdown');
console.log("Setting parent link as active:", parentLink);
// Find the closest parent link and add active class
parentLink.addClass('active');
} else {
console.log("Setting link as active: ", $this.parent());
$this.parent().addClass('active');
}
}
});
});
</script>
In this case, as you have mentioned you encountered problems with ?Agent being present in link – this is what we refer to as query string parameters, which we can safely remove by searching for the unencoded question mark. This is already considered in the solution.
2. With ASP.NET MVC
Doing this in the back end would be more robust and should JavaScript be disabled by the user, this functionality will still work in your website. The disadvantage though, as you might have guessed, is that it is platform-dependent.
There are many ways of going about this. For your specific use-case, as your dropdown links are related to the parent by area, I have adapted another SO answer to cover your specific use-case:
public static string IsSelected(this HtmlHelper html, string area = "", string cssClass = "active")
{
ViewContext viewContext = html.ViewContext;
RouteValueDictionary routeValues = viewContext.RouteData.Values;
string currentArea = routeValues["area"] as string;
return area.Equals(currentArea) ? cssClass : String.Empty;
}
Then use it this way:
<ul class="sidebar-menu" id="navigation-menu">
<li><a asp-area="" asp-controller="Home" asp-action="Index" class="nav-link"><i class="fas fa-home"></i><span>Home
Page</span></a></li>
<li class="nav-item dropdown #Html.IsSelected(area: "Configuration")">
<i class="fas fa-cog"></i><span>Configuration</span>
<ul class="dropdown-menu">
<li><a asp-area="Configuration" asp-controller="AccountCodes" asp-action="Index" class="nav-link">Account
Codes</a></li>
<li><a asp-area="Configuration" asp-controller="Branches" asp-action="Index" class="nav-link">Branches</a>
</li>
</ul>
</li>
<li class="nav-item dropdown #Html.IsSelected(area: "Directory")">
<i class="fas fa-person-booth"></i><span>Directory</span>
<ul class="dropdown-menu">
<li><a asp-area="Directory" asp-controller="Users" asp-action="Index" asp-route-Role="Administrator"
class="nav-link">Administrators</a></li>
<li><a asp-area="Directory" asp-controller="Users" asp-action="Index" asp-route-Role="Manager"
class="nav-link">Managers</a></li>
<li><a asp-area="Directory" asp-controller="Users" asp-action="Index" asp-route-Role="Agent"
class="nav-link">Agents</a></li>
</ul>
</li>
</ul>
Would this benefit you, please make sure to upvote the other linked answer as well.
I have a menu with a submenu
The html
<ul class="nav navbar-nav float-xs-right top-nav">
<li class="nav-item"><a class="nav-link" href="/our-work/">Our Work</a></li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="/what-we-do/">What We Do</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="/what-we-do/we-develop/">We Develop</a>
<a class="dropdown-item" href="/what-we-do/we-promote/">We Promote</a>
<a class="dropdown-item" href="/what-we-do/we-support/">We Support</a>
</div>
</li>
<li class="nav-item"><a class="nav-link" href="/contact/">Contact</a></li>
</ul>
I am adding bg color using jQuery
function activeMenu() {
var curr_url = window.location.pathname ;
var curr_menu = $("a[href$='" + curr_url + "']");
$(curr_menu).css("background", "#fff");
}
activeMenu();
It is changing bg color of a tag and if it is submenu than the submenu's bg color is changing. But I want to change the bg color of the parent menu not the submenu.
Is there a possible solution to select the parent menu using jQuery?
See this jQuery method: https://api.jquery.com/parent/
In your case, I think this is what you're looking for;
function activeMenu() {
var curr_url = window.location.pathname ;
var curr_menu = $("a[href$='" + curr_url + "']");
$(curr_menu).parent(".dropdown-toggle").css("background", "#fff");
}
activeMenu();
You can do this with vanilla javascript. Let's say your <ul> has an id of "menu":
const menu = document.getElementById("menu").children;
const list = [...menu]
const currentPage = list.filter(li => li.children[0].pathname == window.location.pathname)
currentPage[0].className = "active"