thenikso / angular-inview

AngularJS directive to check if a DOM element is in the browser viewport.
http://thenikso.github.io/angular-inview/
MIT License
480 stars 112 forks source link

Angular expression is not evaluated for an element when scrolling too fast by dragging the scrollbar #102

Open vinaynb opened 8 years ago

vinaynb commented 8 years ago

Firstly this issue occurs when you have a large vertical scrolling area and you need to scroll a few hundred pixels very fast via dragging scroll bar to reproduce this.

I have maybe like 5000px of height to scroll and i have elements at 1500px and 2000px which have in view expressions attached to them. When i scroll too fast from 5000px to 0px at top of page by dragging the scroll bar it skips and fails to fire inview events for elements at 1500 and 2000px. I checked #98 which is similiar but the use case is a bit different. Therein he works on a scrollable container and here in my case i am working on whole tag.

Any help ?

vinaynb commented 8 years ago

Update

I did some reading and found that it may be possible that as scroll events are fired too quickly the browser is not able to run all the callbacks coming in at that speed and that maybe the reason they are skipped someway. I am not sure about this. Trying a few things. Will keep this thread updated.

vinaynb commented 8 years ago

UPDATE

I looked deeper into the source code and found out that its the browser that, when scrolling fast, basically is not firing the onscroll callback that many times when it would if you would scrolling a little slower.

So i guess we can look more into issues with this library once we are sure it receives onscroll events callback form browser (which in this case doesn't happen). I have no idea how to get around this.

I can use debounce and limit scroll events but that does not solve my use case as i have elements at various heights that need repositioning during scroll and right now i do that repositioning in a function that is being called by inview.

vinaynb commented 8 years ago

@thenikso Any chance you could have a pointer in the right direction to fix this ?

slavafomin commented 8 years ago

I think one approach would be to interpolate scrolling events between last two known scrolling positions, however, it could be difficult to implement properly.

thenikso commented 8 years ago

some kind of delayed check might fix this. The library already have a check for the actual element position here so triggering the check should do. This of course assuming that any scroll event is triggered at all.

Anyone tried this already?

vinaynb commented 8 years ago

Well it fires scroll event that is for sure because i put logs in onscroll callback and normally it would fire for 100 times for example so when scrolling fast it would log just 8 or 9 times.

But i am skeptical about that check that the library performs because i am guessing that the check function would indicate if any element is inview or went out of inview. Deciding that former or later from both is possible if onscroll fires frequently and scroll coordinates are available to us. In case when we are scrolling too fast the scroll event fires less frequently and newer coordinates are not available more frequently.

For ex library needs scroll offsets top - 200px and bottom 300px to trigger inview callback for particular element. But when scrolling too fast the offsets we have when onscroll fires is top 100px and bottom 200px. In this case the inview call back won't fire at all.

I suppose you already know this but this was just to mention the stuff i know here if it helps in any way.

thenikso commented 8 years ago

@vinaynb it would be nice if you could try this issue in v2, see #107

Also and example so that I could understand/reproduce the problem would be great

farshad9037 commented 7 years ago

@vinaynb

In IE 11, when we click and drag scrollbar it was not invoking inview. Also If we I try to scroll to last using 'ctrl + end'. This fix solves my issue. Am using Version: 2.2.0 Update 'signalFromEvent' method with below code. It should work. We should set useCapture 'true'

function signalFromEvent (target, event) { return new QuickSignal(function (subscriber) { var handler = function (e) { subscriber(e); }; var el = angular.element(target); el[0].addEventListener(event, handler, true); // el.on(event, handler); subscriber.$dispose = function () { el[0].removeEventListener(event, handler, true); // el.off(event, handler); }; }); }