Reputation: 13295
I need to detect the direction in that a user scrolls - "up" or "down". Based on the code found in this answer: How can I determine the direction of a jQuery scroll event?
I tried to wrap it in a function so it's a bit more differentiated - but unfortunately, it's not working. I think it has something to do with how I return the value, but the direction is always "up". Being fairly new to JavaScript I am having problems solving this issue.
Here is the code:
$(document).ready(function () {
'use strict';
var lastScrollTop = 0,
st,
direction;
function detectDirection() {
st = window.pageYOffset;
if (st > lastScrollTop) {
direction = "down";
} else {
direction = "up";
}
lastScrollTop = st;
return direction;
}
$(window).bind('scroll', function() {
detectDirection();
console.log(detectDirection());
});
});
And I've also set up a Fiddle.
Could you please help me spotting where the problem is?
Upvotes: 12
Views: 17748
Reputation: 473
I'm providing a new answer because while BarMar's answer solves your immediate problem, the solution doesn't help you structure the code in a way that will enable you to do two things.
Scope the scroll object more broadly, allowing you to access its attributes elsewhere. This would allow you to do something if the scroll position is a certain value.
Improve the performance of the scrolling.
// Your current functionality
$(document).ready(function() {
var scroll = {
down: true,
pos: 0
};
var scrollPos;
var detectDirection = function() {
scrollPos = window.pageYOffset;
if (scrollPos > scroll.pos) {
scroll.down = true;
} else {
scroll.down = false;
}
scroll.pos = scrollPos;
};
$(window).on('optimizedScroll', function() {
detectDirection();
// Do something based on scroll direction
if (scroll.down == true) {
// fooFunction();
} else {
// barFunction();
}
// Do something based on scroll position,
// where scrollTrigger is a number
if (scroll.pos > scrollTrigger) {
// bazFunction();
}
});
});
// Improve scroll performance
(function() {
var throttle = function(type, name, obj) {
var obj = obj || window;
var running = false;
var func = function() {
if (running) {
return;
}
running = true;
requestAnimationFrame(function() {
obj.dispatchEvent(new CustomEvent(name));
running = false;
});
};
obj.addEventListener(type, func);
};
throttle('scroll', 'optimizedScroll');
})();
Rather than using .bind(), you should use .on(), as per the jQuery .bind() documentation.
The Immediately Invoked Function Expression (IIFE) to improve the scroll performance comes from the MDN documentation for the scroll event.
Upvotes: 1
Reputation: 314
The code as it is will not work since we never update the lastScrollTop, here is the working code...
$(function(config){
var lastScrollTop = 0, // setting initial scrolltop as top of page
direction; // direction of scroll 1)up -1)down 0)static
function detectDirection() {
// current scrollTop can't be cached or in the local global scope
var st = window.pageYOffset;
if (st > lastScrollTop) {
// scrolling down
direction = -1;
} else if (st < lastScrollTop ){
// scrolling up
direction = 1;
} else {
// static
direction = 0;
}
// updated lastscrolltop with new current top
lastScrollTop = st;
// return the direction
return direction;
}`
I used 0 as static/ 1 as scrolling up/ -1 as scrolling down
Hope that helps someone.
Upvotes: 2
Reputation: 42109
See what you get with this:
if (st > lastScrollTop) {
direction = "down";
} else if (st < lastScrollTop ){
direction = "up";
} else {
direction = "static";
}
In addition to what Barmar stated, you could get rid of the line (the call) above the console output and just keep:
console.log(detectDirection());
Upvotes: 2
Reputation: 781096
$(window).bind('scroll', function() {
var dir = detectDirection();
console.log(dir);
});
You were calling detectDirection()
twice during each scroll event. The first one detected the correct direction, but the second one just saw it in the same place, so it returned "up", and that's what you logged.
Upvotes: 6