Gwouten Gwouten - 1 month ago 8
jQuery Question

jQuery addClass is not working when scrolling to top fast

I have some buttons I would like to appear when scrolling down on the page and I have used scrollTo.js to animate the scrolling when clicking on an anchor.

To show and hide the buttons I am simply adding and removing a class 'hidden'.

Everything works just fine, unless you scroll a long distance to the top at once: when I do this, I can see that the class 'hidden' is added as soon as the distance to the top of the page is less then 282px, but immediately after that this class is removed again, leaving the buttons visible. If I then scroll just a little, the class is added again correctly.

What could be causing this behaviour?

JS

var $nav = $('nav');
var $content = $('#content');
var $toTop = $('#to-top');

function scrollWindow(){
var scrollTop = $(window).scrollTop();
console.log(scrollTop);
if (scrollTop > 282) {
$nav.addClass('minimalized');
$content.css('padding-top', $nav.height()+'px');
showButtons();
} else {
$nav.removeClass('minimalized');
$content.css('padding-top', '0px');
hideButtons();
}
}

function showButtons() {
console.log('showing buttons');
setTimeout(function(){
$('#dutch').removeClass('hidden');
$('#fixed-logo').removeClass('hidden');
}, 300);
setTimeout(function(){
$('#english').removeClass('hidden');
}, 400);
setTimeout(function(){
$('#to-top').removeClass('hidden');
}, 500);
}

function hideButtons() {
console.log('hiding buttons');
$('#fixed-logo').addClass('hidden');
$('#dutch').addClass('hidden');
$('#english').addClass('hidden');
//$('#to-top').addClass('hidden');
}

$(window).scroll(scrollWindow);

$toTop.click(function(event){
event.preventDefault();
$.scrollTo(0,500);
hideButtons();
});

$('nav ul li:nth-child(2) a').click(function(event){
event.preventDefault();
var target = $('#references').offset().top - 80;
$.scrollTo(target,500);
});

$('nav ul li:nth-child(3) a').click(function(event){
event.preventDefault();
var target = $('#contact').offset().top - 80;
$.scrollTo(target,500);
});


SCSS

#to-top, #dutch, #english{
width: 26px;
height: 21px;
position: fixed;
border: 1px solid #559f99;
text-align: center;
text-decoration: none;
top: 240px;
right: 15%;
padding: 1rem;
border-radius: 50%;
transition: all 0.3s;
padding-top: 19px;
text-transform: uppercase;
font-family: $abel;
font-size: 1.2rem;
color: $bluegreen;
background: none;
&:hover{
color: $white;
background: $bluegreen;
transition: all 0.3s;
}
&.hidden{
right: -100px;
transition: right 0.6s;
}
}
#dutch{
top: 100px;
&.hidden{
right: -100px;
transition: right 0.6s;
}
}
#english{
top: 170px;
&.hidden{
right: -100px;
transition: right 0.6s;
}
}


HTML

<a id="dutch" class="hidden" href="#">NL</a>
<a id="english" class="hidden" href="#">EN</a>
<a id="to-top" class="hidden" href="#top">Top</a>


Codepen:
http://codepen.io/Gwouten/pen/LRBzbo

Ted Ted
Answer

Your setTimeouts overlap each other. I think you should remove them or make your code smarter to detect an active timeout before trying to execute something different on the same element:

http://codepen.io/anon/pen/ALgQPN

The class is removed and then added again when you quickly scroll up and down.