There's a couple things I'm trying to make happen with a sticky nav on a website. I have it working in all browsers, except Firefox.
I want the links to change as the window scrolls.
I want to add a class to change the navigation at a certain point.
Here's the code that's been working in Chrome:
<section id="nav">
<nav>
<ul>
<li id="p1">Snap</li>
<li id="p2">Organize</li>
<li id="p3">Store</li>
<li id="p4">Unify</li>
<li id="p5">Share</li>
<li id="n-play" class="sticky-dl">Get it on Google Play</li>
<li id="n-app" class="sticky-dl">Download on the App Store</li>
</ul>
</nav>
</section>
The Javascript/jQuery
// Auto Nav Active Switching
var nav = $('#nav-sticky-wrapper').height();
var navh = nav+1;
var b = $('section#b').offset().top - navh;
var c = $('section#c').offset().top - navh;
var d = $('section#d').offset().top - navh;
var e = $('section#e').offset().top - navh;
var f = $('section#f').offset().top - navh;
var remove = $('nav ul li a');
setInterval(function() {
if ( $(window).scrollTop() < b ) {
$('section#nav ul').removeClass('stuck');
$('section#nav ul li.sticky-dl').fadeOut(250);
} else {
$('section#nav ul').addClass('stuck');
$('section#nav ul li.sticky-dl').fadeIn(250);
}
if ( $(window).scrollTop() < c ) {
$(remove).removeClass('active');
$('#nb').addClass('active');
} else if ( $(window).scrollTop() >= c && $(window).scrollTop() < d ) {
$(remove).removeClass('active');
$('#nc').addClass('active');
} else if ( $(window).scrollTop() >= d && $(window).scrollTop() < e ) {
$(remove).removeClass('active');
$('#nd').addClass('active');
//bonusoff();
} else if ( $(window).scrollTop() >= e && $(window).scrollTop() < f ) {
$(remove).removeClass('active');
$('#ne').addClass('active');
// Runs Bonus Animation upon Entry
bonus();
} else if ( $(window).scrollTop() >= f ) {
$(remove).removeClass('active');
$('#nf').addClass('active');
}
});
Does Firefox not respond to setInterval or something? Thanks in advance!
setInterval requires a ** delay time** to wait. What is the delay you want? ex: setInterval(function(){...}, 3000);
Related
I'm trying to add a bottom border to appear under the tabs on a navigation bar depending on where you are on the webpage, but when I test to see if my code works, the CSS doesn't get applied. When I check in chrome's dev tools, the class gets added to the elements properly, the border just doesn't appear visually. I've just starting to learn JavaScript so I can't figure out why exactly this isn't working.
I did this following this YouTube tutorial https://www.youtube.com/watch?v=3-2Pj5hxwrw, my code matches his exactly except for a couple notes.
I've played with the required scroll position since my screen is bigger than the one he was using, but it still has the same issue of it adding the class correctly, but the CSS not being applied at all. All related code is under here and any insight would be appreciated!
HTML:
</div>
<ul class="navbar_menu">
<li class="navbar_item">
Home
</li>
<li class="navbar_item">
About
</li>
<li class="navbar_item">
<a href="#services" class="navbar_links" id="services-page"
>Services</a
>
</li>
<li class="navbar_btn">
Sign Up
</li>
</ul>
</div>
CSS:
.highlight {
border-bottom: 4px solid rgb(132,0,255);
}
JavaScript:
const highlightMenu = () => {
const elem = document.querySelector('.highlight');
const homeMenu = document.querySelector('#home-page');
const aboutMenu = document.querySelector('#about-page');
const servicesMenu = document.querySelector('#services-page');
let scrollPos = window.scrollY;
if(window.innerWidth > 960 && scrollPos < 600) {
homeMenu.classList.add('highLight');
aboutMenu.classList.remove('highLight');
return;
} else if (window.innerWidth > 960 && scrollPos < 1400) {
aboutMenu.classList.add('highLight');
homeMenu.classList.remove('highLight');
servicesMenu.classList.remove('highLight');
return;
} else if (window.innerWidth > 960 && scrollPos < 2345) {
servicesMenu.classList.add('highLight');
aboutMenu.classList.remove('highLight');
return;
}
if((elem && window.innerWidth < 960 && scrollPos < 600) || elem) {
elem.classList.remove('highLight');
}
}
window.addEventListener('scroll', highlightMenu);
window.addEventListener('click', highlightMenu);
Just needed to close your anonymous function, in this cases I advice you to use JS validator, so you won't waste time for these kind of mistakes.
const highlightMenu = () => {
const elem = document.querySelector('.highlight');
const homeMenu = document.querySelector('#home-page');
const aboutMenu = document.querySelector('#about-page');
const servicesMenu = document.querySelector('#services-page');
let scrollPos = window.scrollY;
if(window.innerWidth > 960 && scrollPos < 600) {
homeMenu.classList.add('highLight');
aboutMenu.classList.remove('highLight');
return;
} else if (window.innerWidth > 960 && scrollPos < 1400) {
aboutMenu.classList.add('highLight');
homeMenu.classList.remove('highLight');
servicesMenu.classList.remove('highLight');
return;
} else if (window.innerWidth > 960 && scrollPos < 2345) {
servicesMenu.classList.add('highLight');
aboutMenu.classList.remove('highLight');
return;
}
if((elem && window.innerWidth < 960 && scrollPos < 600) || elem) {
elem.classList.remove('highLight');
}
}
What I'm trying to do is a onepage website where the first "section" is a big background image (actually 4 of them, same size and same position) which should change when the user scrolls ( Just accessed the website - image1 ; Scrolled down once - image2; Scrolled down once again: image3 and so on). I tried with the js from http://jsfiddle.net/WTkqn/, but the problem is the images are fixed, though I need the webpage to scroll down as usually after the last image. I'm pretty new to javascript so any help would be highly appreciated.
As an example is http://airnauts.com/, after all the scrolling to the top area is done, the website scrolls down to the rest of the content.
$(document).ready(function(){
var offset2 = $(document).height();
var lineHF = offset2 - $("#bottommark").position().top;
$(window).scroll(function(){
var offset1 = $(document).height();
var offset = $(window).scrollTop();
var lineH = offset1 - $("#bottommark").position().top - offset;
var lineHpart = lineHF/5;
$("span").html(lineH);
if (lineH > lineHpart*4) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful1.jpg");
}
if ((lineH < lineHpart*4) && (lineH > lineHpart*3)) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful2.jpg");
}
if ((lineH < lineHpart*3) && (lineH > lineHpart*2)) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful3.jpg");
}
if (lineH < lineHpart*2 && lineH > lineHpart*1) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful4.jpg");
}
if (lineH < lineHpart) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful5.jpg");
}
});
});
Try this. I've added an additional condition lineH > lineHpart/2 in the last if-else statement which coincides with the height of the image. Also, in the last else, i've changed the css property from position:fixed to position:relative. On the way up, once the condition matches for last if-else, it would set the property from position:relative to position:fixed.
$(document).ready(function(){
var offset2 = $(document).height();
var lineHF = offset2 - $("#bottommark").position().top;
var changeRelative = false;
$(window).scroll(function(){
var offset1 = $(document).height();
var offset = $(window).scrollTop();
var lineH = offset1 - $("#bottommark").position().top - offset;
var lineHpart = lineHF/5;
$("#animation").css("position","fixed"); // set position:fixed by default
$("span").html(lineH);
if (lineH > lineHpart*4) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful1.jpg");
}
else if ((lineH < lineHpart*4) && (lineH > lineHpart*3)) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful2.jpg");
}
else if ((lineH < lineHpart*3) && (lineH > lineHpart*2)) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful3.jpg");
}
else if (lineH < lineHpart*2 && lineH > lineHpart*1) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful4.jpg");
}
else if (lineH < lineHpart && lineH > lineHpart/2) {
$("#animation").attr("src", "http://coverjunction.s3.amazonaws.com/manual/low/colorful5.jpg");
}
else
{
$("#animation").css("position","relative");
}
});
});
Here's a working example : https://jsfiddle.net/WTkqn/301/
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");
here is an interesting question.
I have a navigation bar that looks like this:
< div id = "main_nav" >
< ul >
< li id = "Tab1" > Home < / li >
< li id = "Tab2" > Home1 < / li >
< li id = "Tab3" > Home2 < / li >
< li id = "etc" > etc etc < / li >
...
< / ul >
< / div >
So the #main_nav has fixed width of 980px with overflow hidden and tabs are inline block.
When the screen width decreased in size, the tabs are overflowing and are beyond the screen view, thous are hidden.
To make it fun, I created a property to catch the last tab and see if it is overflowing, if it does, fire the event so the tab changes the from block to something else like responsive design.
Here is the code:
$( window ).on( 'resize', function(){ resize(); } );
function resize() {
var pageWidth = $ ( "#main_nav" ).width();
var elementWidth = $ ( "#tab14" ).width();
var elementLeft = $ ( "#tab14" ).position().left;
if ( pageWidth - ( elementWidth + elementLeft ) < 0 ) {
$ ( 'ul > li' ) .css ( { 'float': 'left' } );
}
else {
$ ( 'ul > li' ) .css ( { 'float': '' } );
}
}
The problem: The tabs starts flickering as it checks if #tab14 is overflown and on refresh you need to resize window to get to that state.
The question:
1. Not related to the issue but, what is a good Jquery counter to find the number of the last tab automatically and fill in to the $("#tab NUMBER?").width();
To avoid flickering, I tried the Timer, none worked. Do any of you know how to Save a Cookie of the Screen Width when the Tab event (tab overflowing) fired? So I can fire the else event only after that screen width reached to return tab to its original shape.
Your input is very appreciated! Thank you.
You can save cookies in JavaScript by using the window.localStorage method. Take a look at https://developer.mozilla.org/en/docs/Web/Guide/API/DOM/Storage for more information.
Thank you all, here is my own solution:
Responsive Navigation on Overflow:
$(window).on('resize', function(){
ress_nav();
});
function more_nav() {
$('#main_nav li').css({'width': ''});
$('#main_nav li').css({'float': ''});
}
function less_nav() {
$('#main_nav li').css({'width': '50%'});
$('#main_nav li').css({'float': 'left'});
}
function ress_nav() {
var lastTab = $("#main_nav li:last-child");
var winWidth = $(window).width();
var elWidth = $(lastTab).width();
var elLeft = $(lastTab).position().left;
if (winWidth - (elWidth + elLeft) < 0) {
$.cookie('winWidth', winWidth);
less_nav();
}
else if ($(window).width() > $.cookie('winWidth')){
$.removeCookie('winWidth', winWidth);
more_nav();
}
}
if ($(window).width() > $.cookie('winWidth')) {more_nav()} else {less_nav()}
Hope it helps anyone looking for such a function.
Thank you.
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);