UNPKG

@ng-bootstrap/ng-bootstrap

Version:
186 lines 28.9 kB
import { ChangeDetectorRef, inject, Injectable, NgZone, PLATFORM_ID } from '@angular/core'; import { Subject } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; import { NgbScrollSpyConfig } from './scrollspy-config'; import { DOCUMENT, isPlatformBrowser } from '@angular/common'; import { toFragmentElement } from './scrollspy.utils'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import * as i0 from "@angular/core"; const MATCH_THRESHOLD = 3; /** * A scrollspy service that allows tracking of elements scrolling in and out of view. * * It can be instantiated manually, or automatically by the `ngbScrollSpy` directive. * * @since 15.1.0 */ export class NgbScrollSpyService { constructor() { this._observer = null; this._containerElement = null; this._fragments = new Set(); this._preRegisteredFragments = new Set(); this._active$ = new Subject(); this._distinctActive$ = this._active$.pipe(distinctUntilChanged()); this._active = ''; this._config = inject(NgbScrollSpyConfig); this._document = inject(DOCUMENT); this._platformId = inject(PLATFORM_ID); this._scrollBehavior = this._config.scrollBehavior; this._diChangeDetectorRef = inject(ChangeDetectorRef, { optional: true }); this._changeDetectorRef = this._diChangeDetectorRef; this._zone = inject(NgZone); this._distinctActive$.pipe(takeUntilDestroyed()).subscribe((active) => { this._active = active; this._changeDetectorRef?.markForCheck(); }); } /** * Getter for the currently active fragment id. Returns empty string if none. */ get active() { return this._active; } /** * An observable emitting the currently active fragment. Emits empty string if none. */ get active$() { return this._distinctActive$; } /** * Starts the scrollspy service and observes specified fragments. * * You can specify a list of options to pass, like the root element, initial fragment, scroll behavior, etc. * See the [`NgbScrollSpyOptions`](#/components/scrollspy/api#NgbScrollSpyOptions) interface for more details. */ start(options) { if (isPlatformBrowser(this._platformId)) { this._cleanup(); const { root, rootMargin, scrollBehavior, threshold, fragments, changeDetectorRef, processChanges } = { ...options, }; this._containerElement = root ?? this._document.documentElement; this._changeDetectorRef = changeDetectorRef ?? this._diChangeDetectorRef; this._scrollBehavior = scrollBehavior ?? this._config.scrollBehavior; const processChangesFn = processChanges ?? this._config.processChanges; const context = {}; this._observer = new IntersectionObserver((entries) => processChangesFn({ entries, rootElement: this._containerElement, fragments: this._fragments, scrollSpy: this, options: { ...options }, }, (active) => this._active$.next(active), context), { root: root ?? this._document, ...(rootMargin && { rootMargin }), ...(threshold && { threshold }), }); // merging fragments added before starting and the ones passed as options for (const element of [...this._preRegisteredFragments, ...(fragments ?? [])]) { this.observe(element); } this._preRegisteredFragments.clear(); } } /** * Stops the service and unobserves all fragments. */ stop() { this._cleanup(); this._active$.next(''); } /** * Scrolls to a fragment, it must be known to the service and contained in the root element. * An id or an element reference can be passed. * * [`NgbScrollToOptions`](#/components/scrollspy/api#NgbScrollToOptions) can be passed. */ scrollTo(fragment, options) { const { behavior } = { behavior: this._scrollBehavior, ...options }; if (this._containerElement) { const fragmentElement = toFragmentElement(this._containerElement, fragment); if (fragmentElement) { const heightPx = fragmentElement.offsetTop - this._containerElement.offsetTop; this._containerElement.scrollTo({ top: heightPx, behavior }); let lastOffset = this._containerElement.scrollTop; let matchCounter = 0; // we should update the active section only after scrolling is finished // and there is no clean way to do it at the moment const containerElement = this._containerElement; this._zone.runOutsideAngular(() => { const updateActiveWhenScrollingIsFinished = () => { const sameOffsetAsLastTime = lastOffset === containerElement.scrollTop; if (sameOffsetAsLastTime) { matchCounter++; } else { matchCounter = 0; } if (!sameOffsetAsLastTime || (sameOffsetAsLastTime && matchCounter < MATCH_THRESHOLD)) { lastOffset = containerElement.scrollTop; requestAnimationFrame(updateActiveWhenScrollingIsFinished); } else { this._zone.run(() => this._active$.next(fragmentElement.id)); } }; requestAnimationFrame(updateActiveWhenScrollingIsFinished); }); } } } /** * Adds a fragment to observe. It must be contained in the root element. * An id or an element reference can be passed. */ observe(fragment) { if (!this._observer) { this._preRegisteredFragments.add(fragment); return; } const fragmentElement = toFragmentElement(this._containerElement, fragment); if (fragmentElement && !this._fragments.has(fragmentElement)) { this._fragments.add(fragmentElement); this._observer.observe(fragmentElement); } } /** * Unobserves a fragment. * An id or an element reference can be passed. */ unobserve(fragment) { if (!this._observer) { this._preRegisteredFragments.delete(fragment); return; } const fragmentElement = toFragmentElement(this._containerElement, fragment); if (fragmentElement) { this._fragments.delete(fragmentElement); // we're removing and re-adding all current fragments to recompute active one this._observer.disconnect(); for (const fragment of this._fragments) { this._observer.observe(fragment); } } } ngOnDestroy() { this._cleanup(); } _cleanup() { this._fragments.clear(); this._observer?.disconnect(); this._changeDetectorRef = this._diChangeDetectorRef; this._scrollBehavior = this._config.scrollBehavior; this._observer = null; this._containerElement = null; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbScrollSpyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbScrollSpyService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbScrollSpyService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsc3B5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2Nyb2xsc3B5L3Njcm9sbHNweS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBYSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdEcsT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUUzQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBRWhFLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQztBQXlGMUI7Ozs7OztHQU1HO0FBSUgsTUFBTSxPQUFPLG1CQUFtQjtJQW1CL0I7UUFsQlEsY0FBUyxHQUFnQyxJQUFJLENBQUM7UUFFOUMsc0JBQWlCLEdBQXVCLElBQUksQ0FBQztRQUM3QyxlQUFVLEdBQUcsSUFBSSxHQUFHLEVBQVcsQ0FBQztRQUNoQyw0QkFBdUIsR0FBRyxJQUFJLEdBQUcsRUFBd0IsQ0FBQztRQUUxRCxhQUFRLEdBQUcsSUFBSSxPQUFPLEVBQVUsQ0FBQztRQUNqQyxxQkFBZ0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLENBQUM7UUFDOUQsWUFBTyxHQUFHLEVBQUUsQ0FBQztRQUViLFlBQU8sR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNyQyxjQUFTLEdBQUcs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USxDQUFDLENBQUM7WUFDOUMsT0FBTztTQUNQO1FBRUQsTUFBTSxlQUFlLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRTVFLElBQUksZUFBZSxFQUFFO1lBQ3BCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRXhDLDZFQUE2RTtZQUM3RSxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBRTVCLEtBQUssTUFBTSxRQUFRLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDdkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDakM7U0FDRDtJQUNGLENBQUM7SUFFRCxXQUFXO1FBQ1YsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFTyxRQUFRO1FBQ2YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUM7UUFDcEQsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQztRQUNuRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO0lBQy9CLENBQUM7OEdBcE1XLG1CQUFtQjtrSEFBbkIsbUJBQW1CLGNBRm5CLE1BQU07OzJGQUVOLG1CQUFtQjtrQkFIL0IsVUFBVTttQkFBQztvQkFDWCxVQUFVLEVBQUUsTUFBTTtpQkFDbEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3RvclJlZiwgaW5qZWN0LCBJbmplY3RhYmxlLCBOZ1pvbmUsIE9uRGVzdHJveSwgUExBVEZPUk1fSUQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5nYlNjcm9sbFNweVJlZiB9IGZyb20gJy4vc2Nyb2xsc3B5JztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgTmdiU2Nyb2xsU3B5Q29uZmlnIH0gZnJvbSAnLi9zY3JvbGxzcHktY29uZmlnJztcbmltcG9ydCB7IERPQ1VNRU5ULCBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyB0b0ZyYWdtZW50RWxlbWVudCB9IGZyb20gJy4vc2Nyb2xsc3B5LnV0aWxzJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcblxuY29uc3QgTUFUQ0hfVEhSRVNIT0xEID0gMztcblxuZXhwb3J0IHR5cGUgTmdiU2Nyb2xsU3B5UHJvY2Vzc0NoYW5nZXMgPSAoXG5cdHN0YXRlOiB7XG5cdFx0ZW50cmllczogSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeVtdO1xuXHRcdHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudDtcblx0XHRmcmFnbWVudHM6IFNldDxFbGVtZW50Pjtcblx0XHRzY3JvbGxTcHk6IE5nYlNjcm9sbFNweVNlcnZpY2U7XG5cdFx0b3B0aW9uczogTmdiU2Nyb2xsU3B5T3B0aW9ucztcblx0fSxcblx0Y2hhbmdlQWN0aXZlOiAoYWN0aXZlOiBzdHJpbmcpID0+IHZvaWQsXG5cdGNvbnRleHQ6IG9iamVjdCxcbikgPT4gdm9pZDtcblxuLyoqXG4gKiBPcHRpb25zIHBhc3NlZCB0byB0aGUgYE5nYlNjcm9sbFNweVNlcnZpY2Uuc3RhcnQoKWAgbWV0aG9kIGZvciBzY3JvbGxzcHkgaW5pdGlhbGl6YXRpb24uXG4gKlxuICogSXQgY29udGFpbnMgYSBzdWJzZXQgb2YgdGhlIGBJbnRlcnNlY3Rpb25PYnNlcnZlckluaXRgIG9wdGlvbnMsIGFzIHdlbGwgYWRkaXRpb25hbCBvcHRpb25hbCBwcm9wZXJ0aWVzXG4gKiBsaWtlIGBjaGFuZ2VEZXRlY3RvclJlZmAgb3IgYGZyYWdtZW50c2BcbiAqXG4gKiBAc2luY2UgMTUuMS4wXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTmdiU2Nyb2xsU3B5T3B0aW9ucyBleHRlbmRzIFBpY2s8SW50ZXJzZWN0aW9uT2JzZXJ2ZXJJbml0LCAncm9vdCcgfCAncm9vdE1hcmdpbicgfCAndGhyZXNob2xkJz4ge1xuXHQvKipcblx0ICogQW4gb3B0aW9uYWwgcmVmZXJlbmNlIHRvIHRoZSBjaGFuZ2UgZGV0ZWN0b3IsIHRoYXQgc2hvdWxkIGJlIG1hcmtlZCBmb3IgY2hlY2sgd2hlbiBhY3RpdmUgZnJhZ21lbnQgY2hhbmdlcy5cblx0ICogSWYgaXQgaXMgbm90IHByb3ZpZGVkLCB0aGUgc2VydmljZSB3aWxsIHRyeSB0byBnZXQgaXQgZnJvbSB0aGUgREkuIEV4LiB3aGVuIHVzaW5nIHRoZSBgbmdiU2Nyb2xsU3B5YCBkaXJlY3RpdmUsXG5cdCAqIGl0IHdpbGwgbWFyayBmb3IgY2hlY2sgdGhlIGRpcmVjdGl2ZSdzIGhvc3QgY29tcG9uZW50LlxuXHQgKlxuXHQgKiBgLm1hcmtGb3JDaGVjaygpYCB3aWxsIGJlIGNhbGxlZCBvbiB0aGUgY2hhbmdlIGRldGVjdG9yIHdoZW4gdGhlIGFjdGl2ZSBmcmFnbWVudCBjaGFuZ2VzLlxuXHQgKi9cblx0Y2hhbmdlRGV0ZWN0b3JSZWY/OiBDaGFuZ2VEZXRlY3RvclJlZjtcblxuXHQvKipcblx0ICogQW4gb3B0aW9uYWwgaW5pdGlhbCBmcmFnbWVudCB0byBzY3JvbGwgdG8gd2hlbiB0aGUgc2VydmljZSBzdGFydHMuXG5cdCAqL1xuXHRpbml0aWFsRnJhZ21lbnQ/OiBzdHJpbmcgfCBIVE1MRWxlbWVudDtcblxuXHQvKipcblx0ICogQW4gb3B0aW9uYWwgbGlzdCBvZiBmcmFnbWVudHMgdG8gb2JzZXJ2ZSB3aGVuIHRoZSBzZXJ2aWNlIHN0YXJ0cy5cblx0ICogWW91IGNhbiBhbHRlcm5hdGl2ZWx5IHVzZSBgLmFkZEZyYWdtZW50KClgIHRvIGFkZCBmcmFnbWVudHMuXG5cdCAqL1xuXHRmcmFnbWVudHM/OiAoc3RyaW5nIHwgSFRNTEVsZW1lbnQpW107XG5cblx0LyoqXG5cdCAqIEFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gdGhlIGBJbnRlcnNlY3Rpb25PYnNlcnZlcmAgZGV0ZWN0cyBhIGNoYW5nZS5cblx0ICogSXQgaXMgdXNlZCB0byBkZXRlcm1pbmUgaWYgY3VycmVudGx5IGFjdGl2ZSBmcmFnbWVudCBzaG91bGQgYmUgY2hhbmdlZC5cblx0ICpcblx0ICogWW91IGNhbiBvdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIHByb3ZpZGUgeW91ciBvd24gc2Nyb2xsc3B5IGxvZ2ljLlxuXHQgKiBJdCBwcm92aWRlczpcblx0ICogIC0gYSBzY3JvbGxzcHkgYHN0YXRlYCAob2JzZXJ2ZXIgZW50cmllcywgcm9vdCBlbGVtZW50LCBmcmFnbWVudHMsIHNjcm9sbFNweSBpbnN0YW5jZSwgZXRjLilcblx0ICogIC0gYSBgY2hhbmdlQWN0aXZlYCBmdW5jdGlvbiB0aGF0IHNob3VsZCBiZSBjYWxsZWQgd2l0aCB0aGUgbmV3IGFjdGl2ZSBmcmFnbWVudFxuXHQgKiAgLSBhIGBjb250ZXh0YCB0aGF0IGlzIHBlcnNpc3RlZCBiZXR3ZWVuIGNhbGxzXG5cdCAqL1xuXHRwcm9jZXNzQ2hhbmdlcz86IE5nYlNjcm9sbFNweVByb2Nlc3NDaGFuZ2VzO1xuXG5cdC8qKlxuXHQgKiBBbiBvcHRpb25hbCBgSW50ZXJzZWN0aW9uT2JzZXJ2ZXJgIHJvb3QgZWxlbWVudC4gSWYgbm90IHByb3ZpZGVkLCB0aGUgZG9jdW1lbnQgZWxlbWVudCB3aWxsIGJlIHVzZWQuXG5cdCAqL1xuXHRyb290PzogSFRNTEVsZW1lbnQ7XG5cblx0LyoqXG5cdCAqIEFuIG9wdGlvbmFsIGBJbnRlcnNlY3Rpb25PYnNlcnZlcmAgbWFyZ2luIGZvciB0aGUgcm9vdCBlbGVtZW50LlxuXHQgKi9cblx0cm9vdE1hcmdpbj86IHN0cmluZztcblxuXHQvKipcblx0ICogQW4gb3B0aW9uYWwgZGVmYXVsdCBzY3JvbGwgYmVoYXZpb3IgdG8gdXNlIHdoZW4gdXNpbmcgdGhlIGAuc2Nyb2xsVG8oKWAgbWV0aG9kLlxuXHQgKi9cblx0c2Nyb2xsQmVoYXZpb3I/OiAnYXV0bycgfCAnc21vb3RoJztcblxuXHQvKipcblx0ICogQW4gb3B0aW9uYWwgYEludGVyc2VjdGlvbk9ic2VydmVyYCB0aHJlc2hvbGQuXG5cdCAqL1xuXHR0aHJlc2hvbGQ/OiBudW1iZXIgfCBudW1iZXJbXTtcbn1cblxuLyoqXG4gKiBTY3JvbGwgb3B0aW9ucyBwYXNzZWQgdG8gdGhlIGAuc2Nyb2xsVG8oKWAgbWV0aG9kLlxuICogQW4gZXh0ZW5zaW9uIG9mIHRoZSBzdGFuZGFyZCBgU2Nyb2xsT3B0aW9uc2AgaW50ZXJmYWNlLlxuICpcbiAqIEBzaW5jZSAxNS4xLjBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOZ2JTY3JvbGxUb09wdGlvbnMgZXh0ZW5kcyBTY3JvbGxPcHRpb25zIHtcblx0LyoqXG5cdCAqIFNjcm9sbCBiZWhhdmlvciBhcyBkZWZpbmVkIGluIHRoZSBgU2Nyb2xsT3B0aW9uc2AgaW50ZXJmYWNlLlxuXHQgKi9cblx0YmVoYXZpb3I/OiAnYXV0bycgfCAnc21vb3RoJztcbn1cblxuLyoqXG4gKiBBIHNjcm9sbHNweSBzZXJ2aWNlIHRoYXQgYWxsb3dzIHRyYWNraW5nIG9mIGVsZW1lbnRzIHNjcm9sbGluZyBpbiBhbmQgb3V0IG9mIHZpZXcuXG4gKlxuICogSXQgY2FuIGJlIGluc3RhbnRpYXRlZCBtYW51YWxseSwgb3IgYXV0b21hdGljYWxseSBieSB0aGUgYG5nYlNjcm9sbFNweWAgZGlyZWN0aXZlLlxuICpcbiAqIEBzaW5jZSAxNS4xLjBcbiAqL1xuQEluamVjdGFibGUoe1xuXHRwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIE5nYlNjcm9sbFNweVNlcnZpY2UgaW1wbGVtZW50cyBOZ2JTY3JvbGxTcHlSZWYsIE9uRGVzdHJveSB7XG5cdHByaXZhdGUgX29ic2VydmVyOiBJbnRlcnNlY3Rpb25PYnNlcnZlciB8IG51bGwgPSBudWxsO1xuXG5cdHByaXZhdGUgX2NvbnRhaW5lckVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgX2ZyYWdtZW50cyA9IG5ldyBTZXQ8RWxlbWVudD4oKTtcblx0cHJpdmF0ZSBfcHJlUmVnaXN0ZXJlZEZyYWdtZW50cyA9IG5ldyBTZXQ8c3RyaW5nIHwgSFRNTEVsZW1lbnQ+KCk7XG5cblx0cHJpdmF0ZSBfYWN0aXZlJCA9IG5ldyBTdWJqZWN0PHN0cmluZz4oKTtcblx0cHJpdmF0ZSBfZGlzdGluY3RBY3RpdmUkID0gdGhpcy5fYWN0aXZlJC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpO1xuXHRwcml2YXRlIF9hY3RpdmUgPSAnJztcblxuXHRwcml2YXRlIF9jb25maWcgPSBpbmplY3QoTmdiU2Nyb2xsU3B5Q29uZmlnKTtcblx0cHJpdmF0ZSBfZG9jdW1lbnQgPSBpbmplY3QoRE9DVU1FTlQpO1xuXHRwcml2YXRlIF9wbGF0Zm9ybUlkID0gaW5qZWN0KFBMQVRGT1JNX0lEKTtcblx0cHJpdmF0ZSBfc2Nyb2xsQmVoYXZpb3IgPSB0aGlzLl9jb25maWcuc2Nyb2xsQmVoYXZpb3I7XG5cdHByaXZhdGUgX2RpQ2hhbmdlRGV0ZWN0b3JSZWYgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cdHByaXZhdGUgX2NoYW5nZURldGVjdG9yUmVmID0gdGhpcy5fZGlDaGFuZ2VEZXRlY3RvclJlZjtcblx0cHJpdmF0ZSBfem9uZSA9IGluamVjdChOZ1pvbmUpO1xuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHRoaXMuX2Rpc3RpbmN0QWN0aXZlJC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCgpKS5zdWJzY3JpYmUoKGFjdGl2ZSkgPT4ge1xuXHRcdFx0dGhpcy5fYWN0aXZlID0gYWN0aXZlO1xuXHRcdFx0dGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWY/Lm1hcmtGb3JDaGVjaygpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHRlciBmb3IgdGhlIGN1cnJlbnRseSBhY3RpdmUgZnJhZ21lbnQgaWQuIFJldHVybnMgZW1wdHkgc3RyaW5nIGlmIG5vbmUuXG5cdCAqL1xuXHRnZXQgYWN0aXZlKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMuX2FjdGl2ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbiBvYnNlcnZhYmxlIGVtaXR0aW5nIHRoZSBjdXJyZW50bHkgYWN0aXZlIGZyYWdtZW50LiBFbWl0cyBlbXB0eSBzdHJpbmcgaWYgbm9uZS5cblx0ICovXG5cdGdldCBhY3RpdmUkKCk6IE9ic2VydmFibGU8c3RyaW5nPiB7XG5cdFx0cmV0dXJuIHRoaXMuX2Rpc3RpbmN0QWN0aXZlJDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTdGFydHMgdGhlIHNjcm9sbHNweSBzZXJ2aWNlIGFuZCBvYnNlcnZlcyBzcGVjaWZpZWQgZnJhZ21lbnRzLlxuXHQgKlxuXHQgKiBZb3UgY2FuIHNwZWNpZnkgYSBsaXN0IG9mIG9wdGlvbnMgdG8gcGFzcywgbGlrZSB0aGUgcm9vdCBlbGVtZW50LCBpbml0aWFsIGZyYWdtZW50LCBzY3JvbGwgYmVoYXZpb3IsIGV0Yy5cblx0ICogU2VlIHRoZSBbYE5nYlNjcm9sbFNweU9wdGlvbnNgXSgjL2NvbXBvbmVudHMvc2Nyb2xsc3B5L2FwaSNOZ2JTY3JvbGxTcHlPcHRpb25zKSBpbnRlcmZhY2UgZm9yIG1vcmUgZGV0YWlscy5cblx0ICovXG5cdHN0YXJ0KG9wdGlvbnM/OiBOZ2JTY3JvbGxTcHlPcHRpb25zKSB7XG5cdFx0aWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMuX3BsYXRmb3JtSWQpKSB7XG5cdFx0XHR0aGlzLl9jbGVhbnVwKCk7XG5cblx0XHRcdGNvbnN0IHsgcm9vdCwgcm9vdE1hcmdpbiwgc2Nyb2xsQmVoYXZpb3IsIHRocmVzaG9sZCwgZnJhZ21lbnRzLCBjaGFuZ2VEZXRlY3RvclJlZiwgcHJvY2Vzc0NoYW5nZXMgfSA9IHtcblx0XHRcdFx0Li4ub3B0aW9ucyxcblx0XHRcdH07XG5cdFx0XHR0aGlzLl9jb250YWluZXJFbGVtZW50ID0gcm9vdCA/PyB0aGlzLl9kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdFx0XHR0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZiA9IGNoYW5nZURldGVjdG9yUmVmID8/IHRoaXMuX2RpQ2hhbmdlRGV0ZWN0b3JSZWY7XG5cdFx0XHR0aGlzLl9zY3JvbGxCZWhhdmlvciA9IHNjcm9sbEJlaGF2aW9yID8/IHRoaXMuX2NvbmZpZy5zY3JvbGxCZWhhdmlvcjtcblx0XHRcdGNvbnN0IHByb2Nlc3NDaGFuZ2VzRm4gPSBwcm9jZXNzQ2hhbmdlcyA/PyB0aGlzLl9jb25maWcucHJvY2Vzc0NoYW5nZXM7XG5cblx0XHRcdGNvbnN0IGNvbnRleHQgPSB7fTtcblx0XHRcdHRoaXMuX29ic2VydmVyID0gbmV3IEludGVyc2VjdGlvbk9ic2VydmVyKFxuXHRcdFx0XHQoZW50cmllcykgPT5cblx0XHRcdFx0XHRwcm9jZXNzQ2hhbmdlc0ZuKFxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRlbnRyaWVzLFxuXHRcdFx0XHRcdFx0XHRyb290RWxlbWVudDogdGhpcy5fY29udGFpbmVyRWxlbWVudCEsXG5cdFx0XHRcdFx0XHRcdGZyYWdtZW50czogdGhpcy5fZnJhZ21lbnRzLFxuXHRcdFx0XHRcdFx0XHRzY3JvbGxTcHk6IHRoaXMsXG5cdFx0XHRcdFx0XHRcdG9wdGlvbnM6IHsgLi4ub3B0aW9ucyB9LFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdChhY3RpdmU6IHN0cmluZykgPT4gdGhpcy5fYWN0aXZlJC5uZXh0KGFjdGl2ZSksXG5cdFx0XHRcdFx0XHRjb250ZXh0LFxuXHRcdFx0XHRcdCksXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRyb290OiByb290ID8/IHRoaXMuX2RvY3VtZW50LFxuXHRcdFx0XHRcdC4uLihyb290TWFyZ2luICYmIHsgcm9vdE1hcmdpbiB9KSxcblx0XHRcdFx0XHQuLi4odGhyZXNob2xkICYmIHsgdGhyZXNob2xkIH0pLFxuXHRcdFx0XHR9LFxuXHRcdFx0KTtcblxuXHRcdFx0Ly8gbWVyZ2luZyBmcmFnbWVudHMgYWRkZWQgYmVmb3JlIHN0YXJ0aW5nIGFuZCB0aGUgb25lcyBwYXNzZWQgYXMgb3B0aW9uc1xuXHRcdFx0Zm9yIChjb25zdCBlbGVtZW50IG9mIFsuLi50aGlzLl9wcmVSZWdpc3RlcmVkRnJhZ21lbnRzLCAuLi4oZnJhZ21lbnRzID8/IFtdKV0pIHtcblx0XHRcdFx0dGhpcy5vYnNlcnZlKGVsZW1lbnQpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9wcmVSZWdpc3RlcmVkRnJhZ21lbnRzLmNsZWFyKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFN0b3BzIHRoZSBzZXJ2aWNlIGFuZCB1bm9ic2VydmVzIGFsbCBmcmFnbWVudHMuXG5cdCAqL1xuXHRzdG9wKCkge1xuXHRcdHRoaXMuX2NsZWFudXAoKTtcblx0XHR0aGlzLl9hY3RpdmUkLm5leHQoJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNjcm9sbHMgdG8gYSBmcmFnbWVudCwgaXQgbXVzdCBiZSBrbm93biB0byB0aGUgc2VydmljZSBhbmQgY29udGFpbmVkIGluIHRoZSByb290IGVsZW1lbnQuXG5cdCAqIEFuIGlkIG9yIGFuIGVsZW1lbnQgcmVmZXJlbmNlIGNhbiBiZSBwYXNzZWQuXG5cdCAqXG5cdCAqIFtgTmdiU2Nyb2xsVG9PcHRpb25zYF0oIy9jb21wb25lbnRzL3Njcm9sbHNweS9hcGkjTmdiU2Nyb2xsVG9PcHRpb25zKSBjYW4gYmUgcGFzc2VkLlxuXHQgKi9cblx0c2Nyb2xsVG8oZnJhZ21lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBvcHRpb25zPzogTmdiU2Nyb2xsVG9PcHRpb25zKSB7XG5cdFx0Y29uc3QgeyBiZWhhdmlvciB9ID0geyBiZWhhdmlvcjogdGhpcy5fc2Nyb2xsQmVoYXZpb3IsIC4uLm9wdGlvbnMgfTtcblxuXHRcdGlmICh0aGlzLl9jb250YWluZXJFbGVtZW50KSB7XG5cdFx0XHRjb25zdCBmcmFnbWVudEVsZW1lbnQgPSB0b0ZyYWdtZW50RWxlbWVudCh0aGlzLl9jb250YWluZXJFbGVtZW50LCBmcmFnbWVudCk7XG5cblx0XHRcdGlmIChmcmFnbWVudEVsZW1lbnQpIHtcblx0XHRcdFx0Y29uc3QgaGVpZ2h0UHggPSBmcmFnbWVudEVsZW1lbnQub2Zmc2V0VG9wIC0gdGhpcy5fY29udGFpbmVyRWxlbWVudC5vZmZzZXRUb3A7XG5cblx0XHRcdFx0dGhpcy5fY29udGFpbmVyRWxlbWVudC5zY3JvbGxUbyh7IHRvcDogaGVpZ2h0UHgsIGJlaGF2aW9yIH0pO1xuXG5cdFx0XHRcdGxldCBsYXN0T2Zmc2V0ID0gdGhpcy5fY29udGFpbmVyRWxlbWVudC5zY3JvbGxUb3A7XG5cdFx0XHRcdGxldCBtYXRjaENvdW50ZXIgPSAwO1xuXG5cdFx0XHRcdC8vIHdlIHNob3VsZCB1cGRhdGUgdGhlIGFjdGl2ZSBzZWN0aW9uIG9ubHkgYWZ0ZXIgc2Nyb2xsaW5nIGlzIGZpbmlzaGVkXG5cdFx0XHRcdC8vIGFuZCB0aGVyZSBpcyBubyBjbGVhbiB3YXkgdG8gZG8gaXQgYXQgdGhlIG1vbWVudFxuXHRcdFx0XHRjb25zdCBjb250YWluZXJFbGVtZW50ID0gdGhpcy5fY29udGFpbmVyRWxlbWVudDtcblx0XHRcdFx0dGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgdXBkYXRlQWN0aXZlV2hlblNjcm9sbGluZ0lzRmluaXNoZWQgPSAoKSA9PiB7XG5cdFx0XHRcdFx0XHRjb25zdCBzYW1lT2Zmc2V0QXNMYXN0VGltZSA9IGxhc3RPZmZzZXQgPT09IGNvbnRhaW5lckVsZW1lbnQuc2Nyb2xsVG9wO1xuXG5cdFx0XHRcdFx0XHRpZiAoc2FtZU9mZnNldEFzTGFzdFRpbWUpIHtcblx0XHRcdFx0XHRcdFx0bWF0Y2hDb3VudGVyKys7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRtYXRjaENvdW50ZXIgPSAwO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAoIXNhbWVPZmZzZXRBc0xhc3RUaW1lIHx8IChzYW1lT2Zmc2V0QXNMYXN0VGltZSAmJiBtYXRjaENvdW50ZXIgPCBNQVRDSF9USFJFU0hPTEQpKSB7XG5cdFx0XHRcdFx0XHRcdGxhc3RPZmZzZXQgPSBjb250YWluZXJFbGVtZW50LnNjcm9sbFRvcDtcblxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUodXBkYXRlQWN0aXZlV2hlblNjcm9sbGluZ0lzRmluaXNoZWQpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5fem9uZS5ydW4oKCkgPT4gdGhpcy5fYWN0aXZlJC5uZXh0KGZyYWdtZW50RWxlbWVudC5pZCkpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0cmVxdWVzdEFuaW1hdGlvbkZyYW1lKHVwZGF0ZUFjdGl2ZVdoZW5TY3JvbGxpbmdJc0ZpbmlzaGVkKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBmcmFnbWVudCB0byBvYnNlcnZlLiBJdCBtdXN0IGJlIGNvbnRhaW5lZCBpbiB0aGUgcm9vdCBlbGVtZW50LlxuXHQgKiBBbiBpZCBvciBhbiBlbGVtZW50IHJlZmVyZW5jZSBjYW4gYmUgcGFzc2VkLlxuXHQgKi9cblx0b2JzZXJ2ZShmcmFnbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpIHtcblx0XHRpZiAoIXRoaXMuX29ic2VydmVyKSB7XG5cdFx0XHR0aGlzLl9wcmVSZWdpc3RlcmVkRnJhZ21lbnRzLmFkZChmcmFnbWVudCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgZnJhZ21lbnRFbGVtZW50ID0gdG9GcmFnbWVudEVsZW1lbnQodGhpcy5fY29udGFpbmVyRWxlbWVudCwgZnJhZ21lbnQpO1xuXG5cdFx0aWYgKGZyYWdtZW50RWxlbWVudCAmJiAhdGhpcy5fZnJhZ21lbnRzLmhhcyhmcmFnbWVudEVsZW1lbnQpKSB7XG5cdFx0XHR0aGlzLl9mcmFnbWVudHMuYWRkKGZyYWdtZW50RWxlbWVudCk7XG5cdFx0XHR0aGlzLl9vYnNlcnZlci5vYnNlcnZlKGZyYWdtZW50RWxlbWVudCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFVub2JzZXJ2ZXMgYSBmcmFnbWVudC5cblx0ICogQW4gaWQgb3IgYW4gZWxlbWVudCByZWZlcmVuY2UgY2FuIGJlIHBhc3NlZC5cblx0ICovXG5cdHVub2JzZXJ2ZShmcmFnbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpIHtcblx0XHRpZiAoIXRoaXMuX29ic2VydmVyKSB7XG5cdFx0XHR0aGlzLl9wcmVSZWdpc3RlcmVkRnJhZ21lbnRzLmRlbGV0ZShmcmFnbWVudCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgZnJhZ21lbnRFbGVtZW50ID0gdG9GcmFnbWVudEVsZW1lbnQodGhpcy5fY29udGFpbmVyRWxlbWVudCwgZnJhZ21lbnQpO1xuXG5cdFx0aWYgKGZyYWdtZW50RWxlbWVudCkge1xuXHRcdFx0dGhpcy5fZnJhZ21lbnRzLmRlbGV0ZShmcmFnbWVudEVsZW1lbnQpO1xuXG5cdFx0XHQvLyB3ZSdyZSByZW1vdmluZyBhbmQgcmUtYWRkaW5nIGFsbCBjdXJyZW50IGZyYWdtZW50cyB0byByZWNvbXB1dGUgYWN0aXZlIG9uZVxuXHRcdFx0dGhpcy5fb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuXG5cdFx0XHRmb3IgKGNvbnN0IGZyYWdtZW50IG9mIHRoaXMuX2ZyYWdtZW50cykge1xuXHRcdFx0XHR0aGlzLl9vYnNlcnZlci5vYnNlcnZlKGZyYWdtZW50KTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRuZ09uRGVzdHJveSgpIHtcblx0XHR0aGlzLl9jbGVhbnVwKCk7XG5cdH1cblxuXHRwcml2YXRlIF9jbGVhbnVwKCkge1xuXHRcdHRoaXMuX2ZyYWdtZW50cy5jbGVhcigpO1xuXHRcdHRoaXMuX29ic2VydmVyPy5kaXNjb25uZWN0KCk7XG5cdFx0dGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYgPSB0aGlzLl9kaUNoYW5nZURldGVjdG9yUmVmO1xuXHRcdHRoaXMuX3Njcm9sbEJlaGF2aW9yID0gdGhpcy5fY29uZmlnLnNjcm9sbEJlaGF2aW9yO1xuXHRcdHRoaXMuX29ic2VydmVyID0gbnVsbDtcblx0XHR0aGlzLl9jb250YWluZXJFbGVtZW50ID0gbnVsbDtcblx0fVxufVxuIl19