Scroll Measure Service - ScrollMeasure

An angular service that uses the Scroll Strategies from Angular Materials to create an observable that emits an event whenever a user scrolls to the bottom of the page.

This service allows an element contained in a bootstrap to measure the scroll position of the entire page, and this allows for infinite scrolling without creating a "bounding box"

scroll-measure-service.ts

import {EventEmitter, Injectable} from "@angular/core";
import {ScrollDispatcher} from "@angular/material";
import {Observable} from "rxjs/Observable";
import {Subscription} from "rxjs/Subscription";

class ScrollableDetails{
    elementName:string;
    //Since we are using viewChild, what is the type here?
    elementRef;
    pageHeight:number;
    scrollPos:number;
    clientHeight:number;
    updateStats(){
        let scrollWindow = this.elementRef;
        this.clientHeight = scrollWindow.clientHeight;
        this.pageHeight = scrollWindow.scrollHeight;
        this.scrollPos = scrollWindow.scrollTop;
    }
}

@Injectable()
export class ScrollMeasure{
    //Collection of all scrollable objects
    scrollableCollection:ScrollableDetails[] = [];
    pagationTrigger:EventEmitter<any> = new EventEmitter<any>();
    scrollSubscriptions:Subscription;

    //@TODO: Figure out way to make this reasonably Configerable
    static pageLengths:number = 2;

    //Injected services
    constructor(private _scroll:ScrollDispatcher){
        this.initScrollMeasure();
    }

    initScrollMeasure(){
        //Stream that sends all scrollable references whenever a scroll event is set off.

        //Stream that updates all entries during scroll event
        let bufferTime = 200; //ms
        this.scrollSubscriptions = this._scroll.scrolled(200,()=>{this.scrollableCollection.forEach(ScrollableObject=>{
            let scrollWindow = ScrollableObject.elementRef;
            ScrollableObject.updateStats();

            if(ScrollMeasure._calculateHasHitBottom(ScrollableObject)){
                this.pagationTrigger.emit();
            }

        })});
    }
    ngOnDestroy(){
        this.scrollSubscriptions.unsubscribe();
    }
    /*
        Returns a stream that emits an event whenever a scroll object has hit the bottom of the page. 
     */
    subscribeToPaginationEmitter(functionToPerform):void{
        this.scrollSubscriptions.add(this.pagationTrigger.subscribe(functionToPerform));
    }

    static _calculateHasHitBottom(scrollable:ScrollableDetails):boolean{
        const triggerDistance = ScrollMeasure.pageLengths * scrollable.clientHeight;
        return scrollable.scrollPos + scrollable.clientHeight + triggerDistance >= scrollable.pageHeight;
    }

    register(elementReference):void{
        let newEntry = new ScrollableDetails();
        newEntry.elementRef = elementReference.nativeElement;
        newEntry.updateStats();
        this.scrollableCollection.push(newEntry);
    }
}

results matching ""

    No results matching ""