Making a menu class active when scrolled past - javascript

Note: Using Bootstrap
I want to assign a menu item the 'active' class when the anchor is 50px away from top of the screen. This means that i need to unassign the active class in js and assign a new one.
This is my Menu
<nav class="navbar navbar-default" data-spy="affix" data-offset-top="34">
<div class="container">
<div class="navbar-collapse collapse navbar-responsive-collapse" id="main-menu">
<ul class="nav navbar-nav">
<li id="whatbutton">What We Are</li>
<li id="whybutton">Why Us</li>
<li id="offerbutton">What We Offer</li>
<li id="contactbutton">Contact Us</li>
</ul>
<ul class="nav navbar-nav pull-right">
<li>Right Link</li>
</ul>
</div>
</div>
</nav>
And these are my h1's
<h1 id="whatissm" name="whatissm"><span>sometexthere</span></h1>
<h1 id="whyusesm" name="whyusesm"><span>somtexthere</span></h1>
<h1 id="whatdoessmoffer" name="whatdoessmoffer"><span>sometexthere</span></h1>
<h1 id="contactus" name="contactus"><span>Contact Us</span></h1>
Now this is where I start to struggle...
from an early post i understand that my js should look something like this
<script>
//smooth scrolling
$(function() {
$('[data-toggle="popover"]').popover();
$('[title]').tooltip({container: 'body'});
});
$('a').click(function() {
var reduce = 150;
$('html, body').animate({
scrollTop: $('[name="' + $.attr(this, 'href').substr(1) + '"]').offset().top - reduce
}, 500);
return false;
});
//Making class active by scrolling past it
$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
var anchors = $('body').find('.anchor');
for (var i = 0; i < anchors.length; i++){
if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
$(anchors[i]).addClass('active');
} else {
$(anchors[i]).removeClass('active');
}
}
});
</script>
But unfortunately that code isn't working for me. 1) It doesn't unassign the active class 2) it's just not working.
Edit: Similar to this http://getbootstrap.com/css/ (when you scroll the active class in the right menu changes)
Edit2: Added my code for the scroll down active effect... i'm fairly new to js so i may have implemented it wrong somehow.

EDIT: Understood the actual issue:
$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
var anchors = $('body').find('h1');
for (var i = 0; i < anchors.length; i++){
if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').addClass('active');
} else {
$('nav ul li a[href="#' + $(anchors[i]).attr('id') + '"]').removeClass('active');
}
}
});
Same technique; checking if each of your h1 elements are both below the elements top position and above the elements bottom position. If true, get the id of the element and select the corrosponding navigation item and add active class to it.
Updated fiddle: http://jsfiddle.net/yrz54fqm/1/
Old answer
Following code should give you the result you're looking for
$(window).scroll(function(){
var scrollTop = $(document).scrollTop();
var anchors = $('body').find('.anchor');
for (var i = 0; i < anchors.length; i++){
if (scrollTop > $(anchors[i]).offset().top - 50 && scrollTop < $(anchors[i]).offset().top + $(anchors[i]).height() - 50) {
$(anchors[i]).addClass('active');
} else {
$(anchors[i]).removeClass('active');
}
}
});
You need to listen for the scroll event on the window, and check if each of your elements are both below the elements top position and above the elements bottom position.
Replace the var anchors = $('body').find('.anchor'); on line 3 with whatever the anchor class names are in your situation. Here's a fiddle with HTML and CSS aswell: http://jsfiddle.net/yrz54fqm/
Hope it helps :)

/**
*
* #param {Element} - element 1 that used to get offset when scrolling
* #param {Element} - activated when passing element 1
* #param {String} - class name to add to element 2 when element 1 is passed
*/
this.ScrollBetween = function(targetElement, pElement, className) {
$(window).scroll(function() {
var scrollTop = $(window).scrollTop(),
targetOffsetTop = $(targetElement).offset().top,
targetHeight = $(targetElement).height();
(scrollTop > targetOffsetTop - 50 && scrollTop < targetOffsetTop + targetHeight - 50 ? $(pElement).addClass(className) : $(pElement).removeClass(className));
});
};
Made a function so it way easier to understand. Right now it is used in a JQuery Object but can be simply changed to regular function by changing it to
function ScrollBetween(targetElement, pElement, className){
.............
}
Can be called by
ScrollBetween($("#section-1"), $("li-1"), "active");

