Highlight current page with CSS and Javascript - javascript

I've managed to get it so when I click on say "about" then it adds the class that I've called "active" however it doesn't remove the previous "active" on the home page link
Here is my HTML
<nav id="main-nav" role="navigation">
<ul>
<li>
Home
</li>
<li>
About
</li>
<ul>
</nav>
and here is my javascript
function setActive() {
aObj = document.getElementById('main-nav').getElementsByTagName('a');
for(i=0;i<aObj.length;i++) {
if(document.location.href.indexOf(aObj[i].href)>=0) {
aObj[i].className='active';
}
}
}
window.onload = setActive;
Basically what I want to be able to do is the following:
When on homepage it adds the class "active" so that I can highlight the link with CSS.
Then when I click on About it removes the "active" class from home (thus removing the highlighted css) and adds the "active" class to about (thus adding the highlighted css).

Just add aObj[i].className = ""; before the if condition.
function setActive() {
aObj = document.getElementById('main-nav').getElementsByTagName('a');
for(i=0;i<aObj.length;i++) {
aObj[i].className = "";
if(document.location.href.indexOf(aObj[i].href)>=0) {
aObj[i].className='active';
}
}
}
window.onload = setActive;
What this is basically doing is removing every class from all the links and only adding the 'active' class if it's the correct page. But since it seems the page is refreshing, I don't know how the class would persist from one page to the other, so it would be helpful to have a link to the code.

I checked the source of your page and I think the problem lies in the way the links are created (the JavaScript code you have posted is okay).
PROBLEM : The URL of the "Home" tab is
https://dhctranslations.com/
And the other URLs (hrefs) on the navigation are
About Tab - https://dhctranslations.com/about
Certified Translation Tab - https://dhctranslations.com/certified-translation-services
Pricing Tab - https://dhctranslations.com/pricing
...
...
The check you are doing in your function is 'indexOf' check. That is why the condition always returns true for the 'Home' tab (as this part of the URL is common to all other links).
SUGGESTION : To remedy this you can either change the 'indexOf' check and replace it with equality check in your code
OR change the URL of the 'Home' tab to something like
https://dhctranslations.com/home
Please note that these are just my suggestions and I am pretty sure that you can work out a solution that suits better to your application's design/architecture.
UPDATE : Here is the modified code that works (Please note this is just to give you an idea and is not a clean solution at all)
aObj = document.getElementById('main-nav').getElementsByTagName('a');
for(i=0;i<aObj.length;i++) {
aObj[i].className = "";
// Changed the condition
// Concatenated the "/" for comparison as the array does not have trailing "/"s stored
if(document.location.href === aObj[i].href+"/") {
aObj[i].className='active';
}
}

Related

Is there a way with either vanilla Javascript or Jquery to select a span class before in the DOM?

I am designing a Squarespace site, so I do not have direct access to the HTML. I would like to add some CSS to the site's drop down menu system. And the way the menu system is setup, it does give not assign ID names, only class names. So, it has one DIV and within that one DIV, it has several SPAN classes. The problem is that all the folder SPANS are all named the same and all the HREF classes are all named the same. What I would like to happen for example, is that if the user clicks on a either "About Us," "Memstaff Team, or "Careers," I would like to add (not replace) a class named "currentFolder" to the "/about" HREF which is the SPAN right before it (which has a class name of "Header-nav-folder-title"). But I do not want to effect the other HREF that comes after, which also has the same exact CLASS name of "Header-nav-folder-title." I would also like to remove the class "currentFolder" when a user clicks on any of the other links so I can repeat the process. I am aware of Jquery's .closest() and .find() but do not know enough on how to use them properly.
<div class="Header-nav-inner">
<span class="Header-nav-item Header-nav-item--folder">
About
<span class="Header-nav-folder">
About Us
MEMStaff Team
Careers
</span>
</span><span class="Header-nav-item Header-nav-item--folder">
Job Seekers
<span class="Header-nav-folder">
Submit a Resume
MEMStaff Jobs
Referral Bonus</span>
</span>For Employers
Contact
</div>
$('a.Header-nav-folder-item').click(function() {
//Remove active class from all title elements
$('.Header-nav-folder-title').removeClass('active');
// Add class to correct title element
$(this).parent().siblings('.Header-nav-folder-title').eq(0).addClass('active');
});
// Remove active class when clicking on bottom two links
$('a.Header-nav-item').click(function() {
//Remove active class from all title elements
$('.Header-nav-folder-title').removeClass('active');
});
Here is some code that I think may solve your problem. You should set it to run whenever the page navigates (document load probably).
Note that this will only work if the page path exactly matches the link href.
// Get all of the folders
const folders = document.querySelectorAll('span.Header-nav-item--folder');
// Loop through the folders
for (const folder of folders) {
// Variable for if one of the folder contents is the current page
let childIsCurrent = false;
// Get all of the links in the dropdown
const links = folder.querySelectorAll('a.Header-nav-folder-item');
// Loop through the links
for (const link of links) {
// Compare the link href with our current path
if (link.href === location.pathname)
childIsCurrent = true;
}
// Find the folder title
const title = folder.querySelector('a.Header-nav-folder-title');
// Add or remove the class
if (childIsCurrent)
title.classList.add('currentFolder');
else
title.classList.remove('currentFolder');
}

