I've completed some javascript courses but actually using it on functional web items is very humbling.
I have a navbar with same-page page links. I would like to change the nav items to active both when they are clicked, and when the page is scrolled to that section of the page. I would also like to change the innerHTML of the active nav items.
My javascript is clearly a mess. I'd like to try to at least get this solved and then it's back to practicing JS.
<div class="collapse navbar-collapse" style="background-color: #1e3d58;" id="navbarToggler">
<ul class="navbar-nav text-center mx-auto mb-2 mb-sm-0">
<li class="nav-item">
<a class="nav-link" href="#home">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#skills">Skills</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
<div class="d-none d-sm-flex mt-sm-2 mt-md-0 justify-content-center">
<a class="btn btn-social-icon btn-linkedin" href="#"><i class="fab fa-2x fa-github-square"></i></a>
<a class="btn btn-social-icon btn-linkedin" href="http://www.linkedin.com/in/"><i
class="fab fa-2x fa-linkedin"></i></a>
</div>
</div>
.nav-item {
padding: 0px 2vw 0px 2vw;
}
.nav-link {
color: #e8eef1 !important;
}
nav .fab {
color: #e8eef1;
margin: 0px -8px 0px -8px;
}
nav {
max-height: 60px;
}
document.querySelector(function () {
document.querySelector(".nav-item").click(function () {
document.querySelector(".nav-item").each(function () {
document.querySelector(this).querySelector("a").removeClass("active");
});
document.querySelector(this).querySelector("a").classList.add("active");
});
});
document.querySelector(function () {
for (document.querySelector(".nav-item")) {
if document.querySelector("a").hasClass("active")
then document.querySelector("a").innerHTML = "<" document.querySelector('a') "/>"
};
});
CodePudding user response:
The js would be something like:
let navItems = document.querySelectorAll('li.nav-item a');
navItems.forEach((el) => {
el.addEventListener('click',() => {
if (!el.classList.contains('active') {
navItems.forEach((others) => {
//Remove the update to innerHTML for all of the items however you plan on doing that, I would suggest just adding or removing a class to update their style
others.classList.remove('active');
};
el.classList.add('active');
};
});
});
CodePudding user response:
I was able to find a solution to this that solved all 3 problems.
- The active class changes when nav item is clicked
- The active class changes when page is scrolled to page section
- The textContent of the navbar item links are changed when the a link class is active
Javascript
const sections = document.querySelectorAll('section');
const navLi = document.querySelectorAll('#navbarToggler li a')
window.addEventListener('scroll', ()=> {
let current = "";
sections.forEach( section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if(scrollY >= (sectionTop - sectionHeight/3)){
current = section.getAttribute('id');
}
})
navLi.forEach( a => {
a.classList.remove('active');
if(a.classList.contains(current)){
a.classList.add('active')
}
})
})
window.addEventListener('scroll'||'click', ()=> {
navLi.forEach( a => {
const navText= a.textContent;
if (a.classList.contains('active')){
if(a.textContent == "Home"){
a.textContent = "<Home/>"
}
if(a.textContent == "About"){
a.textContent = "<About/>"
}
if(a.textContent == "Skills"){
a.textContent = "<Skills/>"
}
if(a.textContent == "Contact"){
a.textContent = "<Contact/>"
}
}
else {
if(a.textContent == "<Home/>"){
a.textContent = "Home"
}
if(a.textContent == "<About/>"){
a.textContent = "About"
}
if(a.textContent == "<Skills/>"){
a.textContent = "Skills"
}
if(a.textContent == "<Contact/>"){
a.textContent = "Contact"
}
}
})
})
HTML
<nav class="navbar navbar-expand-md navbar-dark fixed-top" style="background-color: #1e3d58;">
<div class=" container">
<a class="navbar-brand" href="#home"><strong>.Vince-clicks{}</strong></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggler"
aria-controls="navbarToggler" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" style="background-color: #1e3d58;" id="navbarToggler">
<ul class="navbar-nav text-center mx-auto mb-2 mb-sm-0">
<li class="nav-item">
<a class="nav-link home active" href="#home">Home</a>
</li>
<li class="nav-item">
<a class="nav-link about" href="#about">About</a>
</li>
<li class="nav-item">
<a class="nav-link skills" href="#skills">Skills</a>
</li>
<li class="nav-item">
<a class="nav-link contact" href="#contact">Contact</a>
</li>
</ul>
<div class="d-none d-sm-flex mt-sm-2 mt-md-0 justify-content-center">
<a class="btn btn-social-icon btn-linkedin" href="#"><i class="fab fa-2x fa-github-square"></i></a>
<a class="btn btn-social-icon btn-linkedin" href="http://www.linkedin.com/in/"><i
class="fab fa-2x fa-linkedin"></i></a>
</div>
</div>
</div>
</nav>
Each page section also has an appropriate id.
Hope this helps others who had the same issue.