redoc/src/services/ScrollService.ts

72 lines
1.7 KiB
TypeScript
Raw Normal View History

2017-10-12 00:01:37 +03:00
import { debounce, bind } from 'decko';
import { EventEmitter } from 'eventemitter3';
const EVENT = 'scroll';
export class ScrollService {
private _scrollParent: Window | HTMLElement;
private _emiter: EventEmitter;
private _prevOffsetY: number = 0;
constructor() {
this._scrollParent = window;
this._emiter = new EventEmitter();
this.bind();
}
bind() {
this._prevOffsetY = this.scrollY();
this._scrollParent.addEventListener('scroll', this.handleScroll);
}
dispose() {
this._scrollParent.removeEventListener('scroll', this.handleScroll);
this._emiter.removeAllListeners(EVENT);
}
scrollY(): number {
if (this._scrollParent === window) {
return window.pageYOffset;
} else if (this._scrollParent instanceof HTMLElement) {
return this._scrollParent.scrollTop;
} else {
return 0;
}
}
isElementBellow(el: Element | null) {
if (el === null) return;
return el.getBoundingClientRect().top > 0;
}
isElementAbove(el: Element | null) {
if (el === null) return;
return Math.trunc(el.getBoundingClientRect().top) <= 0;
}
subscribe(cb): () => void {
const emmiter = this._emiter.addListener(EVENT, cb);
return () => emmiter.removeListener(EVENT, cb);
}
scrollIntoView(element: Element | null) {
if (element === null) {
return;
}
element.scrollIntoView();
}
scrollIntoViewBySelector(selector: string) {
const element = document.querySelector(selector);
this.scrollIntoView(element);
}
@bind
@debounce(100)
handleScroll() {
const scrollY = this.scrollY();
const isScrolledDown = scrollY - this._prevOffsetY > 0;
this._prevOffsetY = this.scrollY();
this._emiter.emit(EVENT, isScrolledDown);
}
}