import { NgZone } from "@angular/core"; import { fromEvent, Subscription } from "rxjs"; import { filter } from "rxjs/operators"; import { IElementRef } from "./IElementRef"; export class HoverSet { public activeElement: Element; public allTargets: Element[][]; public subs: Subscription[] = []; private eventOptions: AddEventListenerOptions = { passive: true, capture: true }; constructor(zone: NgZone, elements: IElementRef[], classSelector: string, hoverClasses: string[]) { this.allTargets = elements.map(el => this.getTarget(el.element, classSelector)); for (const innerTargets of this.allTargets) { const newSubs = zone.runOutsideAngular(() => this.getMouseEventSubs(innerTargets, classSelector, hoverClasses)); this.subs = this.subs.concat(newSubs); } } private getMouseEventSubs(innerTargets: Element[], classSelector: string, hoverClasses: string[]) { let _subs2 = innerTargets.map((innerTarget, ii, iarr) => fromEvent(innerTarget, "mouseleave", this.eventOptions) .pipe(filter(e => e.target === innerTarget)) .subscribe(e => { const selector = this.getSelector(classSelector, ii); document .querySelectorAll(selector) .forEach(res => { for (const hoverClass of hoverClasses) res.classList.remove(hoverClass) }); }) ); let _subs1 = innerTargets.map((innerTarget, ii, iarr) => fromEvent(innerTarget, "mouseenter", this.eventOptions) .pipe(filter(e => e.target === innerTarget)) .subscribe(e => { const selector = this.getSelector(classSelector, ii); document .querySelectorAll(selector) .forEach(res => { for (const hoverClass of hoverClasses) res.classList.add(hoverClass) }); }) ); return _subs1.concat(_subs2); } private getSelector(selector: string, rowIndex: number): string { return `${selector}:nth-child(${rowIndex + 1})`; } private getTarget(el: Element, selector: string): Element[] { return Array.from(el.querySelectorAll(selector)); } }