angular-infinite-scroller icon indicating copy to clipboard operation
angular-infinite-scroller copied to clipboard

Proposal for update

Open SergeyMNet opened this issue 7 years ago • 0 comments
trafficstars

It's a great example! I don't have time for creating PR, but I think you definitely should update project to RxJs6. Here is my proposal:

import { Directive, AfterViewInit, ElementRef, Input } from '@angular/core';
import { Observable } from 'rxjs';
import { fromEvent } from 'rxjs';
import { map, pairwise, filter, startWith, exhaustMap } from 'rxjs/operators';


interface ScrollPosition {
  sH: number;
  sT: number;
  cH: number;
}

const DEFAULT_SCROLL_POSITION: ScrollPosition = {
  sH: 0,
  sT: 0,
  cH: 0
};

@Directive({
  selector: '[appScroller]'
})
export class ScrollerDirective implements AfterViewInit {

  private scrollEvent$: Observable<any>;
  private userScrolledDown$: Observable<any>;
  private requestStream$: Observable<any>;
  private requestOnScroll$: Observable<any>;

  @Input()
  scrollCallback;

  @Input()
  immediateCallback;

  @Input()
  scrollPercent = 70;

  constructor(private elm: ElementRef) { }

  ngAfterViewInit() {
    this.registerScrollEvent();
    this.streamScrollEvents();
    this.requestCallbackOnScroll();
  }

  private registerScrollEvent() {
    // this.scrollEvent$ = fromEvent(this.elm.nativeElement, 'scroll');
    this.scrollEvent$ = fromEvent(window, 'scroll');

  }

  private streamScrollEvents() {
    this.userScrolledDown$ = this.scrollEvent$.pipe(
      map((e: any): ScrollPosition => ({
        sH: e.target.scrollHeight,
        sT: e.target.scrollTop,
        cH: e.target.clientHeight
      })),
      pairwise(),
      filter(positions => this.isUserScrollingDown(positions) && this.isScrollExpectedPercent(positions[1])));
  }

  private requestCallbackOnScroll() {
    this.requestOnScroll$ = this.userScrolledDown$;

    if (this.immediateCallback) {
      this.requestOnScroll$ = this.requestOnScroll$.pipe(
        startWith([DEFAULT_SCROLL_POSITION, DEFAULT_SCROLL_POSITION]));
    }

    this.requestOnScroll$.pipe(
      exhaustMap(() => {
        return this.scrollCallback();
      }))
      .subscribe((data) => { console.log(data); }, (err) => console.log(err));

  }

  private isUserScrollingDown = (positions) => {
    return positions[0].sT < positions[1].sT;
  }

  private isScrollExpectedPercent = (position) => {
    return ((position.sT + position.cH) / position.sH) > (this.scrollPercent / 100);
  }

}

SergeyMNet avatar Nov 15 '18 12:11 SergeyMNet