Sticky Nav Sticks Too Late - javascript

I'm creating a page with sticky nav and it doesn't stick to the top immediately after the header image moves away (it's less than full page size). It only sticks after the size of one full page image has passed. The text inside the nav bar also moves after it sticks.
You can view the code here: https://jsfiddle.net/zinctan/7a436ojz/
This is my javascript:
$(function() {
// when we scroll down the window, do this:
$(window).scroll(function(){
//Getting the scroll percentage
var windowHeight = $(window).height();
var scrollHeight = $(window).scrollTop();
var scrollPercentage = (scrollHeight / windowHeight);
console.log(scrollPercentage);
// if we have scrolled past 200, add the alternate class to nav bar
if(scrollPercentage > 1) {
$('.navHighlighter').addClass('scrolling');
} else {
$('.navHighlighter').removeClass('scrolling');
}
});
$('a[href*=#]:not([href=#])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top - 80
}, 1000);
return false;
}
}
}); // code courtesy of CSS-Tricks
// apply the class of nav-active to the current nav link
$('a').on('click', function(e) {
e.preventDefault();
$('li.nav-active').removeClass('nav-active');
$(this).parent('li').addClass('nav-active');
});
// get an array of 'href' of each a tag
var navLink = $('ul.navHighlighter a');
console.log(navLink);
var aArray = [];
for(var i = 0; i < navLink.length; i++) {
console.log(i);
var aChild = navLink[i];
var navArray = $(aChild).attr('href');
console.log(navArray);
aArray.push(navArray);
console.log(aArray);
var selector = aArray.join(" , ");
console.log(selector);
}
$(window).scroll(function(){
var scrollTop = $(window).scrollTop();
var tops = [];
$(selector).each(function(){
var top = $(this).position().top - 90;
if(scrollTop > top) {
var id = $(this).attr('id');
$('.nav-active').removeClass('nav-active');
$('a[href="#'+id+'"]').parent().addClass('nav-active');
}
tops.push(top);
});
});
});
Any help would be useful! Thank you :)

First of all it is a good practice to use:
$(document).ready(function(){
});
and then write your jQuery code in that function in order to assure that your script code will run after your html web page is fully loaded.
Now, I think that that should work:
$(document).ready(function() {
var topDist = $(".navHighlighter").position(); //save the position of your navbar, better use an id for that
$(document).scroll(function () {
var scroll = $(this).scrollTop();
if (scroll > topDist.top) { //when the scrolling reaches the very top of your navbar
$('.navHighlighter').addClass('scrolling');
} else {
$('.navHighlighter').removeClass('scrolling');
}
});
*rest of your code goes here*
});
Also, add:
top:0;
width: 100%;
to your .scrolling class in order to command your navbar to start just at the top of the user's window and to cover the whole width of the web page (position:fixed creates some issues on that so you have to set the width of your element, remember that).
I hope I helped and I got your demands right. Happy coding! :)

Related

Scroll a specific element inside container using JS or jQuery

I have huge sidebar element and when the page is scrolled sidebar point to the current element that is in a viewport. But sometimes active element is out of sidebar visible space i.e below or above borders. And then the user needs to scroll manually to be able to see active element.
I want to try use logic for determining if the active element is out sidebar visible space and auto scroll if needed.
$(window).on('scroll', function () {
var scrollTop = $(this).scrollTop();
var container = $('#sectionMenu');
var containerHeight = container.height();
$(data).each(function () {
var topDistance = $(this).offset().top - 250;
var id = $(this).attr('id');
var elem = $('#_' + id);
if ((topDistance) < scrollTop && (topDistance + $(this).height() * 0.95) > scrollTop) {
if (autoScrollFlag) {
if (!elem.hasClass('sideBarActive')) {
var scrollPosition = elem.offset().top - container.offset().top;
removeActiveMenuItems(data);
elem.addClass('sideBarActive');
if (containerHeight < scrollPosition) {
// TODO automated scroll
}
}
}
autoScrollFlag = 1;
}
});
});
The solution that has worked for me was like this.
if (containerHeight < scrollPosition) {
container.animate({
scrollTop: '+=100px'
}, 800);
}

