UNPKG

ng-spy

Version:

A lightweight, dependecy-free scrollspy for angular. Use this library to spy on HTML elements on your page when the window is scrolled or resized.

104 lines 17.4 kB
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "./window.service"; export class ScrollSpyService { constructor(windowService) { this.windowService = windowService; this.stopSpying$ = new Subject(); this.activeSpyTarget$ = new Subject(); this.spyTargets = []; this.thresholdTop = 0; this.thresholdBottom = 0; this.isSpying = false; this.scrollEvent = this.windowService.scrollEvent.pipe(takeUntil(this.stopSpying$)); this.resizeEvent = this.windowService.resizeEvent.pipe(takeUntil(this.stopSpying$)); } spy({ scrollContainer, thresholdTop = 0, thresholdBottom = 0 } = {}) { // this is to prevent duplicate listeners if (this.isSpying) { return; } this.isSpying = true; this.scrollContainer = scrollContainer; this.thresholdTop = thresholdTop; this.thresholdBottom = thresholdBottom; this.scrollEvent.subscribe(() => this.checkActiveElement(scrollContainer)); this.resizeEvent.subscribe(() => this.checkActiveElement(scrollContainer)); if (scrollContainer != null) { this.windowService.getScrollEventForContainer(scrollContainer) .pipe(takeUntil(this.stopSpying$)) .subscribe(() => this.checkActiveElement(scrollContainer)); } this.checkActiveElement(scrollContainer); } addTarget(target) { this.spyTargets.push({ ...target }); this.checkActiveElement(this.scrollContainer); } removeTarget(target) { this.spyTargets = this.spyTargets.filter(spyTarget => target !== spyTarget.name); this.checkActiveElement(this.scrollContainer); } checkActiveElement(scrollContainer) { let activeTarget = null; for (const target of this.spyTargets) { const activeElement = activeTarget != null ? activeTarget.element : null; if (this.isElementActive(target.element, scrollContainer, activeElement)) { activeTarget = target; } } this.activeSpyTarget$.next(activeTarget ? activeTarget.name : null); } isElementActive(element, scrollContainer, currentActiveElement) { const targetOffsetTop = this.windowService.getElementOffsetTop(element); const targetHeight = this.windowService.getElementHeight(element); if (currentActiveElement != null && this.windowService.getElementOffsetTop(currentActiveElement) > targetOffsetTop) { return false; } const hasContainer = (scrollContainer != null); const isInsideWindow = this.isElementInsideWindow(hasContainer, targetHeight, targetOffsetTop); if (isInsideWindow && !hasContainer) { return true; } return isInsideWindow && hasContainer && this.isElementInsiedScrollContainer(scrollContainer, targetHeight, targetOffsetTop); } isElementInsideWindow(hasContainer, elementHeight, elementOffsetTop) { const scrollTop = this.windowService.scrollTop; const viewportHeight = this.windowService.viewportHeight; // target bottom edge is below window top edge && target top edge is above window bottom edge // if target has a container, don't check for thresholds on the window if (hasContainer) { return elementOffsetTop + elementHeight > scrollTop && elementOffsetTop < scrollTop + viewportHeight; } return elementOffsetTop + elementHeight > scrollTop + this.thresholdTop && elementOffsetTop < scrollTop + viewportHeight - this.thresholdBottom; } isElementInsiedScrollContainer(container, elementHeight, elementOffsetTop) { const scrollContainerScrollTop = this.windowService.getElementScrollTop(container); const scrollContainerHeight = this.windowService.getElementHeight(container); const elementOffsetTopFromParent = elementOffsetTop - this.windowService.getElementOffsetTop(container); // element bottom edge is below container top edge && element top edge is above container bottom edge return elementOffsetTopFromParent + elementHeight > scrollContainerScrollTop + this.thresholdTop && elementOffsetTopFromParent < scrollContainerScrollTop + scrollContainerHeight - this.thresholdBottom; } get activeSpyTarget() { return this.activeSpyTarget$.asObservable(); } stopSpying() { this.stopSpying$.next(); this.spyTargets = []; this.isSpying = false; } } ScrollSpyService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: ScrollSpyService, deps: [{ token: i1.WindowService }], target: i0.ɵɵFactoryTarget.Injectable }); ScrollSpyService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: ScrollSpyService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: ScrollSpyService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return [{ type: i1.WindowService }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsLXNweS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctc3B5L3NyYy9saWIvc2Nyb2xsLXNweS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBYyxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkQsT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7OztBQU8zQyxNQUFNLE9BQU8sZ0JBQWdCO0lBVzNCLFlBQW9CLGFBQTRCO1FBQTVCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBVnhDLGdCQUFXLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM1QixxQkFBZ0IsR0FBRyxJQUFJLE9BQU8sRUFBVSxDQUFDO1FBR3pDLGVBQVUsR0FBZ0IsRUFBRSxDQUFDO1FBQzdCLGlCQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLG9CQUFlLEdBQUcsQ0FBQyxDQUFDO1FBRXBCLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFHdkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQ3BGLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUN0RixDQUFDO0lBRUQsR0FBRyxDQUFDLEVBQUUsZUFBZSxFQUFFLFlBQVksR0FBRyxDQUFDLEVBQUUsZUFBZSxHQUFHLENBQUMsS0FBaUIsRUFBRTtRQUM3RSx5Q0FBeUM7UUFDekMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLE9BQU87U0FDUjtRQUVELElBQUks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d0IsR0FBRyxxQkFBcUIsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO0lBQzVHLENBQUM7SUFFRCxJQUFJLGVBQWU7UUFDakIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDOUMsQ0FBQztJQUVELFVBQVU7UUFDUixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7OzZHQWxIVSxnQkFBZ0I7aUhBQWhCLGdCQUFnQixjQUZmLE1BQU07MkZBRVAsZ0JBQWdCO2tCQUg1QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVsZW1lbnRSZWYsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFNweVRhcmdldCB9IGZyb20gJy4vc3B5LXRhcmdldC5tb2RlbCc7XG5pbXBvcnQgeyBXaW5kb3dTZXJ2aWNlIH0gZnJvbSAnLi93aW5kb3cuc2VydmljZSc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIFNjcm9sbFNweVNlcnZpY2Uge1xuICBwcml2YXRlIHN0b3BTcHlpbmckID0gbmV3IFN1YmplY3QoKTtcbiAgcHJpdmF0ZSBhY3RpdmVTcHlUYXJnZXQkID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xuICBwcml2YXRlIHNjcm9sbEV2ZW50OiBPYnNlcnZhYmxlPEV2ZW50PjtcbiAgcHJpdmF0ZSByZXNpemVFdmVudDogT2JzZXJ2YWJsZTxFdmVudD47XG4gIHByaXZhdGUgc3B5VGFyZ2V0czogU3B5VGFyZ2V0W10gPSBbXTtcbiAgcHJpdmF0ZSB0aHJlc2hvbGRUb3AgPSAwO1xuICBwcml2YXRlIHRocmVzaG9sZEJvdHRvbSA9IDA7XG4gIHByaXZhdGUgc2Nyb2xsQ29udGFpbmVyOiBFbGVtZW50UmVmO1xuICBwcml2YXRlIGlzU3B5aW5nID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSB3aW5kb3dTZXJ2aWNlOiBXaW5kb3dTZXJ2aWNlKSB7XG4gICAgdGhpcy5zY3JvbGxFdmVudCA9IHRoaXMud2luZG93U2VydmljZS5zY3JvbGxFdmVudC5waXBlKHRha2VVbnRpbCh0aGlzLnN0b3BTcHlpbmckKSk7XG4gICAgdGhpcy5yZXNpemVFdmVudCA9IHRoaXMud2luZG93U2VydmljZS5yZXNpemVFdmVudC5waXBlKHRha2VVbnRpbCh0aGlzLnN0b3BTcHlpbmckKSk7XG4gIH1cblxuICBzcHkoeyBzY3JvbGxDb250YWluZXIsIHRocmVzaG9sZFRvcCA9IDAsIHRocmVzaG9sZEJvdHRvbSA9IDAgfTogU3B5T3B0aW9ucyA9IHt9KSB7XG4gICAgLy8gdGhpcyBpcyB0byBwcmV2ZW50IGR1cGxpY2F0ZSBsaXN0ZW5lcnNcbiAgICBpZiAodGhpcy5pc1NweWluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuaXNTcHlpbmcgPSB0cnVlO1xuICAgIHRoaXMuc2Nyb2xsQ29udGFpbmVyID0gc2Nyb2xsQ29udGFpbmVyO1xuICAgIHRoaXMudGhyZXNob2xkVG9wID0gdGhyZXNob2xkVG9wO1xuICAgIHRoaXMudGhyZXNob2xkQm90dG9tID0gdGhyZXNob2xkQm90dG9tO1xuXG4gICAgdGhpcy5zY3JvbGxFdmVudC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5jaGVja0FjdGl2ZUVsZW1lbnQoc2Nyb2xsQ29udGFpbmVyKSk7XG4gICAgdGhpcy5yZXNpemVFdmVudC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5jaGVja0FjdGl2ZUVsZW1lbnQoc2Nyb2xsQ29udGFpbmVyKSk7XG5cbiAgICBpZiAoc2Nyb2xsQ29udGFpbmVyICE9IG51bGwpIHtcbiAgICAgIHRoaXMud2luZG93U2VydmljZS5nZXRTY3JvbGxFdmVudEZvckNvbnRhaW5lcihzY3JvbGxDb250YWluZXIpXG4gICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLnN0b3BTcHlpbmckKSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNoZWNrQWN0aXZlRWxlbWVudChzY3JvbGxDb250YWluZXIpKTtcbiAgICB9XG5cbiAgICB0aGlzLmNoZWNrQWN0aXZlRWxlbWVudChzY3JvbGxDb250YWluZXIpO1xuICB9XG5cbiAgYWRkVGFyZ2V0KHRhcmdldDogU3B5VGFyZ2V0KSB7XG4gICAgdGhpcy5zcHlUYXJnZXRzLnB1c2goeyAuLi50YXJnZXQgfSk7XG4gICAgdGhpcy5jaGVja0FjdGl2ZUVsZW1lbnQodGhpcy5zY3JvbGxDb250YWluZXIpO1xuICB9XG5cbiAgcmVtb3ZlVGFyZ2V0KHRhcmdldDogc3RyaW5nKSB7XG4gICAgdGhpcy5zcHlUYXJnZXRzID0gdGhpcy5zcHlUYXJnZXRzLmZpbHRlcihzcHlUYXJnZXQgPT4gdGFyZ2V0ICE9PSBzcHlUYXJnZXQubmFtZSk7XG4gICAgdGhpcy5jaGVja0FjdGl2ZUVsZW1lbnQodGhpcy5zY3JvbGxDb250YWluZXIpO1xuICB9XG5cbiAgY2hlY2tBY3RpdmVFbGVtZW50KHNjcm9sbENvbnRhaW5lcj86IEVsZW1lbnRSZWYpIHtcbiAgICBsZXQgYWN0aXZlVGFyZ2V0OiBTcHlUYXJnZXQgPSBudWxsO1xuXG4gICAgZm9yIChjb25zdCB0YXJnZXQgb2YgdGhpcy5zcHlUYXJnZXRzKSB7XG4gICAgICBjb25zdCBhY3RpdmVFbGVtZW50ID0gYWN0aXZlVGFyZ2V0ICE9IG51bGwgPyBhY3RpdmVUYXJnZXQuZWxlbWVudCA6IG51bGw7XG4gICAgICBpZiAodGhpcy5pc0VsZW1lbnRBY3RpdmUodGFyZ2V0LmVsZW1lbnQsIHNjcm9sbENvbnRhaW5lciwgYWN0aXZlRWxlbWVudCkpIHtcbiAgICAgICAgYWN0aXZlVGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuYWN0aXZlU3B5VGFyZ2V0JC5uZXh0KGFjdGl2ZVRhcmdldCA/IGFjdGl2ZVRhcmdldC5uYW1lIDogbnVsbCk7XG4gIH1cblxuICBpc0VsZW1lbnRBY3RpdmUoZWxlbWVudDogRWxlbWVudFJlZiwgc2Nyb2xsQ29udGFpbmVyPzogRWxlbWVudFJlZiwgY3VycmVudEFjdGl2ZUVsZW1lbnQ/OiBFbGVtZW50UmVmKSB7XG4gICAgY29uc3QgdGFyZ2V0T2Zmc2V0VG9wID0gdGhpcy53aW5kb3dTZXJ2aWNlLmdldEVsZW1lbnRPZmZzZXRUb3AoZWxlbWVudCk7XG4gICAgY29uc3QgdGFyZ2V0SGVpZ2h0ID0gdGhpcy53aW5kb3dTZXJ2aWNlLmdldEVsZW1lbnRIZWlnaHQoZWxlbWVudCk7XG5cbiAgICBpZiAoY3VycmVudEFjdGl2ZUVsZW1lbnQgIT0gbnVsbCAmJiB0aGlzLndpbmRvd1NlcnZpY2UuZ2V0RWxlbWVudE9mZnNldFRvcChjdXJyZW50QWN0aXZlRWxlbWVudCkgPiB0YXJnZXRPZmZzZXRUb3ApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNDb250YWluZXIgPSAoc2Nyb2xsQ29udGFpbmVyICE9IG51bGwpO1xuXG4gICAgY29uc3QgaXNJbnNpZGVXaW5kb3cgPSB0aGlzLmlzRWxlbWVudEluc2lkZVdpbmRvdyhoYXNDb250YWluZXIsIHRhcmdldEhlaWdodCwgdGFyZ2V0T2Zmc2V0VG9wKTtcblxuICAgIGlmIChpc0luc2lkZVdpbmRvdyAmJiAhaGFzQ29udGFpbmVyKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXNJbnNpZGVXaW5kb3cgJiYgaGFzQ29udGFpbmVyICYmIHRoaXMuaXNFbGVtZW50SW5zaWVkU2Nyb2xsQ29udGFpbmVyKHNjcm9sbENvbnRhaW5lciwgdGFyZ2V0SGVpZ2h0LCB0YXJnZXRPZmZzZXRUb3ApO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0VsZW1lbnRJbnNpZGVXaW5kb3coaGFzQ29udGFpbmVyOiBib29sZWFuLCBlbGVtZW50SGVpZ2h0OiBudW1iZXIsIGVsZW1lbnRPZmZzZXRUb3A6IG51bWJlcikge1xuICAgIGNvbnN0IHNjcm9sbFRvcCA9IHRoaXMud2luZG93U2VydmljZS5zY3JvbGxUb3A7XG4gICAgY29uc3Qgdmlld3BvcnRIZWlnaHQgPSB0aGlzLndpbmRvd1NlcnZpY2Uudmlld3BvcnRIZWlnaHQ7XG5cbiAgICAvLyB0YXJnZXQgYm90dG9tIGVkZ2UgaXMgYmVsb3cgd2luZG93IHRvcCBlZGdlICYmIHRhcmdldCB0b3AgZWRnZSBpcyBhYm92ZSB3aW5kb3cgYm90dG9tIGVkZ2VcbiAgICAvLyBpZiB0YXJnZXQgaGFzIGEgY29udGFpbmVyLCBkb24ndCBjaGVjayBmb3IgdGhyZXNob2xkcyBvbiB0aGUgd2luZG93XG4gICAgaWYgKGhhc0NvbnRhaW5lcikge1xuICAgICAgcmV0dXJuIGVsZW1lbnRPZmZzZXRUb3AgKyBlbGVtZW50SGVpZ2h0ID4gc2Nyb2xsVG9wXG4gICAgICAmJiBlbGVtZW50T2Zmc2V0VG9wIDwgc2Nyb2xsVG9wICsgdmlld3BvcnRIZWlnaHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRPZmZzZXRUb3AgKyBlbGVtZW50SGVpZ2h0ID4gc2Nyb2xsVG9wICsgdGhpcy50aHJlc2hvbGRUb3BcbiAgICAmJiBlbGVtZW50T2Zmc2V0VG9wIDwgc2Nyb2xsVG9wICsgdmlld3BvcnRIZWlnaHQgLSB0aGlzLnRocmVzaG9sZEJvdHRvbTtcbiAgfVxuXG4gIHByaXZhdGUgaXNFbGVtZW50SW5zaWVkU2Nyb2xsQ29udGFpbmVyKGNvbnRhaW5lcjogRWxlbWVudFJlZiwgZWxlbWVudEhlaWdodDogbnVtYmVyLCBlbGVtZW50T2Zmc2V0VG9wOiBudW1iZXIpIHtcbiAgICBjb25zdCBzY3JvbGxDb250YWluZXJTY3JvbGxUb3AgPSB0aGlzLndpbmRvd1NlcnZpY2UuZ2V0RWxlbWVudFNjcm9sbFRvcChjb250YWluZXIpO1xuICAgIGNvbnN0IHNjcm9sbENvbnRhaW5lckhlaWdodCA9IHRoaXMud2luZG93U2VydmljZS5nZXRFbGVtZW50SGVpZ2h0KGNvbnRhaW5lcik7XG4gICAgY29uc3QgZWxlbWVudE9mZnNldFRvcEZyb21QYXJlbnQgPSBlbGVtZW50T2Zmc2V0VG9wIC0gdGhpcy53aW5kb3dTZXJ2aWNlLmdldEVsZW1lbnRPZmZzZXRUb3AoY29udGFpbmVyKTtcblxuICAgIC8vIGVsZW1lbnQgYm90dG9tIGVkZ2UgaXMgYmVsb3cgY29udGFpbmVyIHRvcCBlZGdlICYmIGVsZW1lbnQgdG9wIGVkZ2UgaXMgYWJvdmUgY29udGFpbmVyIGJvdHRvbSBlZGdlXG4gICAgcmV0dXJuIGVsZW1lbnRPZmZzZXRUb3BGcm9tUGFyZW50ICsgZWxlbWVudEhlaWdodCA+IHNjcm9sbENvbnRhaW5lclNjcm9sbFRvcCArIHRoaXMudGhyZXNob2xkVG9wXG4gICAgICAmJiBlbGVtZW50T2Zmc2V0VG9wRnJvbVBhcmVudCA8IHNjcm9sbENvbnRhaW5lclNjcm9sbFRvcCArIHNjcm9sbENvbnRhaW5lckhlaWdodCAtIHRoaXMudGhyZXNob2xkQm90dG9tO1xuICB9XG5cbiAgZ2V0IGFjdGl2ZVNweVRhcmdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5hY3RpdmVTcHlUYXJnZXQkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgc3RvcFNweWluZygpIHtcbiAgICB0aGlzLnN0b3BTcHlpbmckLm5leHQoKTtcbiAgICB0aGlzLnNweVRhcmdldHMgPSBbXTtcbiAgICB0aGlzLmlzU3B5aW5nID0gZmFsc2U7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFNweU9wdGlvbnMge1xuICBzY3JvbGxDb250YWluZXI/OiBFbGVtZW50UmVmO1xuICB0aHJlc2hvbGRUb3A/OiBudW1iZXI7XG4gIHRocmVzaG9sZEJvdHRvbT86IG51bWJlcjtcbn1cbiJdfQ==