1 | /**
|
2 | * @license
|
3 | * Copyright Google LLC All Rights Reserved.
|
4 | *
|
5 | * Use of this source code is governed by an MIT-style license that can be
|
6 | * found in the LICENSE file at https://angular.io/license
|
7 | */
|
8 | import { coerceElement } from '@angular/cdk/coercion';
|
9 | import { Platform } from '@angular/cdk/platform';
|
10 | import { Injectable, NgZone, Optional, Inject } from '@angular/core';
|
11 | import { fromEvent, of as observableOf, Subject, Observable } from 'rxjs';
|
12 | import { auditTime, filter } from 'rxjs/operators';
|
13 | import { DOCUMENT } from '@angular/common';
|
14 | import * as i0 from "@angular/core";
|
15 | import * as i1 from "@angular/cdk/platform";
|
16 | /** Time in ms to throttle the scrolling events by default. */
|
17 | export const DEFAULT_SCROLL_TIME = 20;
|
18 | /**
|
19 | * Service contained all registered Scrollable references and emits an event when any one of the
|
20 | * Scrollable references emit a scrolled event.
|
21 | */
|
22 | class ScrollDispatcher {
|
23 | constructor(_ngZone, _platform, document) {
|
24 | this._ngZone = _ngZone;
|
25 | this._platform = _platform;
|
26 | /** Subject for notifying that a registered scrollable reference element has been scrolled. */
|
27 | this._scrolled = new Subject();
|
28 | /** Keeps track of the global `scroll` and `resize` subscriptions. */
|
29 | this._globalSubscription = null;
|
30 | /** Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. */
|
31 | this._scrolledCount = 0;
|
32 | /**
|
33 | * Map of all the scrollable references that are registered with the service and their
|
34 | * scroll event subscriptions.
|
35 | */
|
36 | this.scrollContainers = new Map();
|
37 | this._document = document;
|
38 | }
|
39 | /**
|
40 | * Registers a scrollable instance with the service and listens for its scrolled events. When the
|
41 | * scrollable is scrolled, the service emits the event to its scrolled observable.
|
42 | * @param scrollable Scrollable instance to be registered.
|
43 | */
|
44 | register(scrollable) {
|
45 | if (!this.scrollContainers.has(scrollable)) {
|
46 | this.scrollContainers.set(scrollable, scrollable.elementScrolled().subscribe(() => this._scrolled.next(scrollable)));
|
47 | }
|
48 | }
|
49 | /**
|
50 | * De-registers a Scrollable reference and unsubscribes from its scroll event observable.
|
51 | * @param scrollable Scrollable instance to be deregistered.
|
52 | */
|
53 | deregister(scrollable) {
|
54 | const scrollableReference = this.scrollContainers.get(scrollable);
|
55 | if (scrollableReference) {
|
56 | scrollableReference.unsubscribe();
|
57 | this.scrollContainers.delete(scrollable);
|
58 | }
|
59 | }
|
60 | /**
|
61 | * Returns an observable that emits an event whenever any of the registered Scrollable
|
62 | * references (or window, document, or body) fire a scrolled event. Can provide a time in ms
|
63 | * to override the default "throttle" time.
|
64 | *
|
65 | * **Note:** in order to avoid hitting change detection for every scroll event,
|
66 | * all of the events emitted from this stream will be run outside the Angular zone.
|
67 | * If you need to update any data bindings as a result of a scroll event, you have
|
68 | * to run the callback using `NgZone.run`.
|
69 | */
|
70 | scrolled(auditTimeInMs = DEFAULT_SCROLL_TIME) {
|
71 | if (!this._platform.isBrowser) {
|
72 | return observableOf();
|
73 | }
|
74 | return new Observable((observer) => {
|
75 | if (!this._globalSubscription) {
|
76 | this._addGlobalListener();
|
77 | }
|
78 | // In the case of a 0ms delay, use an observable without auditTime
|
79 | // since it does add a perceptible delay in processing overhead.
|
80 | const subscription = auditTimeInMs > 0
|
81 | ? this._scrolled.pipe(auditTime(auditTimeInMs)).subscribe(observer)
|
82 | : this._scrolled.subscribe(observer);
|
83 | this._scrolledCount++;
|
84 | return () => {
|
85 | subscription.unsubscribe();
|
86 | this._scrolledCount--;
|
87 | if (!this._scrolledCount) {
|
88 | this._removeGlobalListener();
|
89 | }
|
90 | };
|
91 | });
|
92 | }
|
93 | ngOnDestroy() {
|
94 | this._removeGlobalListener();
|
95 | this.scrollContainers.forEach((_, container) => this.deregister(container));
|
96 | this._scrolled.complete();
|
97 | }
|
98 | /**
|
99 | * Returns an observable that emits whenever any of the
|
100 | * scrollable ancestors of an element are scrolled.
|
101 | * @param elementOrElementRef Element whose ancestors to listen for.
|
102 | * @param auditTimeInMs Time to throttle the scroll events.
|
103 | */
|
104 | ancestorScrolled(elementOrElementRef, auditTimeInMs) {
|
105 | const ancestors = this.getAncestorScrollContainers(elementOrElementRef);
|
106 | return this.scrolled(auditTimeInMs).pipe(filter(target => {
|
107 | return !target || ancestors.indexOf(target) > -1;
|
108 | }));
|
109 | }
|
110 | /** Returns all registered Scrollables that contain the provided element. */
|
111 | getAncestorScrollContainers(elementOrElementRef) {
|
112 | const scrollingContainers = [];
|
113 | this.scrollContainers.forEach((_subscription, scrollable) => {
|
114 | if (this._scrollableContainsElement(scrollable, elementOrElementRef)) {
|
115 | scrollingContainers.push(scrollable);
|
116 | }
|
117 | });
|
118 | return scrollingContainers;
|
119 | }
|
120 | /** Use defaultView of injected document if available or fallback to global window reference */
|
121 | _getWindow() {
|
122 | return this._document.defaultView || window;
|
123 | }
|
124 | /** Returns true if the element is contained within the provided Scrollable. */
|
125 | _scrollableContainsElement(scrollable, elementOrElementRef) {
|
126 | let element = coerceElement(elementOrElementRef);
|
127 | let scrollableElement = scrollable.getElementRef().nativeElement;
|
128 | // Traverse through the element parents until we reach null, checking if any of the elements
|
129 | // are the scrollable's element.
|
130 | do {
|
131 | if (element == scrollableElement) {
|
132 | return true;
|
133 | }
|
134 | } while ((element = element.parentElement));
|
135 | return false;
|
136 | }
|
137 | /** Sets up the global scroll listeners. */
|
138 | _addGlobalListener() {
|
139 | this._globalSubscription = this._ngZone.runOutsideAngular(() => {
|
140 | const window = this._getWindow();
|
141 | return fromEvent(window.document, 'scroll').subscribe(() => this._scrolled.next());
|
142 | });
|
143 | }
|
144 | /** Cleans up the global scroll listener. */
|
145 | _removeGlobalListener() {
|
146 | if (this._globalSubscription) {
|
147 | this._globalSubscription.unsubscribe();
|
148 | this._globalSubscription = null;
|
149 | }
|
150 | }
|
151 | static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: ScrollDispatcher, deps: [{ token: i0.NgZone }, { token: i1.Platform }, { token: DOCUMENT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
152 | static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: ScrollDispatcher, providedIn: 'root' }); }
|
153 | }
|
154 | export { ScrollDispatcher };
|
155 | i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: ScrollDispatcher, decorators: [{
|
156 | type: Injectable,
|
157 | args: [{ providedIn: 'root' }]
|
158 | }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i1.Platform }, { type: undefined, decorators: [{
|
159 | type: Optional
|
160 | }, {
|
161 | type: Inject,
|
162 | args: [DOCUMENT]
|
163 | }] }]; } });
|
164 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsLWRpc3BhdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY2RrL3Njcm9sbGluZy9zY3JvbGwtZGlzcGF0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFBYSxVQUFVLEVBQUUsTUFBTSxFQUFhLFFBQVEsRUFBRSxNQUFNLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxFQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksWUFBWSxFQUFFLE9BQU8sRUFBZ0IsVUFBVSxFQUFXLE1BQU0sTUFBTSxDQUFDO0FBQ2hHLE9BQU8sRUFBQyxTQUFTLEVBQUUsTUFBTSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFakQsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDOzs7QUFFekMsOERBQThEO0FBQzlELE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztBQUV0Qzs7O0dBR0c7QUFDSCxNQUNhLGdCQUFnQjtJQUkzQixZQUNVLE9BQWUsRUFDZixTQUFtQixFQUNHLFFBQWE7UUFGbkMsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNmLGNBQVMsR0FBVCxTQUFTLENBQVU7UUFNN0IsOEZBQThGO1FBQzdFLGNBQVMsR0FBRyxJQUFJLE9BQU8sRUFBd0IsQ0FBQztRQUVqRSxxRUFBcUU7UUFDckUsd0JBQW1CLEdBQXdCLElBQUksQ0FBQztRQUVoRCxpR0FBaUc7UUFDekYsbUJBQWMsR0FBRyxDQUFDLENBQUM7UUFFM0I7OztXQUdHO1FBQ0gscUJBQWdCLEdBQXFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFoQjdELElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO0lB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QyxDQUFDO1FBQ3JGLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDRDQUE0QztJQUNwQyxxQkFBcUI7UUFDM0IsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUU7WUFDNUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUM7U0FDakM7SUFDSCxDQUFDOzhHQTFLVSxnQkFBZ0IsZ0VBT0wsUUFBUTtrSEFQbkIsZ0JBQWdCLGNBREosTUFBTTs7U0FDbEIsZ0JBQWdCOzJGQUFoQixnQkFBZ0I7a0JBRDVCLFVBQVU7bUJBQUMsRUFBQyxVQUFVLEVBQUUsTUFBTSxFQUFDOzswQkFRM0IsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7Y29lcmNlRWxlbWVudH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7UGxhdGZvcm19IGZyb20gJ0Bhbmd1bGFyL2Nkay9wbGF0Zm9ybSc7XG5pbXBvcnQge0VsZW1lbnRSZWYsIEluamVjdGFibGUsIE5nWm9uZSwgT25EZXN0cm95LCBPcHRpb25hbCwgSW5qZWN0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7ZnJvbUV2ZW50LCBvZiBhcyBvYnNlcnZhYmxlT2YsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiwgT2JzZXJ2YWJsZSwgT2JzZXJ2ZXJ9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHthdWRpdFRpbWUsIGZpbHRlcn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHR5cGUge0Nka1Njcm9sbGFibGV9IGZyb20gJy4vc2Nyb2xsYWJsZSc7XG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG4vKiogVGltZSBpbiBtcyB0byB0aHJvdHRsZSB0aGUgc2Nyb2xsaW5nIGV2ZW50cyBieSBkZWZhdWx0LiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0NST0xMX1RJTUUgPSAyMDtcblxuLyoqXG4gKiBTZXJ2aWNlIGNvbnRhaW5lZCBhbGwgcmVnaXN0ZXJlZCBTY3JvbGxhYmxlIHJlZmVyZW5jZXMgYW5kIGVtaXRzIGFuIGV2ZW50IHdoZW4gYW55IG9uZSBvZiB0aGVcbiAqIFNjcm9sbGFibGUgcmVmZXJlbmNlcyBlbWl0IGEgc2Nyb2xsZWQgZXZlbnQuXG4gKi9cbkBJbmplY3RhYmxlKHtwcm92aWRlZEluOiAncm9vdCd9KVxuZXhwb3J0IGNsYXNzIFNjcm9sbERpc3BhdGNoZXIgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAvKiogVXNlZCB0byByZWZlcmVuY2UgY29ycmVjdCBkb2N1bWVudC93aW5kb3cgKi9cbiAgcHJvdGVjdGVkIF9kb2N1bWVudDogRG9jdW1lbnQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSBfcGxhdGZvcm06IFBsYXRmb3JtLFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoRE9DVU1FTlQpIGRvY3VtZW50OiBhbnksXG4gICkge1xuICAgIHRoaXMuX2RvY3VtZW50ID0gZG9jdW1lbnQ7XG4gIH1cblxuICAvKiogU3ViamVjdCBmb3Igbm90aWZ5aW5nIHRoYXQgYSByZWdpc3RlcmVkIHNjcm9sbGFibGUgcmVmZXJlbmNlIGVsZW1lbnQgaGFzIGJlZW4gc2Nyb2xsZWQuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX3Njcm9sbGVkID0gbmV3IFN1YmplY3Q8Q2RrU2Nyb2xsYWJsZSB8IHZvaWQ+KCk7XG5cbiAgLyoqIEtlZXBzIHRyYWNrIG9mIHRoZSBnbG9iYWwgYHNjcm9sbGAgYW5kIGByZXNpemVgIHN1YnNjcmlwdGlvbnMuICovXG4gIF9nbG9iYWxTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBLZWVwcyB0cmFjayBvZiB0aGUgYW1vdW50IG9mIHN1YnNjcmlwdGlvbnMgdG8gYHNjcm9sbGVkYC4gVXNlZCBmb3IgY2xlYW5pbmcgdXAgYWZ0ZXJ3YXJkcy4gKi9cbiAgcHJpdmF0ZSBfc2Nyb2xsZWRDb3VudCA9IDA7XG5cbiAgLyoqXG4gICAqIE1hcCBvZiBhbGwgdGhlIHNjcm9sbGFibGUgcmVmZXJlbmNlcyB0aGF0IGFyZSByZWdpc3RlcmVkIHdpdGggdGhlIHNlcnZpY2UgYW5kIHRoZWlyXG4gICAqIHNjcm9sbCBldmVudCBzdWJzY3JpcHRpb25zLlxuICAgKi9cbiAgc2Nyb2xsQ29udGFpbmVyczogTWFwPENka1Njcm9sbGFibGUsIFN1YnNjcmlwdGlvbj4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHNjcm9sbGFibGUgaW5zdGFuY2Ugd2l0aCB0aGUgc2VydmljZSBhbmQgbGlzdGVucyBmb3IgaXRzIHNjcm9sbGVkIGV2ZW50cy4gV2hlbiB0aGVcbiAgICogc2Nyb2xsYWJsZSBpcyBzY3JvbGxlZCwgdGhlIHNlcnZpY2UgZW1pdHMgdGhlIGV2ZW50IHRvIGl0cyBzY3JvbGxlZCBvYnNlcnZhYmxlLlxuICAgKiBAcGFyYW0gc2Nyb2xsYWJsZSBTY3JvbGxhYmxlIGluc3RhbmNlIHRvIGJlIHJlZ2lzdGVyZWQuXG4gICAqL1xuICByZWdpc3RlcihzY3JvbGxhYmxlOiBDZGtTY3JvbGxhYmxlKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNjcm9sbENvbnRhaW5lcnMuaGFzKHNjcm9sbGFibGUpKSB7XG4gICAgICB0aGlzLnNjcm9sbENvbnRhaW5lcnMuc2V0KFxuICAgICAgICBzY3JvbGxhYmxlLFxuICAgICAgICBzY3JvbGxhYmxlLmVsZW1lbnRTY3JvbGxlZCgpLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9zY3JvbGxlZC5uZXh0KHNjcm9sbGFibGUpKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlLXJlZ2lzdGVycyBhIFNjcm9sbGFibGUgcmVmZXJlbmNlIGFuZCB1bnN1YnNjcmliZXMgZnJvbSBpdHMgc2Nyb2xsIGV2ZW50IG9ic2VydmFibGUuXG4gICAqIEBwYXJhbSBzY3JvbGxhYmxlIFNjcm9sbGFibGUgaW5zdGFuY2UgdG8gYmUgZGVyZWdpc3RlcmVkLlxuICAgKi9cbiAgZGVyZWdpc3RlcihzY3JvbGxhYmxlOiBDZGtTY3JvbGxhYmxlKTogdm9pZCB7XG4gICAgY29uc3Qgc2Nyb2xsYWJsZVJlZmVyZW5jZSA9IHRoaXMuc2Nyb2xsQ29udGFpbmVycy5nZXQoc2Nyb2xsYWJsZSk7XG5cbiAgICBpZiAoc2Nyb2xsYWJsZVJlZmVyZW5jZSkge1xuICAgICAgc2Nyb2xsYWJsZVJlZmVyZW5jZS51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5zY3JvbGxDb250YWluZXJzLmRlbGV0ZShzY3JvbGxhYmxlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBvYnNlcnZhYmxlIHRoYXQgZW1pdHMgYW4gZXZlbnQgd2hlbmV2ZXIgYW55IG9mIHRoZSByZWdpc3RlcmVkIFNjcm9sbGFibGVcbiAgICogcmVmZXJlbmNlcyAob3Igd2luZG93LCBkb2N1bWVudCwgb3IgYm9keSkgZmlyZSBhIHNjcm9sbGVkIGV2ZW50LiBDYW4gcHJvdmlkZSBhIHRpbWUgaW4gbXNcbiAgICogdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgXCJ0aHJvdHRsZVwiIHRpbWUuXG4gICAqXG4gICAqICoqTm90ZToqKiBpbiBvcmRlciB0byBhdm9pZCBoaXR0aW5nIGNoYW5nZSBkZXRlY3Rpb24gZm9yIGV2ZXJ5IHNjcm9sbCBldmVudCxcbiAgICogYWxsIG9mIHRoZSBldmVudHMgZW1pdHRlZCBmcm9tIHRoaXMgc3RyZWFtIHdpbGwgYmUgcnVuIG91dHNpZGUgdGhlIEFuZ3VsYXIgem9uZS5cbiAgICogSWYgeW91IG5lZWQgdG8gdXBkYXRlIGFueSBkYXRhIGJpbmRpbmdzIGFzIGEgcmVzdWx0IG9mIGEgc2Nyb2xsIGV2ZW50LCB5b3UgaGF2ZVxuICAgKiB0byBydW4gdGhlIGNhbGxiYWNrIHVzaW5nIGBOZ1pvbmUucnVuYC5cbiAgICovXG4gIHNjcm9sbGVkKGF1ZGl0VGltZUluTXM6IG51bWJlciA9IERFRkFVTFRfU0NST0xMX1RJTUUpOiBPYnNlcnZhYmxlPENka1Njcm9sbGFibGUgfCB2b2lkPiB7XG4gICAgaWYgKCF0aGlzLl9wbGF0Zm9ybS5pc0Jyb3dzZXIpIHtcbiAgICAgIHJldHVybiBvYnNlcnZhYmxlT2Y8dm9pZD4oKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyOiBPYnNlcnZlcjxDZGtTY3JvbGxhYmxlIHwgdm9pZD4pID0+IHtcbiAgICAgIGlmICghdGhpcy5fZ2xvYmFsU3Vic2NyaXB0aW9uKSB7XG4gICAgICAgIHRoaXMuX2FkZEdsb2JhbExpc3RlbmVyKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEluIHRoZSBjYXNlIG9mIGEgMG1zIGRlbGF5LCB1c2UgYW4gb2JzZXJ2YWJsZSB3aXRob3V0IGF1ZGl0VGltZVxuICAgICAgLy8gc2luY2UgaXQgZG9lcyBhZGQgYSBwZXJjZXB0aWJsZSBkZWxheSBpbiBwcm9jZXNzaW5nIG92ZXJoZWFkLlxuICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID1cbiAgICAgICAgYXVkaXRUaW1lSW5NcyA+IDBcbiAgICAgICAgICA/IHRoaXMuX3Njcm9sbGVkLnBpcGUoYXVkaXRUaW1lKGF1ZGl0VGltZUluTXMpKS5zdWJzY3JpYmUob2JzZXJ2ZXIpXG4gICAgICAgICAgOiB0aGlzLl9zY3JvbGxlZC5zdWJzY3JpYmUob2JzZXJ2ZXIpO1xuXG4gICAgICB0aGlzLl9zY3JvbGxlZENvdW50Kys7XG5cbiAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLl9zY3JvbGxlZENvdW50LS07XG5cbiAgICAgICAgaWYgKCF0aGlzLl9zY3JvbGxlZENvdW50KSB7XG4gICAgICAgICAgdGhpcy5fcmVtb3ZlR2xvYmFsTGlzdGVuZXIoKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuX3JlbW92ZUdsb2JhbExpc3RlbmVyKCk7XG4gICAgdGhpcy5zY3JvbGxDb250YWluZXJzLmZvckVhY2goKF8sIGNvbnRhaW5lcikgPT4gdGhpcy5kZXJlZ2lzdGVyKGNvbnRhaW5lcikpO1xuICAgIHRoaXMuX3Njcm9sbGVkLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBvYnNlcnZhYmxlIHRoYXQgZW1pdHMgd2hlbmV2ZXIgYW55IG9mIHRoZVxuICAgKiBzY3JvbGxhYmxlIGFuY2VzdG9ycyBvZiBhbiBlbGVtZW50IGFyZSBzY3JvbGxlZC5cbiAgICogQHBhcmFtIGVsZW1lbnRPckVsZW1lbnRSZWYgRWxlbWVudCB3aG9zZSBhbmNlc3RvcnMgdG8gbGlzdGVuIGZvci5cbiAgICogQHBhcmFtIGF1ZGl0VGltZUluTXMgVGltZSB0byB0aHJvdHRsZSB0aGUgc2Nyb2xsIGV2ZW50cy5cbiAgICovXG4gIGFuY2VzdG9yU2Nyb2xsZWQoXG4gICAgZWxlbWVudE9yRWxlbWVudFJlZjogRWxlbWVudFJlZiB8IEhUTUxFbGVtZW50LFxuICAgIGF1ZGl0VGltZUluTXM/OiBudW1iZXIsXG4gICk6IE9ic2VydmFibGU8Q2RrU2Nyb2xsYWJsZSB8IHZvaWQ+IHtcbiAgICBjb25zdCBhbmNlc3RvcnMgPSB0aGlzLmdldEFuY2VzdG9yU2Nyb2xsQ29udGFpbmVycyhlbGVtZW50T3JFbGVtZW50UmVmKTtcblxuICAgIHJldHVybiB0aGlzLnNjcm9sbGVkKGF1ZGl0VGltZUluTXMpLnBpcGUoXG4gICAgICBmaWx0ZXIodGFyZ2V0ID0+IHtcbiAgICAgICAgcmV0dXJuICF0YXJnZXQgfHwgYW5jZXN0b3JzLmluZGV4T2YodGFyZ2V0KSA+IC0xO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBSZXR1cm5zIGFsbCByZWdpc3RlcmVkIFNjcm9sbGFibGVzIHRoYXQgY29udGFpbiB0aGUgcHJvdmlkZWQgZWxlbWVudC4gKi9cbiAgZ2V0QW5jZXN0b3JTY3JvbGxDb250YWluZXJzKGVsZW1lbnRPckVsZW1lbnRSZWY6IEVsZW1lbnRSZWYgfCBIVE1MRWxlbWVudCk6IENka1Njcm9sbGFibGVbXSB7XG4gICAgY29uc3Qgc2Nyb2xsaW5nQ29udGFpbmVyczogQ2RrU2Nyb2xsYWJsZVtdID0gW107XG5cbiAgICB0aGlzLnNjcm9sbENvbnRhaW5lcnMuZm9yRWFjaCgoX3N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uLCBzY3JvbGxhYmxlOiBDZGtTY3JvbGxhYmxlKSA9PiB7XG4gICAgICBpZiAodGhpcy5fc2Nyb2xsYWJsZUNvbnRhaW5zRWxlbWVudChzY3JvbGxhYmxlLCBlbGVtZW50T3JFbGVtZW50UmVmKSkge1xuICAgICAgICBzY3JvbGxpbmdDb250YWluZXJzLnB1c2goc2Nyb2xsYWJsZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gc2Nyb2xsaW5nQ29udGFpbmVycztcbiAgfVxuXG4gIC8qKiBVc2UgZGVmYXVsdFZpZXcgb2YgaW5qZWN0ZWQgZG9jdW1lbnQgaWYgYXZhaWxhYmxlIG9yIGZhbGxiYWNrIHRvIGdsb2JhbCB3aW5kb3cgcmVmZXJlbmNlICovXG4gIHByaXZhdGUgX2dldFdpbmRvdygpOiBXaW5kb3cge1xuICAgIHJldHVybiB0aGlzLl9kb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3c7XG4gIH1cblxuICAvKiogUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gdGhlIHByb3ZpZGVkIFNjcm9sbGFibGUuICovXG4gIHByaXZhdGUgX3Njcm9sbGFibGVDb250YWluc0VsZW1lbnQoXG4gICAgc2Nyb2xsYWJsZTogQ2RrU2Nyb2xsYWJsZSxcbiAgICBlbGVtZW50T3JFbGVtZW50UmVmOiBFbGVtZW50UmVmIHwgSFRNTEVsZW1lbnQsXG4gICk6IGJvb2xlYW4ge1xuICAgIGxldCBlbGVtZW50OiBIVE1MRWxlbWVudCB8IG51bGwgPSBjb2VyY2VFbGVtZW50KGVsZW1lbnRPckVsZW1lbnRSZWYpO1xuICAgIGxldCBzY3JvbGxhYmxlRWxlbWVudCA9IHNjcm9sbGFibGUuZ2V0RWxlbWVudFJlZigpLm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICAvLyBUcmF2ZXJzZSB0aHJvdWdoIHRoZSBlbGVtZW50IHBhcmVudHMgdW50aWwgd2UgcmVhY2ggbnVsbCwgY2hlY2tpbmcgaWYgYW55IG9mIHRoZSBlbGVtZW50c1xuICAgIC8vIGFyZSB0aGUgc2Nyb2xsYWJsZSdzIGVsZW1lbnQuXG4gICAgZG8ge1xuICAgICAgaWYgKGVsZW1lbnQgPT0gc2Nyb2xsYWJsZUVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfSB3aGlsZSAoKGVsZW1lbnQgPSBlbGVtZW50IS5wYXJlbnRFbGVtZW50KSk7XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKiogU2V0cyB1cCB0aGUgZ2xvYmFsIHNjcm9sbCBsaXN0ZW5lcnMuICovXG4gIHByaXZhdGUgX2FkZEdsb2JhbExpc3RlbmVyKCkge1xuICAgIHRoaXMuX2dsb2JhbFN1YnNjcmlwdGlvbiA9IHRoaXMuX25nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBjb25zdCB3aW5kb3cgPSB0aGlzLl9nZXRXaW5kb3coKTtcbiAgICAgIHJldHVybiBmcm9tRXZlbnQod2luZG93LmRvY3VtZW50LCAnc2Nyb2xsJykuc3Vic2NyaWJlKCgpID0+IHRoaXMuX3Njcm9sbGVkLm5leHQoKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQ2xlYW5zIHVwIHRoZSBnbG9iYWwgc2Nyb2xsIGxpc3RlbmVyLiAqL1xuICBwcml2YXRlIF9yZW1vdmVHbG9iYWxMaXN0ZW5lcigpIHtcbiAgICBpZiAodGhpcy5fZ2xvYmFsU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9nbG9iYWxTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMuX2dsb2JhbFN1YnNjcmlwdGlvbiA9IG51bGw7XG4gICAgfVxuICB9XG59XG4iXX0= |
\ | No newline at end of file |