Remove class when scroll position is above first anchor link - javascript

I need some advice: I have a second navigation on my website that gets sticky as soon as it reaches the bottom of my top navigation. The second navigation contains different anchor links. When clicking on one anchor link the page scrolls to this appropriate section and marks the link with a different color and underline-style. Something like this:
+-------------------------------
| Navigation
+-------------------------------
| Second Navigation
+-------------------------------
Some content (different height)
+-------------------------------
| Anchor link 1
+-------------------------------
Some content (different height)
+-------------------------------
| Anchor link 2
+-------------------------------
...
This is the script I use to highlight (or to add a class for styling) the active links in this second navigation:
jQuery(function ($) {
$(window).scroll(function () {
var scrollPos = $(window).scrollTop();
$('.secondary-nav-section').each(function (i) {
var topPos = $(this).offset().top;
if ((topPos - scrollPos) <= 182) {
$('.secondary-nav-menu-item-active').removeClass('secondary-nav-menu-item-active')
$('.secondary-nav-menu ul li').eq(i).addClass('secondary-nav-menu-item-active')
}
})
});
});
Now to the problem: This code works fine as long as I scroll down and then up and down between the different divs with anchor links.
But as soon as I scroll further up as the first div with an anchor link my script does not remove the class secondary-nav-menu-item-active for the first menu link.
What code should I add to my script so the first menu item is only highlighted if the scroll position is "inside" the first anchor link section?
Thanks for any advice.

In the meantime, I found a working solution. Maybe it helps someone else as well:
jQuery(function ($) {
$(window).scroll(function () {
var scrollPos = $(window).scrollTop();
$('.secondary-nav-menu-item-active').removeClass('secondary-nav-menu-item-active');
$('.secondary-nav-section').each(function (i) {
var topPos = $(this).offset().top;
if ((topPos - scrollPos) <= 182) {
$('.secondary-nav-menu-item-active').removeClass('secondary-nav-menu-item-active');
$('.secondary-nav-menu ul li').eq(i).addClass('secondary-nav-menu-item-active');
}
})
});
});
So, what was missing is this line of code:
$('.secondary-nav-menu-item-active').removeClass('secondary-nav-menu-item-active');
before adding the class to highlight the active second menu entry.

Related

On my website, i have a sticky header as well as a sticky tab section

On my website, I have a sticky header as well as a sticky tab section. The particular section of that respective tabs when we scroll that section hides under the header and the sticky tabs, I have used Javascript to do this. I want the sections to appear just after the sticky tabs, which are now opening bit under the sticky tabs.
There is an issue with the height of the header and the sticky tabs.
I want the script in which the section will scroll wondering the heights of the header and the sticky tabs, so that it will be visible properly.
Below is the script which I have used.
//script for sticky section like tabs starts
// Click event
offset = 0;
$('#primary-navwrapper li a[href^="#"]').click(function(event) {
// Prevent from default action to intitiate
event.preventDefault();
//remove active from all anchor and add it to the clicked anchor
$('#primary-navwrapper li a[href^="#"]').removeClass("active")
$(this).addClass('active');
// 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
var target = $(anchorId).offset().top - offset;
console.log(target);
$('html, body').stop().animate({ scrollTop: target }, 600, function () {
window.location.hash = anchorId;
});
return false;
});
//check the pages when scroll event occurs
$(window).scroll(function(){
// Get the current vertical position of the scroll bar
position = $(this).scrollTop();
$('#primary-navwrapper li a[href^="#"]').each(function(){
var anchorId = $(this).attr('href');
var target = $(anchorId).offset().top - offset;
// check if the document has crossed the page
console.log(position,target);
if(position>=target){
//remove active from all anchor and add it to the clicked anchor
$('#primary-navwrapper li a[href^="#"]').removeClass("active")
$(this).addClass('active');
}
})
})
$(function(){
//set our scroll state after dom ready
$(window).scroll();
})
//script for sticky section like tabs ends

Highlighting current section in navbar

