angularjs-scroll-glue icon indicating copy to clipboard operation
angularjs-scroll-glue copied to clipboard

scroll goes too soon

Open Kukunin opened this issue 9 years ago • 8 comments

Hello here. I'm trying to use this directive for my case, and it seems it doesn't work properly.

I have scrollable div, with AJAX messages there. So, I expect, that after message is added, container will scroll down for it. But, it doesn't work.

My inverstigations:

$window.addEventListener('resize', scrollIfGlued, false); doesn't call the callback. Callback is called from scope.$watch(scrollIfGlued); immediately after AJAX query done (it's noticeable from stacktrace), and scroll function is called too early, when el.scrollHeight isn't enought high.

The solution is

scope.$watch(function() {                                   
  $timeout(scrollIfGlued, 0, false);                                  
}); 

I'd commit pull request, but test fails for me, and I can't repair them.

I understand, it sounds like edge case, but it will make directive more robust

Kukunin avatar Jul 23 '15 16:07 Kukunin

I can confirm that the "fix" from kukunin is working for me, I have a similar case where messages are updated asynchronically .

musikele avatar Jul 31 '15 10:07 musikele

:+1: Looking forward for a fix to async messages as well

jahvi avatar Oct 12 '15 19:10 jahvi

My bad it does seem to be fixed in the latest version, npm is still on 2.0.4 that's why it wasn't working on my end.

jahvi avatar Oct 12 '15 19:10 jahvi

Yea I have requested NPM parity in a separate issue, but have not heard from the author. It has been 4.5 months since I created that issue. I think this author is not-so-committed to this being a public project. Maybe someone will eventually fork and be committed to maintaining?

Smolations avatar Feb 10 '16 17:02 Smolations

Just want to note that:

scope.$watch(function() { $timeout(scrollIfGlued, 0, false); });

Did not work for me, but:

scope.$watch(function() { $timeout(scrollIfGlued, 100, false); });

Did.

twelve6 avatar Feb 19 '16 21:02 twelve6

I can confirm this. The scrollIfGlued function is called for every $digest cycle. This can cause problems like threema-ch/threema-web#18 ("scrolling up sometimes fails") if a lot of events are dispatched (e.g. when there's an animation running at the same time in the same scope), because the function is called before the scrolling event has finished and is out of the "glue" zone.

In addition to running the function at the end of the $digest cycle, I also wanted to delay it a bit (like @twelve6 mentioned) and add some debouncing. I ended up at this:

scope.$watch(() => {
    const ctx = this;
    if (ctx.watchPromise === undefined) {
        ctx.watchPromise = $timeout(() => {
            scrollIfGlued();
            ctx.watchPromise = undefined;
        }, 10, false);
    }
});

This way, the scrollIfGlued function is not called more often than once every 10ms.

dbrgn avatar Jun 25 '18 13:06 dbrgn

It seems reasonable to debounce this behavior. If you could provide the change as a pull request, that'd be great.

oliversalzburg avatar Jun 25 '18 13:06 oliversalzburg

Actually it still does not work properly in all cases :slightly_frowning_face: Still debugging...

dbrgn avatar Jun 25 '18 13:06 dbrgn