Problems with change the active list when scrolling navbar - javascript

I'm trying to change active when scrolling in nav bar but it's doesn't work with my code
Here, this is my js code
<script>
let navbar = document.getElementById("nav ul li");
let viewportHeight = window.innerHeight;
let navHeight = document.getElementById("nav ul li").offsetHeight;
let navbarLinks = document.querySelectorAll("nav ul li a");
window.addEventListener("scroll", e => {
scrollpos = window.scrollY;
navbarLinks.forEach(link => {
let section = document.querySelector(link.hash);
if (section.offsetTop <= scrollpos + 20 &&
section.offsetTop + section.offsetHeight > scrollpos + 20) {
link.classList.add("active");
} else {
link.classList.remove("active");
}
});
});
</script>
Here, this is my html code
<nav>
<div class="header">Profile</div>
<ul class="nav-links">
<li>About</li>
<li>Social</li>
<li>MyWorks</li>
<li>Development</li>
<li>Encouragement</li>
<li>Technique</li>
</ul>
</nav>

Ok,
I think you should use document.querySelectorAll(...) instead of document.getElementById(...), (line 2 & 4)
because you are using a CSS QUERY SELECTOR. you should use getElementById only when you are selecting an element by it's id.

Related

How to auto scroll up li element when the corresponding element is showing using jQuery

I have this HTML page:
https://shibbir.dev/demo-work/html-one-page/
On this page, you will see a second sticky sidebar whose title is "Credit ipotecar"
In this sidebar, I have a few li elements. If you click on any li element you will scroll down to the corresponding div on the right side.
But the problem is I can see only a few li elements on the sidebar thus I can't click on other li elements to see another corresponding div.
So, how can I make the last li element scroll up once I click on the last viewable li element?
Something like this example:
https://discount.ro/cataloage/pepco-ro/cupon-de-reducere-pepco-colectia-de-rochii-din-bumbac-organic-02-15-iunie-2022-16353/#section11
My JS Code:
(function ($) {
"use strict";
$(document).ready(function () {
$(window).scroll(function () {
var scrollBar = $(this).scrollTop();
var navigate = document.querySelector(".sh-body-container div").offsetTop
$(".sh-body-container div").each(function (index) {
var elTop = $(this).offset().top;
var elHeight = $(this).height();
if (scrollBar >= elTop - navigate && scrollBar < elTop + elHeight) {
$(".sh-body-sidebar ul li").eq(index).addClass("sidebarActive").siblings().removeClass("sidebarActive");
}
});
});
$(".sh-see-more").click(function(e){
e.preventDefault();
var that = $(this);
that.prev(".sh-see-more-details").toggleClass("is-active");
});
$(".hide-show").click(function(e){
e.preventDefault();
var that = $(this);
var plusSign = that.children("a").text();
if( "+" == plusSign ) {
that.children("a").text("-");
} else {
that.children("a").text("+");
}
var faq = that.next(".sh-faq-answer").toggleClass("faq-active");;
});
$(".sh-mobile-calculator-icon").click(function() {
$(".sh-calculator").addClass("show-calculator");
$(".show-filter").show();
$(".show-filter a").click(function() {
$(".sh-calculator").removeClass("show-calculator");
});
});
});
})(jQuery);

Scroll offset changing menu item class

