import { NgZone } from "@angular/core"; import { from, fromEvent, Subscription } from "rxjs"; import { filter, map, tap } from "rxjs/operators"; import { IElementRef } from "./IElementRef"; export class ScrollSet { public activeElement: Element; public allTargets: Element[]; public scrollProp: string; public subs: Subscription[]; private eventOptions: AddEventListenerOptions = { passive: true, capture: true }; constructor(zone: NgZone, scrollDirection: "vertical" | "horizontal", elements: IElementRef[], eventName: string, className: string = null) { this.allTargets = elements.map(el => this.getTarget(el.element, className)); this.scrollProp = scrollDirection === "vertical" ? "scrollTop" : "scrollLeft"; const subs1 = elements.map((source, i, arr) => { return zone.runOutsideAngular(() => { const targets = this.allTargets.filter((trgt, ii) => i !== ii); const thisEl = this.allTargets[i]; return from(source[eventName]) .pipe( tap(ev => { if (!this.activeElement) this.activeElement = thisEl; }), filter(ev => thisEl === this.activeElement) ).subscribe(e => { for (let target of targets) { target[this.scrollProp] = thisEl[this.scrollProp]; } }); }); }); const subs2 = this.allTargets .map(source => zone.runOutsideAngular(() => fromEvent(source, "mouseenter", this.eventOptions) .pipe(map(ev => ev.currentTarget as Element)) .subscribe(activeEl => this.activeElement = activeEl) )); this.subs = subs1.concat(subs2); } private getTarget(el: Element, className: string): Element { return className ? el.getElementsByClassName(className).item(0) : el; } }