3

I've made a JS script to scroll only to some of my page elements

TLDR: I want to check if the page is scrolling/moving so I can prevent more scrolls before the actual one finishes.

I want to stop after each scrollIntoView(), but what happens is that if the user rolls the mouse wheel more than one step, it will scroll accordingly. How can I make the scrolling stop and negate any wheel events that happens while the page is still scrolling, so the user is force to move from div to div instead of being able to scroll directly from the start to the end of the page?

I've tried to set a variable to false before firing scrollIntoView() and the true after, but it doesnt work since scrollIntoView() doesn't wait until the view finished scrolling

var up = null;
var down = null;

// Get in which part of page the scroll started and where it should go if going up or down
function div(x) {

    // If called by html element, get only the id
    if( x.id ) {
        x = x.id;
    }

    switch(x) {
        case 's1':
            up = null;
            down = 's2';
            break;
        case 's2':
            up = 's1';
            down = 's3'
            break;
        case 's3':
            up = 's2';
            down ='s4';
            break;
        case 's4':
            up = 's3';
            down = null;
            break;
        default:
            up = null;
            down = null;
            break;
        }
}

window.addEventListener('wheel', function(e) {  

    e.preventDefault(); // Prevent default scrolling

    // If scrolling UP and there's something up
    if (e.deltaY < 0 && up) {

        // scroll the desired div to view
        document.getElementById(up).scrollIntoView();

        // call div() again to refresh id's/position in case cursor hasnt moved and refreshed already
        div(up);
    }

    // same but scrolling down
    if (e.deltaY > 0 && down) {
        document.getElementById(down).scrollIntoView();
        div(down);
    }
});

And i'm using this structure:

<div id='s1' onmouseover="div(this)">
    <!--content-->
</div>
<div id='s2' onmouseover="div(this)">
    <!--content-->
</div>
<div id='s3' onmouseover="div(this)">
    <!--content-->
</div>
<div id='s4' onmouseover="div(this)">
    <!--content-->
</div>
Mateus Ramos
  • 190
  • 2
  • 12
  • possible duplicate (https://stackoverflow.com/questions/20026502/prevent-mouse-wheel-scrolling-but-not-scrollbar-event-javascript) – Ryan Wilson Jan 14 '19 at 19:31
  • @RyanWilson I don't think so. I don't want to prevent every wheel scroll, just wait until the scrolling animation has finished before starting another one – Mateus Ramos Jan 14 '19 at 19:40
  • As far as I can see you have three options: a) detect when `scrollIntoView` has finished by comparing the scroll offset and the element's y b) implement your own `scrollIntoView`, allowing you to run code when finished c) use a jQuery solution with a callback where you can run code when finished –  Jan 14 '19 at 19:43
  • @ChrisG for (b) and (c), what can I check for the "finished status"? Is there any global variable or function that is triggered in the browser while the view is moving so I can check that? Because the scrollIntoView() is already finished even if the view itself is still moving – Mateus Ramos Jan 14 '19 at 19:48
  • b) will essentially use a), i.e. also compare the document's scroll offset and the element's y coordinate. c) will do the calculation beforehand, then call jQuery's animate(), which supports a "has ended"-callback. There's no magic shortcut, you need to manually grab the current scrollTop and element's y position. –  Jan 14 '19 at 19:51
  • @ChrisG which would be that callback? the "complete" is called after the scroll start but before the animation ends – Mateus Ramos Jan 14 '19 at 21:04

0 Answers0