jquery issues when changing active navigation class on scroll and on click - javascript

I'm doing a single page where navigation .active class should change both on scroll and on click. I'm also changing class of header when scrolling down (".large" and ".small"), but this two scripts somehow don't work with each other.
For header resizing I'm doing this:
$(document).on("scroll",function(){
if($(document).scrollTop()>200){
$('header').removeClass('large').addClass('small');
} else{
$('header').removeClass('small').addClass('large');
}
});
For change active class I'm doing this:
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('active');
})
$(this).addClass('active');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 500, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('#top-menu a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.
position().top + refElement.height() > scrollPos) {
$('#top-menu ul li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
This works perfectly when scrolling, but clicking on a top nav link just crashes "header" function and it doesn't resize anymore. Can anyone see what's the problem is?

As f00bar mentioned, $(document).off("scroll"); removes the eventhandler. The scroll event wont be fired anymore. so your top code wont run after a click.

Related

Using two ScrollTop() functions in jQuery?

I'm building a single page website which uses smooth scrolling to anchors for navigation. I'm also trying to add a 'back to the top' button but can't seem to get the animation working (clicking the button doesn't do anything). I believe it's because I'm using two scrollTop functions. Is this correct and how can I solve this?
// Smooth scrolling for page anchors
$(document).ready(function () {
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
var target = this.hash;
var $target = $(target);
$('html, body').animate({
'scrollTop': $target.offset().top
}, 1000, 'swing');
});
});
// Sticky back to top button
$(document).ready(function () {
$(window).scroll(function () {
if ($(this).scrollTop() > 600) {
$('.go-top').fadeIn("500");
} else {
$('.go-top').fadeOut("500");
}
});
$('.go-top').click(function () {
$('html, body').animate({
scrollTop: 0
}, 800);
return false;
});
});
Found the solution - I had to removed the second $(document).ready(function () { line of code.

Cannot read property 'top' of undefined Jquery/javascript

Probably this question has been answered many times before, but i can't find anything that related to my code.
Everything works properly, when the menu nav is open, etc. the smooth scrolling works as well, except when i click the arrow-down to go the the next section, smooth scrolling doesnt work.
I have been looking at it and trying to figure it out for a while but i am unable to do so.
I am still learning jquery and javascript.
A full DEMO of this code in use can be found HERE.
Open dev tools and you will see the errors in the console.
EDIT
added..
.arrow-down-wrapper a[href^="#"]
to
$('nav.mobile-nav a[href^="#"], .arrow-down-wrapper a[href^="#"]').on('click', function (e) {
...
}
Smooth scrolling not works for the 'arrow-down', but i am still getting
'Uncaught TypeError: Cannot read property 'top' of undefined'
console.log(target); outputs the correct targets. #Home, #about, etc..
This is the code i have:
//smooth transition to sctions when links in header are clicked
function onScroll(event){
var scrollPosition = $(document).scrollTop();
$('nav.mobile-nav a').each(function () {
var currentLink = $(this);
var refElement = $(currentLink.attr("href"));
if (refElement.position().top <= scrollPosition && refElement.position().top + refElement.height() > scrollPosition) {
$('nav.mobile-nav a').removeClass("current");
currentLink.addClass("current");
}
else{
currentLink.removeClass("current");
}
});
}
$(document).ready(function () {
$(document).on("scroll", onScroll);
$('nav.mobile-nav a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('nav.mobile-nav a').each(function () {
$(this).removeClass('current');
});
$(this).addClass('current');
var target = this.hash;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 1000, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
The issue was that the code wasn't specific enough. The loop was iterating through all the items in the list, that is all the links that where #tags, and links to other pages. That is the reason i was getting the error of top not defined, that item it was looking for didn't exist. a[href^="#"' after adding that, loop only iterated the items with # ID tags.
Commented the changes i made
//smooth transition to sctions when links in header are clicked
function onScroll(event){
var scrollPosition = $(document).scrollTop();
$('nav.mobile-nav a[href^="#"').each(function () { //added a[href^="#"] so that the loop only iterates over the elements with the ID tag
var currentLink = $(this);
var refElement = $(currentLink.attr("href"));
console.log(currentLink.attr("href")); //log
if (refElement.position().top <= scrollPosition && refElement.position().top + refElement.height() > scrollPosition) {
$('nav.mobile-nav a').removeClass("current");
currentLink.addClass("current");
}
else{
currentLink.removeClass("current");
}
});
}
$(document).ready(function () {
$(document).on("scroll", onScroll);
$('nav.mobile-nav a[href^="#"], .arrow-down-wrapper a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('nav.mobile-nav a').each(function () {
$(this).removeClass('current');
});
$(this).addClass('current');
var target = this.hash;
$target = $(target);
console.log(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top - 100
}, 1000, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
That is a style so the value, in javascript, would need to be .style.top not just .top. That is why you are getting 'undefined'. There is no top property assigned to the object you are using.
I don't use jQuery but, in javascript, to retrieve the top property, you could do something like:
var a = document.getElementsByTagName('div')[0];
var b = a.style.top;
console.log(parseInt(b,10)); //cause b will be equal to 'nnpx' and parseInt removes the 'px'
However, this doesn't read any top value set in CSS. You need to set the value with javascript in order to read that. There is a way to read the value set in a CSS stylesheet but I don't recall how.
I don't actually get the problem.
Opening the dev tools i have some errors but the smooth scroll on your website works quite fine for me.
Have a look at this jsfiddle i made:
https://jsfiddle.net/p4x3d2dn/1/
HTML
<ul class="nav">
<li><a class="scroll" href="#section_home">Home</a></li>
<li><a class="scroll" href="#section_about">About</a></li>
<li><a class="scroll" href="#section_team">Team</a></li>
<li><a class="scroll" href="#section_gallery">Gallery</a></li>
<li><a class="scroll" href="#section_contact">Contact</a></li>
</ul>
<section id="section_home">
<h1>Home</h1>
</section>
<section id="section_about">
<h1>About</h1>
</section>
<section id="section_team">
<h1>Team</h1>
</section>
<section id="section_gallery">
<h1>Gallery</h1>
</section>
<section id="section_contact">
<h1>Contact</h1>
</section>
Adding other links (such as a scroll down arrow) is just a matter of adding the correct href attribute to the .scroll tag:
<a class="scroll" href="#section_whatever_you_want">
<i class="fa fa-chevron-down"></i>
</a>
A slightly different approach must be taken if you have custom generated sections and you are not in control of the DOM
This is all the javascript you need:
$(document).ready(function() {
$(".scroll").on("click", function() {
//event.preventDefault();
var el = $(this).attr("href");
$('html, body').animate({
scrollTop: $(el).offset().top
}, 2000);
});
});

After adding a "current" class to an active item in a menu using jQuery, how can css changes be made to the container of the item?

I have added an "active" class to the current item in a menu bar and have implemented a Smooth Scroll feature to it as well. ( http://jsfiddle.net/T98VG/ )
I want the background color of the item to change in the menu bar but this doesn't seem to be working properly. So far, the background color of the link in the menu bar changes, not the container the link is in. How can I implement this?
jQuery code used to add "active" state to current item (this works fine):
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('#nav a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('#nav a').each(function () {
$(this).removeClass('current');
});
$(this).addClass('current');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top-0
}, 1000, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('#nav a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('#nav a').removeClass("current");
currLink.addClass("current");
}
else{
currLink.removeClass("current");
}
});
}
Here's a JSFiddle with the code I have so far and the problem ( http://jsfiddle.net/T98VG/ ). In the menu bar with 4 items: #1, #2, #3 and #4, only the background color of the active link gets highlighted. I'd like the box "nav li" to be filled with the color as well.
I'm new to coding so all help is welcome. Thank you!
You can use the parent() call on each link, and add the current class to the parent of the links (the <li>'s) instead of the links themselves.
See the updated JSFiddle

Fixing nav to top, then add margin to body

Currently using this:
$(function(){ // document ready
var stickyTop = $('.navigation-wrap').offset().top; // returns number
$(window).scroll(function(){ // scroll event
var windowTop = $(window).scrollTop(); // returns number
if (stickyTop < windowTop) {
$('.navigation-wrap').addClass('sticky');
}
else {
$('.navigation-wrap').removeClass('sticky');
}
});
});
And that sticks the navigation to the top of the screen perfectly, however... when using the following:
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('navactive');
});
$(this).addClass('navactive');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 500, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
To highlight the current button depending on how far down the page you have scrolled. The problem is now that the 50px navigation is covering the top of the content. If you click on one of the buttons, the page scrolls down and covers the title.
Is there any way of adding a 50px margin to the code so the nav doesn't get in the way? I did try using offset, but couldn't get it to work.
Yeah, add more pixels in this line:
'scrollTop': $target.offset().top+2
For example:
'scrollTop': $target.offset().top+52
You can take a look at a similar solution I proposed.

jquery scroll issues on ipad

http://jqueryfordesigners.com/demo/scroll-link-nav.html
The link above is more or less what im looking for in terms of the active state responding to the scroll position.
But if one tries this on an ipad the active state sticks in certain places and trying to navigate purely by tapping the buttons, it stops scrolling after the first tap.
Anyone know any fixes for this for the ipad issues?
I have one solution which does the scrolling on all browsers
http://jsfiddle.net/t9mna/1/ all browsers
$("nav ul li a").click(function(){
$(".selected").removeClass("selected");
$(this).addClass("selected");
var $scrollTo = $($(this).attr("href"));
$('html, body').animate({
scrollTop: $scrollTo.offset().top
}, 500);
});
​and another for just iPad, i don't have an iPad so i personally can't test it so let me know how it goes
http://jsfiddle.net/t9mna/3/ just for iPad //not been tested by me
function isiPad() {
return navigator.userAgent.match(/iPad/i);
}
$("nav ul li a").click(function(){
$(".selected").removeClass("selected");
$(this).addClass("selected");
var $scrollTo = $($(this).attr("href"));
$(function() {
if ($(isiPad).length != 1) {
$('html, body').animate({
scrollTop: $scrollTo.offset().top
}, 500);
}
});
});​
$("nav ul li a").click(function(){
$(".selected").removeClass("selected");
$(this).addClass("selected");
var $scrollTo = $($(this).attr("href"));
$(function() {
if ($(isiPad).length != 1) {
$('html, body').animate({
scrollTop: $.scrollTo.offset().top //point
}, 500);
}
});
});​

Categories

Resources