dzimi
dzimi

Reputation: 829

Detecting scroll direction - boolean variable wrong on first scroll change direction

I want to detect whether I am scrolling up or down. I also have a global variable which should be true if scrolling down and false if up.

The problem is, if I scroll down once, and keep scrolling down, the console logs true and down, but if I then scroll up just once, it logs 'up' correctly but also true instead of false. Same goes when scrolling the other way around.

So basically the down variable is wrong after first scroll change which changes direction.

<div id="id0" data-id="0" class="nbhd red scrolledto"></div>
<div id="id1" data-id="1" class="nbhd yellow"></div>
<div id="id2" data-id="2" class="nbhd green"></div>
<div id="id3" data-id="3" class="nbhd blue"></div>

var down = true;

    function setHeights() {
        $('.nbhd').css('height', window.innerHeight);
    }

    function scrollDirection() {
        var lastScrollTop = $(window).scrollTop();

        $(window).scroll(function(event) {

            var st = $(this).scrollTop();

            if (st > lastScrollTop){
                // down
                down = true;
                console.log('down');
            } else if (st < lastScrollTop) {
                // up
                down = false;
                console.log('up');
            }

            lastScrollTop = st;

        });

        console.log(down);
    }

    setHeights();

    $( window ).on( "scroll", function() {
        scrollDirection();
    });

fiddle: https://jsfiddle.net/gh3cgrqL/

Upvotes: 1

Views: 1392

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074485

Part of the problem is that you're hooking the scroll event every time anything scrolls, because you have this:

$( window ).on( "scroll", function() {
    scrollDirection();
});

...which calls scrollDirection every time there's any scrolling, and within scrollDirection you have this:

$(window).scroll(function(event) {
    // ...
});

...which adds another handler. Each time. After a relatively small amount of scrolling the page will become sluggish and ultimately non-responsive as all those event hanlders stack up.

Separately, since scrollDirection is called repeatedly, your lastScroll is updated before the inner handlers have a chance to work with it.

Just hook up a single handler, and remember the last scroll position:

var lastScroll = 0;
var down = false;
$(window).on("scroll", function() {
    var scroll = $(this).scrollTop();
    down = scroll > lastScroll;
    lastScroll = scroll;
});

Live Example:

(function() {
    var lastScroll = 0;
    var down = false;
    $(window).on("scroll", function() {
        var scroll = $(this).scrollTop();
        down = scroll > lastScroll;
        lastScroll = scroll;
        $("#indicator").text(down ? "down" : "up");
    });
})();
<div id="indicator" style="position: fixed; top: 0; left: 0; right: 0"><em>(No scroll yet)</em></div>
<div style="margin-top: 1.1em">
<div>
  scroll over this
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
  <br>.
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Upvotes: 1

Related Questions