I'm using the following fixed navigation plug-in - https://codyhouse.co/demo/vertical-fixed-navigation/index.html
It works great when each section has 100% height as it picks the center of the section, but my sections aren't 100% height.
Is there a way to adapt this to work with smaller sections?
Here's a fiddle I created
As you can see, it doesn't even highlight the top or bottom sections as they aren't in the center point of the screen.
JS:
jQuery(document).ready(function($){
var contentSections = $('.cd-section'),
navigationItems = $('#cd-vertical-nav a');
updateNavigation();
$(window).on('scroll', function(){
updateNavigation();
});
//smooth scroll to the section
navigationItems.on('click', function(event){
event.preventDefault();
smoothScroll($(this.hash));
});
//smooth scroll to second section
$('.cd-scroll-down').on('click', function(event){
event.preventDefault();
smoothScroll($(this.hash));
});
//open-close navigation on touch devices
$('.touch .cd-nav-trigger').on('click', function(){
$('.touch #cd-vertical-nav').toggleClass('open');
});
//close navigation on touch devices when selectin an elemnt from the list
$('.touch #cd-vertical-nav a').on('click', function(){
$('.touch #cd-vertical-nav').removeClass('open');
});
function updateNavigation() {
contentSections.each(function(){
$this = $(this);
var activeSection = $('#cd-vertical-nav a[href="#'+$this.attr('id')+'"]').data('number') - 1;
if ( ( $this.offset().top - $(window).height()/2 < $(window).scrollTop() ) && ( $this.offset().top + $this.height() - $(window).height()/2 > $(window).scrollTop() ) ) {
navigationItems.eq(activeSection).addClass('is-selected');
}else {
navigationItems.eq(activeSection).removeClass('is-selected');
}
});
}
function smoothScroll(target) {
$('body,html').animate(
{'scrollTop':target.offset().top},
600
);
}
});
edit: make your section containers a % height. ex: height: 100% it will not work properly with a fixed height.
change your updateNavigation to look like this, don't copy and paste this as you can see the if else statement needs work to check if you are at the bottom of the page.
function updateNavigation() {
contentSections.each(function(){
$this = $(this);
var activeSection = $('#cd-vertical-nav a[href="#'+$this.attr('id')+'"]').data('number') - 1;
if ( ( $this.offset().top - $(window).height()/2 < $(window).scrollTop() ) && ( $this.offset().top + $this.height() - $(window).height()/2 > $(window).scrollTop() ) ) {
navigationItems.eq(activeSection).addClass('is-selected');
}
else if(!$(window).scrollTop() ){
navigationItems.eq(activeSection).removeClass('is-selected');
navigationItems.eq(0).addClass('is-selected');
}
else if(check if you are at the bottom of the page not sure how){
navigationItems.eq(activeSection).removeClass('is-selected');
navigationItems.eq(navigationItems.length -1).addClass('is-selected');
}else {
navigationItems.eq(activeSection).removeClass('is-selected');
}
});
}
Related
I have a navbar that hides when I scroll down and shows up when I scroll up. That works fine.
But on smaller screens I have a full width menu that expands with a hamburger toggle and when I scroll even then hides. Is there a solution to fix that?
I also wonder if the navbar always could be visible when it's on top of the page.
Thanks on behalf.
My website
// detect scroll top or down
if ($('.smart-scroll').length > 0) { // check if element exists
var last_scroll_top = 0;
$(window).on('scroll', function() {
scroll_top = $(this).scrollTop();
if(scroll_top < last_scroll_top) {
$('.smart-scroll').removeClass('scrolled-down').addClass('scrolled-up');
}
else {
$('.smart-scroll').removeClass('scrolled-up').addClass('scrolled-down');
}
last_scroll_top = scroll_top;
});
}
Found the solution:
// detect scroll top or down
if ($('.smart-scroll').length > 0) { // check if element exists
var last_scroll_top = 0;
$(window).on('scroll', function() {
scroll_top = $(this).scrollTop();
if(scroll_top > last_scroll_top && last_scroll_top > 40) {
$('.smart-scroll').removeClass('scrolled-up').addClass('scrolled-down');
}
else {
$('.smart-scroll').removeClass('scrolled-down').addClass('scrolled-up');
}
last_scroll_top = scroll_top;
});
}
$(document).ready(function(){
$(".navbar").on('shown.bs.collapse', function(){
$('.smart-scroll').removeClass('scrolled-down').addClass('scrolled-no');
});
$(".navbar").on('hidden.bs.collapse', function(){
$('.smart-scroll').removeClass('scrolled-no').addClass('scrolled-down');
});
});
I have two menus on a page, I am trying to show the one when the page is loaded and the other when there is a scroll.
This is my page Link
I would like to show the white part when position is at the top
and the blue part when there is a scroll past the top position
This is what am trying presently
<script type="text/javascript" src="//code.jquery.com/jquery-git.js"></script>
<script type='text/javascript'>//<![CDATA[
$(function(){
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-bar-below op-page-header cf').addClass('banner include-nav');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('banner include-nav').addClass('nav-bar-below op-page-header cf');
}
}
lastScrollTop = st;
}
});//]]>
</script>
can some one please help its not working for me
You can just detect if the scroll is at the top of the page or not whenever scroll event fired. if yes, show white header, and vice versa
$(window).scroll( function() {
var scrollPosition = $(window).scrollTop();
if(scrollPosition === 0) {
//show white header
}
else {
//show blue header
}
}
Of course you have to make sure when page first load, it show the white one first (use css). since the code above won't run Until user do scroll (fire this event)
*EDIT
for this :
"and the blue part when there is a scroll past the top position"
you can try this plugin
http://stickyjs.com/
sample code for fix the menu at top position.
$(document).scroll(function() {
var y = $(document).scrollTop()
var header = $('.include-nav');
var blue-menu = $('.cf');
var screenHeight = header.height();
if (y >= screenHeight) {
blue-menu.css({
position : "fixed",
"top" : "0",
"left" : "0"
});
header.css("position", "relative");
} else {
blue-menu.css("position", "relative");
}
});
I'm using this function to hide my header when scrolling down, and showing it again when scrolling up
$(function(){
var lastScrollTop = 0, delta = 5;
$('.item').scroll(function() {
var nowScrollTop = $(this).scrollTop();
if(Math.abs(lastScrollTop - nowScrollTop) >= delta){
if (nowScrollTop > lastScrollTop){
$('header').fadeTo(0,0); // scrolling down
} else {
$('header').fadeTo(0,1); // scrolling up
}
lastScrollTop = nowScrollTop;
}
});
});
Additionally I'm using this function to show the header when the cursor is in the top 200px of the page:
$(window).on('mousemove', function(e) {
if ( e.pageY < 200 ) {
$('header').fadeTo(0,1);
}
});
The problem is that when I'm scrolling with my mouse being in the top 200px of the window, the two functions collide, and the header keeps toggling between being shown and hidden.
Now, I've read elsewhere that I need to unbind and bind the mousemove when scrolling. I don't know however how to do that.
EDIT:
Here's a link to jsfiddle: https://jsfiddle.net/zrmg646L/
EDIT 2:
Here's a link to the jsfiddle with the solution in action: http://jsfiddle.net/zrmg646L/3/
Try this. Unbind mousemove on scroll and rebind it after not scrolled for 250ms
function fadeHeader(e) {
if ( e.pageY < 200 ) {
$('header').fadeTo(0,1);
}
}
$(function(){
$(window).mousemove(fadeHeader);
var lastScrollTop = 0, delta = 5;
$('.item').scroll(function() {
$(window).unbind('mousemove', fadeHeader);
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
$(window).mousemove(fadeHeader);
}, 250));
var nowScrollTop = $(this).scrollTop();
if(Math.abs(lastScrollTop - nowScrollTop) >= delta){
if (nowScrollTop > lastScrollTop){
$('header').fadeTo(0,0);
} else {
$('header').fadeTo(0,1); // scrolling up
}
lastScrollTop = nowScrollTop;
}
});
});
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);
}
}
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');
}
});
});
});