Adding active class on scroll applying at bottom not top - javascript

I am trying to implement some code I found on SO which adds the class "active" when the matching div is on the page. So scroll down, get to the div and the active class is added to the correct menu item.
Currently, it is working but with some hitches, right now it's applying the active class at the bottom of the div, not when it hits the top. So I think I am at a bit of a loss.
Here is the current JS:
<script>
// Cache selectors
var lastId,
topMenu = $("#nav"),
topMenuHeight = topMenu.outerHeight()+15,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e){
var href = $(this).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top-topMenuHeight+1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});
// Bind to scroll
$(window).scroll(function(){
// Get container scroll position
var fromTop = $(this).scrollTop()+topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href='#"+id+"']").parent().addClass("active");
}
});
</script>
You can view the original js here on jsfiddle but mine is not acting like this one: http://jsfiddle.net/mekwall/up4nu/
The issue I see: on fiddle it works but the divs on fiddle have no height just a top value, if you add height like any div would have it causes the issue.

Found a far better solution to what I had above and I made a codepen for it.
https://codepen.io/LukeD1uk/pen/MVeGQW
$(window).scroll(function() {
var windscroll = $(window).scrollTop();
if (windscroll >= 100) {
$('section').each(function(i) {
if ($(this).position().top <= windscroll - 0) {
$('nav li.active').removeClass('active');
$('nav li').eq(i).addClass('active');
}
});
} else {
$('nav li.active').removeClass('active');
$('nav li:first').addClass('active');
}
}).scroll();

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);

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.

After trigger click using a hash in the URL the page needs to scroll to top

I am calling a page with a hash in the url so that when it is submitted in the browser the the element with the hash id is clicked. It works fine, but I need the page to immediately scroll to the top after the click. I have tried: $(window).scrollTop(0); but it only seems to work if the page is already loaded.
Here is the Javascript:
<script type="text/javascript">
var thisHash = window.location.hash;
$(document).ready(function()
{
if(window.location.hash)
{
$(thisHash).trigger('click');
}
});
</script>
When I have a url like http://www.example.com#part2 and run it in the browser the element with the hash #part2 is clicked correctly, but the page is scrolled to the element. I would like the page to be scrolled to the top of the page after the element is clicked.
Do you know a way to scroll to the top afterward or have the click "not scroll" to the element to start with?
I have tried the setTimeout function and $(window).scrollTop(0); but they don't seem to work after the click and the page load.
$(window).scrollTop(0); works when I manually run it in the console of chrome after the page is already loaded.
It seems like the $(window).scrollTop(0); gets ignored for some reason.
I think you want to do something like this check out this js fiddle
JSFiddle
code
function scrollnav(){
$('#nav a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 1000, function () {
window.location.hash = target;
});
});
var aChildren = $("ul#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);
}
var windowPos = $(window).scrollTop(); // get the offset of the window from the top of page
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 pos = $("a[href='" + theID + "']").parent();
if (windowPos >= divPos ) {
$("ul#nav li").removeClass("active");
$(pos).addClass("active");
var finder = $("ul#nav li.active").index();
size =$('ul#nav li').width();
var onclick = finder * size;
$('span').css('left', onclick + 'px');
}
}
}
$(window).scroll(function() {
scrollnav()
});
scroll top on page reload
Check JS fiddle here
code
$(window).load(function(){
//alert("scroll")
$('html, body').stop().animate({
'scrollTop': 0
}, 1000)
})
Try
window.scroll(0, 0); // X, Y
or
window.scrollBy(0, -document.body.scrollTop)

Transition List Item Scrolling - HTML

Here's the FIDDLE.
List item that appears on clicking the up and down arrows.
When I click on it. It appears instantly which I don't want it to be like that.
I wanted to add a transition to it but I don't have any clue whether to apply it on a li or a tag.
Besides I'm here hiding and revealing li items on click. But I need the transition like when I click on the up arrow, I want the hidden element to push the active element downwards and vice versa.
Someone help me in this.
I updated your FIDDLE
you may check it out.
var
cur = 2,
$container = $('.dropdown-container'),
$ul = $('.dropdown'),
$ul_length = $('.dropdown li').children().length,
$up = $('.up'),
$down = $('.down'),
changeLi = function (cur) {
var $cur_li = $('.dropdown li:nth-child(' + cur + ')');
$('.current_selected').removeClass('current_selected');
$cur_li.addClass('current_selected');
$container
.height($cur_li.outerHeight())
.width($cur_li.outerWidth());
$up.offset({
left: ($container.outerWidth() - $up.outerWidth()) / 2
});
$down.offset({
left: ($container.outerWidth() - $down.outerWidth()) / 2
});
$ul.animate({
top: -$cur_li.position().top
}, 200);
};
$up.on('click', function () {
cur--;
if (cur < 1) {
cur = 1;
return false;
}
changeLi(cur);
});
$down.on('click', function () {
cur++;
if (cur > $ul_length) {
cur = $ul_length;
return false;
}
changeLi(cur);
});
changeLi(cur);
You can add animatation like slideUp, slideDown etc.
var cur = 2;
$('.up').click(function() {
if(cur <= 0) return;
var last = cur;
cur --;
$('.dropdown li').eq(last).hide(500).addClass('hide');
$('.dropdown li').eq(cur).show(100).removeClass('hide');
});
$('.down').click(function() {
if(cur >= $('.dropdown li').length - 1) return;
var last = cur;
cur ++;
$('.dropdown li').eq(last).hide(500).addClass('hide');
$('.dropdown li').eq(cur).show(100).removeClass('hide');
});

Add Class to Menu Item When Scroll

I want the menu items to look like they are selected when you are scrolling through certain sections of a single page website
I tried capturing the position of each element and store it in a variable and then apply a class when the top of that element passes the top of the page.
Java Script:
var blockone = Math.abs($("#one").position().top);
var blocktwo = Math.abs($("#two").position().top);
var blockthr = Math.abs($("#thr").position().top);
var blockfou = Math.abs($("#fou").position().top);
var blockfiv = Math.abs($("#fiv").position().top);
var blocksix = Math.abs($("#six").position().top);
function removeSelected() {
$('#menu li').removeClass('selected');
}
$("#frame").scroll( function() {
$("#menu li:nth-child(1)").addClass('selected');
var value = $(this).scrollTop();
if ( value < blocktwo ){
removeSelected();
$("#menu li:nth-child(1)").addClass('selected');
} else if (value < blockthr){
removeSelected();
$("#menu li:nth-child(2)").addClass('selected');
} else if (value < blockfou){
removeSelected();
$("#menu li:nth-child(3)").addClass('selected');
} else if (value < blockfiv){
removeSelected();
$("#menu li:nth-child(4)").addClass('selected');
} else if (value < blocksix) {
removeSelected();
$("#menu li:nth-child(5)").addClass('selected');
} else {
removeSelected();
$("#menu li:last-child").addClass('selected');
}
});
What am I missing? I have a working jfiddle here: http://jsfiddle.net/zer0ruth/pgbef/1/
The only problem is that you bind the scroll even on #frame while it should be on window.
But well, I saw that only after playing around with you code, so I have a free optimised code for you: http://jsfiddle.net/pgbef/15/.
Saving you position in array is better than having 6 var and you can had a section without changing code:
var position = [];
$('.block').each(function(){
position.push(Math.abs($(this).position().top))
})
Then your scroll function is way shorter too!
$(window).scroll( function() {
var value = $(this).scrollTop() + $('#menu').height();
$.each(position, function(i){
if(this > value){
$('.selected').removeClass('selected');
$("#menu li").eq(i-1).addClass('selected');
return false;
}
})
});

Categories