3

I am using the following function in a single page application in Angular. When I click on the menu item, I scroll to the relevant div.

scroll (el) {
    this.sharedService.isClicked.next(true);
    el.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

How do I check if the element has finished scrolling? I want to avoid the setTimeout function.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
user1288906
  • 419
  • 2
  • 13
  • 25

3 Answers3

1

This worked for me (I declare this snippet public domain, feel free to re-use):

scrollAndDo = function(currPageXOffset,currPageYOffset) {
    $('#SomeElement')[0].scrollIntoView({behavior: 'smooth',block:'nearest',inline: 'nearest'});
    currPageXOffset = window.pageXOffset;
    currPageYOffset = window.pageYOffset;
    var scrollDone = setInterval(function () {
        if ( currPageXOffset == window.pageXOffset && currPageYOffset == window.pageYOffset ) {
            clearInterval(scrollDone);
            console.log('I have finished scrolling');
        }
        currPageXOffset = window.pageXOffset;
        currPageYOffset = window.pageYOffset;
    },50);
};
scrollAndDo();
0

hope this helps..

  var scrollIntoviewCompleted = false;
  var currentVisible = false;
  var onceVisible = false;
  $(window).scroll(function(){
     $.fn.isOnScreen = function(){
        var element = this.get(0);
        var bounds = element.getBoundingClientRect();
        return bounds.top < window.innerHeight && bounds.bottom > 0;
    }
        if ($('.targetdiv').isOnScreen()) {
            currentVisible = true;
            onceVisible =true;
        } 
        else
        {
            currentVisible = false;
        }
        if(onceVisible == true && currentVisible == false){
            scrollIntoviewCompleted = true;
            console.log("scrollIntoViewCompleted");
        }

});
Neha
  • 2,136
  • 5
  • 21
  • 50
0

Based on an answer in this question I was able to make this for my tests... and this assumes that you are @Injecting window into your angular components

let win: Window;

const onScrollEnd = (fn: () => void): void => {
    let scrollTimeout: number | undefined;
    const listener = (): void => {
        win.clearTimeout(scrollTimeout);
        scrollTimeout = win.setTimeout(() => {
            win.removeEventListener('scroll', listener);
            fn();
        }, 100);
    };
    win.addEventListener('scroll', listener);
};

beforeEach(() => {
    //Standard component test setup stuff goes here...    

    win = TestBed.get('Window');
});

And then in my test I can do this:

it('should scroll the window down when...', (done: DoneFn) => {
    component.shouldScroll = true;
    fixture.detectChanges();

    onScrollEnd(() => {
        expect(win.scrollY).toBeGreaterThan(0);
        done();
    });
});
Chris Barr
  • 29,851
  • 23
  • 95
  • 135