I have a scrolling page with a navbar and I want the section the user is scrolling through to be highlighted in the navbar. At the moment it almost accomplishes this, but is highlighting the incorrect link.
A demonstration is at http://codepen.io/meek/pen/NNprYb?editors=1000
The code that does this is as follows:
// highlight current tab
$(window).on("scroll", function() {
var currentPos = $(window).scrollTop();
$('.nav li a').each(function() {
var sectionLink = $(this);
var section = $(sectionLink.attr('href'));
if(section.position().top <= currentPos && sectionLink.offset().top + section.height() >= currentPos) {
$('.nav li').removeClass('active');
sectionLink.parent().addClass('active');
}
else {
sectionLink.parent().removeClass('active');
}
});
});
I've tried several things, but can't get it to reliably add the active class to the correct session. Help appreciated!
edit: to be clearer, the problem is that it's only highlighting the section when you've scrolled a bit into it, instead of right at the top, meaning that when you click a section to scroll to the top of that section automatically, that section is not highlighted.
edit2: So changing the if statement to:
if(currentPos + $('#nav-wrapper').outerHeight() >= section.position().top && currentPos + $('#nav-wrapper').outerHeight() <= sectionLink.offset().top + section.outerHeight()) {
has made an improvement although not completely fixed the issue. The home, about and portfolio sections all highlight the correct link but not contact.
You need to account for the height of the navbar and subtract it from the top of the section you want highlighted.
The height is currently hardcoded in your CSS at 75px but I included a jQuery selector for the height in case it needs to change/disappear for smaller screens.
Nice work by the way.
$(window).on("scroll", function() {
var currentPos = $(window).scrollTop();
$('.nav li a').each(function() {
var sectionLink = $(this);
// capture the height of the navbar
var navHeight = $('#nav-wrapper').outerHeight() + 1;
var section = $(sectionLink.attr('href'));
// subtract the navbar height from the top of the section
if(section.position().top - navHeight <= currentPos && sectionLink.offset().top + section.height()> currentPos) {
$('.nav li').removeClass('active');
sectionLink.parent().addClass('active');
} else {
sectionLink.parent().removeClass('active');
}
});
});

Making nav bar effects using scroll AND click in jQuery

I want a nav to highlight (or something similar) once a user clicks on it AND when a user scrolls to the corresponding section.
However, on my computer when one clicks on any of the nav events after3, only nav event 3 changes. I'm guessing this is because after one clicks on 4 or 5, the scroll bar is already at the bottom of the page, so 4 and 5 never reach the top. The only div at the top is post 3, so my code highlights nav event 3 and ignores the click.
Is there any way I can fix this? Ive tried if statements (only highlight nav event if it's at the top AND the scrollbar isn't at the bottom or the top isn't the last item).
Here is a more accurate fiddle, using a fix below showing what I am talking about. The fix now highlights on scroll, but if you click option 5, it will not highlight.
$('.option').children('a').click(function() {
$('.option').css('background-color', '#CCCCCC;');
$(this).css('background-color', 'red');
var postId = $($(this).attr('href'));
var postLocation = postId.offset().top;
$(window).scrollTop(postLocation);
});
$(window).scroll(function() {
var scrollBar = $(this).scrollTop();
var allPosts = [];
var post = $('.content').offset();
var lastPost = allPosts.legnth-1
var windowHeight = $(window).height();
var bottomScroll = windowHeight-scrollBar;
$(".content").each(function(){
allPosts.push($(this).attr('id'));
});
i = 0;
for(i in allPosts){
var currentPost = "#"+allPosts[i];
var postPosition = $(currentPost).offset().top;
if (scrollBar >= postPosition){
$('.option').css('background-color', '#CCCCCC');
$('#nav'+allPosts[i]).css('background-color', 'red');
};
};
});
I think you've overdone your scroll() handler, to keep it simple you just needs to check if the scrollbar/scrollTop reaches the '.contents' offset top value but should not be greater than its offset().top plus its height().
$(window).scroll(function () {
var scrollBar = $(this).scrollTop();
$(".content").each(function (index) {
var elTop = $(this).offset().top;
var elHeight = $(this).height();
if (scrollBar >= elTop - 5 && scrollBar < elTop + elHeight) {
/* $(this) '.content' is the active on the vewport,
get its index to target the corresponding navigation '.option',
like this - $('.Nav li').eq(index)
*/
}
});
});
And you actually don't need to set $(window).scrollTop(postLocation); because of the default <a> tag anchoring on click, you can omit that one and it will work fine. However if you are looking to animate you need first to prevent this default behavior:
$('.option').children('a').click(function (e) {
e.preventDefault();
var postId = $($(this).attr('href'));
var postLocation = postId.offset().top;
$('html, body').animate({scrollTop:postLocation},'slow');
});
See the demo.
What you are trying to implement from scratch, although commendable, has already been done by the nice folks at Bootstrap. It is called a Scrollspy and all you need to do to implement it is include Bootstrap js and css (you also need jquery but you already have that) and make some minor changes to your html.
Scrollspy implementation steps.
And here is a demonstration. Notice only one line of js. :D
$('body').scrollspy({ target: '.navbar-example' });

CSS: Making Horizontal scrollable Menu

I want to add a menu to my application screens. The menu will have the menu icons which are horizontal scroll-able one menu at a time when left or right arrow pressed. Based on the menu screen the menu should be scrolled to that menu icon for that menu screen.
Ex.:
< menu1 | menu2 | menu3 >
Say there are 6 menu icons and 3 are visible at a time. on press of right arrow, it should scroll one item at a time.
and if my screen is related to menu 4, the menu4 has to be positioned.
< menu4 | menu5 | menu6 >
And also each menu item should be clickable.
Please let me know, How I can achieve this.
Update
Have js for MouseOver
<script type="text/javascript">
$(function () {
var div = $('div.sc_menu'),
ul = $('ul.sc_menu'),
ulPadding = 15;
var divWidth = div.width();
div.css({ overflow: 'hidden' });
var lastLi = ul.find('li:last-child');
div.mousemove(function (e) {
var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + ulPadding;
var left = (e.pageX - div.offset().left) * (ulWidth - divWidth) / divWidth;
div.scrollLeft(left);
});
});
</script>
JSFiddle
Check here
Update3
Update 4
This is dynamic menu retreived from db build with ul & li's. If there is more Li than screen width, I simply want an arrow to left & right side to scroll extra li's, if any.
See this fiddle:
http://jsfiddle.net/kzQFQ/49/
$(document).ready(function () {
$('.right').click(function () {
var position = $('.container').position();
var r=position.left-$(window).width()
$('.container').animate({
'left': ''+r+'px'
});
});
$('.left').click(function () {
var position = $('.container').position();
var l=position.left+$(window).width()
if(l<=0)
{
$('.container').animate({
'left': ''+l+'px'
});
}
});
});
Good article about horizontal scrollable menu here
And DEMO (Note: Reduce the size of the browser)
hop this should be help you see link
http://jquery.malsup.com/cycle/int2.html
see Non-Image Content at the last of page
see this fiddle: http://fiddle.jshell.net/vac9x/1/

Active state not being set by smooth-scroll plugin (JS modification)

I'm having some trouble with a script which takes care of smooth scrolling as well as the active state on my main navigation. Plugin: http://tinyurl.com/amz4kob
Please note that the navigation bar is fixed so effectively has no height.
I've got two issues which I can't seem to overcome:
On page load the active state is applied to the contact link. If you scroll down 1px the active state is correctly applied to the home link.
I can't for the life of me figure out how to modify the script to pay attention to anchors within an element with a certain ID? i.e. I only want this script to apply the active state to the elements within the tag.
Any help would be greatly appreciated.
#rrfive
To make life easy here is the commented script:
$(document).ready(function() {
//Get Sections top position
function getTargetTop(elem){
//gets the id of the section header
//from the navigation's href e.g. ("#html")
var id = elem.attr("href");
//Height of the navigation
var offset = 0;
//Gets the distance from the top and subtracts the height of the nav.
return $(id).offset().top - offset;
}
//Smooth scroll when user click link that starts with #
$('a[href^="#"]').click(function(event) {
//gets the distance from the top of the section refenced in the href.
var target = getTargetTop($(this));
//scrolls to that section.
$('html, body').animate({scrollTop:target}, 500);
//prevent the browser from jumping down to section.
event.preventDefault();
});
//Pulling sections from main nav.
var sections = $('a[href^="#"]');
// Go through each section to see if it's at the top.
// if it is add an active class
function checkSectionSelected(scrolledTo){
//How close the top has to be to the section.
var threshold = 54;
var i;
for (i = 0; i < sections.length; i++) {
//get next nav item
var section = $(sections[i]);
//get the distance from top
var target = getTargetTop(section);
//Check if section is at the top of the page.
if (scrolledTo > target - threshold && scrolledTo < target + threshold) {
sections.removeClass("active");
section.addClass("active");
}
};
}
//Check if page is already scrolled to a section.
checkSectionSelected($(window).scrollTop());
$(window).scroll(function(e){
checkSectionSelected($(window).scrollTop())
});
});
The plugin you're using checks the position of the <div class="section"></div> elements on the page, but because you've made them display:none;, all the sections are returning "0 pixels" from the top of the page, and since the "CONTACT" section is the last on the page, it's stopping there.
So, simply remove display:none; from .section in your CSS and it'll work fine.
.section {
/*display: none; <-- Comment this line out. */
height: 100%;
min-width: 990px;
}

Categories

Resources