REACT nav bar requires two clicks

Summary
When a user clicks the hamburger icon className='.landing-page-hamburger' it takes two clicks to toggle the navigation className='landing-page-nav-links' and I can't figure out why.
The display value for .landing-page-nav-links is set to none by default in the CSS.
Problem
Navigation bar is requiring two clicks to toggle the display value
Expected Result
Would expect to only need one click
LandingPage.js
import React from 'react';
const LandingPage = () => {
const toggleNav = () => {
const navLinks = document.querySelector('.landing-page-nav-links');
if (navLinks.style.display === 'none') {
navLinks.style.display = 'initial';
} else {
navLinks.style.display = 'none';
}
}
return (
<nav className='landing-page-nav'>
<h1 className='take-notes-logo'>Take Notes</h1>
<span className='landing-page-hamburger' onClick={() => toggleNav()}>☰</span>
<ul className='landing-page-nav-links'>
<li>Sign Up</li>
<li>Log In</li>
</ul>
</nav>
);
};
export default LandingPage;
This is happening because your external CSS is not setting a style property on your element. The first click sets it to none because it isn't there at all. Your second click will now work as expected.
To fix this, either set the style of .landing-page-hamburger inline, or just toggle classes and let your external CSS handle it.
EDIT: The OP asks an excellent question. The .style property refers to the element's CSSStyleDeclaration object. This is a HTMLElement interface that you are directly manipulating. Notice, when you inspect an element in your console, the CSSStyleDeclaration does not necessarily match what you see in the CSS you get from the style sheet. Also, note that the properties are JS-style camelCase; this illustrates that this is not a direct mapping, yet they both effect the element.
So my initial description of the property being not there at all isn't accurate. It's there, and it's set to the empty string, which is the default CSSStyleDeclaration. So you set it to "none" on the second click and all goes well from there. Your initial CSS declaration is working correctly, but not figuring into your if statement because it's not referring to the same thing. Same effect, but you're interfacing with your element in a different way.

Active class added to a wrong document object in a menu

Here is my JS code which add an active class to the parent of all <a> objects which contain a href path who match with my current URL.
aObj = document.getElementById('menuG').getElementsByTagName('a');
for(i=0;i<aObj.length;i++) {
if(document.location.href.indexOf(aObj[i].href)>=0) {
alert("Button n°"+i+" - Value : "+document.location.href.indexOf(aObj[i].href));
aObj[i].parentElement.className='active';
}
}
My problem is that the first button which have href="/" is always active.
The code document.location.href.indexOf(aObj[i].href) always return 0 for the first button and i don't understand why.
Here is my html code :
<ul class="nav navbar-nav" id="menuG">
<li>Mes Fichiers</li>
<li>Historique</li>
<li>Profil</li>
</ul>
Thanks for your time.
Any URL will most likely contain the / of that first link tag. If you use indexOf(), it will find the / in any page of your website. Hence, that first link's parent will always get styled.
You can test it for yourself in the console of your browser. In an HTTPS website, the first match of / is in position 6 (7th character in a URL). indexOf just returns the position of the first match, and the / that's the href of your first link will always get a match.
You could replace the href of the first link with something like index.html, and then force a redirect from http://example.com to http://example.com/index.html. Your other bet is to change the way you check if this is the current page, by, for example, checking if window.location.href is strictly equal (===) to the href of a link tag: window.location.href === aObj[i].href.

