2

Let me preface by saying I am relatively green in respect to JavaScript. However, I am trying to create a JavaScript function that will listen for a wheel event, determine the direction of the scroll and scroll the next part of the page into view. Similar to a swipe gesture. I have it working in Firefox as intended, user scrolls down the page moves down, up the page moves up. However, in Chrome and Edge, the element.scrollIntoView() function seems to be called, but nothing happens.

I am using Blazor with JSInterop to get the page to scroll.

Here is the gist of the file:

// scrolldetection.js //

window.scrolldetection {
    scrollSetup: function (elementId) {
        autoscroller(elementId);
    }
}

function autoscroller(elementId) {
    // Set up vars
    var idList = document.getElementById(elementId).children.id;
    var idListIndex = // Gets current index based on current location on page
    var curDirection;
    
    document.addEventListener("wheel", function () {
        var currentPos = window.scrollY;
        if (!curDirection) {
            // Check for what direction user scrolls

            idListIndex = // Function that determines new index
            scrollScreen(idList, idListIndex);
        }
        var timerId = setTimeout(function () {
            curDirection = undefined;
            clearTimeout(timerId);
        }, 700);
    }
}

function scrollScreen(idList, curIndex) {
    console.log("list index: " + curIndex);
    element = document.getElementById(idList[curIndex]);
    console.log(element.id);
    element.scrollIntoView({ behavior: 'smooth' });
}

I have another function that calls scrollIntoView() on the same elements, via a button press. Works just fine.

Here is that function:

// anchorlink.js // This one works as intended //

window.anchorlink = {
    scrollIntoView: function (elementId) {
        var elem = document.getElementById(elementId);
        if (elem) {
            elem.scrollIntoView({ behavior: 'smooth' });
        }
    }
}

The console.log() calls within the scrollScreen() function show up properly in the console in each browser. Leading me to believe that element.scrollIntoView() is being called, but something is going wrong to make it not function appropriately. If there is any other information you need, I will be happy to provide, thanks.

Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
  • If you want to close your question, the proper procedure is not to edit "Closed" into the title; just delete it if you aren't going to share(and don't want others to offer answers) via an answer(via the below form) the methodology you took to solve it yourself. – Daedalus Jan 02 '22 at 02:54
  • 1
    I'll add an answer with what I decided on, thanks for the heads up. – Matthew Volpe Jan 02 '22 at 02:59

1 Answers1

0

After working on this some more, I decided the concept I was using wasn't as user friendly as I had hoped.

I decided to let the user scroll freely along the page and when they stop scrolling, then determine the closest DOM element and scroll to it. Works on Edge, Chrome and Firefox.

window.contentcenter = {
    contentCenter: function (elementId) {
        var centeringFunction = debounce(function () { autocenter(elementId) }, 200);
        document.addEventListener("scroll", centeringFunction);
    }
}

function autocenter(elementId) {
    var currentElement = detectCurrentElement(elementId);
    currentElement.scrollIntoView({ behavior: "smooth" });
}

function detectCurrentElement(elementId) {
    var element = document.getElementById(elementId);
    var currentPos = window.scrollY;
    var contentIdList = getContentIdList(elementId);
    var currentElement = closestContent(currentPos, element, contentIdList);

    return currentElement;
}

function closestContent(pos, element, contentIdList) {
    var contentId = Math.round(pos / (element.offsetHeight / contentIdList.length));
    var currentElement = document.getElementById(contentIdList[contentId]);
    return currentElement;
}

function getContentIdList(elementId) {
    var idList = []
    var childElements = document.getElementById(elementId).children;
    for (var i = 0; i < childElements.length; i++) {
        idList.push(childElements[i].id);
    }
    return idList;
}

function debounce(func, timeout) {
    var timer;
    return function () {
        var context = this, args = arguments;
        var later = function () {
            timer = null;
            func.apply(context, args);
        };
        clearTimeout(timer);
        timer = setTimeout(later, timeout)
    };
}