@nova-ui/bits
Version:
SolarWinds Nova Framework
190 lines • 27.9 kB
JavaScript
// © 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 { DOCUMENT } from "@angular/common";
import { Inject, Injectable } from "@angular/core";
import _isNil from "lodash/isNil";
import * as i0 from "@angular/core";
/**
* @dynamic
* @ignore
*/
export class PositionService {
constructor(document) {
this.document = document;
}
/**
* __Description:__
* Takes two HTMLElements (hostElement and targetElement) and calculates a position for the targetElement.
* @param hostElement If you want to display tooltip for some textbox, hostElement is textbox.
* @param targetElement Tooltip (or popover) element, for which position will be returned.
* @param placementAndAlign String in format "placement-align", e.g. "top-center".
* 'Placement' could be 'right', 'left', 'top' (default), 'bottom'. It defines how target will be placed
* to the host.
* 'Align' could be 'right', 'left', 'top', 'bottom' and 'center' (default). It defines whether one of the target's
* edges will be aligned to host's one. Be aware that horizontal placements need vertical alignment and vice verca.
* Possible values of 'placementAndAlign' could be: 'top' (the same as 'top-center'), 'top-right', 'left-bottom',
* 'bottom-left' etc.
* @param appendToBody Specifies whether target element is appended to the body.
* When not, service seeks for the first positioned parent of host.
* @returns Object literal { top:number, left:number } that contains
* coordinates for the top left corner of targetElement.
*/
getPosition(hostElement, targetElement, placementAndAlign, appendToBody) {
const placement = placementAndAlign.split("-")[0];
const align = placementAndAlign.split("-")[1];
let shiftByX;
let shiftByY;
const hostElementPosition = appendToBody
? this.offset(hostElement)
: this.position(hostElement);
switch (align) {
case "right":
shiftByX =
hostElementPosition.width - targetElement.offsetWidth;
shiftByY =
(hostElementPosition.height - targetElement.offsetHeight) /
2;
break;
case "left":
shiftByX = 0;
shiftByY =
(hostElementPosition.height - targetElement.offsetHeight) /
2;
break;
case "top":
shiftByX =
(hostElementPosition.width - targetElement.offsetWidth) / 2;
shiftByY = 0;
break;
case "bottom":
shiftByX =
(hostElementPosition.width - targetElement.offsetWidth) / 2;
shiftByY =
hostElementPosition.height - targetElement.offsetHeight;
break;
case "center":
default:
shiftByX =
(hostElementPosition.width - targetElement.offsetWidth) / 2;
shiftByY =
(hostElementPosition.height - targetElement.offsetHeight) /
2;
break;
}
let targetElementPosition;
switch (placement) {
case "right":
targetElementPosition = {
top: hostElementPosition.top + shiftByY,
left: hostElementPosition.left + hostElementPosition.width,
};
break;
case "left":
targetElementPosition = {
top: hostElementPosition.top + shiftByY,
left: hostElementPosition.left - targetElement.offsetWidth,
};
break;
case "bottom":
targetElementPosition = {
top: hostElementPosition.top + hostElementPosition.height,
left: hostElementPosition.left + shiftByX,
};
break;
case "top":
default:
targetElementPosition = {
top: hostElementPosition.top - targetElement.offsetHeight,
left: hostElementPosition.left + shiftByX,
};
break;
}
return targetElementPosition;
}
position(nativeElement) {
let offsetParentBoundingClientRect = { top: 0, left: 0 };
const elementBoundingClientRect = this.offset(nativeElement);
const offsetParentElement = this.parentOffsetEl(nativeElement);
if (offsetParentElement !== this.document) {
offsetParentBoundingClientRect = this.offset(offsetParentElement);
offsetParentBoundingClientRect.top +=
offsetParentElement.clientTop - offsetParentElement.scrollTop;
offsetParentBoundingClientRect.left +=
offsetParentElement.clientLeft - offsetParentElement.scrollLeft;
}
const boundingClientRect = nativeElement.getBoundingClientRect();
return {
width: boundingClientRect.width || nativeElement.offsetWidth,
height: boundingClientRect.height || nativeElement.offsetHeight,
top: elementBoundingClientRect.top -
offsetParentBoundingClientRect.top,
left: elementBoundingClientRect.left -
offsetParentBoundingClientRect.left,
};
}
offset(nativeElement) {
const boundingClientRect = nativeElement.getBoundingClientRect();
if (_isNil(this.document.defaultView)) {
throw new Error("Document defaultView is not available");
}
return {
width: boundingClientRect.width || nativeElement.offsetWidth,
height: boundingClientRect.height || nativeElement.offsetHeight,
top: boundingClientRect.top +
(this.document.defaultView.pageYOffset ||
this.document.documentElement.scrollTop),
left: boundingClientRect.left +
(this.document.defaultView.pageXOffset ||
this.document.documentElement.scrollLeft),
};
}
getStyle(nativeElement, cssProp) {
if (_isNil(this.document.defaultView)) {
throw new Error("Document defaultView is not available");
}
if (this.document.defaultView.getComputedStyle) {
return this.document.defaultView.getComputedStyle(nativeElement)[cssProp];
}
// finally try and get inline style
return nativeElement.style[cssProp];
}
isStaticPositioned(nativeElement) {
return ((this.getStyle(nativeElement, "position") || "static") === "static");
}
parentOffsetEl(nativeElement) {
let offsetParent = nativeElement.offsetParent || this.document;
while (offsetParent &&
offsetParent !== this.document &&
this.isStaticPositioned(offsetParent)) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || this.document;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PositionService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PositionService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PositionService, decorators: [{
type: Injectable,
args: [{ providedIn: "root" }]
}], ctorParameters: () => [{ type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zaXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9wb3NpdGlvbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxNQUFNLE1BQU0sY0FBYyxDQUFDOztBQVNsQzs7O0dBR0c7QUFFSCxNQUFNLE9BQU8sZUFBZTtJQUN4QixZQUFzQyxRQUFrQjtRQUFsQixhQUFRLEdBQVIsUUFBUSxDQUFVO0lBQUcsQ0FBQztJQUM1RDs7Ozs7Ozs7Ozs7Ozs7OztPQWdCRztJQUNJLFdBQVcsQ0FDZCxXQUF3QixFQUN4QixhQUEwQixFQUMxQixpQkFBeUIsRUFDekIsWUFBc0I7UUFFdEIsTUFBTSxTQUFTLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sS0FBSyxHQUFHLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxJQUFJLFFBQWdCLENBQUM7UUFDckIsSUFBSSxRQUFnQixDQUFDO1FBQ3JCLE1BQU0sbUJBQW1CLEdBQUcsWUFBWTtZQUNwQyxDQUFD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RSxZQUFZLEdBQUcsWUFBWSxDQUFDLFlBQVksQ0FBQztTQUM1QztRQUVELE9BQU8sWUFBWSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDekMsQ0FBQzsrR0E3TFEsZUFBZSxrQkFDSixRQUFRO21IQURuQixlQUFlLGNBREYsTUFBTTs7NEZBQ25CLGVBQWU7a0JBRDNCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFFakIsTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCBfaXNOaWwgZnJvbSBcImxvZGFzaC9pc05pbFwiO1xuXG4vKipcbiAqIFNlcnZpY2UgZm9yIGNhbGN1bGF0aW5nIGVsZW1lbnQncyBwb3NpdGlvbiAoZS5nLiB0b29sdGlwLCBwb3BvdmVyKS5cbiAqIEZvciBub3cgaGFzIG9uZSBwdWJsaWMgbWV0aG9kICdnZXRDb29yZGluYXRlcycgKHNlZSBtZXRob2QgZGVzY3JpcHRpb24pLlxuICovXG5cbnR5cGUgT3VyQ1NTID0gQ1NTU3R5bGVEZWNsYXJhdGlvbiAmIHsgW2tleTogc3RyaW5nXTogYW55IH07XG5cbi8qKlxuICogQGR5bmFtaWNcbiAqIEBpZ25vcmVcbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiBcInJvb3RcIiB9KVxuZXhwb3J0IGNsYXNzIFBvc2l0aW9uU2VydmljZSB7XG4gICAgY29uc3RydWN0b3IoQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQpIHt9XG4gICAgLyoqXG4gICAgICogX19EZXNjcmlwdGlvbjpfX1xuICAgICAqIFRha2VzIHR3byBIVE1MRWxlbWVudHMgKGhvc3RFbGVtZW50IGFuZCB0YXJnZXRFbGVtZW50KSBhbmQgY2FsY3VsYXRlcyBhIHBvc2l0aW9uIGZvciB0aGUgdGFyZ2V0RWxlbWVudC5cbiAgICAgKiBAcGFyYW0gIGhvc3RFbGVtZW50IElmIHlvdSB3YW50IHRvIGRpc3BsYXkgdG9vbHRpcCBmb3Igc29tZSB0ZXh0Ym94LCBob3N0RWxlbWVudCBpcyB0ZXh0Ym94LlxuICAgICAqIEBwYXJhbSAgIHRhcmdldEVsZW1lbnQgVG9vbHRpcCAob3IgcG9wb3ZlcikgZWxlbWVudCwgZm9yIHdoaWNoIHBvc2l0aW9uIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAgICogQHBhcmFtICAgcGxhY2VtZW50QW5kQWxpZ24gU3RyaW5nIGluIGZvcm1hdCBcInBsYWNlbWVudC1hbGlnblwiLCBlLmcuIFwidG9wLWNlbnRlclwiLlxuICAgICAqICdQbGFjZW1lbnQnIGNvdWxkIGJlICdyaWdodCcsICdsZWZ0JywgJ3RvcCcgKGRlZmF1bHQpLCAnYm90dG9tJy4gSXQgZGVmaW5lcyBob3cgdGFyZ2V0IHdpbGwgYmUgcGxhY2VkXG4gICAgICogdG8gdGhlIGhvc3QuXG4gICAgICogJ0FsaWduJyBjb3VsZCBiZSAncmlnaHQnLCAnbGVmdCcsICd0b3AnLCAnYm90dG9tJyBhbmQgJ2NlbnRlcicgKGRlZmF1bHQpLiBJdCBkZWZpbmVzIHdoZXRoZXIgb25lIG9mIHRoZSB0YXJnZXQnc1xuICAgICAqIGVkZ2VzIHdpbGwgYmUgYWxpZ25lZCB0byBob3N0J3Mgb25lLiBCZSBhd2FyZSB0aGF0IGhvcml6b250YWwgcGxhY2VtZW50cyBuZWVkIHZlcnRpY2FsIGFsaWdubWVudCBhbmQgdmljZSB2ZXJjYS5cbiAgICAgKiBQb3NzaWJsZSB2YWx1ZXMgb2YgJ3BsYWNlbWVudEFuZEFsaWduJyBjb3VsZCBiZTogJ3RvcCcgKHRoZSBzYW1lIGFzICd0b3AtY2VudGVyJyksICd0b3AtcmlnaHQnLCAnbGVmdC1ib3R0b20nLFxuICAgICAqICdib3R0b20tbGVmdCcgZXRjLlxuICAgICAqIEBwYXJhbSAgIGFwcGVuZFRvQm9keSBTcGVjaWZpZXMgd2hldGhlciB0YXJnZXQgZWxlbWVudCBpcyBhcHBlbmRlZCB0byB0aGUgYm9keS5cbiAgICAgKiBXaGVuIG5vdCwgc2VydmljZSBzZWVrcyBmb3IgdGhlIGZpcnN0IHBvc2l0aW9uZWQgcGFyZW50IG9mIGhvc3QuXG4gICAgICogQHJldHVybnMgT2JqZWN0IGxpdGVyYWwgeyB0b3A6bnVtYmVyLCBsZWZ0Om51bWJlciB9IHRoYXQgY29udGFpbnNcbiAgICAgKiBjb29yZGluYXRlcyBmb3IgdGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0YXJnZXRFbGVtZW50LlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRQb3NpdGlvbihcbiAgICAgICAgaG9zdEVsZW1lbnQ6IEhUTUxFbGVtZW50LFxuICAgICAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICAgICAgcGxhY2VtZW50QW5kQWxpZ246IHN0cmluZyxcbiAgICAgICAgYXBwZW5kVG9Cb2R5PzogYm9vbGVhblxuICAgICk6IHsgdG9wOiBudW1iZXI7IGxlZnQ6IG51bWJlciB9IHtcbiAgICAgICAgY29uc3QgcGxhY2VtZW50ID0gcGxhY2VtZW50QW5kQWxpZ24uc3BsaXQoXCItXCIpWzBdO1xuICAgICAgICBjb25zdCBhbGlnbiA9IHBsYWNlbWVudEFuZEFsaWduLnNwbGl0KFwiLVwiKVsxXTtcbiAgICAgICAgbGV0IHNoaWZ0QnlYOiBudW1iZXI7XG4gICAgICAgIGxldCBzaGlmdEJ5WTogbnVtYmVyO1xuICAgICAgICBjb25zdCBob3N0RWxlbWVudFBvc2l0aW9uID0gYXBwZW5kVG9Cb2R5XG4gICAgICAgICAgICA/IHRoaXMub2Zmc2V0KGhvc3RFbGVtZW50KVxuICAgICAgICAgICAgOiB0aGlzLnBvc2l0aW9uKGhvc3RFbGVtZW50KTtcbiAgICAgICAgc3dpdGNoIChhbGlnbikge1xuICAgICAgICAgICAgY2FzZSBcInJpZ2h0XCI6XG4gICAgICAgICAgICAgICAgc2hpZnRCeVggPVxuICAgICAgICAgICAgICAgICAgICBob3N0RWxlbWVudFBvc2l0aW9uLndpZHRoIC0gdGFyZ2V0RWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgICAgICBzaGlmdEJ5WSA9XG4gICAgICAgICAgICAgICAgICAgIChob3N0RWxlbWVudFBvc2l0aW9uLmhlaWdodCAtIHRhcmdldEVsZW1lbnQub2Zmc2V0SGVpZ2h0KSAvXG4gICAgICAgICAgICAgICAgICAgIDI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwibGVmdFwiOlxuICAgICAgICAgICAgICAgIHNoaWZ0QnlYID0gMDtcbiAgICAgICAgICAgICAgICBzaGlmdEJ5WSA9XG4gICAgICAgICAgICAgICAgICAgIChob3N0RWxlbWVudFBvc2l0aW9uLmhlaWdodCAtIHRhcmdldEVsZW1lbnQub2Zmc2V0SGVpZ2h0KSAvXG4gICAgICAgICAgICAgICAgICAgIDI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwidG9wXCI6XG4gICAgICAgICAgICAgICAgc2hpZnRCeVggPVxuICAgICAgICAgICAgICAgICAgICAoaG9zdEVsZW1lbnRQb3NpdGlvbi53aWR0aCAtIHRhcmdldEVsZW1lbnQub2Zmc2V0V2lkdGgpIC8gMjtcbiAgICAgICAgICAgICAgICBzaGlmdEJ5WSA9IDA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiYm90dG9tXCI6XG4gICAgICAgICAgICAgICAgc2hpZnRCeVggPVxuICAgICAgICAgICAgICAgICAgICAoaG9zdEVsZW1lbnRQb3NpdGlvbi53aWR0aCAtIHRhcmdldEVsZW1lbnQub2Zmc2V0V2lkdGgpIC8gMjtcbiAgICAgICAgICAgICAgICBzaGlmdEJ5WSA9XG4gICAgICAgICAgICAgICAgICAgIGhvc3RFbGVtZW50UG9zaXRpb24uaGVpZ2h0IC0gdGFyZ2V0RWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiY2VudGVyXCI6XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHNoaWZ0QnlYID1cbiAgICAgICAgICAgICAgICAgICAgKGhvc3RFbGVtZW50UG9zaXRpb24ud2lkdGggLSB0YXJnZXRFbGVtZW50Lm9mZnNldFdpZHRoKSAvIDI7XG4gICAgICAgICAgICAgICAgc2hpZnRCeVkgPVxuICAgICAgICAgICAgICAgICAgICAoaG9zdEVsZW1lbnRQb3NpdGlvbi5oZWlnaHQgLSB0YXJnZXRFbGVtZW50Lm9mZnNldEhlaWdodCkgL1xuICAgICAgICAgICAgICAgICAgICAyO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGxldCB0YXJnZXRFbGVtZW50UG9zaXRpb246IHsgdG9wOiBudW1iZXI7IGxlZnQ6IG51bWJlciB9O1xuICAgICAgICBzd2l0Y2ggKHBsYWNlbWVudCkge1xuICAgICAgICAgICAgY2FzZSBcInJpZ2h0XCI6XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudFBvc2l0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICB0b3A6IGhvc3RFbGVtZW50UG9zaXRpb24udG9wICsgc2hpZnRCeVksXG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IGhvc3RFbGVtZW50UG9zaXRpb24ubGVmdCArIGhvc3RFbGVtZW50UG9zaXRpb24ud2lkdGgsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJsZWZ0XCI6XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudFBvc2l0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICB0b3A6IGhvc3RFbGVtZW50UG9zaXRpb24udG9wICsgc2hpZnRCeVksXG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IGhvc3RFbGVtZW50UG9zaXRpb24ubGVmdCAtIHRhcmdldEVsZW1lbnQub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJib3R0b21cIjpcbiAgICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50UG9zaXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcDogaG9zdEVsZW1lbnRQb3NpdGlvbi50b3AgKyBob3N0RWxlbWVudFBvc2l0aW9uLmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogaG9zdEVsZW1lbnRQb3NpdGlvbi5sZWZ0ICsgc2hpZnRCeVgsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJ0b3BcIjpcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudFBvc2l0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICB0b3A6IGhvc3RFbGVtZW50UG9zaXRpb24udG9wIC0gdGFyZ2V0RWxlbWVudC5vZmZzZXRIZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IGhvc3RFbGVtZW50UG9zaXRpb24ubGVmdCArIHNoaWZ0QnlYLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRhcmdldEVsZW1lbnRQb3NpdGlvbjtcbiAgICB9XG5cbiAgICBwcml2YXRlIHBvc2l0aW9uKG5hdGl2ZUVsZW1lbnQ6IEhUTUxFbGVtZW50KToge1xuICAgICAgICB3aWR0aDogbnVtYmVyO1xuICAgICAgICBoZWlnaHQ6IG51bWJlcjtcbiAgICAgICAgdG9wOiBudW1iZXI7XG4gICAgICAgIGxlZnQ6IG51bWJlcjtcbiAgICB9IHtcbiAgICAgICAgbGV0IG9mZnNldFBhcmVudEJvdW5kaW5nQ2xpZW50UmVjdCA9IHsgdG9wOiAwLCBsZWZ0OiAwIH07XG4gICAgICAgIGNvbnN0IGVsZW1lbnRCb3VuZGluZ0NsaWVudFJlY3QgPSB0aGlzLm9mZnNldChuYXRpdmVFbGVtZW50KTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0UGFyZW50RWxlbWVudCA9IHRoaXMucGFyZW50T2Zmc2V0RWwobmF0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgaWYgKG9mZnNldFBhcmVudEVsZW1lbnQgIT09IHRoaXMuZG9jdW1lbnQpIHtcbiAgICAgICAgICAgIG9mZnNldFBhcmVudEJvdW5kaW5nQ2xpZW50UmVjdCA9IHRoaXMub2Zmc2V0KG9mZnNldFBhcmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgb2Zmc2V0UGFyZW50Qm91bmRpbmdDbGllbnRSZWN0LnRvcCArPVxuICAgICAgICAgICAgICAgIG9mZnNldFBhcmVudEVsZW1lbnQuY2xpZW50VG9wIC0gb2Zmc2V0UGFyZW50RWxlbWVudC5zY3JvbGxUb3A7XG4gICAgICAgICAgICBvZmZzZXRQYXJlbnRCb3VuZGluZ0NsaWVudFJlY3QubGVmdCArPVxuICAgICAgICAgICAgICAgIG9mZnNldFBhcmVudEVsZW1lbnQuY2xpZW50TGVmdCAtIG9mZnNldFBhcmVudEVsZW1lbnQuc2Nyb2xsTGVmdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGJvdW5kaW5nQ2xpZW50UmVjdCA9IG5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdpZHRoOiBib3VuZGluZ0NsaWVudFJlY3Qud2lkdGggfHwgbmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogYm91bmRpbmdDbGllbnRSZWN0LmhlaWdodCB8fCBuYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCxcbiAgICAgICAgICAgIHRvcDpcbiAgICAgICAgICAgICAgICBlbGVtZW50Qm91bmRpbmdDbGllbnRSZWN0LnRvcCAtXG4gICAgICAgICAgICAgICAgb2Zmc2V0UGFyZW50Qm91bmRpbmdDbGllbnRSZWN0LnRvcCxcbiAgICAgICAgICAgIGxlZnQ6XG4gICAgICAgICAgICAgICAgZWxlbWVudEJvdW5kaW5nQ2xpZW50UmVjdC5sZWZ0IC1cbiAgICAgICAgICAgICAgICBvZmZzZXRQYXJlbnRCb3VuZGluZ0NsaWVudFJlY3QubGVmdCxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9mZnNldChuYXRpdmVFbGVtZW50OiBhbnkpOiB7XG4gICAgICAgIHdpZHRoOiBudW1iZXI7XG4gICAgICAgIGhlaWdodDogbnVtYmVyO1xuICAgICAgICB0b3A6IG51bWJlcjtcbiAgICAgICAgbGVmdDogbnVtYmVyO1xuICAgIH0ge1xuICAgICAgICBjb25zdCBib3VuZGluZ0NsaWVudFJlY3QgPSBuYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBpZiAoX2lzTmlsKHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXcpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJEb2N1bWVudCBkZWZhdWx0VmlldyBpcyBub3QgYXZhaWxhYmxlXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdpZHRoOiBib3VuZGluZ0NsaWVudFJlY3Qud2lkdGggfHwgbmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogYm91bmRpbmdDbGllbnRSZWN0LmhlaWdodCB8fCBuYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCxcbiAgICAgICAgICAgIHRvcDpcbiAgICAgICAgICAgICAgICBib3VuZGluZ0NsaWVudFJlY3QudG9wICtcbiAgICAgICAgICAgICAgICAodGhpcy5kb2N1bWVudC5kZWZhdWx0Vmlldy5wYWdlWU9mZnNldCB8fFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3ApLFxuICAgICAgICAgICAgbGVmdDpcbiAgICAgICAgICAgICAgICBib3VuZGluZ0NsaWVudFJlY3QubGVmdCArXG4gICAgICAgICAgICAgICAgKHRoaXMuZG9jdW1lbnQuZGVmYXVsdFZpZXcucGFnZVhPZmZzZXQgfHxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdCksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTdHlsZShuYXRpdmVFbGVtZW50OiBIVE1MRWxlbWVudCwgY3NzUHJvcDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKF9pc05pbCh0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRG9jdW1lbnQgZGVmYXVsdFZpZXcgaXMgbm90IGF2YWlsYWJsZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdGhpcy5kb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKFxuICAgICAgICAgICAgICAgICAgICBuYXRpdmVFbGVtZW50XG4gICAgICAgICAgICAgICAgKSBhcyBPdXJDU1NcbiAgICAgICAgICAgIClbY3NzUHJvcF07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaW5hbGx5IHRyeSBhbmQgZ2V0IGlubGluZSBzdHlsZVxuICAgICAgICByZXR1cm4gKG5hdGl2ZUVsZW1lbnQuc3R5bGUgYXMgT3VyQ1NTKVtjc3NQcm9wXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGlzU3RhdGljUG9zaXRpb25lZChuYXRpdmVFbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgKHRoaXMuZ2V0U3R5bGUobmF0aXZlRWxlbWVudCwgXCJwb3NpdGlvblwiKSB8fCBcInN0YXRpY1wiKSA9PT0gXCJzdGF0aWNcIlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgcGFyZW50T2Zmc2V0RWwobmF0aXZlRWxlbWVudDogSFRNTEVsZW1lbnQpOiBhbnkge1xuICAgICAgICBsZXQgb2Zmc2V0UGFyZW50OiBhbnkgPSBuYXRpdmVFbGVtZW50Lm9mZnNldFBhcmVudCB8fCB0aGlzLmRvY3VtZW50O1xuXG4gICAgICAgIHdoaWxlIChcbiAgICAgICAgICAgIG9mZnNldFBhcmVudCAmJlxuICAgICAgICAgICAgb2Zmc2V0UGFyZW50ICE9PSB0aGlzLmRvY3VtZW50ICYmXG4gICAgICAgICAgICB0aGlzLmlzU3RhdGljUG9zaXRpb25lZChvZmZzZXRQYXJlbnQpXG4gICAgICAgICkge1xuICAgICAgICAgICAgb2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvZmZzZXRQYXJlbnQgfHwgdGhpcy5kb2N1bWVudDtcbiAgICB9XG59XG4iXX0=