IF scroll up - call function - javascript

I wanna call my_function1 when user scroll up (in the full-screen height page) or call my_function2 when the user scrolls down.
When I open a page with this code, it will always immediately run function in else {} (in this code example "slide_down();". What am I doing wrong, please?
var position = $(window).scrollTop();
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll > position) {
slide_up();
} else {
slide_down();
}
position = scroll;
});

Here is the code that detects if the user has scrolled up or down and is mobile friendly too.
console.log() is acting up in code snippets as the log is called for every pixel scrolled.
var lastScrollTop = 0;
// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
window.addEventListener("scroll", function(){
var st = window.pageYOffset || document.documentElement.scrollTop;
if (st > lastScrollTop){
// Do scroll down code
console.log("Down");
} else {
// Do scroll up code
console.log("Up");
}
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
div {
height: 300px;
border: 1px solid;
}
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>

This is working in my scenario (detecting mouse wheel in full-screen page)
// Detect IE version
var iev=0;
var ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
var trident = !!navigator.userAgent.match(/Trident\/7.0/);
var rv=navigator.userAgent.indexOf("rv:11.0");
if (ieold) iev=new Number(RegExp.$1);
if (navigator.appVersion.indexOf("MSIE 10") != -1) iev=10;
if (trident&&rv!=-1) iev=11;
// Firefox or IE 11
if(typeof InstallTrigger !== 'undefined' || iev == 11) {
var lastScrollTop = 0;
$(window).on('scroll', function() {
st = $(this).scrollTop();
if(st < lastScrollTop) {
console.log('Up');
}
else if(st > lastScrollTop) {
console.log('Down');
}
lastScrollTop = st;
});
}
// Other browsers
else {
$('body').on('mousewheel', function(e){
if(e.originalEvent.wheelDelta > 0) {
console.log('Up');
}
else if(e.originalEvent.wheelDelta < 0) {
console.log('Down');
}
});
}

Related

How to tell if the user is scrolling down or up [duplicate]

So I am trying to use the JavaScript on scroll to call a function. But I wanted to know if I could detect the direction of the the scroll without using jQuery. If not then are there any workarounds?
I was thinking of just putting a 'to top' button but would like to avoid that if I could.
I have now just tried using this code but it didn't work:
if document.body.scrollTop <= 0 {
alert ("scrolling down")
} else {
alert ("scrolling up")
}
It can be detected by storing the previous scrollTop value and comparing the current scrollTop value with it.
JavaScript :
var lastScrollTop = 0;
// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
element.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
if (st > lastScrollTop) {
// downscroll code
} else if (st < lastScrollTop) {
// upscroll code
} // else was horizontal scroll
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
Simple way to catch all scroll events (touch and wheel)
window.onscroll = function(e) {
// print "false" if direction is down and "true" if up
console.log(this.oldScroll > this.scrollY);
this.oldScroll = this.scrollY;
}
Use this to find the scroll direction. This is only to find the direction of the Vertical Scroll. Supports all cross browsers.
var scrollableElement = document.body; //document.getElementById('scrollableElement');
scrollableElement.addEventListener('wheel', checkScrollDirection);
function checkScrollDirection(event) {
if (checkScrollDirectionIsUp(event)) {
console.log('UP');
} else {
console.log('Down');
}
}
function checkScrollDirectionIsUp(event) {
if (event.wheelDelta) {
return event.wheelDelta > 0;
}
return event.deltaY < 0;
}
Example
You can try doing this.
function scrollDetect(){
var lastScroll = 0;
window.onscroll = function() {
let currentScroll = document.documentElement.scrollTop || document.body.scrollTop; // Get Current Scroll Value
if (currentScroll > 0 && lastScroll <= currentScroll){
lastScroll = currentScroll;
document.getElementById("scrollLoc").innerHTML = "Scrolling DOWN";
}else{
lastScroll = currentScroll;
document.getElementById("scrollLoc").innerHTML = "Scrolling UP";
}
};
}
scrollDetect();
html,body{
height:100%;
width:100%;
margin:0;
padding:0;
}
.cont{
height:100%;
width:100%;
}
.item{
margin:0;
padding:0;
height:100%;
width:100%;
background: #ffad33;
}
.red{
background: red;
}
p{
position:fixed;
font-size:25px;
top:5%;
left:5%;
}
<div class="cont">
<div class="item"></div>
<div class="item red"></div>
<p id="scrollLoc">0</p>
</div>
Initialize an oldValue
Get the newValue by listening to the event
Subtract the two
Conclude from the result
Update oldValue with the newValue
// Initialization
let oldValue = 0;
//Listening on the event
window.addEventListener('scroll', function(e){
// Get the new Value
newValue = window.pageYOffset;
//Subtract the two and conclude
if(oldValue - newValue < 0){
console.log("Up");
} else if(oldValue - newValue > 0){
console.log("Down");
}
// Update the old value
oldValue = newValue;
});
This is an addition to what prateek has answered.There seems to be a glitch in the code in IE so i decided to modify it a bit nothing fancy(just another condition)
$('document').ready(function() {
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
console.log("down")
}
else if(st == lastScrollTop)
{
//do nothing
//In IE this is an important condition because there seems to be some instances where the last scrollTop is equal to the new one
}
else {
console.log("up")
}
lastScrollTop = st;
});});
While the accepted answer works, it is worth noting that this will fire at a high rate. This can cause performance issues for computationally expensive operations.
The recommendation from MDN is to throttle the events. Below is a modification of their sample, enhanced to detect scroll direction.
Modified from: https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event
// ## function declaration
function scrollEventThrottle(fn) {
let last_known_scroll_position = 0;
let ticking = false;
window.addEventListener("scroll", function () {
let previous_known_scroll_position = last_known_scroll_position;
last_known_scroll_position = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function () {
fn(last_known_scroll_position, previous_known_scroll_position);
ticking = false;
});
ticking = true;
}
});
}
// ## function invocation
scrollEventThrottle((scrollPos, previousScrollPos) => {
if (previousScrollPos > scrollPos) {
console.log("going up");
} else {
console.log("going down");
}
});
This simple code would work: Check the console for results.
let scroll_position = 0;
let scroll_direction;
window.addEventListener('scroll', function(e){
scroll_direction = (document.body.getBoundingClientRect()).top > scroll_position ? 'up' : 'down';
scroll_position = (document.body.getBoundingClientRect()).top;
console.log(scroll_direction);
});
You can get the scrollbar position using document.documentElement.scrollTop. And then it is simply matter of comparing it to the previous position.
If anyone looking to achieve it with React hooks
const [scrollStatus, setScrollStatus] = useState({
scrollDirection: null,
scrollPos: 0,
});
useEffect(() => {
window.addEventListener("scroll", handleScrollDocument);
return () => window.removeEventListener("scroll", handleScrollDocument);
}, []);
function handleScrollDocument() {
setScrollStatus((prev) => { // to get 'previous' value of state
return {
scrollDirection:
document.body.getBoundingClientRect().top > prev.scrollPos
? "up"
: "down",
scrollPos: document.body.getBoundingClientRect().top,
};
});
}
console.log(scrollStatus.scrollDirection)
I personally use this code to detect scroll direction in javascript...
Just you have to define a variable to store lastscrollvalue and then use this if&else
let lastscrollvalue;
function headeronscroll() {
// document on which scroll event will occur
var a = document.querySelector('.refcontainer');
if (lastscrollvalue == undefined) {
lastscrollvalue = a.scrollTop;
// sets lastscrollvalue
} else if (a.scrollTop > lastscrollvalue) {
// downscroll rules will be here
lastscrollvalue = a.scrollTop;
} else if (a.scrollTop < lastscrollvalue) {
// upscroll rules will be here
lastscrollvalue = a.scrollTop;
}
}
Modifying Prateek's answer, if there is no change in lastScrollTop, then it would be a horizontal scroll (with overflow in the x direction, can be used by using horizontal scrollbars with a mouse or using scrollwheel + shift.
const containerElm = document.getElementById("container");
let lastScrollTop = containerElm.scrollTop;
containerElm.addEventListener("scroll", (evt) => {
const st = containerElm.scrollTop;
if (st > lastScrollTop) {
console.log("down scroll");
} else if (st < lastScrollTop) {
console.log("up scroll");
} else {
console.log("horizontal scroll");
}
lastScrollTop = Math.max(st, 0); // For mobile or negative scrolling
});
This seems to be working fine.
document.addEventListener('DOMContentLoaded', () => {
var scrollDirectionDown;
scrollDirectionDown = true;
window.addEventListener('scroll', () => {
if (this.oldScroll > this.scrollY) {
scrollDirectionDown = false;
} else {
scrollDirectionDown = true;
}
this.oldScroll = this.scrollY;
// test
if (scrollDirectionDown) {
console.log('scrolling down');
} else {
console.log('scrolling up');
}
});
});
Sometimes there are inconsistencies in scrolling behavior which does not properly update the scrollTop attribute of an element. It would be safer to put some threshold value before deciding the scroll direction.
let lastScroll = 0
let threshold = 10 // must scroll by 10 units to know the direction of scrolling
element.addEventListener("scroll", () => {
let newScroll = element.scrollTop
if (newScroll - lastScroll > threshold) {
// "up" code here
} else if (newScroll - lastScroll < -threshold) {
// "down" code here
}
lastScroll = newScroll
})
let arrayScroll = [];
window.addEventListener('scroll', ()=>{
arrayScroll.splice(1); //deleting unnecessary data so that array does not get too big
arrayScroll.unshift(Math.round(window.scrollY));
if(arrayScroll[0] > arrayScroll[1]){
console.log('scrolling down');
} else{
console.log('scrolling up');
}
})
I have self-made the above solution. I am not sure if this solution may cause any considerable performance issue comparing other solutions as I have just started learning JS and not yet have completed my begginer course. Any suggestion or advice from experienced coder is highly appriciated. ThankYou!