Related

JQuery fadeIn() when element comes into viewport

I would like to fadeIn() different elements as soon as they come into viewport view, when scrolling down a page.
My code however fades in all DIVs (that have the ".fadethis" class) at once, instead of only when that specific element comes into view:
$(window).scroll(function() {
$(".fadethis").each(function() {
var top_of_element = $(this).offset().top;
var bottom_of_element = $(this).offset().top + $(this).outerHeight();
var bottom_of_screen = $(window).scrollTop() + window.innerHeight;
var top_of_screen = $(window).scrollTop();
if((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)){
$(this).fadeIn(10000);
}
});
});
CSS
.fadethis{
display:none;
}
Import jQuery, animate.less and waypoint
Javascript:
$(document).ready(function(){
$('.fromLeft').waypoint(function()
{
$(this.element).css('opacity',1);
$(this.element).addClass("bounceInLeft");
},
{offset:'100%'});
$('.fromRight').waypoint(function()
{
$(this.element).css('opacity',1);
$(this.element).addClass("bounceInRight");
},{offset:'100%'});
$('.appear').waypoint(function()
{
$(this.element).css('opacity',1);
$(this.element).addClass("fadeIn");
},{offset:'100%'});
});
And HTML
<div class="animated onView fromLeft">
appears from left
</div>
Here you can see an example I made

Add and remove class using javascript on scroll

I need to add class via javascript on scroll. My issue is I need to add and remove class on reaching a particular section id
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
$(".clearHeader1").removeClass("video-background");
$(".clearHeader11").addclass("video-foreground");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="id1" class="clearHeader1 video-background"></section>
<section id="id2" class="clearHeader1"></section>
Try this one
if($(window).scrollTop() >= $('#id1').offset().top + $('#id1').outerHeight() - window.innerHeight) {
$("#id1").removeClass("active");
console.log("removeClass");
}else{
console.log("addClass");
$("#id1").addClass("active");
}
Try this
$(window).scroll(function() {
var scroll = $(this).scrollTop();
var section1Height = $('#id1').offset().top + $('#id1').outerHeight() - window.innerHeight;
if (scroll >= section1Height ) {
$(".clearHeader1").removeClass("video-background");
$(".clearHeader11").addclass("video-foreground");
}
}

Scrolling issue while sticking header and setting the tab active | Jquery

I have developed a page, which has a fixed menu once the page is scrolled and also the tabs will become active on their appropriate section id's.
I have almost completed the functionality but I am facing some problems :
Scrolling is not appropriate and it is not stopping at the exact position of the container. Example : If i scroll to section3, the tab should get select once the section3 container hits, but I need to scroll a little bit to get the tab selected.
Once I click on the tab, then the page is getting freezed unable to do any scroll on the page neither able to select any other tab.
i have seen lot of demo's and tried but failed to implement. as per my knowledge i did this demo.
Please help me out with the current code change where I have done wrong.
this is what I tried.
demo Link
HTML:
<div class="top_layer">Top Layer</div>
<div class='menu'>
<ul>
<li>basic 1</li>
<li>basic 2</li>
<li>basic 3</li>
<li>basic 4</li>
</ul>
</div>
<div id="basic1" class="section">basic 1</div>
<div id="basic2" class="section">basic 2</div>
<div id="basic3" class="section">basic 3</div>
<div id="basic4" class="section">basic 4</div>
JS:
var menuSection = $('.section') , navLists = $('.menu ul li'),
navLists_height = navLists.outerHeight(), headerOffset = $('.top_layer').offset().top;
$(window).on('scroll', function () {
var window_top = $(window).scrollTop() + 12;
if (window_top > headerOffset) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
var cur_position = $(this).scrollTop();
menuSection.each(function() {
var top = $(this).offset().top - navLists_height,
bottom = top + $(this).outerHeight();
if (cur_position >= top && cur_position <= bottom) {
navLists.find('a').removeClass('active');
menuSection.removeClass('active');
$(this).addClass('active');
navLists.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
}
});
navLists.find('a').on('click', function () {
var $el = $(this)
, id = $el.attr('href');
$('html, body').animate({
scrollTop: $(id).offset().top - navLists_height
}, 500);
return false;
});
});
I have update the code , check fiddle , your navlist selecting anchors should be outsideof window scroll.
var menuSection = $('.section'),
navLists = $('.menu ul li'),
navLists_height = navLists.outerHeight(),
headerOffset = $('.top_layer').offset().top;
$(window).on('scroll', function() {
var window_top = $(window).scrollTop() + 12;
if (window_top > headerOffset) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
var cur_position = $(this).scrollTop() + 70;//70 for fixed header height
menuSection.each(function() {
var top = $(this).offset().top - navLists_height,
bottom = top + $(this).outerHeight();
if (cur_position >= top && cur_position <= bottom) {
navLists.find('a').removeClass('active');
menuSection.removeClass('active');
$(this).addClass('active');
navLists.find('a[href="#' + $(this).attr('id') + '"]').addClass('active');
}
});
});
navLists.find('a').on('click', function() {
var $el = $(this),
id = $el.attr('href');
$('html, body').animate({
scrollTop: $(id).offset().top - navLists_height
}, 500);
return false;
});

use jquery to add class both on click of nav item AND scroll past div

I am looking to use jquery to add a class of "selected" both on clicking of a nav item as well as scrolling past that section div.
So far I have got the class added on clicking of the nav item but I am unsure how to neatly add the same affect when scrolling past each section div.
Here's my script for adding the class on click (which is pretty straightforward and standard):
$('#fixednav li').click(function(){
$('#fixednav li').removeClass("selected");
$(this).addClass("selected");
});
...It all works great when user clicks the items in the fixed menu. But how do I add the selected class when user just scrolls down the page without using the fixed menu? Each section has a div id so I would think it would be easy to add something in to add the class on scroll past the div id....
Here's my fiddle
Scroll down a bit to see the fixed nav pop in....
i had the same issue and i used scrollspy to fix it here is the link and demo on bootstrap :
scrollspy
if you get some pb please let me know.
Check if this helps you fiddle
This is the js used, check the fiddle for html and css.
var hei = $("#header").height();
$(window).scroll(function(){
if($(window).scrollTop() > hei){
$("#header").addClass('fixed');
$('.body-wrapper').css('margin-top',hei);
}else{
$("#header").removeClass('fixed');
$('.body-wrapper').css('margin-top','0');
}
});
$("#header li a").on('click', function(event){
event.preventDefault();
var header_height = $("#header").height();
var target = $(this).attr('href');
$('html, body').animate({
scrollTop: $(target).offset().top-header_height
}, 1000);
});
var aChildren = $("#header 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-hei-30; // 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("nav-active");
} else {
$("a[href='" + theID + "']").removeClass("nav-active");
}
}
});