How to stop scroll when dynamic div ends

I want to stop scroll after a dynamic div reaches its end. This div will be holding dynamic content so the size never stays the same. I know how to lock in position when scroll hits a pre-defined height, but not sure how to do it when the hight is constantly changing. here's what i'm using for my standard locking scroll when it hits specific point:
var profile_rc = $("#profile-rc");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 285) {
profile_rc.addClass("p-right-column");
} else {
profile_rc.removeClass("p-right-column");
}
});
Looks like you are using jQuery, the following 2 examples might help.
Detecting dynamic height of screen
<script>
$(function(){
var windowHeight = $(window).height();
$(window).resize(function() {
windowHeight = $(window).height();
console.log(windowHeight);
});
});
<script>
Detecting dynamic height of a div
<script>
$(function(){
var divHeight = $('#your-div-id').css("height");
$( window ).on("resize", function() {
divHeight = $('#your-div-id').css("height");
console.log(divHeight);
});
});
</script>
I got it to work doing this:
$(window).scroll(function() {
var divHeight = $('#farleft-cont').outerheight(true);
var ycbc = $('#target-div');
var scroll = $(window).scrollTop();
if (scroll >= divHeight) {
ycbc.addClass("target-div-fixed");
} else {
ycbc.removeClass("target-div-fixed");
}
});

scroll to next div already in browser