Code applied at top of page versus scrolling

I'm trying to add conditional statements to my code but can't seem to get it to work. I want to apply .nav-down-top to #s-nav when the user is at the top of the screen , and .nav-down to #s-nav when not at top of page.
code
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight();
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 150);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop && st > navbarHeight ) {
// Scroll Down
$('#s-nav').removeClass('nav-down').addClass('nav-up');
} else {
// !!!! Code issue
// Scroll Up (# top of screen)
if ($(window).scrollTop() === 0) {
$('#s-nav').removeClass('nav-up').addClass('nav-down-top');
} else {
// Scroll Up (NOT # top of screen)
if (st + $(window).height() < $(document).height()) {
$('#s-nav').removeClass('nav-up').addClass('nav-down');
}
//
} else {
$('#s-nav').removeClass('nav-up').addClass('nav-down');
}
lastScrollTop = st;
}
});
html
<nav id="s-nav" class="nav-down"> ...
So as I said, you weren't removing both unused classes and you had some issues with your code (missing closing angle brackets, orphaned else statement). The working function would look like this:
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop && st > navbarHeight ) {
// Scroll Down
$('#s-nav').removeClass('up').removeClass('top').addClass('down');
} else {
// Scroll Up (# top of screen)
if (st === 0) {
$('#s-nav').removeClass('up').removeClass('down').addClass('top');
} else {//if (st + $(window).height() < $(document).height()) {
$('#s-nav').removeClass('down').removeClass('top').addClass('up');
}
}
}
lastScrollTop = st;
}
Fiddle: https://jsfiddle.net/wm6kvm6u/

Dont scroll the body when mouse is over child element

I'm trying to stop my main page from scrolling when the user hits the bottom of two specific sections of a page using the following code, but it's stopping the mouse wheel from working over those divs at all.
var scroller = document.querySelector('#Filters');
scroller.addEventListener('wheel', listener);
function listener(event)
{
var elem = event.currentTarget;
if ((event.deltaY < 0 && elem.scrollTop === 0) ||
(event.deltaY > 0 && elem.offsetHeight + elem.scrollTop >= elem.scrollHeight))
{
event.preventDefault();
}
else if ((event.deltaX < 0 && elem.scrollLeft === 0) ||
(event.deltaX > 0 && elem.offsetWidth + elem.scrollLeft >= elem.scrollWidth))
{
event.preventDefault();
}
}
You can use a more efficient solution than recalculating the scroll in js, disabling the body scrolling when scrolling the child element.
HTML:
<div onmouseover="disableScroll();" onmouseout="enableScroll();">
content
</div>
JS:
var body = document.getElementsByTagName('body')[0];
function enableScroll() {
body.style.overflowY = 'auto';
}
function disableScroll() {
body.style.overflowY = 'hidden';
}

If scrollTop is greater than value, then do this ONLY ONCE

When user scrolls past 10px from the top, I'd like to hijack their scroll and scroll them down to certain div. After this happens once, I'd like to release the scroll to be free to scroll wherever. How do I do this?
My current code works but it won't let user to scroll freely after that initial scroll:
$(window).scroll(function() {
//if I scroll more than 1000px...
if($(window).scrollTop() > 10){
$('html,body').animate({scrollTop : $('#main').offset().top}, 900, function(){
h = 2;
});
}
});
Try:
var scrolled = false;
$(window).scroll(function() {
//if I scroll more than 1000px...
if($(window).scrollTop() > 10 && scrolled == false){
$('html,body').animate({scrollTop : $('#main').offset().top}, 900, function(){
h = 2;
});
scrolled = true;
} else if($(window).scrollTop() == 0) {
scrolled = false;
}
});

Add class to element upon scroll

I'd like to add a class to an element when a user first scrolls away from the top of the page. If the user then scrolls back up and hits the top of the page I'd like that class removed.
Use of jQuery in the solution is fine.
try
$(window).scroll(function() {
$("id or class").removeClass("active");
var scroll = $(window).scrollTop();
if (scroll <= 500) {
$("#one").addClass("active");
}
else if (scroll <= 1000) {
$("#tow").addClass("active");
}
else {
$("#three").addClass("active");
}
}
So here is the solution you're looking for. Just customize it with your div tags.
$(document).ready(function () {
$(window).scroll(function(){
// get the height of #wrap
var h = $('#top').height();
var y = $(window).scrollTop();
if( y > (h*.25) ){
$("#sidef").fadeIn(1100);
} else {
$('#sidef').fadeOut(75);
}
});
});
var notAdded = true;
$(window).scroll(function(){
if( $(this).scrollTop() == 0){
$(elem).removeClass('classname');
notAdded = true;
}
else if(notAdded){
$(elem).addClass('classname');
notAdded = false;
}
});

Categories

Resources