jQuery class change based on scroll ignoring last section

I'm using jQuery to guide my pages scrolling and change the color of a nav item to correspond to the section you're in. Everything's working well, but the script is ignoring the last section on the page (Contact).
This is largely based on another question here on Stack, but I've modified the code to fit my needs and then ran into the issue.
Test site:
http://dev4.dhut.ch/
HTML:
<nav>
<ul>
<li class="active">MUSIC</li>
<li>PHOTOS</li>
<li>LYRICS</li>
<li>NEWS</li>
<li>INFO</li>
<li>CONTACT</li>
</ul>
<span></span>
</nav>
JavaScript:
var $sections = $('section'),
$navs = $('nav > ul > li'),
topsArray = $sections.map(function(){
return $(this).position().top - 100;
}).get(),
len = topsArray.length,
currentIndex = 0,
getCurrent = function(top){
for(var i = 0; i < len; i++){
if(top > topsArray[i] && topsArray[i+1] && top < topsArray[i+1]){
return i;
}
}
};
$(document).scroll(function(e){
var scrollTop = $(this).scrollTop(),
checkIndex = getCurrent( scrollTop );
if( checkIndex !== currentIndex ){
currentIndex = checkIndex;
$navs.eq( currentIndex ).addClass('active').siblings('.active').removeClass('active');
}
});
I think the following line is where the problem lies:
if(top > topsArray[i] && topsArray[i+1] && top < topsArray[i+1]){
Specifically topsArray[i+1] is undefined for the last iteration of i. Try pushing one more value into topsArray that includes the height of the entire page.
topsArray = $sections.map(function(){
return $(this).position().top - 100;
}).get(),
topsArray.push(document.height);

Categories

Resources