I have a page in Magento with all the categories and products listed. On top I have a menu with the categories and the items you scroll by must get a class so I can change the color.
I have this script at the moment:
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('ul.nf-category-menu li a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('ul.nf-category-menu li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
But the class is changing from div to div to soon, can I give some offset so the class will be added later?
Update:
It's no changing the "active" class to soon when te title is 150px away from the top, I would like to change the class around 80px from top.
Regards,
I already fixed it, it was quite simple after trying some things. This is how it was done:
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('ul.nf-category-menu li a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top+243 <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('ul.nf-category-menu li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
if (refElement.position().top had to be changed to: if (refElement.position().top+243 where 243 is the amount of pixels of the offset.

Page scrolling active navigation javascript

I've got a fixed top navigation and im trying to get the links to change to active when scrolling down the page. Currently i've got it working to a point where if you click it will add an active class and go to the correct position. When you scroll up or down it should change to the previous/next section in the nav which i cant get working. any ideas?
Thanks
html:
<body id="page-top">
<nav id="mainNav" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<img src="img/nav-logo.png" id="company-logo-large">
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right" id="mainmenu">
<li>
<a class="page-scroll" href="#about">About</a>
</li>
<li>
<a class="page-scroll" href="#services">Services</a>
</li>
<li>
<a class="page-scroll" href="#team">Team</a>
</li>
</ul>
</div>
</div>
</nav>
section where nav scrolls to:
<section id="about"></section>
<section id="services"></section>
<section id="team"></section>
javascript:
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('active');
})
$(this).addClass('active');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 500, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('#mainNav a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('#mainNav li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
Any help would be appreciated.
I think already answered this. check Highlight active menu item on scroll
and this jsfiddle:
// JavaScript Document
// Can also be used with $(document).ready() / $(window).load()
$(document).ready(function(){
$('body').css('display', 'none');
$('body').fadeIn(500);
// An offset to push the content down from the top
var listElement = $('#primary-navwrapper li');
var offset = $('#header').outerHeight();
listElement.find('a[href^="#"]').click(function(event) {
// Prevent from default action to intitiate
event.preventDefault();
// The id of the section we want to go to.
var anchorId = $(this).attr("href");
// Our scroll target : the top position of the
// section that has the id referenced by our href.
if (anchorId.length > 1 && $(anchorId).length > 0)
{
var target = $(anchorId).offset().top - offset;
}
else
{
var target = 0;
}
//console.log(target);
$('html, body').animate({ scrollTop: target }, 500, function () {
//window.location.hash = '!' + id;
window.location.hash = anchorId;
});
setActiveListElements();
});
// Update current item class
function setActiveListElements(event){
var windowPos = $(window).scrollTop();
$('#primary-navwrapper li a[href^="#"]').each(function() {
var currentLink = $(this);
if ($(currentLink.attr("href")).length > 0)
{
var refElement = $(currentLink.attr("href"));
if (refElement.position().top <= windowPos && (refElement.position().top + refElement.height() + $("#primary-navwrapper").height() ) > windowPos) {
$('#primary-navwrapper li a').removeClass("current");
currentLink.addClass("current");
}
else{
currentLink.removeClass("current");
}
}
});
}
// Update menu item on scroll
$(window).scroll(function() {
// Call function
setActiveListElements();
});
$('.backtotop').click(function () {
$('html, body').animate({ scrollTop: 0}, 1250);
return false;
});
});

jQuery change active class from a to li

We use some jQuery to make our navigation sticky from some point on the page and to add an active class to sections on the page. Currently the active class is added to the a class inside the li. But I want to add this to the li instead of the a href.
How can I achieve this?
Code:
<script>
$j(window).scroll(function(){
var sticky = $j('.menu-header-product'),
scroll = $j(window).scrollTop();
var elementOffset=jQuery("#productnav").offset();
if (scroll >= elementOffset.top - 57) sticky.addClass('sticky');
else sticky.removeClass('sticky');
});
$j(window).scroll(function(){
var sticky = $j('.content'),
scroll = $j(window).scrollTop();
var elementOffset=jQuery("#productnav").offset();
if (scroll >= elementOffset.top - 57) sticky.addClass('sticky');
else sticky.removeClass('sticky');
});
$j(document).ready(function () {
$j(document).on("scroll", onScroll);
$j('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$j(document).off("scroll");
$j('li').each(function () {
$j(this).parent().removeClass('active');
})
$j(this).parent().addClass('active');
var target = this.hash;
$jtarget = $j(target);
$j('html, body').stop().animate({
'scrollTop': $jtarget.offset().top - 120 /**just subtract the height of the fixed html part */
}, 500, 'swing', function () {
window.location.hash = target;
$j(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPosition = $j(document).scrollTop();
$j('nav li').each(function () {
var currentLink = $j(this);
var refElement = $j(currentLink.attr("href"));
if (refElement.position().top - 125 <= scrollPosition && refElement.position().top - 125 + refElement.height() > scrollPosition) {
$j('nav ul li a').parent().removeClass("active");
currentLink.parent().addClass("active");
}
else{
currentLink.parent().removeClass("active");
}
});
}
</script>
You can use jQuery's parent selector. So
$j(this).addClass('active');
becomes
$j(this).parent().addClass('active');
You would also need to change the selector $j('a') to $j('li'). I would recommend filtering to only lis in your navigation, i.e. $j('nav li'). Finally, you'd have to update the onScroll event similarly.

Cannot read top of Undefined jquery scroll

I've tried to find a solution to this error but with no luck so I'll post my specific problem. I have a jquery scroll that scrolls to the hashtags in the menu and when reached the specific target hashtags it should change the menu item color from grey to white. Everything works fine with one small error.
When you click on the menu item it scrolls down but then you have to scroll 1-5px more in order for the script to change the menu item to active (white color), the console also gives me a "cannot read property 'top' of undefined. Im clueless because the script gathers the menu items in an array and if I console.log the array the items are there. If I console.log the height and position of the div it returns values but still gives me the error messages.
<div class="header">
<div id="nav-anchor"></div>
<div class="container-fluid menu-content">
<div class="row">
<div class="col-md-6">
<img src="images/logotype.png" alt="Logotype" title="" class="brand">
</div><!-- end col md 6 brand -->
<div class="col-md-6 menu">
<nav>
<ul>
<li>About</li>
<li>Work</li>
<li>Cases</li>
<li>Meet us</li>
<li>Follow us</li>
</ul>
</nav>
</div><!-- end col md 6 menu -->
</div><!-- end row -->
</div><!-- end container -->
</div><!-- end header -->
$(document).ready(function(){
/**
* This part does the "fixed navigation after scroll" functionality
* We use the jQuery function scroll() to recalculate our variables as the
* page is scrolled/
*/
$(window).scroll(function(){
var window_top = $(window).scrollTop(); // the "12" should equal the margin-top value for nav.stick
var div_top = $('.header').offset().top;
});
/**
* This part causes smooth scrolling using scrollto.js
* We target all a tags inside the nav, and apply the scrollto.js to it.
*/
$(".menu li a").click(function(evn){
evn.preventDefault();
$('html,body').scrollTo(this.hash, this.hash);
if (window_top > div_top) {
$('nav').addClass('stick');
} else {
$('nav').removeClass('stick');
}
});
/**
* This part handles the highlighting functionality.
* We use the scroll functionality again, some array creation and
* manipulation, class adding and class removing, and conditional testing
*/
var aChildren = $("nav li").children(); // find the a children of the list items
var aArray = []; // create the empty aArray
for (var i=0; i < aChildren.length; i++) {
var aChild = aChildren[i];
var ahref = $(aChild).attr('href');
aArray.push(ahref);
} // this for loop fills the aArray with attribute href values
$(window).scroll(function(){
var windowPos = $(window).scrollTop(); // get the offset of the window from the top of page
var windowHeight = $(window).height(); // get the height of the window
var docHeight = $(document).height();
for (var i=0; i < aArray.length; i++) {
var theID = aArray[i];
var divPos = $(theID).offset().top; // get the offset of the div from the top of page
var divHeight = $(theID).height(); // get the height of the div in question
if (windowPos >= divPos && windowPos < (divPos + divHeight)) {
$("a[href='" + theID + "']").addClass("active");
} else {
$("a[href='" + theID + "']").removeClass("active");
}
}
if(windowPos + windowHeight == docHeight) {
if (!$("nav li:last-child a").hasClass("active")) {
var navActiveCurrent = $(".active").attr("href");
$("a[href='" + navActiveCurrent + "']").removeClass("active");
$("nav li:last-child a").addClass("active");
}
}
});
});
window_top needs to be a global variable, also you can add the specified amount of pixels you need to the actual variable so var div_top = $('.header').offset().top + 5;

Categories