@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
453 lines • 67.2 kB
JavaScript
import { Component, EventEmitter, HostBinding, HostListener, Injector, Input, Output } from '@angular/core';
import { KeyCode } from '@microsoft/windows-admin-center-sdk/core/data/accessibility-manager';
import { LogLevel } from '@microsoft/windows-admin-center-sdk/core/diagnostics/log-level';
import { CoreBaseComponent } from '../common/base.component';
import * as i0 from "@angular/core";
/**
* Resizer component
*/
export class ResizerComponent extends CoreBaseComponent {
/**
* Initializes a new instance of the @see ResizerComponent class.
* @param injector The angular injection service. required by @see SmeInjectableBase decorator in the @see BaseComponent class
*/
constructor(injector) {
super(injector);
this.isResizing = false;
this._orientation = 'bottom';
/**
* It indicates whether to show the half transparent cover ont he resizer host.
* In some case (like Data Table column resizer), the cover is not needed since data table would handle the UI of resizing by itself.
*/
this.showResizerCover = true;
/**
* It indicates whether to let the screen reader to read this resizer control.
* In some case (like Data Table column resizer), we don't want the screen reader to read it as part of the column header.
*/
this.visibleToScreenReader = true;
/**
* Determines if the resizer is accessible to the screen readers
*/
this.focusable = false;
/**
* It's fired then the resizing is finished.
*/
this.resized = new EventEmitter();
/**
* It's fired then the resizing is happening.
*/
this.resizing = new EventEmitter();
}
/**
* The source name to use for logging
*/
get logSourceName() {
return 'ResizerComponent';
}
/**
* It defines the orientation of the element which holds the resizer in the resizing layout.
*/
set orientation(newOrientation) {
if (this._orientation !== newOrientation) {
this._orientation = newOrientation;
if (this.resizerHostBodyElement?.parentNode) {
this.resizerHostBodyElement.parentNode.removeChild(this.resizerHostBodyElement);
}
if (this.resizerIndicatorElement?.parentNode) {
this.resizerIndicatorElement.parentNode.removeChild(this.resizerIndicatorElement);
}
// To support orientation changes by window size changes
// Reset all the parameters and re-build the resizer elements
setTimeout(() => {
this.resizerHostElement = undefined;
this.resizerHostBodyElement = undefined;
this.resizerIndicatorElement = undefined;
this.offsetX = undefined;
this.offsetY = undefined;
this.originalX = undefined;
this.originalY = undefined;
this.ngOnInit();
});
}
}
get orientation() {
return this._orientation;
}
/**
* Indicates that the resizer should be aligned to the top
*/
get alignTop() {
return this.isOriented('bottom', 'left', 'right');
}
/**
* Indicates that the resizer should be aligned to the bottom
*/
get alignBottom() {
return this.isOriented('top', 'left', 'right');
}
/**
* Indicates that the resizer should be aligned to the left
*/
get alignLeft() {
return this.isOriented('top', 'bottom', 'right');
}
/**
* Indicates that the resizer should be aligned to the right
*/
get alignRight() {
return this.isOriented('top', 'bottom', 'left');
}
/**
* Indicates that the resizer moves vertically
*/
get isVertical() {
return this.isOriented('top', 'bottom');
}
/**
* Indicates that the resizer moves horizontally
*/
get isHorizontal() {
return this.isOriented('left', 'right');
}
/**
* Describes the orientation for aria users.
*/
get ariaOrientation() {
return this.isVertical ? 'vertical' : 'horizontal';
}
/**
* Defines the cursor style the resizer should have
*/
get cursor() {
switch (this.orientation) {
case 'top':
return 'n-resize';
case 'bottom':
return 's-resize';
case 'left':
return 'e-resize';
case 'right':
return 'w-resize';
}
}
/**
* Angular lifecycle hook.
*/
ngOnInit() {
super.ngOnInit();
// This is a special implementation for Microsoft Edge.
// In Microsoft Edge, if the resizer div is transparent and it's overlay on the scrollbar,
// the mouse events will be messed up.
// So we need to apply a very transparent but not 100% transparent color to it.
// It won't impact the look and feel, when the browser renders this special color,
// basically no color will be actually rendered.
this.hostElement.nativeElement.style.background = 'rgba(255,255,255,0.003)';
if (this.visibleToScreenReader) {
this.setAttribute('role', 'separator');
this.setAttribute('aria-label', this.strings.MsftSmeShell.Angular.Resizer.Splitter);
}
this.setAttribute('tabindex', this.focusable ? '0' : '-1');
this.setAttribute('aria-hidden', this.focusable ? 'false' : 'true');
if (!this.resizerHostSelector) {
this.log('resizerHostSelector is not set.', LogLevel.Warning);
}
else {
let currentParentElement = this.hostElement.nativeElement.parentElement;
while (!this.resizerHostElement && currentParentElement) {
// Deal with nested html tag, for instance, sme-split-view contains of nested sme-split-view
// Without this if logic, the resizer will be attached to the wrong location because of the querySelector function.
if (currentParentElement.tagName.toLowerCase() === this.resizerHostSelector.toLowerCase()) {
this.resizerHostElement = currentParentElement;
break;
}
else {
this.resizerHostElement = currentParentElement.querySelector(this.resizerHostSelector);
currentParentElement = currentParentElement.parentElement;
}
}
this.resizerHostBodyElement = document.createElement('DIV');
this.resizerHostBodyElement.setAttribute('role', 'presentation');
this.resizerHostBodyElement.classList.add('sme-resizer-host-body');
this.resizerHostBodyElement.classList.add('sme-layout-absolute');
this.resizerHostBodyElement.classList.add('sme-position-inset-none');
this.resizerHostBodyElement.classList.add('sme-layer-above');
this.resizerHostBodyElement.classList.add('sme-layout-none');
this.resizerIndicatorElement = document.createElement('DIV');
this.resizerIndicatorElement.classList.add('sme-resizer-indicator');
this.resizerIndicatorElement.classList.add('sme-layout-none');
this.resizerIndicatorElement.classList.add('sme-layout-absolute');
this.resizerIndicatorElement.classList.add('sme-layer-over');
if (this.showResizerCover) {
this.resizerHostBodyElement.classList.add('sme-background-color-base');
this.resizerHostBodyElement.style.opacity = '0.5';
this.resizerIndicatorElement.classList.add('sme-background-color-base-80');
}
switch (this.orientation) {
case 'top':
this.resizerHostBodyElement.style.cursor = 'n-resize';
this.resizerIndicatorElement.classList.add('sme-position-stretch-h');
this.resizerIndicatorElement.classList.add('sme-height-xxs');
break;
case 'bottom':
this.resizerHostBodyElement.style.cursor = 's-resize';
this.resizerIndicatorElement.classList.add('sme-position-stretch-h');
this.resizerIndicatorElement.classList.add('sme-height-xxs');
break;
case 'left':
this.resizerHostBodyElement.style.cursor = 'e-resize';
this.resizerIndicatorElement.classList.add('sme-width-xxs');
this.resizerIndicatorElement.classList.add('sme-position-stretch-v');
break;
case 'right':
this.resizerHostBodyElement.style.cursor = 'w-resize';
this.resizerIndicatorElement.classList.add('sme-width-xxs');
this.resizerIndicatorElement.classList.add('sme-position-stretch-v');
break;
}
let foundExistingResizerHostBody = false;
if (this.resizerHostElement && this.resizerHostElement.childElementCount) {
for (let i = 0; i < this.resizerHostElement.children.length; i++) {
if (this.resizerHostElement.children[i].classList.contains('sme-resizer-host-body')) {
// remove the resizer host element if it doesn't contain resizer indicator and re-create.
// this issue mostly due to component not initialized before the resizer was initialized.
if (!this.resizerHostBodyElement.querySelector('.sme-resizer-indicator')) {
this.resizerHostElement.children[i].parentNode.removeChild(this.resizerHostElement.children[i]);
}
else {
foundExistingResizerHostBody = true;
this.resizerHostBodyElement = this.resizerHostElement.children[i];
this.resizerIndicatorElement = this.resizerHostBodyElement.querySelector('.sme-resizer-indicator');
break;
}
}
}
}
if (!foundExistingResizerHostBody) {
this.resizerHostElement.appendChild(this.resizerHostBodyElement);
this.resizerHostBodyElement.appendChild(this.resizerIndicatorElement);
}
this.onStartingResizeEventHandler = this.onStartingResizing.bind(this);
this.onResizingEventHandler = this.onResizing.bind(this);
this.onFinishingResizeEventHandler = this.onFinishingResizing.bind(this);
}
}
/**
* It handles the event when mouse down happens on the resizer.
*/
onResizeElementMouseDown() {
this.isResizing = true;
document.body.addEventListener('mousedown', this.onStartingResizeEventHandler);
document.body.addEventListener('mousemove', this.onResizingEventHandler);
document.body.addEventListener('mouseup', this.onFinishingResizeEventHandler);
}
onResizeElementKeyDown($event) {
if (this.isHorizontal) {
switch ($event.keyCode) {
case KeyCode.LeftArrow:
this.resized.emit({
x: -ResizerComponent.keyboardDelta,
y: 0
});
break;
case KeyCode.RightArrow:
this.resized.emit({
x: ResizerComponent.keyboardDelta,
y: 0
});
break;
}
}
else if (this.isVertical) {
switch ($event.keyCode) {
case KeyCode.UpArrow:
this.resized.emit({
x: 0,
y: -ResizerComponent.keyboardDelta
});
break;
case KeyCode.DownArrow:
this.resized.emit({
x: 0,
y: ResizerComponent.keyboardDelta
});
break;
}
}
}
startResize(offsetX, offsetY) {
this.isResizing = true;
this.offsetX = offsetX;
this.offsetY = offsetY;
document.body.style.userSelect = 'none';
this.resizerHostBodyElement.classList.remove('sme-layout-none');
this.resizerIndicatorElement.classList.remove('sme-layout-none');
const resizerHostRect = this.resizerHostBodyElement.getBoundingClientRect();
const resizerElementRect = this.hostElement.nativeElement.getBoundingClientRect();
this.originalX = resizerElementRect.left - resizerHostRect.left;
this.originalY = resizerElementRect.top - resizerHostRect.top;
}
onStartingResizing(event) {
if (this.isResizing) {
this.startResize(event.clientX, event.clientY);
this.onResizing(event);
event.preventDefault();
}
}
onResizing(event) {
if (this.isResizing) {
const resizerHostRect = this.resizerHostBodyElement.getBoundingClientRect();
let indicatorX;
let indicatorY;
let newX;
let newY;
switch (this.orientation) {
case 'top':
newY = this.hostElement.nativeElement.offsetTop + event.clientY - this.offsetY;
this.offsetY = event.clientY;
this.hostElement.nativeElement.style.top = newY + 'px';
indicatorY = resizerHostRect.top === 0 ?
this.hostElement.nativeElement.parentElement.offsetTop + newY :
this.hostElement.nativeElement.parentElement.getBoundingClientRect().top - resizerHostRect.top + newY;
this.resizerIndicatorElement.style.top = indicatorY + 'px';
break;
case 'bottom':
newY = this.hostElement.nativeElement.offsetTop + event.clientY - this.offsetY;
this.offsetY = event.clientY;
this.hostElement.nativeElement.style.top = newY + 'px';
indicatorY = this.originalY + newY;
this.resizerIndicatorElement.style.top = indicatorY + 'px';
break;
case 'left':
newX = this.hostElement.nativeElement.offsetLeft + event.clientX - this.offsetX;
this.offsetX = event.clientX;
this.hostElement.nativeElement.style.left = newX + 'px';
indicatorX = resizerHostRect.left === 0 ?
this.hostElement.nativeElement.parentElement.offsetLeft + newX :
this.hostElement.nativeElement.parentElement.getBoundingClientRect().left - resizerHostRect.left + newX;
this.resizerIndicatorElement.style.left = indicatorX + 'px';
break;
case 'right':
newX = this.hostElement.nativeElement.offsetLeft + event.clientX - this.offsetX;
this.offsetX = event.clientX;
this.hostElement.nativeElement.style.left = newX + 'px';
indicatorX = this.originalX + newX;
this.resizerIndicatorElement.style.left = indicatorX + 'px';
break;
}
this.resizing.emit({ x: indicatorX, y: indicatorY });
}
}
onFinishingResizing() {
if (this.isResizing) {
document.body.removeEventListener('mousedown', this.onStartingResizeEventHandler);
document.body.removeEventListener('mousemove', this.onResizingEventHandler);
document.body.removeEventListener('mouseup', this.onFinishingResizeEventHandler);
this.isResizing = false;
let deltaX;
let deltaY;
const resizerHostRect = this.resizerHostBodyElement.getBoundingClientRect();
const resizerElementRect = this.hostElement.nativeElement.getBoundingClientRect();
const newX = resizerElementRect.left - resizerHostRect.left;
const newY = resizerElementRect.top - resizerHostRect.top;
switch (this.orientation) {
case 'left':
deltaX = newX - this.originalX;
deltaY = 0;
break;
case 'right':
deltaX = newX - this.originalX;
deltaY = 0;
break;
case 'top':
deltaX = 0;
deltaY = newY - this.originalY;
break;
case 'bottom':
deltaX = 0;
deltaY = newY - this.originalY;
break;
}
this.resized.emit({
x: deltaX,
y: deltaY
});
this.resizerHostBodyElement.classList.add('sme-layout-none');
document.body.style.userSelect = 'auto';
this.resizerHostBodyElement.classList.add('sme-layout-none');
this.resizerIndicatorElement.classList.add('sme-layout-none');
this.hostElement.nativeElement.style.left = '';
this.hostElement.nativeElement.style.top = '';
}
}
isOriented(...orientations) {
return orientations.some(o => o === this.orientation);
}
getInitialHostClasses() {
return super.getInitialHostClasses()
.concat([
'sme-layout-absolute',
'sme-layer-over'
]);
}
}
ResizerComponent.keyboardDelta = 20;
/** @nocollapse */ ResizerComponent.ɵfac = function ResizerComponent_Factory(t) { return new (t || ResizerComponent)(i0.ɵɵdirectiveInject(i0.Injector)); };
/** @nocollapse */ ResizerComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: ResizerComponent, selectors: [["sme-resizer"]], hostVars: 15, hostBindings: function ResizerComponent_HostBindings(rf, ctx) { if (rf & 1) {
i0.ɵɵlistener("mousedown", function ResizerComponent_mousedown_HostBindingHandler() { return ctx.onResizeElementMouseDown(); })("keydown", function ResizerComponent_keydown_HostBindingHandler($event) { return ctx.onResizeElementKeyDown($event); });
} if (rf & 2) {
i0.ɵɵattribute("aria-orientation", ctx.ariaOrientation);
i0.ɵɵstyleProp("cursor", ctx.cursor);
i0.ɵɵclassProp("sme-position-top-none", ctx.alignTop)("sme-position-bottom-none", ctx.alignBottom)("sme-position-left-none", ctx.alignLeft)("sme-position-right-none", ctx.alignRight)("sme-height-xxs", ctx.isVertical)("sme-width-xxs", ctx.isHorizontal);
} }, inputs: { resizerHostSelector: "resizerHostSelector", showResizerCover: "showResizerCover", visibleToScreenReader: "visibleToScreenReader", orientation: "orientation", focusable: "focusable" }, outputs: { resized: "resized", resizing: "resizing" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 0, vars: 0, template: function ResizerComponent_Template(rf, ctx) { }, encapsulation: 2 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ResizerComponent, [{
type: Component,
args: [{
selector: 'sme-resizer',
template: ''
}]
}], function () { return [{ type: i0.Injector }]; }, { resizerHostSelector: [{
type: Input
}], showResizerCover: [{
type: Input
}], visibleToScreenReader: [{
type: Input
}], orientation: [{
type: Input
}], focusable: [{
type: Input
}], resized: [{
type: Output
}], resizing: [{
type: Output
}], alignTop: [{
type: HostBinding,
args: ['class.sme-position-top-none']
}], alignBottom: [{
type: HostBinding,
args: ['class.sme-position-bottom-none']
}], alignLeft: [{
type: HostBinding,
args: ['class.sme-position-left-none']
}], alignRight: [{
type: HostBinding,
args: ['class.sme-position-right-none']
}], isVertical: [{
type: HostBinding,
args: ['class.sme-height-xxs']
}], isHorizontal: [{
type: HostBinding,
args: ['class.sme-width-xxs']
}], ariaOrientation: [{
type: HostBinding,
args: ['attr.aria-orientation']
}], cursor: [{
type: HostBinding,
args: ['style.cursor']
}], onResizeElementMouseDown: [{
type: HostListener,
args: ['mousedown']
}], onResizeElementKeyDown: [{
type: HostListener,
args: ['keydown', ['$event']]
}] }); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9yZXNpemVyL3Jlc2l6ZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFFQUFxRSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQztBQUMxRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7QUFFN0Q7O0dBRUc7QUFLSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsaUJBQWlCO0lBeUtuRDs7O09BR0c7SUFDSCxZQUFZLFFBQWtCO1FBQzFCLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQXBLWixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBUW5CLGlCQUFZLEdBQUcsUUFBUSxDQUFDO1FBWWhDOzs7V0FHRztRQUVJLHFCQUFnQixHQUFHLElBQUksQ0FBQztRQUUvQjs7O1dBR0c7UUFFSSwwQkFBcUIsR0FBRyxJQUFJLENBQUM7UUFvQ3BDOztXQUVHO1FBRUksY0FBUyxHQUFHLEtBQUssQ0FBQztRQUV6Qjs7V0FFRztRQUVJLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBNEIsQ0FBQztRQUU5RDs7V0FFRztRQUVJLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBNEIsQ0FBQztJQWlGL0QsQ0FBQztJQTlLRDs7T0FFRztJQUNILElBQWMsYUFBYTtRQUN2QixPQUFPLGtCQUFrQixDQUFDO0lBQzlCLENBQUM7SUFzQ0Q7O09BRUc7SUFDSCxJQUNXLFdBQVcsQ0FBQyxjQUFzQjtRQUN6QyxJQUFJLElB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Z0I7a0dBQWhCLGdCQUFnQjtxR0FBaEIsOEJBQTBCLHNGQUExQixrQ0FBOEI7Ozs7Ozt1RkFBOUIsZ0JBQWdCO2NBSjVCLFNBQVM7ZUFBQztnQkFDUCxRQUFRLEVBQUUsYUFBYTtnQkFDdkIsUUFBUSxFQUFFLEVBQUU7YUFDZjsyREE2QlUsbUJBQW1CO2tCQUR6QixLQUFLO1lBUUMsZ0JBQWdCO2tCQUR0QixLQUFLO1lBUUMscUJBQXFCO2tCQUQzQixLQUFLO1lBT0ssV0FBVztrQkFEckIsS0FBSztZQW1DQyxTQUFTO2tCQURmLEtBQUs7WUFPQyxPQUFPO2tCQURiLE1BQU07WUFPQSxRQUFRO2tCQURkLE1BQU07WUFPSSxRQUFRO2tCQURsQixXQUFXO21CQUFDLDZCQUE2QjtZQVMvQixXQUFXO2tCQURyQixXQUFXO21CQUFDLGdDQUFnQztZQVNsQyxTQUFTO2tCQURuQixXQUFXO21CQUFDLDhCQUE4QjtZQVNoQyxVQUFVO2tCQURwQixXQUFXO21CQUFDLCtCQUErQjtZQVNqQyxVQUFVO2tCQURwQixXQUFXO21CQUFDLHNCQUFzQjtZQVN4QixZQUFZO2tCQUR0QixXQUFXO21CQUFDLHFCQUFxQjtZQVN2QixlQUFlO2tCQUR6QixXQUFXO21CQUFDLHVCQUF1QjtZQVN6QixNQUFNO2tCQURoQixXQUFXO21CQUFDLGNBQWM7WUF3SXBCLHdCQUF3QjtrQkFEOUIsWUFBWTttQkFBQyxXQUFXO1lBU2xCLHNCQUFzQjtrQkFENUIsWUFBWTttQkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5qZWN0b3IsIElucHV0LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBLZXlDb2RlIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kYXRhL2FjY2Vzc2liaWxpdHktbWFuYWdlcic7XHJcbmltcG9ydCB7IExvZ0xldmVsIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kaWFnbm9zdGljcy9sb2ctbGV2ZWwnO1xyXG5pbXBvcnQgeyBDb3JlQmFzZUNvbXBvbmVudCB9IGZyb20gJy4uL2NvbW1vbi9iYXNlLmNvbXBvbmVudCc7XHJcblxyXG4vKipcclxuICogUmVzaXplciBjb21wb25lbnRcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdzbWUtcmVzaXplcicsXHJcbiAgICB0ZW1wbGF0ZTogJydcclxufSlcclxuZXhwb3J0IGNsYXNzIFJlc2l6ZXJDb21wb25lbnQgZXh0ZW5kcyBDb3JlQmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBzb3VyY2UgbmFtZSB0byB1c2UgZm9yIGxvZ2dpbmdcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGdldCBsb2dTb3VyY2VOYW1lKCkge1xyXG4gICAgICAgIHJldHVybiAnUmVzaXplckNvbXBvbmVudCc7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMga2V5Ym9hcmREZWx0YSA9IDIwO1xyXG5cclxuICAgIHByaXZhdGUgaXNSZXNpemluZyA9IGZhbHNlO1xyXG4gICAgcHJpdmF0ZSByZXNpemVySG9zdEVsZW1lbnQ6IEVsZW1lbnQ7XHJcbiAgICBwcml2YXRlIHJlc2l6ZXJIb3N0Qm9keUVsZW1lbnQ6IEhUTUxFbGVtZW50O1xyXG4gICAgcHJpdmF0ZSByZXNpemVySW5kaWNhdG9yRWxlbWVudDogSFRNTEVsZW1lbnQ7XHJcbiAgICBwcml2YXRlIG9mZnNldFg6IG51bWJlcjtcclxuICAgIHByaXZhdGUgb2Zmc2V0WTogbnVtYmVyO1xyXG4gICAgcHJpdmF0ZSBvcmlnaW5hbFg6IG51bWJlcjtcclxuICAgIHByaXZhdGUgb3JpZ2luYWxZOiBudW1iZXI7XHJcbiAgICBwcml2YXRlIF9vcmllbnRhdGlvbiA9ICdib3R0b20nO1xyXG5cclxuICAgIHByaXZhdGUgb25TdGFydGluZ1Jlc2l6ZUV2ZW50SGFuZGxlcjogKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB2b2lkO1xyXG4gICAgcHJpdmF0ZSBvblJlc2l6aW5nRXZlbnRIYW5kbGVyOiAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHZvaWQ7XHJcbiAgICBwcml2YXRlIG9uRmluaXNoaW5nUmVzaXplRXZlbnRIYW5kbGVyOiAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJdCdzIHVzZWQgdG8gbG9jYXRlIHRoZSByZXNpemluZyBob3N0IHdoaWNoIGRlZmluZXMgdGhlIGFyZWEgd2hlcmUgdGhlIHJlc2l6ZXIgY2FuIG1vdmUgYXJvdW5kLlxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIHJlc2l6ZXJIb3N0U2VsZWN0b3I6IHN0cmluZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIEl0IGluZGljYXRlcyB3aGV0aGVyIHRvIHNob3cgdGhlIGhhbGYgdHJhbnNwYXJlbnQgY292ZXIgb250IGhlIHJlc2l6ZXIgaG9zdC5cclxuICAgICAqIEluIHNvbWUgY2FzZSAobGlrZSBEYXRhIFRhYmxlIGNvbHVtbiByZXNpemVyKSwgdGhlIGNvdmVyIGlzIG5vdCBuZWVkZWQgc2luY2UgZGF0YSB0YWJsZSB3b3VsZCBoYW5kbGUgdGhlIFVJIG9mIHJlc2l6aW5nIGJ5IGl0c2VsZi5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzaG93UmVzaXplckNvdmVyID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEl0IGluZGljYXRlcyB3aGV0aGVyIHRvIGxldCB0aGUgc2NyZWVuIHJlYWRlciB0byByZWFkIHRoaXMgcmVzaXplciBjb250cm9sLlxyXG4gICAgICogSW4gc29tZSBjYXNlIChsaWtlIERhdGEgVGFibGUgY29sdW1uIHJlc2l6ZXIpLCB3ZSBkb24ndCB3YW50IHRoZSBzY3JlZW4gcmVhZGVyIHRvIHJlYWQgaXQgYXMgcGFydCBvZiB0aGUgY29sdW1uIGhlYWRlci5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyB2aXNpYmxlVG9TY3JlZW5SZWFkZXIgPSB0cnVlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSXQgZGVmaW5lcyB0aGUgb3JpZW50YXRpb24gb2YgdGhlIGVsZW1lbnQgd2hpY2ggaG9sZHMgdGhlIHJlc2l6ZXIgaW4gdGhlIHJlc2l6aW5nIGxheW91dC5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzZXQgb3JpZW50YXRpb24obmV3T3JpZW50YXRpb246IHN0cmluZykge1xyXG4gICAgICAgIGlmICh0aGlzLl9vcmllbnRhdGlvbiAhPT0gbmV3T3JpZW50YXRpb24pIHtcclxuICAgICAgICAgICAgdGhpcy5fb3JpZW50YXRpb24gPSBuZXdPcmllbnRhdGlvbjtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnJlc2l6ZXJIb3N0Qm9keUVsZW1lbnQ/LnBhcmVudE5vZGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplckhvc3RCb2R5RWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMucmVzaXplckhvc3RCb2R5RWxlbWVudCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnJlc2l6ZXJJbmRpY2F0b3JFbGVtZW50Py5wYXJlbnROb2RlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZXJJbmRpY2F0b3JFbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5yZXNpemVySW5kaWNhdG9yRWxlbWVudCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gVG8gc3VwcG9ydCBvcmllbnRhdGlvbiBjaGFuZ2VzIGJ5IHdpbmRvdyBzaXplIGNoYW5nZXNcclxuICAgICAgICAgICAgLy8gUmVzZXQgYWxsIHRoZSBwYXJhbWV0ZXJzIGFuZCByZS1idWlsZCB0aGUgcmVzaXplciBlbGVtZW50c1xyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplckhvc3RFbGVtZW50ID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVySG9zdEJvZHlFbGVtZW50ID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVySW5kaWNhdG9yRWxlbWVudCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0WCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0WSA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgICAgIHRoaXMub3JpZ2luYWxYID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5vcmlnaW5hbFkgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5nT25Jbml0KCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0IG9yaWVudGF0aW9uKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX29yaWVudGF0aW9uO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGV0ZXJtaW5lcyBpZiB0aGUgcmVzaXplciBpcyBhY2Nlc3NpYmxlIHRvIHRoZSBzY3JlZW4gcmVhZGVyc1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIGZvY3VzYWJsZSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSXQncyBmaXJlZCB0aGVuIHRoZSByZXNpemluZyBpcyBmaW5pc2hlZC5cclxuICAgICAqL1xyXG4gICAgQE91dHB1dCgpXHJcbiAgICBwdWJsaWMgcmVzaXplZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyB4OiBudW1iZXIsIHk6IG51bWJlciB9PigpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSXQncyBmaXJlZCB0aGVuIHRoZSByZXNpemluZyBpcyBoYXBwZW5pbmcuXHJcbiAgICAgKi9cclxuICAgIEBPdXRwdXQoKVxyXG4gICAgcHVibGljIHJlc2l6aW5nID0gbmV3IEV2ZW50RW1pdHRlcjx7IHg6IG51bWJlciwgeTogbnVtYmVyIH0+KCk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgcmVzaXplciBzaG91bGQgYmUgYWxpZ25lZCB0byB0aGUgdG9wXHJcbiAgICAgKi9cclxuICAgIEBIb3N0QmluZGluZygnY2xhc3Muc21lLXBvc2l0aW9uLXRvcC1ub25lJylcclxuICAgIHB1YmxpYyBnZXQgYWxpZ25Ub3AoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNPcmllbnRlZCgnYm90dG9tJywgJ2xlZnQnLCAncmlnaHQnKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSByZXNpemVyIHNob3VsZCBiZSBhbGlnbmVkIHRvIHRoZSBib3R0b21cclxuICAgICAqL1xyXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5zbWUtcG9zaXRpb24tYm90dG9tLW5vbmUnKVxyXG4gICAgcHVibGljIGdldCBhbGlnbkJvdHRvbSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc09yaWVudGVkKCd0b3AnLCAnbGVmdCcsICdyaWdodCcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhdGVzIHRoYXQgdGhlIHJlc2l6ZXIgc2hvdWxkIGJlIGFsaWduZWQgdG8gdGhlIGxlZnRcclxuICAgICAqL1xyXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5zbWUtcG9zaXRpb24tbGVmdC1ub25lJylcclxuICAgIHB1YmxpYyBnZXQgYWxpZ25MZWZ0KCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmlzT3JpZW50ZWQoJ3RvcCcsICdib3R0b20nLCAncmlnaHQnKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSByZXNpemVyIHNob3VsZCBiZSBhbGlnbmVkIHRvIHRoZSByaWdodFxyXG4gICAgICovXHJcbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLnNtZS1wb3NpdGlvbi1yaWdodC1ub25lJylcclxuICAgIHB1YmxpYyBnZXQgYWxpZ25SaWdodCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc09yaWVudGVkKCd0b3AnLCAnYm90dG9tJywgJ2xlZnQnKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSByZXNpemVyIG1vdmVzIHZlcnRpY2FsbHlcclxuICAgICAqL1xyXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5zbWUtaGVpZ2h0LXh4cycpXHJcbiAgICBwdWJsaWMgZ2V0IGlzVmVydGljYWwoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNPcmllbnRlZCgndG9wJywgJ2JvdHRvbScpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhdGVzIHRoYXQgdGhlIHJlc2l6ZXIgbW92ZXMgaG9yaXpvbnRhbGx5XHJcbiAgICAgKi9cclxuICAgIEBIb3N0QmluZGluZygnY2xhc3Muc21lLXdpZHRoLXh4cycpXHJcbiAgICBwdWJsaWMgZ2V0IGlzSG9yaXpvbnRhbCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc09yaWVudGVkKCdsZWZ0JywgJ3JpZ2h0Jyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZXNjcmliZXMgdGhlIG9yaWVudGF0aW9uIGZvciBhcmlhIHVzZXJzLlxyXG4gICAgICovXHJcbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIuYXJpYS1vcmllbnRhdGlvbicpXHJcbiAgICBwdWJsaWMgZ2V0IGFyaWFPcmllbnRhdGlvbigpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc1ZlcnRpY2FsID8gJ3ZlcnRpY2FsJyA6ICdob3Jpem9udGFsJztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgdGhlIGN1cnNvciBzdHlsZSB0aGUgcmVzaXplciBzaG91bGQgaGF2ZVxyXG4gICAgICovXHJcbiAgICBASG9zdEJpbmRpbmcoJ3N0eWxlLmN1cnNvcicpXHJcbiAgICBwdWJsaWMgZ2V0IGN1cnNvcigpIHtcclxuICAgICAgICBzd2l0Y2ggKHRoaXMub3JpZW50YXRpb24pIHtcclxuICAgICAgICAgICAgY2FzZSAndG9wJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnbi1yZXNpemUnO1xyXG4gICAgICAgICAgICBjYXNlICdib3R0b20nOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdzLXJlc2l6ZSc7XHJcbiAgICAgICAgICAgIGNhc2UgJ2xlZnQnOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdlLXJlc2l6ZSc7XHJcbiAgICAgICAgICAgIGNhc2UgJ3JpZ2h0JzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAndy1yZXNpemUnO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluaXRpYWxpemVzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBAc2VlIFJlc2l6ZXJDb21wb25lbnQgY2xhc3MuXHJcbiAgICAgKiBAcGFyYW0gaW5qZWN0b3IgVGhlIGFuZ3VsYXIgaW5qZWN0aW9uIHNlcnZpY2UuIHJlcXVpcmVkIGJ5IEBzZWUgU21lSW5qZWN0YWJsZUJhc2UgZGVjb3JhdG9yIGluIHRoZSBAc2VlIEJhc2VDb21wb25lbnQgY2xhc3NcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IoaW5qZWN0b3I6IEluamVjdG9yKSB7XHJcbiAgICAgICAgc3VwZXIoaW5qZWN0b3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQW5ndWxhciBsaWZlY3ljbGUgaG9vay5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgICAgIHN1cGVyLm5nT25Jbml0KCk7XHJcblxyXG4gICAgICAgIC8vIFRoaXMgaXMgYSBzcGVjaWFsIGltcGxlbWVudGF0aW9uIGZvciBNaWNyb3NvZnQgRWRnZS5cclxuICAgICAgICAvLyBJbiBNaWNyb3NvZnQgRWRnZSwgaWYgdGhlIHJlc2l6ZXIgZGl2IGlzIHRyYW5zcGFyZW50IGFuZCBpdCdzIG92ZXJsYXkgb24gdGhlIHNjcm9sbGJhcixcclxuICAgICAgICAvLyB0aGUgbW91c2UgZXZlbnRzIHdpbGwgYmUgbWVzc2VkIHVwLlxyXG4gICAgICAgIC8vIFNvIHdlIG5lZWQgdG8gYXBwbHkgYSB2ZXJ5IHRyYW5zcGFyZW50IGJ1dCBub3QgMTAwJSB0cmFuc3BhcmVudCBjb2xvciB0byBpdC5cclxuICAgICAgICAvLyBJdCB3b24ndCBpbXBhY3QgdGhlIGxvb2sgYW5kIGZlZWwsIHdoZW4gdGhlIGJyb3dzZXIgcmVuZGVycyB0aGlzIHNwZWNpYWwgY29sb3IsXHJcbiAgICAgICAgLy8gYmFzaWNhbGx5IG5vIGNvbG9yIHdpbGwgYmUgYWN0dWFsbHkgcmVuZGVyZWQuXHJcbiAgICAgICAgdGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLmJhY2tncm91bmQgPSAncmdiYSgyNTUsMjU1LDI1NSwwLjAwMyknO1xyXG5cclxuICAgICAgICBpZiAodGhpcy52aXNpYmxlVG9TY3JlZW5SZWFkZXIpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnc2VwYXJhdG9yJyk7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLlJlc2l6ZXIuU3BsaXR0ZXIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgdGhpcy5mb2N1c2FibGUgPyAnMCcgOiAnLTEnKTtcclxuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCB0aGlzLmZvY3VzYWJsZSA/ICdmYWxzZScgOiAndHJ1ZScpO1xyXG5cclxuICAgICAgICBpZiAoIXRoaXMucmVzaXplckhvc3RTZWxlY3Rvcikge1xyXG4gICAgICAgICAgICB0aGlzLmxvZygncmVzaXplckhvc3RTZWxlY3RvciBpcyBub3Qgc2V0LicsIExvZ0xldmVsLldhcm5pbmcpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGxldCBjdXJyZW50UGFyZW50RWxlbWVudCA9ICg8SFRNTEVsZW1lbnQ+dGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50KS5wYXJlbnRFbGVtZW50O1xyXG4gICAgICAgICAgICB3aGlsZSAoIXRoaXMucmVzaXplckhvc3RFbGVtZW50ICYmIGN1cnJlbnRQYXJlbnRFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAvLyBEZWFsIHdpdGggbmVzdGVkIGh0bWwgdGFnLCBmb3IgaW5zdGFuY2UsIHNtZS1zcGxpdC12aWV3IGNvbnRhaW5zIG9mIG5lc3RlZCBzbWUtc3BsaXQtdmlld1xyXG4gICAgICAgICAgICAgICAgLy8gV2l0aG91dCB0aGlzIGlmIGxvZ2ljLCB0aGUgcmVzaXp