toggle the nav-bar active element

I'm using blade template, the template contains a navigation bar. it is something like this
<ul>
<li class="active">page1</li>
<li>page1</li>
<li>page1</li>
</ul>
Using jquery I can make the li element active once clicked.
Now the problem is when I click on the second link the page2 will be loaded and that page extends the same template so it will load it again and there then the 1st element will be active. The solution that I thought about is adding a div to each page to let me identify the page
<div class="type" data-type="page2"></div>
and when the page is loaded I set the selected li element depending on the page type.
I try this and it is working the only thing is that I don't think it is the perfect solution. Is there an other more simple way to solve this?
Thanks
I'd set a class on the html element to identity your page. That way you can have javascript as well as css react to what type of page you're on. Not that you need css in this particular example, but down the line use-cases might pop-up and then you already have a solution in place.
edit:
Adding class dynamically through a tiny script:
//script in specific page
<script>pagetype = "page2"</script>
//script as part of layout template shared between pages
<script>
$(function(){
$("html").addClass(pagetype);
})
</script>
In my opinion, a better solution would be detecting the current page with Request::segment() (or Request::is(), depending on the stucture of your URLs) method. Combine that with a View composer to avoid passing data to each view manually.
An example:
The view composer:
class PageComposer
{
public function compose($view)
{
$view->with('active', Request::segment(1));
}
}
The service provider:
class PageServiceProvider extends ServiceProvider
{
public function register()
{
View::composer('partials.header', 'PageComposer');
}
}
The part of the header file that is common to all your pages:
<ul id='pages'>
<li id='page1'>page1</li>
<li id='page2'>page2</li>
<li id='page3'>page3</li>
</ul>
The script that changes the active class:
<script>
$(document).ready(function () {
var activeLink = $('#{{ $active }}');
activeLink.addClass('active');
});
</script>
More information about this in Laravel 4 documentation:
Requests
View Composers
You can compare anchor href to pathname and then add style or assign class to correct anchor e.g
...
<li>Link</li>
...
$('a[href="'+window.location.pathname.split('/').pop()+'"]').css({ color: 'red' });
or
$('a[href="'+window.location.pathname.split('/').pop()+'"]').addClass('current');

jQuery Make a Link in Active Status

I am working on a HTML template, but I cannot touch the HTML code, I can only work on CSS and JS files. So I cannot in any way edit the HTML code.
What I am trying to achieve is to put some links in active status when jQuery or Javascript recognizes that the current page URL is the same one of the link I want to put in active status, without editing the HTML code.
Is there a way to do it? I tried in many ways but with no luck.
Here is the HTML code ( Remember I cannot edit it ).
<span class="Tag_Nav_Aux">
Create Account
|
Login
|
My Cart
</span>
The jQuery or Javascript code should work on different links, other than the ones I reported above, since the HTML changes when the user is logged in or logged out.
So the jQuery should point the class Tag_Nav_Aux and add the Active class to any a tag it will find that has the link the same of the current URL.
You can do something like this. Your file name from the URL
var filename = window.location.href.substr(window.location.href.lastIndexOf("/")+1);
After that get the anchor from the navigation and apply some class.
$("span.Tag_Nav_Aux a[href*="+filename+"]").addClass('active');
Here you have to write a CSS active class which will make that link to appear like an active link.
Try this script
jQuery(function($){
$('.Tag_Nav_Aux a').filter(function(){
return $(this).attr('href').toLowerCase() === window.location.pathname.toLowerCase();
}).addClass('active');
});
and create a CSS rule for
.Tag_Nav_Aux a.active{
// style you want the active link to have
}
$(document).ready(function() {
var url = window.location.href.toLowerCase();
$(".Tag_Nav_Aux a").each(function() {
var $this = $(this);
var href = $this.attr("href").toLowerCase();
if(url.indexOf(href) > -1) {
$this.addClass("active");
}
});
});​
I think you need to check the current page url and assign a class to the item like to active.
I usually do putting class="active" based on current URL match with help of server side code.
But if you dont want server code you can do with help of JavaScript
var currentPage=window.location.href;
if(currentPage=="")
{
//logic to find and add a Class for the proper anchor tag
}

Categories