If url is root domain, add class to id - javascript

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.

Related

Adding an active class to the navbar

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')
}
})

Navbar active page

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')
})

Anchor href doesn't work when i add dynamically hr tag after user click

<div class="nav-center">
<ul class="center">
<a class="nav-item" href="">
<li>Random facts</li>
<hr class="line">
</a>
<a class="nav-item" href="/blog/technology/">
<li>Technology</li>
</a>
<a class="nav-item" href="/blog/sport/">
<li>Sports</li>
</a>
<a class="nav-item" href="">
<li>About poeters</li>
</a>
</ul>
</div>
//JavaScript Code
let navItems = document.querySelectorAll(".nav-item");
let addchild = document.createElement("hr");
addchild.classList.add("line");
let Handler = (e) => {
e.preventDefault();
navItems.forEach((node) => {
if (node.contains(removechild)){
node.removeChild(removechild);
}
});
e.currentTarget.appendChild(addchild);
};
navItems.forEach((node) => {
node.addEventListener("click", Handler);
});
See the first anchor tag i added hr tag through html it is showing line below Random Facts and also works fine for my expected link.. But when i add dynamically after user click, line shows but anchor link does not work after user click why??
NOTE: Your HTML is invalid
Here is a version that tests the URL. This script needs to be in all pages
LIVE DEMO
window.addEventListener("load",function() {
// const url = new URL(location.href); // uncomment on your server
const url = new URL("https://www.yourserver.com/blog/technology/");
const path = url.pathname;
let where = path.split("/")
if (!where[where.length-1]) where.pop() // last part of url ending with /
where = where.pop(); // now we have the folder or filename
console.log("w",where,"path",path)
const link = document.querySelector(".nav-center a[href*='"+where+"']");
if (link) link.parentNode.insertBefore(document.createElement("hr"), link.nextSibling);
else console.log("from path",path,"where not found",where)
})
<script src="/blog/scripts/nav.js"></script>
<div class="nav-center">
<ul class="center">
<li><a class="nav-item" href="/blog/index.html">Home</a></li>
<li><a class="nav-item" href="/blog/random/">Random facts</a></li>
<li><a class="nav-item" href="/blog/technology/">Technology</a></li>
<li><a class="nav-item" href="/blog/sport/">Sports</a><br/></li>
<li><a class="nav-item" href="/blog/about/">About</a></li>
</ul>
</div>
<h1>Home</h1>
Here is a version that expect you to fetch/ajax your pages into the existing page. Also it is using delegation
let nav = document.querySelector(".nav-center ul");
let addchild = document.createElement("hr");
addchild.classList.add("line");
const handler = e => {
e.preventDefault();
const tgt = e.target.closest("li");
const url = tgt.querySelector("a")?.href ?? "";
if (url) {
nav.querySelector(".line")?.remove();
tgt.querySelector("a").appendChild(addchild);
// here you would ajax the href into a div elsewhere or target an iFrame
console.log(url)
}
};
nav.addEventListener("click", handler);
<div class="nav-center">
<ul class="center">
<li><a class="nav-item" href="">Random facts</a></li>
<li><a class="nav-item" href="/blog/technology/">Technology</a></li>
<li><a class="nav-item" href="/blog/sport/">Sports</a><br/></li>
<li><a class="nav-item" href="">About poeters</a></li>
</ul>
</div>

Set parent list item of dropdown link to active with jQuery / JavaScript (ASP.NET)

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.

Change menu background color for current page

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"

Categories