I have a series of divs that are 100% height with a scroll to function that takes you to the next div out of the viewport on background click. However, if the next div is already slightly in the viewport the whole thing is counted as being visible and the scroll to bypasses it. Can anyone offer direction on how to get the script to scroll to the div even if it's partially in the viewport already?
Codepen here.
If you begin scrolling slightly in the codepen and then click on the background you'll see that it doesnt scroll you to the div that's already in the viewport but the div after that.
$(document).ready(function() {
// get initial nav height
var $window = $(window);
var wst = $window.scrollTop();
var th = $('div.top').height();
var currentSlide = $('#wrapper').data( 'current-slide', $('div.slide').eq(0) );
$('div.scroll_images').css({ height: 'auto', overflow: 'visible', top: 0 });
$('div.scroll_images div.inner').css({ position: 'absolute', top: 0 });
$('div.slide').each(function() {
$(this).css('padding',function() {
return (($(window).height()-$(this).height())/2)+'px 0'
});
});
// scrollto for click on slide
jQuery.fn.scrollTo = function(hash) {
$this = $(this);
st = $this.offset().top - th; // subtract nav height
$('html, body').animate({ scrollTop: st }, 550
);
}
$('#wrapper').click(function(e){
//get the current slide index from the body tag.
$this = currentSlide.data( 'current-slide' );
$next = $(".slide:below-the-fold");
if($next.length) {
$next.scrollTo($next.attr('id'));
//Save the next slide as the current.
$('#wrapper').data( 'current-slide', $next );
} else {
//Throw us back to the top.
$('div.slide:first').scrollTo($('div.slide:first').attr('id'));
//Save the first slide as the first slide, which
//Cycles us back to the top.
$('#wrapper').data( 'current-slide', $('div.slide:first'));
}
})
//Images fade in
$('img').hide();
$('img').each(function(i) {
if (this.complete) {
$(this).fadeIn();
} else {
$(this).load(function() {
$(this).fadeIn();
});
}
});
//Stop links affecting scroll function
$("a").click(function(e) {
e.stopPropagation();
});
});
(function($) {
$.belowthefold = function(element, settings) {
var fold = $(window).height() + $(window).scrollTop();
return fold <= $(element).offset().top - settings.threshold;
};
$.extend($.expr[':'], {
"below-the-fold": function(a, i, m) {
return $.belowthefold(a, {threshold : 0});
}
});
})(jQuery);
Here's what I might try to do: go through each div in the series. Find the div who's offset() is closest to $(window).scrollTop(). Now, find the next() div after the "current" one and scroll to it.
For comparing the offset() of each div, try something like this:
var closest = $('[selector]:first');
$('[selector]').each(function() {
var oldDistance = Math.abs(closest.offset() - $(window).scrollTop());
var newDistance = Math.abs($(this).offset() - $(window).scrollTop());
if(newDistance < oldDistance) {
closest = $(this);
}
}

Active anchor links not getting set properly on fixed nav on scroll/click

I'm adding and removing a class for active anchor link (color:red). The issue is the class is not being added consistently according to sections and I don't seem to figure this one out.
How can I modify my code as so anchor links get "highlited" when its respective section is on top of the page consistently?
Here is my code:
// for secondary nav
var topRange = 200, // measure from the top of the viewport to X pixels down
edgeMargin = 20, // margin above the top or margin from the end of the page
contentTop = [];
// Set up content an array of locations for secondary nav
$('.overlay-box').find('a').each(function(){
var href = $(this).attr('href');
var name = href.substr(href.lastIndexOf('#')+1);
contentTop.push( $('[name="' + name + '"]').offset().top );
});
// adjust secondary nav on scroll
$(window).scroll(function(){
var winTop = $(window).scrollTop(),
bodyHt = $(document).height(),
vpHt = $(window).height() + edgeMargin; // viewport height + margin
$.each( contentTop, function(i,loc){
if ( ( loc > winTop - edgeMargin && ( loc < winTop + topRange || ( winTop + vpHt ) >= bodyHt ) ) ){
$('.nav-bar li')
.removeClass('anchor-selected')
.eq(i).addClass('anchor-selected');
}
});
});
here is the site:
http://www.icontrol.com/what-we-do/platform-services/
I cant see exactly how you are going about doing this.
I have put together a jsfiddle to achieve what you are looking to do
Hope its what you need :-)
http://jsfiddle.net/66ZbB/
$(document).ready(function() {
$('a').click(function() {
$('a').removeClass('anchor-selected');
var obj = $(this);
$('html, body').animate({
scrollTop: obj.offset().top
}, 1000, function () {
obj.addClass('anchor-selected');
});
});
$(window).scroll(function() {
$('a').removeClass('anchor-selected');
//alert($(window).scrollTop() +":");
$('a').each(function() {
console.log($(this).offset.top);
if (($(window).scrollTop() <= ($(this).offset().top)) && ($(window).scrollTop() > ($(this).offset().top - 20))) {
$(this).addClass('anchor-selected');
}
});
});
});

Get the height of a div jquery

I am trying to make a navigation, that sets the "active" class to links whenever it scrolls a specified ammount of pixels. But there is a div on the page, that get's its size based on user interaction.
This is the code for setting the active class.
$(function() {
//caches a jQuery object containing the header element
var header = $(".active");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >=760) {
header.removeClass('active').addClass("active1");
}
else { header.removeClass('active1').addClass('active');}
});
var header1 = $("#work");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 759 && scroll < 780) {
header1.removeClass('#work').addClass("active");
} else {
header1.removeClass("active").addClass('#work');
}
});
var header2 = $("#about");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll > 779 && scroll < 1450) {
header2.removeClass('#about').addClass("active");
} else {
header2.removeClass("active").addClass('#about');
}
});
var header3 = $("#contact");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll > 1449) {
header3.removeClass('#contact').addClass("active");
} else {
header3.removeClass("active").addClass('#contact');
}
});
});
How do I get the height of a div which has it's class set as auto, and then apply it in the code above ?
EDIT: I tried the $('#ID').height(); but it gets the height when the website is loaded, and it doesn't work after any user interacts with the div.
In basically get the height of the DIV
$('#ID').height();
it returns height.
I guess this is what you are looking for
Sample DEMO
if($("#ID").offset().top < $(window).scrollTop() + $(window).outerHeight())
If you create a fiddle possibly can do the same for you
Hope this helps, Thank you

Categories