UNPKG

@nova-ui/bits

Version:

SolarWinds Nova Framework

250 lines 33.5 kB
// © 2022 SolarWinds Worldwide, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import { AriaDescriber, FocusMonitor } from "@angular/cdk/a11y"; import { coerceBooleanProperty } from "@angular/cdk/coercion"; import { hasModifierKey } from "@angular/cdk/keycodes"; import { Directive, ElementRef, Input, NgZone, ViewContainerRef, } from "@angular/core"; import { Subject } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { TooltipComponent } from "./tooltip.component"; import { KEYBOARD_CODE } from "../../constants/keycode.constants"; import { OverlayPositionService } from "../overlay/overlay-position.service"; import * as i0 from "@angular/core"; import * as i1 from "@angular/cdk/a11y"; import * as i2 from "../overlay/overlay-position.service"; /** * <example-url>./../examples/index.html#/tooltip</example-url> * * @dynamic */ export class TooltipDirective { /** Allows the user to define the position of the tooltip relative to the parent element */ get position() { return this._position; } set position(value) { if (value !== this._position) { this._position = value; this.updateOverlayPositions(); } } /** Disables the display of the tooltip. */ get disabled() { return this._disabled; } set disabled(value) { this._disabled = coerceBooleanProperty(value); // If tooltip is disabled, hide immediately. if (this._disabled) { this.hide(); } } /** Determines whether the tooltip should be displayed when the content is overflowing. By default is `false`. */ get ellipsis() { return this._ellipsis; } set ellipsis(value) { this._ellipsis = coerceBooleanProperty(value); } /** The message to be displayed in the tooltip */ get message() { return this._message; } set message(value) { this._ariaDescriber.removeDescription(this._elementRef.nativeElement, this._message); // If the message is not a string (e.g. number), convert it to a string and trim it. this._message = value != null ? `${value}`.trim() : ""; if (!this._message && this._isTooltipVisible()) { this.hide(); } else { this._updateTooltipMessage(); this._ariaDescriber.describe(this._elementRef.nativeElement, this.message); } } constructor(_elementRef, _viewContainerRef, _ngZone, _ariaDescriber, _focusMonitor, overlayPositionService) { this._elementRef = _elementRef; this._viewContainerRef = _viewContainerRef; this._ngZone = _ngZone; this._ariaDescriber = _ariaDescriber; this._focusMonitor = _focusMonitor; this.overlayPositionService = overlayPositionService; this._position = "top"; this._disabled = false; this._ellipsis = false; this._message = ""; this._manualListeners = new Map(); /** Emits when the component is destroyed. */ this._destroyed = new Subject(); this.overlayPositionService.setOverlayPositionConfig({ arrowSize: 10, arrowPadding: 0, }); const element = _elementRef.nativeElement; this._manualListeners .set("mouseenter", () => this.show()) .set("mouseleave", () => this.hide()); this._manualListeners.forEach((listener, event) => element.addEventListener(event, listener)); _focusMonitor .monitor(_elementRef) .pipe(takeUntil(this._destroyed)) .subscribe((origin) => { // Note that the focus monitor runs outside the Angular zone. if (!origin) { _ngZone.run(() => this.hide()); } else if (origin === "keyboard") { _ngZone.run(() => this.show()); } }); } /** * Dispose the tooltip when destroyed. */ ngOnDestroy() { if (this._tooltipInstance) { this._tooltipInstance = undefined; } // Clean up the event listeners set in the constructor this._manualListeners.forEach((listener, event) => { this._elementRef.nativeElement.removeEventListener(event, listener); }); this._manualListeners.clear(); this._destroyed.next(); this._destroyed.complete(); this._ariaDescriber.removeDescription(this._elementRef.nativeElement, this.message); this._focusMonitor.stopMonitoring(this._elementRef); } /** Shows the tooltip if not disabled or empty */ show() { if (!this.canShowTooltip()) { return; } if (!this._tooltipInstance) { this.createTooltipComponent(); this._updateTooltipMessage(); // wait till overlay view init setTimeout(() => { // added this check here, because of the manual-trigger-example in docs. // "Disabled" attribute is set after 1st "show" is triggered and it should hide the tooltip. // That's why inside setTimeout operation there's one more check if it's disabled. if (!this.canShowTooltip()) { return; } this._tooltipInstance?.show(); }); } else { this._tooltipInstance?.show(); } } /** * Checks if the content is overflowing. * The content is considered overflowing if its scroll width is greater than its client width plus 1. */ isOverflowing() { return (this._elementRef.nativeElement.scrollWidth > this._elementRef.nativeElement.clientWidth + 1); } /** Hides the tooltip */ hide() { // without setTimeout, sometimes 'hide' is called before 'show', because show has setTimeout for it's own reasons. setTimeout(() => this._tooltipInstance?.hide()); } /** Shows/hides the tooltip */ toggle() { this._isTooltipVisible() ? this.hide() : this.show(); } /** Returns true if the tooltip is currently visible to the user */ _isTooltipVisible() { return !!this._tooltipInstance && this._tooltipInstance.isVisible(); } /** Handles the keydown events on the host element. */ _handleKeydown(e) { if (this._isTooltipVisible() && e.code === KEYBOARD_CODE.ESCAPE && !hasModifierKey(e)) { e.preventDefault(); e.stopPropagation(); this.hide(); } } /** Handles the touchend events on the host element. */ _handleTouchend() { this.hide(); } createTooltipComponent() { const tooltipComponentRef = this._viewContainerRef.createComponent(TooltipComponent); this._tooltipInstance = tooltipComponentRef.instance; this._tooltipInstance.toggleReference = this._elementRef; this._tooltipInstance.possiblePositions = this.overlayPositionService.getPossiblePositionsForPlacement(this.position); } updateOverlayPositions() { if (!this._tooltipInstance) { return; } const possiblePositions = this.overlayPositionService.getPossiblePositionsForPlacement(this.position); this._tooltipInstance.updatePossiblePositions(possiblePositions); } /** Updates the tooltip message and repositions the overlay according to the new message length */ _updateTooltipMessage() { if (this._tooltipInstance) { this._tooltipInstance.message = this.message; } } canShowTooltip() { const canShow = !(this.disabled || !this.message || this._isTooltipVisible()); if (this.ellipsis) { return canShow && this.isOverflowing(); } return canShow; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.NgZone }, { token: i1.AriaDescriber }, { token: i1.FocusMonitor }, { token: i2.OverlayPositionService }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TooltipDirective, selector: "[nuiTooltip]", inputs: { position: ["tooltipPlacement", "position"], disabled: ["nuiTooltipDisabled", "disabled"], ellipsis: ["nuiTooltipEllipsis", "ellipsis"], message: ["nuiTooltip", "message"] }, host: { listeners: { "longpress": "show()", "keydown": "_handleKeydown($event)", "touchend": "_handleTouchend()" } }, providers: [OverlayPositionService], exportAs: ["nuiTooltip"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TooltipDirective, decorators: [{ type: Directive, args: [{ selector: "[nuiTooltip]", exportAs: "nuiTooltip", host: { "(longpress)": "show()", "(keydown)": "_handleKeydown($event)", "(touchend)": "_handleTouchend()", }, providers: [OverlayPositionService], }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.NgZone }, { type: i1.AriaDescriber }, { type: i1.FocusMonitor }, { type: i2.OverlayPositionService }], propDecorators: { position: [{ type: Input, args: ["tooltipPlacement"] }], disabled: [{ type: Input, args: ["nuiTooltipDisabled"] }], ellipsis: [{ type: Input, args: ["nuiTooltipEllipsis"] }], message: [{ type: Input, args: ["nuiTooltip"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2x0aXAvdG9vbHRpcC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDaEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZELE9BQU8sRUFDSCxTQUFTLEVBQ1QsVUFBVSxFQUNWLEtBQUssRUFDTCxNQUFNLEVBRU4sZ0JBQWdCLEdBQ25CLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRzNDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7OztBQUc3RTs7OztHQUlHO0FBWUgsTUFBTSxPQUFPLGdCQUFnQjtJQU96QiwyRkFBMkY7SUFDM0YsSUFDSSxRQUFRO1FBQ1IsT0FB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a0JBQWtCO2dCQWFyQixRQUFRO3NCQURYLEtBQUs7dUJBQUMsb0JBQW9CO2dCQWV2QixRQUFRO3NCQURYLEtBQUs7dUJBQUMsb0JBQW9CO2dCQVl2QixPQUFPO3NCQURWLEtBQUs7dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbIi8vIMKpIDIwMjIgU29sYXJXaW5kcyBXb3JsZHdpZGUsIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyAgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbi8vICBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyAgVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgeyBBcmlhRGVzY3JpYmVyLCBGb2N1c01vbml0b3IgfSBmcm9tIFwiQGFuZ3VsYXIvY2RrL2ExMXlcIjtcbmltcG9ydCB7IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gXCJAYW5ndWxhci9jZGsvY29lcmNpb25cIjtcbmltcG9ydCB7IGhhc01vZGlmaWVyS2V5IH0gZnJvbSBcIkBhbmd1bGFyL2Nkay9rZXljb2Rlc1wiO1xuaW1wb3J0IHtcbiAgICBEaXJlY3RpdmUsXG4gICAgRWxlbWVudFJlZixcbiAgICBJbnB1dCxcbiAgICBOZ1pvbmUsXG4gICAgT25EZXN0cm95LFxuICAgIFZpZXdDb250YWluZXJSZWYsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xuXG5pbXBvcnQgeyBUb29sdGlwUG9zaXRpb24gfSBmcm9tIFwiLi9wdWJsaWMtYXBpXCI7XG5pbXBvcnQgeyBUb29sdGlwQ29tcG9uZW50IH0gZnJvbSBcIi4vdG9vbHRpcC5jb21wb25lbnRcIjtcbmltcG9ydCB7IEtFWUJPQVJEX0NPREUgfSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzL2tleWNvZGUuY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPdmVybGF5UG9zaXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4uL292ZXJsYXkvb3ZlcmxheS1wb3NpdGlvbi5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBPdmVybGF5UGxhY2VtZW50IH0gZnJvbSBcIi4uL292ZXJsYXkvdHlwZXNcIjtcblxuLyoqXG4gKiA8ZXhhbXBsZS11cmw+Li8uLi9leGFtcGxlcy9pbmRleC5odG1sIy90b29sdGlwPC9leGFtcGxlLXVybD5cbiAqXG4gKiBAZHluYW1pY1xuICovXG5cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiBcIltudWlUb29sdGlwXVwiLFxuICAgIGV4cG9ydEFzOiBcIm51aVRvb2x0aXBcIixcbiAgICBob3N0OiB7XG4gICAgICAgIFwiKGxvbmdwcmVzcylcIjogXCJzaG93KClcIixcbiAgICAgICAgXCIoa2V5ZG93bilcIjogXCJfaGFuZGxlS2V5ZG93bigkZXZlbnQpXCIsXG4gICAgICAgIFwiKHRvdWNoZW5kKVwiOiBcIl9oYW5kbGVUb3VjaGVuZCgpXCIsXG4gICAgfSxcbiAgICBwcm92aWRlcnM6IFtPdmVybGF5UG9zaXRpb25TZXJ2aWNlXSxcbn0pXG5leHBvcnQgY2xhc3MgVG9vbHRpcERpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gICAgX3Rvb2x0aXBJbnN0YW5jZT86IFRvb2x0aXBDb21wb25lbnQ7XG5cbiAgICBwcml2YXRlIF9wb3NpdGlvbjogVG9vbHRpcFBvc2l0aW9uID0gXCJ0b3BcIjtcbiAgICBwcml2YXRlIF9kaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2VsbGlwc2lzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogQWxsb3dzIHRoZSB1c2VyIHRvIGRlZmluZSB0aGUgcG9zaXRpb24gb2YgdGhlIHRvb2x0aXAgcmVsYXRpdmUgdG8gdGhlIHBhcmVudCBlbGVtZW50ICovXG4gICAgQElucHV0KFwidG9vbHRpcFBsYWNlbWVudFwiKVxuICAgIGdldCBwb3NpdGlvbigpOiBUb29sdGlwUG9zaXRpb24ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcG9zaXRpb247XG4gICAgfVxuICAgIHNldCBwb3NpdGlvbih2YWx1ZTogVG9vbHRpcFBvc2l0aW9uKSB7XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdGhpcy5fcG9zaXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuX3Bvc2l0aW9uID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU92ZXJsYXlQb3NpdGlvbnMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBEaXNhYmxlcyB0aGUgZGlzcGxheSBvZiB0aGUgdG9vbHRpcC4gKi9cbiAgICBASW5wdXQoXCJudWlUb29sdGlwRGlzYWJsZWRcIilcbiAgICBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kaXNhYmxlZDtcbiAgICB9XG4gICAgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX2Rpc2FibGVkID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcblxuICAgICAgICAvLyBJZiB0b29sdGlwIGlzIGRpc2FibGVkLCBoaWRlIGltbWVkaWF0ZWx5LlxuICAgICAgICBpZiAodGhpcy5fZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIERldGVybWluZXMgd2hldGhlciB0aGUgdG9vbHRpcCBzaG91bGQgYmUgZGlzcGxheWVkIHdoZW4gdGhlIGNvbnRlbnQgaXMgb3ZlcmZsb3dpbmcuIEJ5IGRlZmF1bHQgaXMgYGZhbHNlYC4gKi9cbiAgICBASW5wdXQoXCJudWlUb29sdGlwRWxsaXBzaXNcIilcbiAgICBnZXQgZWxsaXBzaXMoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbGxpcHNpcztcbiAgICB9XG4gICAgc2V0IGVsbGlwc2lzKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX2VsbGlwc2lzID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9tZXNzYWdlID0gXCJcIjtcblxuICAgIC8qKiBUaGUgbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRvb2x0aXAgKi9cbiAgICBASW5wdXQoXCJudWlUb29sdGlwXCIpXG4gICAgZ2V0IG1lc3NhZ2UoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21lc3NhZ2U7XG4gICAgfVxuICAgIHNldCBtZXNzYWdlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fYXJpYURlc2NyaWJlci5yZW1vdmVEZXNjcmlwdGlvbihcbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2VcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBJZiB0aGUgbWVzc2FnZSBpcyBub3QgYSBzdHJpbmcgKGUuZy4gbnVtYmVyKSwgY29udmVydCBpdCB0byBhIHN0cmluZyBhbmQgdHJpbSBpdC5cbiAgICAgICAgdGhpcy5fbWVzc2FnZSA9IHZhbHVlICE9IG51bGwgPyBgJHt2YWx1ZX1gLnRyaW0oKSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9tZXNzYWdlICYmIHRoaXMuX2lzVG9vbHRpcFZpc2libGUoKSkge1xuICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVUb29sdGlwTWVzc2FnZSgpO1xuICAgICAgICAgICAgdGhpcy5fYXJpYURlc2NyaWJlci5kZXNjcmliZShcbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfbWFudWFsTGlzdGVuZXJzID0gbmV3IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBFdmVudExpc3RlbmVyT3JFdmVudExpc3RlbmVyT2JqZWN0XG4gICAgPigpO1xuXG4gICAgLyoqIEVtaXRzIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBkZXN0cm95ZWQuICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZGVzdHJveWVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIF9lbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICAgICAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcbiAgICAgICAgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsXG4gICAgICAgIHByaXZhdGUgX2FyaWFEZXNjcmliZXI6IEFyaWFEZXNjcmliZXIsXG4gICAgICAgIHByaXZhdGUgX2ZvY3VzTW9uaXRvcjogRm9jdXNNb25pdG9yLFxuICAgICAgICBwcml2YXRlIG92ZXJsYXlQb3NpdGlvblNlcnZpY2U6IE92ZXJsYXlQb3NpdGlvblNlcnZpY2VcbiAgICApIHtcbiAgICAgICAgdGhpcy5vdmVybGF5UG9zaXRpb25TZXJ2aWNlLnNldE92ZXJsYXlQb3NpdGlvbkNvbmZpZyh7XG4gICAgICAgICAgICBhcnJvd1NpemU6IDEwLFxuICAgICAgICAgICAgYXJyb3dQYWRkaW5nOiAwLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgZWxlbWVudDogSFRNTEVsZW1lbnQgPSBfZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuXG4gICAgICAgIHRoaXMuX21hbnVhbExpc3RlbmVyc1xuICAgICAgICAgICAgLnNldChcIm1vdXNlZW50ZXJcIiwgKCkgPT4gdGhpcy5zaG93KCkpXG4gICAgICAgICAgICAuc2V0KFwibW91c2VsZWF2ZVwiLCAoKSA9PiB0aGlzLmhpZGUoKSk7XG5cbiAgICAgICAgdGhpcy5fbWFudWFsTGlzdGVuZXJzLmZvckVhY2goKGxpc3RlbmVyLCBldmVudCkgPT5cbiAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIpXG4gICAgICAgICk7XG5cbiAgICAgICAgX2ZvY3VzTW9uaXRvclxuICAgICAgICAgICAgLm1vbml0b3IoX2VsZW1lbnRSZWYpXG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKG9yaWdpbikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB0aGUgZm9jdXMgbW9uaXRvciBydW5zIG91dHNpZGUgdGhlIEFuZ3VsYXIgem9uZS5cbiAgICAgICAgICAgICAgICBpZiAoIW9yaWdpbikge1xuICAgICAgICAgICAgICAgICAgICBfbmdab25lLnJ1bigoKSA9PiB0aGlzLmhpZGUoKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcmlnaW4gPT09IFwia2V5Ym9hcmRcIikge1xuICAgICAgICAgICAgICAgICAgICBfbmdab25lLnJ1bigoKSA9PiB0aGlzLnNob3coKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGlzcG9zZSB0aGUgdG9vbHRpcCB3aGVuIGRlc3Ryb3llZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl90b29sdGlwSW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuX3Rvb2x0aXBJbnN0YW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENsZWFuIHVwIHRoZSBldmVudCBsaXN0ZW5lcnMgc2V0IGluIHRoZSBjb25zdHJ1Y3RvclxuICAgICAgICB0aGlzLl9tYW51YWxMaXN0ZW5lcnMuZm9yRWFjaCgobGlzdGVuZXIsIGV2ZW50KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fbWFudWFsTGlzdGVuZXJzLmNsZWFyKCk7XG5cbiAgICAgICAgdGhpcy5fZGVzdHJveWVkLm5leHQoKTtcbiAgICAgICAgdGhpcy5fZGVzdHJveWVkLmNvbXBsZXRlKCk7XG5cbiAgICAgICAgdGhpcy5fYXJpYURlc2NyaWJlci5yZW1vdmVEZXNjcmlwdGlvbihcbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICB0aGlzLl9mb2N1c01vbml0b3Iuc3RvcE1vbml0b3JpbmcodGhpcy5fZWxlbWVudFJlZik7XG4gICAgfVxuXG4gICAgLyoqIFNob3dzIHRoZSB0b29sdGlwIGlmIG5vdCBkaXNhYmxlZCBvciBlbXB0eSAqL1xuICAgIHNob3coKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5jYW5TaG93VG9vbHRpcCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuX3Rvb2x0aXBJbnN0YW5jZSkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVUb29sdGlwQ29tcG9uZW50KCk7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVUb29sdGlwTWVzc2FnZSgpO1xuXG4gICAgICAgICAgICAvLyB3YWl0IHRpbGwgb3ZlcmxheSB2aWV3IGluaXRcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGFkZGVkIHRoaXMgY2hlY2sgaGVyZSwgYmVjYXVzZSBvZiB0aGUgbWFudWFsLXRyaWdnZXItZXhhbXBsZSBpbiBkb2NzLlxuICAgICAgICAgICAgICAgIC8vIFwiRGlzYWJsZWRcIiBhdHRyaWJ1dGUgaXMgc2V0IGFmdGVyIDFzdCBcInNob3dcIiBpcyB0cmlnZ2VyZWQgYW5kIGl0IHNob3VsZCBoaWRlIHRoZSB0b29sdGlwLlxuICAgICAgICAgICAgICAgIC8vIFRoYXQncyB3aHkgaW5zaWRlIHNldFRpbWVvdXQgb3BlcmF0aW9uIHRoZXJlJ3Mgb25lIG1vcmUgY2hlY2sgaWYgaXQncyBkaXNhYmxlZC5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FuU2hvd1Rvb2x0aXAoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX3Rvb2x0aXBJbnN0YW5jZT8uc2hvdygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl90b29sdGlwSW5zdGFuY2U/LnNob3coKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0aGUgY29udGVudCBpcyBvdmVyZmxvd2luZy5cbiAgICAgKiBUaGUgY29udGVudCBpcyBjb25zaWRlcmVkIG92ZXJmbG93aW5nIGlmIGl0cyBzY3JvbGwgd2lkdGggaXMgZ3JlYXRlciB0aGFuIGl0cyBjbGllbnQgd2lkdGggcGx1cyAxLlxuICAgICAqL1xuICAgIGlzT3ZlcmZsb3dpbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsV2lkdGggPlxuICAgICAgICAgICAgdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoICsgMVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKiBIaWRlcyB0aGUgdG9vbHRpcCAqL1xuICAgIGhpZGUoKTogdm9pZCB7XG4gICAgICAgIC8vIHdpdGhvdXQgc2V0VGltZW91dCwgc29tZXRpbWVzICdoaWRlJyBpcyBjYWxsZWQgYmVmb3JlICdzaG93JywgYmVjYXVzZSBzaG93IGhhcyBzZXRUaW1lb3V0IGZvciBpdCdzIG93biByZWFzb25zLlxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuX3Rvb2x0aXBJbnN0YW5jZT8uaGlkZSgpKTtcbiAgICB9XG5cbiAgICAvKiogU2hvd3MvaGlkZXMgdGhlIHRvb2x0aXAgKi9cbiAgICB0b2dnbGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2lzVG9vbHRpcFZpc2libGUoKSA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KCk7XG4gICAgfVxuXG4gICAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgdG9vbHRpcCBpcyBjdXJyZW50bHkgdmlzaWJsZSB0byB0aGUgdXNlciAqL1xuICAgIF9pc1Rvb2x0aXBWaXNpYmxlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gISF0aGlzLl90b29sdGlwSW5zdGFuY2UgJiYgdGhpcy5fdG9vbHRpcEluc3RhbmNlLmlzVmlzaWJsZSgpO1xuICAgIH1cblxuICAgIC8qKiBIYW5kbGVzIHRoZSBrZXlkb3duIGV2ZW50cyBvbiB0aGUgaG9zdCBlbGVtZW50LiAqL1xuICAgIF9oYW5kbGVLZXlkb3duKGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5faXNUb29sdGlwVmlzaWJsZSgpICYmXG4gICAgICAgICAgICBlLmNvZGUgPT09IEtFWUJPQVJEX0NPREUuRVNDQVBFICYmXG4gICAgICAgICAgICAhaGFzTW9kaWZpZXJLZXkoZSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogSGFuZGxlcyB0aGUgdG91Y2hlbmQgZXZlbnRzIG9uIHRoZSBob3N0IGVsZW1lbnQuICovXG4gICAgX2hhbmRsZVRvdWNoZW5kKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVRvb2x0aXBDb21wb25lbnQoKSB7XG4gICAgICAgIGNvbnN0IHRvb2x0aXBDb21wb25lbnRSZWYgPVxuICAgICAgICAgICAgdGhpcy5fdmlld0NvbnRhaW5lclJlZi5jcmVhdGVDb21wb25lbnQoVG9vbHRpcENvbXBvbmVudCk7XG4gICAgICAgIHRoaXMuX3Rvb2x0aXBJbnN0YW5jZSA9IHRvb2x0aXBDb21wb25lbnRSZWYuaW5zdGFuY2U7XG4gICAgICAgIHRoaXMuX3Rvb2x0aXBJbnN0YW5jZS50b2dnbGVSZWZlcmVuY2UgPSB0aGlzLl9lbGVtZW50UmVmO1xuICAgICAgICB0aGlzLl90b29sdGlwSW5zdGFuY2UucG9zc2libGVQb3NpdGlvbnMgPVxuICAgICAgICAgICAgdGhpcy5vdmVybGF5UG9zaXRpb25TZXJ2aWNlLmdldFBvc3NpYmxlUG9zaXRpb25zRm9yUGxhY2VtZW50KFxuICAgICAgICAgICAgICAgIHRoaXMucG9zaXRpb24gYXMgT3ZlcmxheVBsYWNlbWVudFxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZU92ZXJsYXlQb3NpdGlvbnMoKSB7XG4gICAgICAgIGlmICghdGhpcy5fdG9vbHRpcEluc3RhbmNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwb3NzaWJsZVBvc2l0aW9ucyA9XG4gICAgICAgICAgICB0aGlzLm92ZXJsYXlQb3NpdGlvblNlcnZpY2UuZ2V0UG9zc2libGVQb3NpdGlvbnNGb3JQbGFjZW1lbnQoXG4gICAgICAgICAgICAgICAgdGhpcy5wb3NpdGlvbiBhcyBPdmVybGF5UGxhY2VtZW50XG4gICAgICAgICAgICApO1xuICAgICAgICB0aGlzLl90b29sdGlwSW5zdGFuY2UudXBkYXRlUG9zc2libGVQb3NpdGlvbnMocG9zc2libGVQb3NpdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKiBVcGRhdGVzIHRoZSB0b29sdGlwIG1lc3NhZ2UgYW5kIHJlcG9zaXRpb25zIHRoZSBvdmVybGF5IGFjY29yZGluZyB0byB0aGUgbmV3IG1lc3NhZ2UgbGVuZ3RoICovXG4gICAgcHJpdmF0ZSBfdXBkYXRlVG9vbHRpcE1lc3NhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLl90b29sdGlwSW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuX3Rvb2x0aXBJbnN0YW5jZS5tZXNzYWdlID0gdGhpcy5tZXNzYWdlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjYW5TaG93VG9vbHRpcCgpIHtcbiAgICAgICAgY29uc3QgY2FuU2hvdyA9ICEoXG4gICAgICAgICAgICB0aGlzLmRpc2FibGVkIHx8XG4gICAgICAgICAgICAhdGhpcy5tZXNzYWdlIHx8XG4gICAgICAgICAgICB0aGlzLl9pc1Rvb2x0aXBWaXNpYmxlKClcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAodGhpcy5lbGxpcHNpcykge1xuICAgICAgICAgICAgcmV0dXJuIGNhblNob3cgJiYgdGhpcy5pc092ZXJmbG93aW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2FuU2hvdztcbiAgICB9XG59XG4iXX0=