Reputation: 341
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"><a href="#whatissm">What We Are</a></li>
<li id="whybutton"><a href="#whyusesm">Why Us</a></li>
<li id="offerbutton"><a href="#whatdoessmoffer">What We Offer</a></li>
<li id="contactbutton"><a href="#contactus">Contact Us</a></li>
</ul>
<ul class="nav navbar-nav pull-right">
<li><a href="#">Right Link</a></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.
Upvotes: 1
Views: 6246
Reputation: 1
/**
*
* @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");
Upvotes: 0
Reputation: 380
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 :)
Upvotes: 2