UNPKG

gentics-ui-core

Version:

This is the common core framework for the Gentics CMS and Mesh UI, and other Angular applications.

292 lines 42.4 kB
import { Component, HostListener, ElementRef, ChangeDetectorRef, EventEmitter, ChangeDetectionStrategy, Inject } from '@angular/core'; import { KeyCode } from '../../common/keycodes'; import { ConfigService } from '../../module.config'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class DropdownContentWrapper { constructor(elementRef, cd, config) { this.elementRef = elementRef; this.cd = cd; this.config = config; this.contentStyles = { position: 'absolute' }; this.options = { alignment: 'left', width: 'contents', belowTrigger: false }; this.id = 'dropdown-' + Math.random().toString(36).substr(2); this.clicked = new EventEmitter(); this.escapeKeyPressed = new EventEmitter(); this.widthHasBeenAdjusted = false; this.pageMargin = this.config.dropDownPageMargin; this.dropDownMaxHeight = this.config.dropDownMaxHeight; } ngAfterViewInit() { this.setPositionAndSize(true); } /** * Positions and resizes the dropdown contents container. */ setPositionAndSize(initialOpening = false) { const content = this.getDropdownContent(); if (!content) { return; } if (initialOpening) { // When opening for the first time, some extra logic is required this.contentStyles.height = 0; this.contentStyles.opacity = 0; content.setAttribute('id', this.id); } const positionStyles = this.calculatePositionStyles(); Object.assign(this.contentStyles, positionStyles); // const flowUpwards = parseInt(positionStyles.top, 10) < Math.floor(this.trigger.getBoundingClientRect().top); const contentHeight = this.innerHeight(this.elementRef.nativeElement.querySelector('gtx-dropdown-content')); // when flowing upwards, we animate the `top` property, so must remember the final value. const finalTop = parseInt(this.contentStyles.top); if (positionStyles.flowUpwards) { this.contentStyles.top = finalTop + Math.min(contentHeight, parseInt(positionStyles.maxHeight)) + 'px'; } this.contentStyles.width = this.calculateContainerWidth() + 'px'; this.cd.markForCheck(); this.cd.detectChanges(); // Show dropdown. Wrapped in a setTimeout to allow the contents of the dropdown // to re-flow (if needed) so that the true dimensions can then be re-calculated. setTimeout(() => { const maxHeightValue = parseInt(positionStyles.maxHeight); let contentHeight = this.innerHeight(content); if (maxHeightValue < contentHeight) { contentHeight = maxHeightValue; } content.style.maxHeight = Math.max(contentHeight, maxHeightValue) + 'px'; this.contentStyles.height = contentHeight + 'px'; this.contentStyles.width = this.calculateContainerWidth() + 'px'; if (positionStyles.flowUpwards) { this.contentStyles.top = finalTop + 'px'; } this.contentStyles.transform = `translateZ(0)`; this.contentStyles.opacity = 1; if (this.options.width === 'contents') { this.contentStyles.whiteSpace = 'nowrap'; } this.widthHasBeenAdjusted = true; this.cd.markForCheck(); }, 0); } clickHandler(e) { if (e.keyCode === KeyCode.Escape) { this.escapeKeyPressed.emit(true); } } ngOnDestroy() { const content = this.getDropdownContent(); if (content) { content.style.maxHeight = 'none'; } this.contentStyles.opacity = 0; this.contentStyles.maxHeight = 'none'; } /** * Calculates the position of the dropdown based on the height, width. alignment and screen boundaries. */ calculatePositionStyles() { const positionStyles = { flowUpwards: false, maxHeight: this.dropDownMaxHeight + 'px' }; const content = this.getDropdownContent(); const fullHeightContent = content && content.querySelector('.scroller'); const contentHeight = this.innerHeight(fullHeightContent) + this.pageMargin; // Offscreen detection const windowHeight = window.innerHeight; const triggerHeight = this.innerHeight(this.trigger); const offset = this.offset(this.trigger); const triggerLeft = offset.left; const triggerTop = offset.top; const containerWidth = this.calculateContainerWidth(); const currAlignment = this.calculateAlignment(triggerLeft, containerWidth); // Below Origin let verticalOffset = 0; if (this.options.belowTrigger === true) { verticalOffset = triggerHeight; } // Vertical bottom offscreen detection if (verticalOffset + triggerTop + contentHeight > windowHeight) { let adjustedHeight = this.limitHeight(this.innerHeight(content)); const contentLargerThanWindow = windowHeight <= adjustedHeight; // If content is greater than half of the window height, it should // flow upward if the trigger is below the half-way point if (contentLargerThanWindow) { positionStyles.flowUpwards = windowHeight / 2 < triggerTop; } else { positionStyles.flowUpwards = (windowHeight <= triggerTop + adjustedHeight) && (windowHeight / 2 < triggerTop); } if (!positionStyles.flowUpwards) { // If going upwards still goes offscreen, just crop height of dropdown. if (triggerTop + triggerHeight - contentHeight < 0) { adjustedHeight = windowHeight - triggerTop - verticalOffset - this.pageMargin; } } else { if (!verticalOffset) { verticalOffset += triggerHeight + 1; } if (this.options.belowTrigger === true) { verticalOffset -= triggerHeight; } if (triggerTop + triggerHeight - this.pageMargin < adjustedHeight) { adjustedHeight = (triggerTop + triggerHeight) - this.pageMargin; } adjustedHeight = this.limitHeight(adjustedHeight); verticalOffset -= adjustedHeight; } positionStyles.maxHeight = this.limitHeight(adjustedHeight) + 'px'; } // Handle edge alignment let leftPosition = 0; switch (currAlignment) { case 'left': leftPosition = triggerLeft; break; case 'right': leftPosition = triggerLeft + this.trigger.offsetWidth - containerWidth; break; case 'center': default: leftPosition = 0; } positionStyles.top = this.trigger.getBoundingClientRect().top + verticalOffset + 'px'; positionStyles.left = leftPosition + 'px'; return positionStyles; } onContentClick() { this.clicked.emit(true); } /** * Calculates the optimal alignment of the dropdown contents to avoid clipping over the edge of the window. */ calculateAlignment(triggerLeft, containerWidth) { let currAlignment = this.options.alignment; const doesNotFitOnRight = triggerLeft - containerWidth + this.innerWidth(this.trigger) < 0; const doesNotFitOnLeft = window.innerWidth < triggerLeft + containerWidth; if (doesNotFitOnRight && doesNotFitOnLeft) { // Dropdown is wider than screen, force center alignment currAlignment = 'center'; } else if (doesNotFitOnLeft) { // Dropdown goes past screen on right, force right alignment currAlignment = 'right'; } else if (doesNotFitOnRight) { // Dropdown goes past screen on left, force left alignment currAlignment = 'left'; } return currAlignment; } /** * Given a true height of an element, returns a new height which is limited by both * the height of the window and the value of this.dropDownMaxHeight. */ limitHeight(trueHeight) { const windowHeight = window.innerHeight - this.pageMargin * 2; return Math.min(trueHeight, this.dropDownMaxHeight, windowHeight); } getDropdownContent() { return this.elementRef.nativeElement.querySelector('gtx-dropdown-content'); } /** * Returns the width of the container according to the `width` input passed into the component. */ calculateContainerWidth() { switch (this.options.width) { case 'contents': return this.calculateWidthContents(); case 'trigger': return this.calculateWidthTrigger(); case 'expand': return this.calculateWidthExpand(); default: return this.calculateWidthNumber(); } } calculateWidthContents() { const content = this.getDropdownContent(); // if the container is wider than the window, we just set the width to take up the full window if (window.innerWidth < content.offsetWidth) { return window.innerWidth; } else { // adjust the width by 1px once, to eliminate unwanted x-scrollbar when there is a y-scrollbar. // The `widthHasBeenAdjusted` flag prevents the contents from further widening on subsequent // calls to calculatePositionStyles() const adjustment = this.widthHasBeenAdjusted ? 0 : 1; return content.offsetWidth + adjustment; } } calculateWidthTrigger() { return this.trigger.offsetWidth + 1; } calculateWidthExpand() { return Math.max(this.calculateWidthTrigger(), this.calculateWidthContents()); } calculateWidthNumber() { return +this.options.width; } /** * Returns the offset of the element relative to the document. */ offset(elem) { let box = elem.getBoundingClientRect(); let body = document.body; let docEl = document.documentElement; let scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; let scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; let clientTop = docEl.clientTop || body.clientTop || 0; let clientLeft = docEl.clientLeft || body.clientLeft || 0; let top = box.top + scrollTop - clientTop; let left = box.left + scrollLeft - clientLeft; return { top: Math.round(top), left: Math.round(left) }; } innerWidth(el) { if (el) { let style = window.getComputedStyle(el, null); return Number.parseInt(style.getPropertyValue('width')) || el.offsetWidth; } return 0; } innerHeight(el) { if (el) { let style = window.getComputedStyle(el, null); return Number.parseInt(style.getPropertyValue('height')) || el.offsetHeight; } return 0; } } /** @nocollapse */ DropdownContentWrapper.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DropdownContentWrapper, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: ConfigService }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ DropdownContentWrapper.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.8", type: DropdownContentWrapper, selector: "gtx-dropdown-content-wrapper", host: { listeners: { "keydown": "clickHandler($event)" } }, ngImport: i0, template: `<div class="dropdown-content-wrapper" (click)="onContentClick()" [ngStyle]="contentStyles"> <ng-template [ngTemplateOutlet]="content"></ng-template> </div>`, isInline: true, directives: [{ type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.8", ngImport: i0, type: DropdownContentWrapper, decorators: [{ type: Component, args: [{ selector: 'gtx-dropdown-content-wrapper', template: `<div class="dropdown-content-wrapper" (click)="onContentClick()" [ngStyle]="contentStyles"> <ng-template [ngTemplateOutlet]="content"></ng-template> </div>`, changeDetection: ChangeDetectionStrategy.OnPush }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{ type: Inject, args: [ConfigService] }] }]; }, propDecorators: { clickHandler: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24tY29udGVudC13cmFwcGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2Ryb3Bkb3duLWxpc3QvZHJvcGRvd24tY29udGVudC13cmFwcGVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0gsU0FBUyxFQUNULFlBQVksRUFFWixVQUFVLEVBQ1YsaUJBQWlCLEVBQ2pCLFlBQVksRUFDWix1QkFBdUIsRUFDdkIsTUFBTSxFQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUU5QyxPQUFPLEVBQVMsYUFBYSxFQUFDLE1BQU0scUJBQXFCLENBQUM7OztBQVcxRCxNQUFNLE9BQU8sc0JBQXNCO0lBa0IvQixZQUFvQixVQUFzQixFQUN0QixFQUFxQixFQUNFLE1BQWM7UUFGckMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0QixPQUFFLEdBQUYsRUFBRSxDQUFtQjtRQUNFLFdBQU0sR0FBTixNQUFNLENBQVE7UUFoQnpELGtCQUFhLEdBQVE7WUFDakIsUUFBUSxFQUFFLFVBQVU7U0FDdkIsQ0FBQztRQUNGLFlBQU8sR0FBRztZQUNOLFNBQVMsRUFBRSxNQUEyQjtZQUN0QyxLQUFLLEVBQUUsVUFBMkI7WUFDbEMsWUFBWSxFQUFFLEtBQUs7U0FDdEIsQ0FBQztRQUVGLE9BQUUsR0FBVyxXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEUsWUFBTyxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7UUFDbEMscUJBQWdCLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUNuQyx5QkFBb0IsR0FBRyxLQUFLLENBQUM7UUFLakMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJ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LENBQUM7WUFDOUMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLENBQUM7U0FDN0U7UUFDRCxPQUFPLENBQUMsQ0FBQztJQUNiLENBQUM7SUFFTyxXQUFXLENBQUMsRUFBZTtRQUMvQixJQUFJLEVBQUUsRUFBRTtZQUNKLElBQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDOUMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUM7U0FDL0U7UUFDRCxPQUFPLENBQUMsQ0FBQztJQUNiLENBQUM7O3NJQTNTUSxzQkFBc0IsNkVBb0JYLGFBQWE7MEhBcEJ4QixzQkFBc0IsZ0lBUHJCOzs7O3NCQUlROzJGQUdULHNCQUFzQjtrQkFUbEMsU0FBUzttQkFBQztvQkFDUCxRQUFRLEVBQUUsOEJBQThCO29CQUN4QyxRQUFRLEVBQUU7Ozs7c0JBSVE7b0JBQ2xCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2lCQUNsRDs7MEJBcUJnQixNQUFNOzJCQUFDLGFBQWE7NENBbUVqQyxZQUFZO3NCQURYLFlBQVk7dUJBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDb21wb25lbnQsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIEluamVjdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtLZXlDb2RlfSBmcm9tICcuLi8uLi9jb21tb24va2V5Y29kZXMnO1xuaW1wb3J0IHtEcm9wZG93bkFsaWdubWVudCwgRHJvcGRvd25XaWR0aH0gZnJvbSAnLi9kcm9wZG93bi5tb2RlbCc7XG5pbXBvcnQge0NvbmZpZywgQ29uZmlnU2VydmljZX0gZnJvbSAnLi4vLi4vbW9kdWxlLmNvbmZpZyc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnZ3R4LWRyb3Bkb3duLWNvbnRlbnQtd3JhcHBlcicsXG4gICAgdGVtcGxhdGU6IGA8ZGl2IGNsYXNzPVwiZHJvcGRvd24tY29udGVudC13cmFwcGVyXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ29udGVudENsaWNrKClcIlxuICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJjb250ZW50U3R5bGVzXCI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdUZW1wbGF0ZU91dGxldF09XCJjb250ZW50XCI+PC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgIDwvZGl2PmAsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgRHJvcGRvd25Db250ZW50V3JhcHBlciBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gICAgcGFnZU1hcmdpbjogQ29uZmlnWydkcm9wRG93blBhZ2VNYXJnaW4nXTtcbiAgICBkcm9wRG93bk1heEhlaWdodDogQ29uZmlnWydkcm9wRG93bk1heEhlaWdodCddO1xuICAgIGNvbnRlbnQ6IFRlbXBsYXRlUmVmPGFueT47XG4gICAgY29udGVudFN0eWxlczogYW55ID0ge1xuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJ1xuICAgIH07XG4gICAgb3B0aW9ucyA9IHtcbiAgICAgICAgYWxpZ25tZW50OiAnbGVmdCcgYXMgRHJvcGRvd25BbGlnbm1lbnQsXG4gICAgICAgIHdpZHRoOiAnY29udGVudHMnIGFzIERyb3Bkb3duV2lkdGgsXG4gICAgICAgIGJlbG93VHJpZ2dlcjogZmFsc2VcbiAgICB9O1xuICAgIHRyaWdnZXI6IEhUTUxFbGVtZW50O1xuICAgIGlkOiBzdHJpbmcgPSAnZHJvcGRvd24tJyArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cigyKTtcbiAgICBjbGlja2VkID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gICAgZXNjYXBlS2V5UHJlc3NlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICAgIHByaXZhdGUgd2lkdGhIYXNCZWVuQWRqdXN0ZWQgPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgICAgICAgICBwcml2YXRlIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgICAgICAgICBASW5qZWN0KENvbmZpZ1NlcnZpY2UpIHByaXZhdGUgY29uZmlnOiBDb25maWcpIHtcbiAgICAgICAgdGhpcy5wYWdlTWFyZ2luID0gdGhpcy5jb25maWcuZHJvcERvd25QYWdlTWFyZ2luO1xuICAgICAgICB0aGlzLmRyb3BEb3duTWF4SGVpZ2h0ID0gdGhpcy5jb25maWcuZHJvcERvd25NYXhIZWlnaHQ7XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFBvc2l0aW9uQW5kU2l6ZSh0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQb3NpdGlvbnMgYW5kIHJlc2l6ZXMgdGhlIGRyb3Bkb3duIGNvbnRlbnRzIGNvbnRhaW5lci5cbiAgICAgKi9cbiAgICBzZXRQb3NpdGlvbkFuZFNpemUoaW5pdGlhbE9wZW5pbmc6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gdGhpcy5nZXREcm9wZG93bkNvbnRlbnQoKTtcbiAgICAgICAgaWYgKCFjb250ZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluaXRpYWxPcGVuaW5nKSB7XG4gICAgICAgICAgICAvLyBXaGVuIG9wZW5pbmcgZm9yIHRoZSBmaXJzdCB0aW1lLCBzb21lIGV4dHJhIGxvZ2ljIGlzIHJlcXVpcmVkXG4gICAgICAgICAgICB0aGlzLmNvbnRlbnRTdHlsZXMuaGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIHRoaXMuY29udGVudFN0eWxlcy5vcGFjaXR5ID0gMDtcbiAgICAgICAgICAgIGNvbnRlbnQuc2V0QXR0cmlidXRlKCdpZCcsIHRoaXMuaWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcG9zaXRpb25TdHlsZXMgPSB0aGlzLmNhbGN1bGF0ZVBvc2l0aW9uU3R5bGVzKCk7XG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5jb250ZW50U3R5bGVzLCBwb3NpdGlvblN0eWxlcyk7XG4gICAgICAgIC8vIGNvbnN0IGZsb3dVcHdhcmRzID0gcGFyc2VJbnQocG9zaXRpb25TdHlsZXMudG9wLCAxMCkgPCBNYXRoLmZsb29yKHRoaXMudHJpZ2dlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3ApO1xuICAgICAgICBjb25zdCBjb250ZW50SGVpZ2h0ID0gdGhpcy5pbm5lckhlaWdodCh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdndHgtZHJvcGRvd24tY29udGVudCcpKTtcblxuICAgICAgICAvLyB3aGVuIGZsb3dpbmcgdXB3YXJkcywgd2UgYW5pbWF0ZSB0aGUgYHRvcGAgcHJvcGVydHksIHNvIG11c3QgcmVtZW1iZXIgdGhlIGZpbmFsIHZhbHVlLlxuICAgICAgICBjb25zdCBmaW5hbFRvcCA9IHBhcnNlSW50KHRoaXMuY29udGVudFN0eWxlcy50b3ApO1xuICAgICAgICBpZiAocG9zaXRpb25TdHlsZXMuZmxvd1Vwd2FyZHMpIHtcbiAgICAgICAgICAgIHRoaXMuY29udGVudFN0eWxlcy50b3AgPSBmaW5hbFRvcCArIE1hdGgubWluKGNvbnRlbnRIZWlnaHQsIHBhcnNlSW50KHBvc2l0aW9uU3R5bGVzLm1heEhlaWdodCkpICsgJ3B4JztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29udGVudFN0eWxlcy53aWR0aCA9IHRoaXMuY2FsY3VsYXRlQ29udGFpbmVyV2lkdGgoKSArICdweCc7XG4gICAgICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgICAgIC8vIFNob3cgZHJvcGRvd24uIFdyYXBwZWQgaW4gYSBzZXRUaW1lb3V0IHRvIGFsbG93IHRoZSBjb250ZW50cyBvZiB0aGUgZHJvcGRvd25cbiAgICAgICAgLy8gdG8gcmUtZmxvdyAoaWYgbmVlZGVkKSBzbyB0aGF0IHRoZSB0cnVlIGRpbWVuc2lvbnMgY2FuIHRoZW4gYmUgcmUtY2FsY3VsYXRlZC5cbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBtYXhIZWlnaHRWYWx1ZSA9IHBhcnNlSW50KHBvc2l0aW9uU3R5bGVzLm1heEhlaWdodCk7XG4gICAgICAgICAgICBsZXQgY29udGVudEhlaWdodCA9IHRoaXMuaW5uZXJIZWlnaHQoY29udGVudCk7XG4gICAgICAgICAgICBpZiAobWF4SGVpZ2h0VmFsdWUgPCBjb250ZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgY29udGVudEhlaWdodCA9IG1heEhlaWdodFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29udGVudC5zdHlsZS5tYXhIZWlnaHQgPSBNYXRoLm1heChjb250ZW50SGVpZ2h0LCBtYXhIZWlnaHRWYWx1ZSkgKyAncHgnO1xuXG4gICAgICAgICAgICB0aGlzLmNvbnRlbnRTdHlsZXMuaGVpZ2h0ID0gY29udGVudEhlaWdodCArICdweCc7XG4gICAgICAgICAgICB0aGlzLmNvbnRlbnRTdHlsZXMud2lkdGggPSB0aGlzLmNhbGN1bGF0ZUNvbnRhaW5lcldpZHRoKCkgKyAncHgnO1xuXG4gICAgICAgICAgICBpZiAocG9zaXRpb25TdHlsZXMuZmxvd1Vwd2FyZHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnRTdHlsZXMudG9wID0gZmluYWxUb3AgKyAncHgnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jb250ZW50U3R5bGVzLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGVaKDApYDtcbiAgICAgICAgICAgIHRoaXMuY29udGVudFN0eWxlcy5vcGFjaXR5ID0gMTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy53aWR0aCA9PT0gJ2NvbnRlbnRzJykge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udGVudFN0eWxlcy53aGl0ZVNwYWNlID0gJ25vd3JhcCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpZHRoSGFzQmVlbkFkanVzdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH0sIDApO1xuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICAgIGNsaWNrSGFuZGxlcihlOiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmIChlLmtleUNvZGUgPT09IEtleUNvZGUuRXNjYXBlKSB7XG4gICAgICAgICAgICB0aGlzLmVzY2FwZUtleVByZXNzZWQuZW1pdCh0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gdGhpcy5nZXREcm9wZG93bkNvbnRlbnQoKTtcbiAgICAgICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgICAgICAgIGNvbnRlbnQuc3R5bGUubWF4SGVpZ2h0ID0gJ25vbmUnO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29udGVudFN0eWxlcy5vcGFjaXR5ID0gMDtcbiAgICAgICAgdGhpcy5jb250ZW50U3R5bGVzLm1heEhlaWdodCA9ICdub25lJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgcG9zaXRpb24gb2YgdGhlIGRyb3Bkb3duIGJhc2VkIG9uIHRoZSBoZWlnaHQsIHdpZHRoLiBhbGlnbm1lbnQgYW5kIHNjcmVlbiBib3VuZGFyaWVzLlxuICAgICAqL1xuICAgIGNhbGN1bGF0ZVBvc2l0aW9uU3R5bGVzKCk6IHsgdG9wOiBzdHJpbmcsIGxlZnQ6IHN0cmluZywgbWF4SGVpZ2h0OiBzdHJpbmcsIGZsb3dVcHdhcmRzOiBib29sZWFuOyB9IHtcbiAgICAgICAgY29uc3QgcG9zaXRpb25TdHlsZXM6IGFueSA9IHtcbiAgICAgICAgICAgIGZsb3dVcHdhcmRzOiBmYWxzZSxcbiAgICAgICAgICAgIG1heEhlaWdodDogdGhpcy5kcm9wRG93bk1heEhlaWdodCArICdweCdcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZ2V0RHJvcGRvd25Db250ZW50KCk7XG4gICAgICAgIGNvbnN0IGZ1bGxIZWlnaHRDb250ZW50ID0gY29udGVudCAmJiBjb250ZW50LnF1ZXJ5U2VsZWN0b3IoJy5zY3JvbGxlcicpIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBjb25zdCBjb250ZW50SGVpZ2h0ID0gdGhpcy5pbm5lckhlaWdodChmdWxsSGVpZ2h0Q29udGVudCkgKyB0aGlzLnBhZ2VNYXJnaW47XG5cbiAgICAgICAgLy8gT2Zmc2NyZWVuIGRldGVjdGlvblxuICAgICAgICBjb25zdCB3aW5kb3dIZWlnaHQ6IG51bWJlciA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICAgICAgY29uc3QgdHJpZ2dlckhlaWdodDogbnVtYmVyID0gdGhpcy5pbm5lckhlaWdodCh0aGlzLnRyaWdnZXIpO1xuICAgICAgICBjb25zdCBvZmZzZXQgPSB0aGlzLm9mZnNldCh0aGlzLnRyaWdnZXIpO1xuICAgICAgICBjb25zdCB0cmlnZ2VyTGVmdCA9IG9mZnNldC5sZWZ0O1xuICAgICAgICBjb25zdCB0cmlnZ2VyVG9wID0gb2Zmc2V0LnRvcDtcbiAgICAgICAgY29uc3QgY29udGFpbmVyV2lkdGggPSB0aGlzLmNhbGN1bGF0ZUNvbnRhaW5lcldpZHRoKCk7XG4gICAgICAgIGNvbnN0IGN1cnJBbGlnbm1lbnQgPSB0aGlzLmNhbGN1bGF0ZUFsaWdubWVudCh0cmlnZ2VyTGVmdCwgY29udGFpbmVyV2lkdGgpO1xuXG4gICAgICAgIC8vIEJlbG93IE9yaWdpblxuICAgICAgICBsZXQgdmVydGljYWxPZmZzZXQgPSAwO1xuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmJlbG93VHJpZ2dlciA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdmVydGljYWxPZmZzZXQgPSB0cmlnZ2VySGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVmVydGljYWwgYm90dG9tIG9mZnNjcmVlbiBkZXRlY3Rpb25cbiAgICAgICAgaWYgKHZlcnRpY2FsT2Zmc2V0ICsgdHJpZ2dlclRvcCArIGNvbnRlbnRIZWlnaHQgPiB3aW5kb3dIZWlnaHQpIHtcbiAgICAgICAgICAgIGxldCBhZGp1c3RlZEhlaWdodCA9IHRoaXMubGltaXRIZWlnaHQodGhpcy5pbm5lckhlaWdodChjb250ZW50KSk7XG4gICAgICAgICAgICBjb25zdCBjb250ZW50TGFyZ2VyVGhhbldpbmRvdyA9IHdpbmRvd0hlaWdodCA8PSBhZGp1c3RlZEhlaWdodDtcblxuICAgICAgICAgICAgLy8gSWYgY29udGVudCBpcyBncmVhdGVyIHRoYW4gaGFsZiBvZiB0aGUgd2luZG93IGhlaWdodCwgaXQgc2hvdWxkXG4gICAgICAgICAgICAvLyBmbG93IHVwd2FyZCBpZiB0aGUgdHJpZ2dlciBpcyBiZWxvdyB0aGUgaGFsZi13YXkgcG9pbnRcbiAgICAgICAgICAgIGlmIChjb250ZW50TGFyZ2VyVGhhbldpbmRvdykge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uU3R5bGVzLmZsb3dVcHdhcmRzID0gd2luZG93SGVpZ2h0IC8gMiA8IHRyaWdnZXJUb3A7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uU3R5bGVzLmZsb3dVcHdhcmRzID0gKHdpbmRvd0hlaWdodCA8PSB0cmlnZ2VyVG9wICsgYWRqdXN0ZWRIZWlnaHQpICYmICh3aW5kb3dIZWlnaHQgLyAyIDwgdHJpZ2dlclRvcCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghcG9zaXRpb25TdHlsZXMuZmxvd1Vwd2FyZHMpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBnb2luZyB1cHdhcmRzIHN0aWxsIGdvZXMgb2Zmc2NyZWVuLCBqdXN0IGNyb3AgaGVpZ2h0IG9mIGRyb3Bkb3duLlxuICAgICAgICAgICAgICAgIGlmICh0cmlnZ2VyVG9wICsgdHJpZ2dlckhlaWdodCAtIGNvbnRlbnRIZWlnaHQgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkanVzdGVkSGVpZ2h0ID0gd2luZG93SGVpZ2h0IC0gdHJpZ2dlclRvcCAtIHZlcnRpY2FsT2Zmc2V0IC0gdGhpcy5wYWdlTWFyZ2luO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCF2ZXJ0aWNhbE9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbE9mZnNldCArPSB0cmlnZ2VySGVpZ2h0ICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5iZWxvd1RyaWdnZXIgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmVydGljYWxPZmZzZXQgLT0gdHJpZ2dlckhlaWdodDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHJpZ2dlclRvcCArIHRyaWdnZXJIZWlnaHQgLSB0aGlzLnBhZ2VNYXJnaW4gPCBhZGp1c3RlZEhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZEhlaWdodCA9ICh0cmlnZ2VyVG9wICsgdHJpZ2dlckhlaWdodCkgLSB0aGlzLnBhZ2VNYXJnaW47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFkanVzdGVkSGVpZ2h0ID0gdGhpcy5saW1pdEhlaWdodChhZGp1c3RlZEhlaWdodCk7XG4gICAgICAgICAgICAgICAgdmVydGljYWxPZmZzZXQgLT0gYWRqdXN0ZWRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwb3NpdGlvblN0eWxlcy5tYXhIZWlnaHQgPSB0aGlzLmxpbWl0SGVpZ2h0KGFkanVzdGVkSGVpZ2h0KSArICdweCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW5kbGUgZWRnZSBhbGlnbm1lbnRcbiAgICAgICAgbGV0IGxlZnRQb3NpdGlvbjogbnVtYmVyID0gMDtcbiAgICAgICAgc3dpdGNoIChjdXJyQWxpZ25tZW50KSB7XG4gICAgICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgICAgICAgICBsZWZ0UG9zaXRpb24gPSB0cmlnZ2VyTGVmdDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgICAgICAgICBsZWZ0UG9zaXRpb24gPSAgdHJpZ2dlckxlZnQgKyB0aGlzLnRyaWdnZXIub2Zmc2V0V2lkdGggLSBjb250YWluZXJXaWR0aDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGxlZnRQb3NpdGlvbiA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBwb3NpdGlvblN0eWxlcy50b3AgPSB0aGlzLnRyaWdnZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wICsgdmVydGljYWxPZmZzZXQgKyAncHgnO1xuICAgICAgICBwb3NpdGlvblN0eWxlcy5sZWZ0ID0gbGVmdFBvc2l0aW9uICsgJ3B4JztcblxuICAgICAgICByZXR1cm4gcG9zaXRpb25TdHlsZXM7XG4gICAgfVxuXG4gICAgb25Db250ZW50Q2xpY2soKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2xpY2tlZC5lbWl0KHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgdGhlIG9wdGltYWwgYWxpZ25tZW50IG9mIHRoZSBkcm9wZG93biBjb250ZW50cyB0byBhdm9pZCBjbGlwcGluZyBvdmVyIHRoZSBlZGdlIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVBbGlnbm1lbnQodHJpZ2dlckxlZnQ6IG51bWJlciwgY29udGFpbmVyV2lkdGg6IG51bWJlcik6IERyb3Bkb3duQWxpZ25tZW50IHwgJ2NlbnRlcicge1xuICAgICAgICBsZXQgY3VyckFsaWdubWVudDogRHJvcGRvd25BbGlnbm1lbnQgfCAnY2VudGVyJyA9IHRoaXMub3B0aW9ucy5hbGlnbm1lbnQ7XG5cbiAgICAgICAgY29uc3QgZG9lc05vdEZpdE9uUmlnaHQgPSB0cmlnZ2VyTGVmdCAtIGNvbnRhaW5lcldpZHRoICsgdGhpcy5pbm5lcldpZHRoKHRoaXMudHJpZ2dlcikgPCAwO1xuICAgICAgICBjb25zdCBkb2VzTm90Rml0T25MZWZ0ID0gd2luZG93LmlubmVyV2lkdGggPCB0cmlnZ2VyTGVmdCArIGNvbnRhaW5lcldpZHRoO1xuICAgICAgICBpZiAoZG9lc05vdEZpdE9uUmlnaHQgJiYgZG9lc05vdEZpdE9uTGVmdCkge1xuICAgICAgICAgICAgLy8gRHJvcGRvd24gaXMgd2lkZXIgdGhhbiBzY3JlZW4sIGZvcmNlIGNlbnRlciBhbGlnbm1lbnRcbiAgICAgICAgICAgIGN1cnJBbGlnbm1lbnQgPSAnY2VudGVyJztcbiAgICAgICAgfSBlbHNlIGlmIChkb2VzTm90Rml0T25MZWZ0KSB7XG4gICAgICAgICAgICAvLyBEcm9wZG93biBnb2VzIHBhc3Qgc2NyZWVuIG9uIHJpZ2h0LCBmb3JjZSByaWdodCBhbGlnbm1lbnRcbiAgICAgICAgICAgIGN1cnJBbGlnbm1lbnQgPSAncmlnaHQnO1xuICAgICAgICB9IGVsc2UgaWYgKGRvZXNOb3RGaXRPblJpZ2h0KSB7XG4gICAgICAgICAgICAvLyBEcm9wZG93biBnb2VzIHBhc3Qgc2NyZWVuIG9uIGxlZnQsIGZvcmNlIGxlZnQgYWxpZ25tZW50XG4gICAgICAgICAgICBjdXJyQWxpZ25tZW50ID0gJ2xlZnQnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjdXJyQWxpZ25tZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgdHJ1ZSBoZWlnaHQgb2YgYW4gZWxlbWVudCwgcmV0dXJucyBhIG5ldyBoZWlnaHQgd2hpY2ggaXMgbGltaXRlZCBieSBib3RoXG4gICAgICogdGhlIGhlaWdodCBvZiB0aGUgd2luZG93IGFuZCB0aGUgdmFsdWUgb2YgdGhpcy5kcm9wRG93bk1heEhlaWdodC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGxpbWl0SGVpZ2h0KHRydWVIZWlnaHQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IHdpbmRvd0hlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIHRoaXMucGFnZU1hcmdpbiAqIDI7XG4gICAgICAgIHJldHVybiBNYXRoLm1pbih0cnVlSGVpZ2h0LCB0aGlzLmRyb3BEb3duTWF4SGVpZ2h0LCB3aW5kb3dIZWlnaHQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0RHJvcGRvd25Db250ZW50KCk6IEhUTUxFbGVtZW50IHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdndHgtZHJvcGRvd24tY29udGVudCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHdpZHRoIG9mIHRoZSBjb250YWluZXIgYWNjb3JkaW5nIHRvIHRoZSBgd2lkdGhgIGlucHV0IHBhc3NlZCBpbnRvIHRoZSBjb21wb25lbnQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVDb250YWluZXJXaWR0aCgpOiBudW1iZXIge1xuICAgICAgICBzd2l0Y2ggKHRoaXMub3B0aW9ucy53aWR0aCkge1xuICAgICAgICAgICAgY2FzZSAnY29udGVudHMnOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZVdpZHRoQ29udGVudHMoKTtcbiAgICAgICAgICAgIGNhc2UgJ3RyaWdnZXInOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZVdpZHRoVHJpZ2dlcigpO1xuICAgICAgICAgICAgY2FzZSAnZXhwYW5kJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jYWxjdWxhdGVXaWR0aEV4cGFuZCgpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jYWxjdWxhdGVXaWR0aE51bWJlcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVXaWR0aENvbnRlbnRzKCk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLmdldERyb3Bkb3duQ29udGVudCgpO1xuICAgICAgICAvLyBpZiB0aGUgY29udGFpbmVyIGlzIHdpZGVyIHRoYW4gdGhlIHdpbmRvdywgd2UganVzdCBzZXQgdGhlIHdpZHRoIHRvIHRha2UgdXAgdGhlIGZ1bGwgd2luZG93XG4gICAgICAgIGlmICh3aW5kb3cuaW5uZXJXaWR0aCA8IGNvbnRlbnQub2Zmc2V0V2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGFkanVzdCB0aGUgd2lkdGggYnkgMXB4IG9uY2UsIHRvIGVsaW1pbmF0ZSB1bndhbnRlZCB4LXNjcm9sbGJhciB3aGVuIHRoZXJlIGlzIGEgeS1zY3JvbGxiYXIuXG4gICAgICAgICAgICAvLyBUaGUgYHdpZHRoSGFzQmVlbkFkanVzdGVkYCBmbGFnIHByZXZlbnRzIHRoZSBjb250ZW50cyBmcm9tIGZ1cnRoZXIgd2lkZW5pbmcgb24gc3Vic2VxdWVudFxuICAgICAgICAgICAgLy8gY2FsbHMgdG8gY2FsY3VsYXRlUG9zaXRpb25TdHlsZXMoKVxuICAgICAgICAgICAgY29uc3QgYWRqdXN0bWVudCA9IHRoaXMud2lkdGhIYXNCZWVuQWRqdXN0ZWQgPyAwIDogMTtcbiAgICAgICAgICAgIHJldHVybiBjb250ZW50Lm9mZnNldFdpZHRoICsgYWRqdXN0bWVudDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgY2FsY3VsYXRlV2lkdGhUcmlnZ2VyKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyaWdnZXIub2Zmc2V0V2lkdGggKyAxO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FsY3VsYXRlV2lkdGhFeHBhbmQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KHRoaXMuY2FsY3VsYXRlV2lkdGhUcmlnZ2VyKCksIHRoaXMuY2FsY3VsYXRlV2lkdGhDb250ZW50cygpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNhbGN1bGF0ZVdpZHRoTnVtYmVyKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiArdGhpcy5vcHRpb25zLndpZHRoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG9mZnNldCBvZiB0aGUgZWxlbWVudCByZWxhdGl2ZSB0byB0aGUgZG9jdW1lbnQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBvZmZzZXQoZWxlbTogSFRNTEVsZW1lbnQpOiB7IHRvcDogbnVtYmVyOyBsZWZ0OiBudW1iZXI7IH0ge1xuICAgICAgICBsZXQgYm94ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICBsZXQgYm9keSA9IGRvY3VtZW50LmJvZHk7XG4gICAgICAgIGxldCBkb2NFbCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuICAgICAgICBsZXQgc2Nyb2xsVG9wID0gd2luZG93LnBhZ2VZT2Zmc2V0IHx8IGRvY0VsLnNjcm9sbFRvcCB8fCBib2R5LnNjcm9sbFRvcDtcbiAgICAgICAgbGV0IHNjcm9sbExlZnQgPSB3aW5kb3cucGFnZVhPZmZzZXQgfHwgZG9jRWwuc2Nyb2xsTGVmdCB8fCBib2R5LnNjcm9sbExlZnQ7XG5cbiAgICAgICAgbGV0IGNsaWVudFRvcCA9IGRvY0VsLmNsaWVudFRvcCB8fCBib2R5LmNsaWVudFRvcCB8fCAwO1xuICAgICAgICBsZXQgY2xpZW50TGVmdCA9IGRvY0VsLmNsaWVudExlZnQgfHwgYm9keS5jbGllbnRMZWZ0IHx8IDA7XG5cbiAgICAgICAgbGV0IHRvcCAgPSBib3gudG9wICsgIHNjcm9sbFRvcCAtIGNsaWVudFRvcDtcbiAgICAgICAgbGV0IGxlZnQgPSBib3gubGVmdCArIHNjcm9sbExlZnQgLSBjbGllbnRMZWZ0O1xuXG4gICAgICAgIHJldHVybiB7IHRvcDogTWF0aC5yb3VuZCh0b3ApLCBsZWZ0OiBNYXRoLnJvdW5kKGxlZnQpIH07XG4gICAgfVxuXG5cbiAgICBwcml2YXRlIGlubmVyV2lkdGgoZWw6IEhUTUxFbGVtZW50KTogbnVtYmVyIHtcbiAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICBsZXQgc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgbnVsbCk7XG4gICAgICAgICAgICByZXR1cm4gTnVtYmVyLnBhcnNlSW50KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ3dpZHRoJykpIHx8IGVsLm9mZnNldFdpZHRoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5uZXJIZWlnaHQoZWw6IEhUTUxFbGVtZW50KTogbnVtYmVyIHtcbiAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICBsZXQgc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgbnVsbCk7XG4gICAgICAgICAgICByZXR1cm4gTnVtYmVyLnBhcnNlSW50KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2hlaWdodCcpKSB8fCBlbC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxufVxuIl19